ディープラーニングで「顔が似ているAKB48のメンバーを教えてくれるbot」を構築


概要

こんにちは、システム開発部の中村です。
今回は、Facebook Messenger APIを利用して、
画像をアップロードすると、似ているAKB48のメンバーを教えてくれるbotを実装しました。

尚、ディープラーニングやTensorFlowそのものの解説というより、
「エンジンとしてディープラーニングを活用したbotの実装方法」を主眼としている事をご承知おき下さい。

システム構成

Bot応答を行うサーバは諸般の都合によりGo、画像判別はPython(顔検出はOpenCV、分類用の畳込みニューラルネットワークはTensorFlow)で作成しています。
尚、言語間のI/FはgRPCでGoからPythonにRPCを行っています。

実装

Go側

Facebook MessengerからのWebhookを受信して、bot応答を行うWorkerプロセスです。

Messenger Bot Server

WebサーバにはGinを利用しています。
難しい事は特にないですが、トラフィックが増えた際、複数のユーザからのメッセージをまとめてWebhookにPOSTする事があるようなので、
エンタープライズで利用するならそのあたりを注意する必要があると思います。
エラーハンドリングが甘々なのはご容赦下さい。

Python側

画像のパスを与えると、顔を検出して学習済の畳込みニューラルネットで顔の類似度を判定します。

※学習用の画像は、Custom Search APIで取得しました。

OpenCVで顔検出

さて取得してきた画像ですが、いくらディープラーニングとはいえこのままCNNで分類しても大した精度にならないので、まずは顔の部分だけトリミングします。
今回は、検出にOpenCVを利用しました。
NumPy形式のArrayを引数に取って、顔面部分のみトリミングした結果を返します。
尚、なぜか右耳が顔として検出されたホラーな画像もありました。
心霊写真など検出してしまいそうでちょっと怖いです。

結構大変かなと思っていたのですが、これだけです。
あまりにも便利すぎて驚きました。アルゴリズムは今度きちんと勉強しようと思います。

TensorFlowでCNN

収集・前処理した画像を使って、ネットワークの重みを学習させます。

畳込みニューラルネットの構成は、Deep MNIST for Expertsと同じ、

  • 畳込み層1
  • プーリング層1
  • 畳込み層2
  • プーリング層2
  • 全結合層1
  • 全結合層2(ソフトマックス)

の6層です。

チュートリアルだけだとイマイチTensorFlow作法がわからないので、TensorFlow Mechanics 101を熟読するのがオススメです。

モデリングの部分を抜粋します。

訓練の際、下記のようにして訓練結果の重みをバイナリファイルに保存しておく事によって、
RPCによる分類関数の呼び出し時に利用する事ができます。

ネットワークの最深層のソフトマックス関数の実行結果を返す、分類用の関数です。

gRPC

最後に、Go言語で実装したbotサーバから、TensorFlowをRPCします。
gRPCはデータフォーマットにProtocol Buffersを利用しています。
ざっくり説明するとプログラム間で通信するための汎用データ定義で、
定義ファイルである.protoファイルを作成すると、各言語用のシリアライズ/デシリアライズを行うライブラリがコマンドで生成できます。

データ構造の定義

まず下記のような、データ構造を定義するprotoファイルを作成します。
cnn.proto

定義が完了したら、Go, Pythonそれぞれの言語用のライブラリファイルを作成します。

たったこれだけで、cnn.pb.gocnn_pb2.pyというそれぞれの言語用のライブラリが生成されます。

gRPCサーバ構築

生成したライブラリを利用して、gRPCのサーバを実装します。

gRPCクライアント

次はGo言語でgRPCクライアントを実装します。

おわりに

所感

技術的には、プログラミングよりAmazon Linux上でのOpenCVのビルドが一番手間取りました。
また、今回は前処理の大切さを痛感しました。
正面から写っている写真であれば比較的判定精度が高かったのですが、
そもそも顔が斜めになっていたりすると顔の認識が出来なかったりしたので、
回転させたりなどしながらもう少し試行錯誤してみようと思います。

参考文献

プログラミングのための線形代数
そもそも線形代数の基本がわかっていなかったので、1から勉強しました。

深層学習 (機械学習プロフェッショナルシリーズ)
式の展開が結構詳細に書かれているため、ギリギリ読めました。

TensorFlowでアニメゆるゆりの制作会社を識別する
畳込みニューラルネットの実装は、丁寧に解説されているこちらを参考にさせて頂きました。


DACエンジニア採用情報

  関連記事

curry
【小ネタ】JSで要素の組み合わせを列挙する

下記のような、キーの数や要素数が可変のデータの組み合わせを、列挙するjavascriptコードです。 pythonにはitertoolなどの順列・組み合わせ計算を行う定番ライブラリがあるようです。 やっている事ですが、イメージとしては組み合わせを数列に置き換えています。 1桁目が2進数、3桁目が3進 …

data-tenki
気象予報士とビッグデータ解析の意外な関係

DACから気象予報士が誕生しました ビッグデータ解析部のMikeです。 2015年1月の気象予報士試験に合格し、めでたく4月からアドテク業界ただ一人(本当?)の気象予報士となりました 。 そんなわけで、今回は気象予報士とビッグデータ解析の関係についてお話したいと思います。 なぜ気象予報士を目指したか …

shogi
ナイーブベイズで羽生さんと羽生くんを分類してみた

はじめに こんにちは。システム開発部の中村です。 機械学習についての理解を促進するため、 データから分類モデルを自動で構築する古典的な方法である、 ナイーブベイズ分類器を実装してみました。 最近はCloudVisionAPIなど専ら画像解析が流行っていますが、 自分のような初学者には敷居が高そうだっ …

index
Android 非同期処理についてまとめてみた

Androidには、UIに影響を与えないよういくつか非同期処理が用意されています。 今回は非同期処理の代表的な ・Service ・IntentService ・HandlerThread について違いを踏まえながらまとめます! 非同期処理について(http://codezine.jp/articl …

ruby
Railsたった14行でアドサーバーAPIができた話

こんにちは。駆け出しエンジニアの近江です。 最近Railsにハマっているので、私が2年間担当しているアドサーバの、簡易版をRailsで作ってみました。 広告やキャンペーンを登録する管理画面はある前提で、ここからたった14行追加するだけでアドサーバーのHTTP APIを作りたいと思います。ついでに配信 …

heatmap
巨大データベースのスケールアップと引越作業

はじめに ビッグデータ解析部でオーディエンスデータ解析基盤の開発、運用を担当している Mike です。 弊社ではインターネット広告配信ログをはじめとする「ビッグデータ」と呼ぶにふさわしいデータボリュームを扱うオーディエンスデータ解析基盤を構築しています。今秋、そのうちの1構成要素である、データサイズ …

chain
PyStanによるはじめてのマルコフ連鎖モンテカルロ法

はじめに こんにちは。システム開発部の中村です。 社内で行っている『データ解析のための統計モデリング入門』(所謂緑本)の輪読会に参加した所、 大変わかりやすい本だったものの、Macユーザには悲しい事に実装サンプルがWinBUGSだったため、 9章の一般化線形モデルのベイズ推定によるアプローチをPyt …

no image
Polymer on Rails

Web Componentsをご存知だろうか。これが普及すればWebの開発は画期的に変わるだろう。 説明すると長くなるので、LIGさんのにその辺はお任せして。(この記事読んでください。) 簡単に言えば、下記にあるような新たに提案されたブラウザ向けAPIの総称。 Custom Elements, 説明 …

no image
gulp.jsで広告タグの開発環境を整える

SEOの観点から、サイト表示速度の高速化のためJavaScriptファイルから不用な空白や改行、 コメントを除去したりやローカル変数名を短縮するminifyが奨励されていますが、 これはタスクランナーのgulp.jsとプラグインを使って自動化する事が可能です。 ※gulpの基本的な使い方については下 …

スクリーンショット 2015-07-31 16.38.02
【未経験からのRuby on Rails – 第2回】Rubyのプログラムを書いてみる(Mac)

こんにちは。新卒1年目のmatsuariです。 前回はRubyとは何か、簡単にご紹介をしましたが、 今回は実際にRubyファイルを作成して、プログラムを書いてみるところまでご紹介していけたらと思います。 Mac環境のプログラミング初心者向けです。 はじめに、Rubyのプログラムを書くためのファイルを …