料理画像判定のためのバックエンドアーキテクチャ

サービス開発部の外村 (@hokaccha)です。

クックパッドのアプリには「料理きろく」という機能があります。 モバイル端末から料理画像のみを抽出して記録することで食べたものが自動的に記録されていくという機能です。

f:id:hokaccha:20171108125806p:plain

今回はこの料理きろくで画像判定をおこなっているバックエンドのアーキテクチャについて紹介します。なお、実際に判定をおこなう機械学習のモデルのはなしは以下の記事に書かれているのでそちらを参照してください。

料理きろくにおける料理/非料理判別モデルの詳細 - クックパッド開発者ブログ

また、以下のスライドでも料理きろくのバックエンドについて紹介されているのでこちらも参照してみてください。

処理の概要

ざっくりとした画像判定のフローとしては、次のようになります。

  1. クライアントアプリは端末内の画像を判定用に縮小してサーバーにアップロードする
  2. サーバーはアップロードされた画像を機械学習を用いて料理画像かどうかを判定する
  3. クライアントアプリは判定結果を受け取る

クライアントアプリが結果を受け取った後にオリジナルの画像をアップロードしたり、RDBMSにデータを保存するといった処理もありますが、今回は判定処理をクライアントアプリが受け取るまでの流れに絞って解説します。

初期のアーキテクチャ

プロトタイプの段階ではこの処理を単純に料理画像判定用のHTTPのAPIエンドポイントを用意し、そこに画像をアップロードして判定処理を行い、結果をレスポンスで返すという構成で実現していました。

f:id:hokaccha:20171108125340p:plain

Web APIはRailsとUnicornで動いているサーバーで、その後ろに実際に判定をおこなうPythonのサーバーがたっていてRailsのアプリケーションはそこと通信しています。

この処理は画像アップロードに加えて、料理画像判定の処理にディープラーニングを用いているのでそれなりに重たい処理になります。APIサーバーで利用しているUnicornは仕組み上プロセスがリクエストを処理している間他のリクエストをブロックするため、大量のアクセスがきた場合にI/O待ちによりworkerを使い切ってしまいます*1

機能の性質上、端末にある画像をすべてアップロードする*2ので利用者が増えると判定の処理が大量にくる可能性は高かったため、アーキテクチャを変更する必要がありました。

現状のアーキテクチャ

そこでシステムの安定性を高めるため、以下のような方法を取ることにしました。

  • 画像はAPIサーバーにアップロードせず、S3に直接アップロードする
  • サーバー側は料理画像の判定処理をバックグラウンドワーカーで非同期に行う

APIサーバーで重い処理を受けないようにすることでアクセスが集中してもAPIサーバーが詰まらないようにし、バックグラウンドワーカーをスケールアウトさせればサービスがスケール可能になるアーキテクチャを目指しました。

他にもI/O多重化ができるサーバーを導入するであったり、コストを覚悟でUnicornのサーバーをスケールアウトするという方法も考えられますが、今回は社内のノウハウなども加味して一番安定して稼働できそうという判断のもと、このアーキテクチャを採用しました。

最終的な構成としては次のようになります。

f:id:hokaccha:20171108125343p:plain

順に説明していきます。

S3に直接画像をアップロードする

まず、画像アップロードの負荷を軽減するため、S3に直接アップロードすることにしました。そのためにS3のPre-Signed URLを利用しています。

Uploading Objects Using Pre-Signed URLs - Amazon Simple Storage Service

クライアントがアップロード処理を開始するときにAPIサーバーにリクエストし(1)、アップロード可能なS3のURLを取得します。このときAPIサーバーはRDBMSにレコードを作成し、アップロードの状態管理を開始します。クライアントアプリは返ってきたURLに対して画像をアップロードすることでS3に画像がアップロードされます(2)

S3のイベント通知でSQSにエンキューする

S3にはEvent Notificationsという機能があります。

Configuring Amazon S3 Event Notifications - Amazon Simple Storage Service

この機能を使うと、S3にファイルアップロードされたり、変更されるといったイベントが発生されときに、特定のサービスに通知を送ることができます。これを利用し、S3にファイルがアップロードされたときにSQSにエンキューが行われるようにします(3)

バックグラウンドワーカーの処理

バックグラウンドワーカーはSQSのキューをポーリングしていて、エンキューされたメッセージはバックグラウンドワーカーがデキューすることで処理を行います(4)

メッセージのペイロードにはS3にアップロードされたオブジェクトのキーなどの情報が入っているので、その情報を元にバックグラウンドワーカーはS3からアップロードされた画像を取得し(5)、機械学習による判定を行い(6)、結果をAPIサーバーにHTTPで送信し(7)、メッセージの処理を完了させます。

このワーカーはPythonで書かれていて、hakoを利用しECS上で動いており、オートスケールの設定もhakoでおこなっています。

結果の取得

最後にクライアントアプリは結果をAPIサーバーから取得(8)してフローは終了です。

ただ、処理を非同期にした場合に難しいのがこの結果の取得です。同期的に判定ができるのであれば、クライアントアプリは判定結果が返ってくるのを待ってから次の処理に進めばいいのですが、非同期の場合はいつ処理が終わるかクライアントアプリにはわかりません。

今回はクライアントアプリが定期的に結果取得のAPIエンドポイントにリクエストすることで結果を取得するようにしています。料理きろくという機能はユーザーが写真を撮って、後で見た時に自動で写真が記録されている、という機能なのでそのケースではリアルタイム性が求められないので数十分に一回程度のリクエストで後から結果が取得できれば問題ありません*3

ただ、クライアントアプリでそういった処理を定期実行するのは簡単ではなく、様々な苦労がありました。詳しくは料理きろくのAndroidの実装を行った吉田の以下の資料にまとまっています。

まとめ

料理きろくの料理画像判定部分のアーキテクチャについて解説しました。現時点で一日あたり約50万枚以上の画像を判定していますが、大きな問題はなく安定して稼働しています。基本的にはよくあるジョブキューを利用した非同期処理のアーキテクチャですが、S3やSQSはこういったシステムを組むのにとても便利です。

また、最近ではモバイル端末でも機械学習のモデルが動くようになってきています。まだ実用段階まではいっていませんが、それが実現すればこのようなシステムは一切いらなくなり、クライアントの実装も非常にシンプルになるので、できるだけ早く実現してこのシステムがいらなくなる日がくればよいと思っています。

*1:Railsを噛ませずにPythonのサーバーで直接受けてもHTTPサーバーの仕組みがUnicornと同じであれば大きな違いはありません

*2:料理画像以外も判定のために一旦サーバーに保存しているため、ユーザーのプライバシーについては十分に配慮し、判定後には画像は完全に削除し、開発者であってもどのような画像が判定に使われたかを見ることがはできないようになっています

*3:ユーザーが最初に料理きろくを利用する場合に数十枚の画像の判定を進捗を見せながら表示するという要件もあり、この場合は間隔の短いポーリングを行っています

Encoder-Decoder でレシピの材料名を正規化する

研究開発部の原島です。部のマネージメントのかたわら、自然言語処理関連の開発に従事しています。本エントリでは、最近社内で開発した自然言語処理システムを紹介します。

■ 「しょうゆ」のバリエーションは 100 種類以上

クックパッドで以前から解決したかった課題の一つに材料の名前(以下、材料名)の正規化があります。

f:id:jharashima:20171030074621j:plain

クックパッドのレシピは複数の材料から構成され、各材料は名前と分量から構成されています。例えば、上のレシピの一つ目の材料は「豚薄切り肉」が名前で、「200g」が分量です。

さて、この材料名はこのレシピでは「豚薄切り肉」という表現でした。しかし、他のレシピでは「豚うす切り肉」という表現かもしれません。「豚うすぎり肉」や「ぶた薄切り肉」、「豚薄ぎり肉」等の表現もありえますね。

これは異表記同義(いわゆる表記揺れ)の問題ですが、同様の問題は他にも沢山あります。例えば、以下のようなものです。

  • 同義表現系の問題
    • 異表記同義(上述)
    • 異形同義(e.g.「じゃがいも」と「馬鈴薯」)
    • 略記(e.g.「ホットケーキミックス」と「HM」)
    • 綴り間違い(e.g.「アボカド」と「アボガド」)
  • 付属表現系の問題
    • 記号(e.g.「★味噌」)
    • 括弧表現(e.g.「油(炒め用)」)
    • 接頭辞(e.g.「お砂糖」)
    • その他(e.g.「お好みでローズマリー」)

面倒なことに、これらの問題は複合的に発生することも珍しくありません。その結果、例えば、クックパッドにおける「しょうゆ」には、分かっているだけで、100 種類以上のバリエーションが存在しています。

時に、これがサービス開発において問題となります。

例えば、あるレシピのカロリーを計算するとしましょう。そのためには、そのレシピ中の全ての材料名のカロリーが必要です。つまり、材料名ごとにカロリーを登録したデータベースが必要です。

しかし、クックパッドには数百万種類の材料名が存在します。これらの全てに人手でカロリーを登録するのは途方もない作業です。「しょうゆ」は大さじ 1 杯で約 13 kcal ですが、あらゆる「しょうゆ」のバリエーションにこの情報を登録するのは大変です。

こういった時に、「材料名を正規化したい」という考えに至ります。あらゆる「しょうゆ」のバリエーションを全て「しょうゆ」に正規化できれば、「しょうゆ」にだけカロリーを登録すれば良いわけです。大分コストを削減できそうですね。

このように、材料名の正規化は、以前から解決したいと思っていた課題の一つでした。

■ 正規化しよう!とは言え...

どうすれば材料名を正規化できるのでしょうか。

最初に検討すべきは正規表現です。例えば、材料名の冒頭の記号と末尾の括弧表現を除去するというのはどうでしょう。しかし、この方法だと、同義表現系の問題は全く解決できません。

クラウドソーシングはどうでしょう。人手で正規化すれば、全ての問題を解決できそうです。しかし、1 個の材料名を 10 円で正規化できたとしても、数千万円が必要です。仕様変更等でやり直しが発生すれば、さらに必要ですね。

機械学習の出番かもしれません。例えば、何らかの語彙を定義できれば、SVM や Random Forest 等で各材料名を語彙のいずれかに分類できそうです。しかし、そもそも語彙を定義するのが困難です。未知語とかどうしましょう。

材料名の各文字について CRF で「必要」もしくは「不要」というラベルを付与して、必要な文字だけを抽出するというのはどうでしょう。しかし、この方法でも、同義表現系の問題は解決できません。

いずれの手法にも何かしらの問題がありそうです。

■ Encoder-Decoder で正規化しよう!

そこで、クックパッドでは Encoder-Decoder を利用することにしました。

Encoder-Decoder は、おおまかには、「入力の情報を何らかのベクトルに集約し、そのベクトルから出力を生成するモデル」です。前半を処理する部分が Encoder で、後半を処理する部分が Decoder です。

このモデルの利用例としては機械翻訳が代表的です。日英翻訳であれば、日本語文が入力で、その英訳が出力です。入力と出力は一般的には単語列です。正解データ(この場合は日英対訳)さえあれば、翻訳モデルが構築できます。

材料名を正規化する場合、材料名が入力で、その正規化後の表現が出力です。イメージは下図の通りです。上述の通り、Encoder-Decoder の一般的な設定では入力も出力も単語列ですが、我々の設定では文字列になります。図の EOW は End-of-Word の略です。

f:id:jharashima:20171030074722p:plain

Encoder-Decoder は入力から出力を抽出するわけではなく、生成します。そのため、付属表現系の問題だけではなく、同義表現系の問題も解決できます。また、正規化のパターンが学習できれば、未知語にもある程度は対応できます。

なお、このように Encoder-Decoder を正規化に利用するのは我々が最初ではありません(業務に導入したのは我々が最初かもしれません)。例えば、以下の 2 本の論文で同様のアイデアが提案されています。

  • Japanese Text Normalization with Encoder-Decoder Model(Ikeda et al. 2016)
  • 疑似データの事前学習に基づくEncoder-decoder型日本語崩れ表記正規化(斉藤ら 2017)

■ 全体像はどうなってる?

正規化システムの全体像は大きく三つに分割できます。正解データ収集とモデル開発、バッチ実行です。以下でそれぞれについて概説します。

f:id:jharashima:20171030074818p:plain

正解データ収集

Encoder-Decoder を学習(と検証、テスト)するには正解データが必要です。そこで、スタッフが毎日利用する社内ツール(クックパッドと同様、Rails 製)に、正解データを収集するための仕組みを追加しました。普段の業務をこなすと、正解データが自然と MySQL に蓄積されるようにしました。

本エントリの執筆時点で、約 12,000 個の正解データが収集されていました。

モデル開発

開発環境には p2.8xlarge を、フレームワークには Chainer を利用しました。やや詳細な話になりますが、Encoder と Decoder には Stacked Uni-directional LSTM(3 層)を使用しました。なお、我々のタスクでは Bi-directional LSTM や Attention はあまり効果がありませんでした。

PR がマージされると Jenkins が起動して、プログラムの実行環境をまとめた Docker イメージが社内の Docker レポジトリに登録されます。このイメージは後述するバッチで利用されます。

バッチ実行

クックパッドは主に Rails で構築されているため、そのデータの多くは MySQL に蓄積されています。さらに、これらはログデータ等とともに Redshift に集約されています。正規化バッチはこれらのデータをもとに動作しています。

まず、正規化の対象とする材料名を Redshift から取得して、S3 に保存します。次に、Docker イメージをもとに Encoder-Decoder の実行環境をインスタンスに準備した後、材料名を正規化します。最後に、S3 を経由して、結果を MySQL に保存します。

■ 正答率はどれくらい?

最後に、簡単な実験結果を紹介します。実験では正解データの 10% をテストデータに、別の 10% を検証データに、残りの 80% を学習データに使用しました。

手法 正答率
Baseline A(変更なし) 20.8%
Baseline B(正規表現) 28.6%
Encoder-Decoder 71.2%

まず、ベースラインの結果を確認しましょう。Baseline A は、入力をそのまま出力した場合の結果です。正答率(正解との完全一致率)は 20.8% でした。これは、テストデータの約 80% に何らかの正規化が必要ということを意味しています。

Baseline B は正規表現です。冒頭の記号と末尾の括弧表現を入力から除去した場合の結果です。正答率は 28.6% でした。上でも議論したように、正規表現だけで正規化するのはやはり困難でした。

最後に、Encoder-Decoder の正答率は 71.2% でした。同義表現系の問題(e.g. 桜エビ → サクラエビ)や付属表現系の問題(e.g. ※牛乳 → 牛乳)、それらの複合的な問題(e.g. ☆ローリエ → 月桂樹)に幅広く対応できたので、ベースラインより圧倒的に高い正答率となりました。

補足として、この数字はあくまでもテストデータでの値です。我々のテストデータ(と言うより、正解データ)は、テストのため、低頻度の材料名を少なからず含んでいます。現実のデータにおける数字はもう少し高いです。

また、実際に正規化結果を利用する際はスタッフがざっと確認して、明らかな間違いは修正しています。なお、修正されたデータは新たな正解データとして利用できます。

■ Appendix

以下は少し発展的な話題です。Encoder-Decoder でも失敗するのはどういうケースでしょうか。そして、それらのケースはどうすれば改善できるのでしょうか。

探索範囲が狭い

Decoder が N 文字目を出力する際は、その時点での生成確率が一番高い文字を選択します。しかし、確率が二番目に高い文字は無視して良いのでしょうか。N+1 文字目以降を出力する際に後悔しないでしょうか。

そこで、ビームサーチです。N 文字目を出力する際、確率が高い文字を M 個キープしておきます。そして、最終的に生成確率が一番高い文字列を出力としましょう。追加実験では、M = 10 の時、正答率が 72.3% になりました(統計的に優位でした。以降の数字も同様)。

存在しえない文字列を出力

例えば、「こめ油」を「米油」と正規化すべきところ、「コー油」と正規化してしまうケースです。「コー油」という文字列は少なくともクックパッドには存在しません。機械翻訳でも、Encoder-Decoder がおかしな文(単語列)を出力してしまうのはよくある話です。

そこで、このような文字列を出力しないように、Decoder を制御してみました。具体的には、ビームサーチの途中でクックパッドに存在しない文字列が生成された場合、その文字列を正規化候補から除外してみました。トライ木を利用すれば簡単に実装できます。正答率は 72.8% になりました。

入力と無関係の文字列を出力

例えば、「トーモロコシ」を「とうもろこし」と正規化すべきところ、「とろろこんぶ」と正規化してしまうケースです。「とろろこんぶ」は世の中に存在する文字列ですが、もちろんこの正規化は間違いです。

そこで、ビームサーチで取得した正規化候補を入力との類似度(と Encoder-Decoder のスコア)でリランキングしてみました。類似度の計算には word2vec を、その学習データにはクックパッドの全レシピを利用しました。正答率は 73.3% になりました。

その他

さて、まだまだ改善の余地があります。しかし、調査してみたところ、これらの多くは学習データの不足に起因するものでした。ここから先はモデルを改善するよりも、学習データを追加する方が楽かもしれませんね。

■ おわりに

本エントリでは、Encoder-Decoder でレシピの材料名を正規化するシステムについて紹介しました。

このモデルには、レシピの材料名だけでなく、EC サイトの商品名や不動産サイトの物件名等も正規化できる可能性があります。本エントリが、正規化に頭を抱える誰かのお役に立てば幸いです。

最後に、クックパッドの研究開発部では自然言語処理や画像認識の専門家を募集しています。あなたの知識・スキルで世界中の毎日の料理を楽しみにしませんか。ご興味がある方は採用ページを是非ご覧ください。ご連絡をお待ちしております。

クックパッド株式会社 研究開発部 採用情報

高速な研究開発を支えるGPU計算機環境

研究開発部の染谷 ( @ayemos_y ) です。好きな ImageNet のラベル(Synset)は "Eccentric, eccentric person, flake, oddball, geek" です。

クックパッドの研究開発部は2016年7月に発足し、現在はアルバイトを含め13名の体制となっています。その中で、こちらの記事でも紹介されている料理/非料理判別モデルを開発するなど、機械学習/ディープラーニング分野に特に力を入れて取り組んでいます。

最近は、モデルを開発し改善する手法などについて多くの情報にアクセス出来るようになり、このような技術をプロダクトに応用していきたいという気持ちが高まっている現場が多いかと思います。しかし一方で、分析の為のデータへのアクセスや画像認識モデルの実装や実験を行うためのGPU環境の整備など、現場の都合に対応するコストによって開発の勢いが鈍化してしまうような状況もめずらしくありません。

特にそのようなコストがチームのサイズに従って増えていくような場合は(つまり多くの場合においては)、組織のスケーラビリティを損なう重大な問題です。

クックパッドの研究開発部では、このような研究開発、特に機械学習における開発基盤にまつわる課題の解決にも積極的に取り組んでいます。今回はそのような取り組みの一部を紹介したいと思います。

研究開発専用AWSアカウントの利用

クックパッドには技術部開発基盤グループ/モバイル基盤グループなどの組織があり、開発基盤の整備や改善に取り組んでいますが、最近ではこのような組織が部署横断的かつ中央集権的に請け負っていた仕事を、部署ごとに分散出来るような体制に移行しつつあります。(この辺りの詳しい話はAWS Summit Tokyo 2017でも発表しました。 資料 動画 )

その取り組みの一環として、研究開発目的で利用するAWSアカウントを本番アカウントと別に用意し、研究開発部のメンバーの一部(現在は私だけですが)にAdminに近い権限を付与した上で、部署の責任範囲において開発基盤を積極的に改善するという体制が敷かれています。

オンデマンドGPUインスタンス

アカウント分離以前にも研究開発目的でGPUを利用したいという案件がありました。その際にはインフラストラクチャー部への依頼に始まり、必要なコンポーネントなどの要件のすり合わせと実際の作業が行われ、その間コミュニケーションが数往復しました。

結果として、本番アカウントに g2.2xlarge インスタンスが立ち上がり、必要コンポーネントがインストールされて利用可能になるまで4週間程かかりました。このような作業を部内で消化出来るようにするというのがアカウント分離の目的の中心でしたので、アカウントを分離後早速GPU環境の整備に取り組みました。

GPU環境とはつまり、GPUの搭載されたEC2インスタンスで、GPUを利用した開発が出来るものですが、OS環境が(不可逆に)壊れてしまった場合や、2台以上のGPUが必要になった時などを想定すれば、このような環境を低コストで繰り返し用意出来るような状況が望ましいです。手動でセットアップする従来の手法ではこれが実現出来ていないという課題がありました。ドライバーやCUDA Toolkitなど比較的低レイヤなセットアップ作業が多く、手間と時間もかかります。

そこで、最低限のコンポーネントを揃えた状態からAmazon Machine Image(AMI)を作成し、同じ状態のインスタンスを繰り返し立ち上げられるようにしました。

Packer を利用したAMIの構成管理

またさらに、各コンポーネントのバージョンアップや、異なるバージョンでセットアップされた複数のAMIを安定して管理するために、Packerを利用し、機械学習で利用するAMIを作成/構成管理しています。

PackerのChef Solo Provisioner)を利用し、Chefのrecipeと呼ばれるセットアップ手順を定義することで、これを自動で実行し、実行後の状態をAMIとして保存することが出来ます。これにより、手順をコードとして管理しておけるだけでなく、recipeを適切にパラメータ化することで、CUDA8/9をインストールしたAMIをそれぞれ別の名前で作成する等の作業を簡単に行うことが出来ます。(下図)

Slack Chat Botを利用したインスタンスの操作

AMIを用意した事で、必要なコンポーネントがインストールされた状態のGPUインスタンスを繰り返し作成することが出来るようになりました。しかしながらEC2インスタンスをオンデマンドで立ち上げる際には、VPCと特定のサブネット(のうち1つ)、キーペアやセキュリティグループを適切に選んでやる必要があります。またクックパッドではEC2インスタンスへの接続を適切に経由するためにインスタンスへのタグ情報を利用しており、これもまた設定してやる必要があります。

このような一連の操作を繰り返さない為に、Slack上で動作するChat Botから、より抽象度の高い操作によりインスタンスの作成や停止/再開を行えるようにしました。Chat Botの開発にはLitaを利用しました。

蛇足ですが、このような問題を解決するためにコマンドラインで動作するツールを配る事もできますが、Slackをインターフェースにする事で実行環境が統一されるので、開発者ごとの環境の差異を気にしなくて良くなり、また、利用されている様子から使い方を自然に見て覚えられたり、改善のヒントが得られるなどの利点があります。

インスタンスの自動停止

AMIとChat Botを整備したことにより、必要なGPU環境が数分で手に入るようになりました。一方副作用として、立ち上げたインスタンスの落とし忘れにより、アイドルなインスタンスから発生するコストが増えてきました。例えば金曜日の退勤前に実行した実験が深夜に終了し、その後週末の間なにもせずに立ち上がったままである、といったことが頻繁に起こるようになりました。

これ自体はコスト面で致命的な問題になるほどではないのですが、EC2インスタンスの課金も秒単位になったことですし、使用していないインスタンスはなるべく早く停止したいところです。

そんな時は、Amazon CloudWatch EventsとAWS Lambdaを組み合わせることで、「一定時間以上アイドルなインスタンスを停止させる」Pythonスクリプトを「5分毎に実行する」といった構成を非常に簡単に実現することが出来ます。

ちょっとした考察

計算機コストの最適化を考えた時に、例えばコンテナによって仮想化され、場所透明性を持ったワークロードをインスタンスのグループ(あるいはプール)において実行する事で、よりインスタンスのアップタイムを効率的に利用出来るといった手法も考えることが出来ます。

しかしながら複数のワークロードでGPUを共有する場合には、コンテナ化するだけではなく、ワークロードのスケジューリングなどの複雑性を導入する必要が出てきます。またコンテナ仮想化それ自身も、実験環境の可搬性を高めるという点で便利な一方で、ネットワーキング、ロギング、データ永続化など、いくつかの複雑さが導入されるという意味で、実験環境において必要でなければ使わないという姿勢が適切なようにみえます。

そのような理由で現状は、個人に対して個人が専有出来るインスタンスを用意して必要に応じて動かすという構成を取っています。しかしながら今後も使用感やコスト面の課題を探しながら継続的に改善を進めて行くことになります。

まとめ

というわけで、今回はクックパッドの機械学習基盤についてお話しました。 Packerを利用して必要な環境をAMIとして作成/管理し、Chat Botを利用して作成/停止/再開する事で、チームメンバのそれぞれが、長くとも数分で必要なGPU環境を利用出来るという環境を整えました。

研究開発部というと、どうも実際のプロダクトと距離があるという印象ですが、チーム単体で見た時にもそれはやはりユーザーに価値を届け続ける組織である必要があると考えています。言い換えれば、ユーザーとの接点であるプロダクトに繋がるアウトプットをし続ける事が必要であり、その為にすばやい実験や実装が出来る環境があることも重要です。

そのような考えから、機械学習/ディープラーニングを中心とした最新技術へのキャッチアップとその応用はもちろん、チームの成果を最大化するための運用の改善にも積極的に取り組んでいます。

クックパッドで機械学習を利用して新たなサービスを創り出していける方に加え、研究開発部の開発環境を改善していく方も募集しています。 興味のある方はぜひ話を聞きに遊びに来て下さい。

クックパッド株式会社 研究開発部 採用情報

追記(お知らせ)

11月27日-12月1日にラスベガスで開催される AWS re:Invent 2017 にインフラ部のと一緒に登壇します。 "Containerized Machine Learning on AWS" というテーマで料理きろくで利用されている画像判定システムののアーキテクチャを中心に話します。乞うご期待!

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/