ディープラーニングで「顔が似ている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エンジニア採用情報

  関連記事

no image
Treasure Dataで長期間の集計

プラットフォーム・ワン T氏です。プラットフォーム・ワンでは、DSPのMarketOneとSSPのYIELD ONE提供しています。 MarketOneやYIELD ONEのログを調査する場合にTreasure Dataを使うことがあります。Treasure Dataでは大量のデータに対してHive …

no image
Angular.jsのvalueとfactoryの違いを考える

次のようなHTMLがあったとする。 [code language=”html”] <!doctype html> <html lang="jp" ng-app="App"> <head> <me …

GoogleスプレッドシートからTreasureDataへデータを取り込む

AudienceOneの開発を担当しています。skryoです。 またまたTreasureDataネタですが、今回はGoogleスプレッドシートからGoogleAppsScriptを使ってTreasureDataへデータを取り込む手順を紹介したいと思います。 なぜ? Googleスプレッドシート上でマ …

プログラミング初心者がswiftでゲームアプリ的なものを作ってみた。

こんにちは、DAC2年目のkumataです。 普段は素敵な先輩方に囲まれてインフラ周りのお仕事をさせて頂いていますが、 今回は業務とは全く関係ないプログラミングをやってみました。 全く初心者なのですが、swift+Xcodeで簡単にスマホゲーム的なものが作れました。 初心者の目線から作成方法をつらつ …

no image
いま必要なのは「アナリティクスアプローチ」

こんにちは。 ビッグデータ解析部のakiです。 解析部で、Markezineでの連載をはじめましたのでご紹介です。 いま必要なのは「アナリティクスアプローチ」、ビッグデータ活用の課題とこれから (http://markezine.jp/article/detail/21293) マーケターのかた向け …

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

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

fastavroとjqでAVRO形式のファイルからデータを取得しよう

AVRO形式のファイルを取り扱いたい AVROとはApacheプロジェクトのひとつとして開発されているデータ交換形式です。 コンパクトなバイナリで高速なシリアライズ・デシリアライズが行えるため、サーバーログなどに利用されています。 弊社内での一部システムのログデータにも利用されているのですが、専用の …

GoogleAppsScriptとTreasureData REST APIを使ってサーバレスにTwitterのデータを取得

またまたTreasureDataネタです。 ただ、今回はクエリ系のネタではなく、GoogleAppsScriptとTreasureDataのREST APIを使ってTwitterのデータをTreasureDataに入れてみたので、その方法を紹介したいと思います。 はじめに ログデータだけではなく、公 …

iOS端末情報をTreasureDataに送るアプリをswiftで作ってみた。

はじめまして、2年目のOyamanです。 通常業務とは別のことになりますが、Swiftに触れる機会が少しあったので、スマホ関連の記事を書かせていただきます。 はじめに SwiftとTreasureDataのSDKを使って、 iOSの端末情報をTreasureDataへ送るアプリを作ってみます。 今回 …

Scala番外編「Boxに保存したファイルをBox APIを使ってダウンロードしよう!」

はじめに みなさんこんにちは、プロダクト開発本部の亀梨です。 普段はXmediaOneというメディアプランニング・広告運用管理・トラッキング・マーケティング分析を行う 統合プラットフォームの開発を担当しています。 Box APIを使う背景・目的 DACはメディアレップです メディアレップとは、インタ …