2nd Hackarade: Machine Learning Challenge

研究開発部の菊田(@yohei_kikuta)です。機械学習を活用した新規サービスの研究開発(主として画像分析系)に取り組んでいます。 最近読んだ論文で面白かったものを3つ挙げろと言われたら以下を挙げます。

以前本ブログで紹介した Hackarade: MRI Internal Challenge ですが、その第二回として機械学習を題材にしたハッカソンが七月末に開催されました。 Hackarade ではエンジニアにとって長期的に有益となる技術を題材にしようという想いがあります。 今回はクックパッドの研究開発部が発足して一年経ち成長したというタイミングも重なることもあり、機械学習こそが時宜にかなったものであろうということでテーマが決まりました。

隆盛を極めている機械学習をほぼ全てのエンジニアが経験するという有意義な会となりましたので、この記事ではその様子についてお伝えします。

第二回 Hackarade の概要

第二回 Hackarade の概要を簡単に紹介します。 同様のイベントを開催しようと考えている方も少なくないと思いますので、参考になれば幸いです。

目標

目標は次のように設定しました。 全エンジニアが参加するイベントなので知識や経験のばらつきが多いことを考慮し、全員に持ち帰ってもらいたいものをベースとしつつ、機械学習に詳しい人にも有益となるよう発展的な内容も盛り込むよう努力しました。

  • 参加者全員
    • 機械学習を自分の言葉で定義できるようになる
    • 機械学習がどのような問題に適用できるのか理解する
    • 自分自身で機械学習のモデルを作る経験をする
    • 機械学習に関連する話題に興味を持つようになる
  • 機械学習に強い興味のある参加者
    • 独力で機械学習の勉強を続けていけるようになる
    • 最先端の機械学習トピックの一端を理解する
    • サービス改善や開発に機械学習を使って貢献できるようになる

時間割

時間割は次のように設定しました。 講義のコマでは私が講義をして、実習のコマではクックパッドのデータを使って機械学習を体験し、ハッカソンのコマでは各自が興味のあるトピックに取り組むという流れで進めました。 機械学習に馴染みが薄い人も多かったので、系統的な講義や実習を多めにして実感を掴んでもらえるよう留意しました。

  • 10:00-10:10 オープニング
  • 10:10-11:00 [講義] 機械学習とは何か
  • 11:10-12:00 [実習] レシピ分類(テキストデータ)
  • 13:00-14:30 [講義] Deep Learning(画像分析)
  • 14:40-16:10 [実習] レシピ分類(画像データ)
  • 16:20-19:00 [ハッカソン] 各自が興味あるトピックにチャレンジ
  • 19:00- パーティー & 成果発表

講義と実習の内容紹介

講義と実習で具体的に何をやったかという内容を簡単に説明します。資料は後日近い内容のものをインターンでも使用してそちらを公開しますので、興味のある方は今しばらくお待ち下さい。 クックパッドには非日本語話者も多いため、説明は日本語で実施しましたが、講義資料や実習資料などは全て英語で作成しました。

全エンジニアが参加する大きなイベントなので、資料作成はかなり気合を入れて一ヶ月前から着手しました。 資料の情報密度は相当高いものとなりましたが、参加者の能力を信じてやり切りました。 結果的には、消化不良の部分も当然あったものの、非常に満足度の高いイベントとすることができました。

講義

講義は「機械学習とは何か」と「Deep Learning(画像分析)」の二本立てでした。

機械学習とは何か

機械学習とは何かという定義から始まり、機械学習を俯瞰できるように以下の内容を説明しました。 機械学習界隈でよく出てくる言葉の意味や関係を説明し、頭の中を整理できるような構成になっています。 また、自己学習ができるように機械学習を学ぶための書籍やウェブ上の有用な情報などもまとめて共有しました。

  • 機械学習が使われている事例
  • 回帰や分類など、どのような問題に機械学習を適用できるのか
  • 機械学習の学習アルゴリズムの種類
  • 機械学習をサービスで活用するためのポイント
  • 機械学習の発展を追うのに有用な情報源

講義では機械学習の “expert” になるための最短経路の話もしました。 当然ここで述べている “expert” は冗談ですが、最低限を経験してみるという意味ではこれくらいの内容が必要かなと考えており、Hackarade でも可視化の部分以外は体験してもらうことにしました。

Deep Learning(画像分析)

Deep Learning に関しては、基礎的な説明の後に CNN にフォーカスして詳しく説明しました。 概念だけでなく具体的な演算としてどんなことをしているかにも踏み込み、Deep Learning の内部では実際に何が行われいるかが理解できるような構成になっています。 クックパッドでは画像分析(に限らずですが)の様々なタスクに取り組んでいるので、その適用事例に関しても共有しました。

  • Deep Learning の定義(なぜ昔のアイデアがうまくいくようになったのか)
  • 表現力、段階的で自動的な特徴量抽出、などの Deep Learning の特徴
  • CNN の動機とその基礎的な構成要素
  • CNN の進化
  • クックパッドにおける CNN の応用事例

一時間半の講義でしたが、内容が凝縮されたかなり濃い講義になりました。 パーセプトロンや誤差逆伝播法のような基礎から、以下のような CNN の進化に関しても少し言及しました。

この後に各モデルの鍵となるアイデアとその意味を説明するスライドが続きます。 時間的に一つ一つを丁寧に説明することは出来ませんでしたが、こうやって主要なモデルをいくつか並べてみるとどんなアイデアが鍵になって発展しているのかが分かり、興味深いですよね。

実習

実習は「レシピ分類(テキストデータ)」と「レシピ分類(画像データ)」の二本立てでした。 分析の環境を効率よく構築するために、準備した Dockerfile を用いて各自のノートPCで docker image をビルドしてもらい、立ち上げたコンテナで jupyter notebook を使って分析をするという形にしました。 そのため GPU は使用しませんでしたが、nvidia-docker を使えば同じスクリプトで GPU を使った分析もできるようになっています。

レシピ分類(テキストデータ)

レシピのタイトルや材料や手順のテキストデータを特徴ベクトル化して、該当のカテゴリ(e.g., ご飯もの、スイーツ)のレシピか否かを当てる二値分類モデルを作成しました。 テキストデータが対象だったため、MeCab を用いた形態素解析、不要な情報を除くための各種前処理、tf-idf を用いた特徴ベクトルの作成などが経験できるように準備をしました。 モデルは scikit-learn の Random Forest と Xgboost の Gradient Boosting Decision Tree を使いました。

そもそも jupyter notebook に不慣れだったり特徴ベクトルが具体的にどのような値になっているか不明瞭であったりで難しい点もありましたが、モデル構築の経験やモデルが正解する場合や間違える場合の具体的な例を見るなどして、実際のサービスで扱っている問題設定と同様のものを経験する機会となりました。

レシピ分類(画像データ)

まずは MNIST のデータを用いて、講義で学んだ MLP や CNN といったモデルを動かしてみました。 簡単にモデルを構築できるように、今回は TensorFlow backend の Keras を使いました。 一通り経験した後には、オリジナルのモデルを構築してその精度を確かめてもらいました。

次にレシピの画像からどのカテゴリ(e.g., パスタ、ラーメン)のレシピかを当てる多値分類モデルを作成しました。 実際の業務と近い分析をしてもらうために、ImageNet で事前学習をした InceptionV3 モデルを fine-tuning するというタスクに取り組んでもらいました。 学習に時間がかかるので画像は600枚程度とかなり少なめにしましたが、それでも10分単位で時間がかかり、最近のモデルは CPU では学習が困難だという実感が得られたのではないかと思います。

それ以外にも、公開されている学習済みのモデルを使えば物体検出などもお手軽に試せるということも軽く紹介し、手元で動かせるようになってもらいました。

CNN は学習は大変ですが、画像は見た目にも分かりやすいので楽しんで取り組んでもらえたように見受けられました。 モデルが間違えた画像を調べることでそもそも答えのラベルが合っているのかを疑問視するという気付きを得られたことも、実際のサービスに適用する場合には重要なので良い経験になったと思います。 また、学習の際の各種パラメタをどうやって決めればいいのかという疑問がたくさん出てきましたが、なかなか難しい話なので私も教えてもらいたいですね。

ハッカソンの紹介

ハッカソンでは各自が興味のあるトピックに対して issue を切り、そこに達成した成果や困難だと感じた点などを記述していく方式で進めました。 二時間半ほどの短い時間で新しいことに取り組むという難しい挑戦だったので、事前にトピックを考えてきてもらったり、取り組みやすそうな様々な問題を準備しておいて提示するといった工夫をしました。 結果として 40 個もの issue が切られ、多くの参加者が楽しんで主体的に取り組んでくれました。

ここではそのうちのいくつかを紹介したいと思います。

正規表現を Neural Network で解く

正規表現エンジンを NN で作れるかということを題材にして、16文字のランダムな文字列を生成し、/a+b+c/ にマッチするか否かを解いてみたという話です。 限られた時間でデータの準備から結果の検証までを行ったお手本のようなトピックでした。 対象が画像ではないですが CNN の kernel を 1*1 にして適用することで精度が上がることも実験していて、パラメタ数と精度の関係やモデルの中でどうやって認識しているのかなどの議論が発生する興味深いものとなりました。

モバイルで自分たちが学習したモデルを動かす

TensorFlow の example をベースとしてクックパッドアプリの料理きろくでも使っている料理/非料理判定モデルをモバイルで動かしてみようという話です。 実務的に興味がありながらもなかなか着手できていなかったこのトピックも、今回のハッカソンによって Android, iOS 共に料理/非料理判定モデルを動かすところまで実装ができ、みんなの興味を惹きました。 あまり機械学習を経験してこなかったモバイルエンジニアも、実習で一通り触ってからタスクに取り組むことで業務に利用していける感覚を掴めたという好例でした。

キッチンカメラの画像で人検出をして人数をカウントする

クックパッドのキッチンには様子を確認する用途のキッチンカメラがありますが、人検出を利用することでキッチンに人が何人いるかをカウントして slack に通知を出すという話です。 機械学習のモデルとしては研究開発部が作成している API があったため、そちらを使用しています。 多くの要素が絡む総合格闘技的なトピックでしたが、スピーディーに実装してみんなが確認できるものが出来上がったので、どうすれば人数カウントの精度が上がるかという議論も含めて盛り上がっていました。

究極のカレーレシピを錬成する

RNN を使ってカレーのレシピを生成してみようという話です。 講義では RNN には触れませんでしたが、torch-rnn を使ってカレーのレシピを生成するモデルを学習し、実際にレシピを生成して出力するというところまでやり切っていました。 生成系は難しいためみんなの笑いを誘うような出力(例えば材料に玉ねぎが三回も出てくる)もありましたが、カレーという特定のカテゴリに絞ったことで材料や手順がある程度理解ができるものであったのは興味深いものでした。

業務と結びつきの深いトピックを考えてみる

プロの作ったレシピとそれ以外を判別する、広告CTRを予測するモデルを構築する、料理教室のレッスンの説明文から特徴ベクトルを作って比較をする、サービス上の重複画像を排除する、アクセスログデータからの攻撃検出、など実際のサービスを意識したにしたトピックも数多く挙げられました。 問題設計やデータセットの構築に時間を要するためすぐに結果を出すというのは難しいものがほとんどでしたが、実際のサービスに活かせそうな部分を考えてみる良いきっかけとなったかと思います。

No Free Lunch Theorem の証明を理解する

話としては何度も聞いたことがあるがどのように証明するかは知らない人が多い No Free Lunch Theorem の証明を理解しようという話です。 硬派なトピックであり、個人的にはこれを選んだ人がいてテンションが上がりました。 評価関数の関数空間を探索アルゴリズムによって分割するという考えは、アルゴリズムの優劣を理論的に論じるのにも有用ですね!

その他

全部は紹介できませんが、その他にも、データセット構築する、新しいライブラリを試してみる、マインスイーパーを解かせる、アニメの速報テロップやL字を判定する、など面白いトピックが盛り沢山でした。 また、公開されているレポジトリを触っていたらバグを発見したため修正 PR を送って OSS に貢献をする人もいました。

これらの成果は美味しい食事を楽しみながら発表をして、歓声や質問が飛び交うとても楽しい時間になりました。 今回の食事のメインは TensorFlow ロゴのライスケーキで、実現が難しいオーダーにも関わらず料理人の方に素敵に仕上げてもらいました。

反省点

概ね上手くいきましたが、以下の点が反省点として挙げられます。

  • 開始時にみんなで一斉にレポジトリを clone して帯域を圧迫してしまった。
  • docker や jupyter notebook に馴染みのない人向けの基本的な説明があるとよかった。
  • 長時間椅子に座って講義を聞いたり実習をしたりするのは大変。
  • みんな楽しみすぎて、ブログに載せるための良い写真があまり撮れていなかった。

まとめ

社内のエンジニアには機械学習に馴染みのない人も少なくありませんでしたが、最高の講義だった、機械学習の系統的な理解が得られて良かった、実際に触ってみることでサービスへの活用方法などがイメージできた、など好評を博しました。 企画側としては限られた時間でのハッカソンが盛り上がるかを特に懸念していましたが、優秀なエンジニアが多いため面白い取り組みをして結果を出すところまで到達する人も多く、実に楽しく有意義なものとなりました。 機械学習は広く深い分野なので一日のイベントでできることには限りがありますが、これを契機に個々人が自発的に機械学習に取り組むようになってくれれば嬉しい限りです。

いかがでしたでしょうか。 クックパッドでは、機械学習を用いて新たなサービスを創り出していける方を募集しています。 興味のある方はぜひ話を聞きに遊びに来て下さい。
クックパッド株式会社 研究開発部 採用情報

/* */ @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;*/ /*}*/