ディープラーニングで「顔が似ている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
gulp.jsで広告タグの開発環境を整える

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

【Hivemall入門】RandomForestで毒キノコ推定モデルを作る

こんにちは。俺やで。 今回も前回から間が空いてしましたが、ビッグデータに対応したHiveで使える機械学習ライブラリ、 Hivemallの使い方について、書かせていただければと思います。 なお今回はQiitaのTreasure Data / Advent Calender 2015の12/3日分として …

no image
Polymer core-ajax の使い方

Polymerのcore-ajaxの使い方。 まずは、index.html [code language=”html” title=”index.html”] <!doctype html> <html> <head&gt …

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

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

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

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

【未経験からのRuby on Rails – 第2回】Rubyのプログラムを書いてみる(Mac)

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

Tableauを利用してMySQLとRedshiftのクロスDBジョインを実現する

はじめに RedshiftやTreasureDataなどのデータマート用のDBにはID単位の解析結果が格納され、ローカルのMySQLにはIDに紐づいた名称マスタが管理されている構成の場合、データマートのクロス集計結果に対してIDに紐づいた名称を付与したいことがあります。 データマート用に用意したDB …

no image
【未経験からのRuby on Rails – 第1回】楽しく書けるプログラミング言語 “Ruby” とは

こんにちは、はじめまして。新卒1年目のmatsuari(女子)です。 この度、Rubyの勉強を始めることになりまして、 まずはたくさんあるプログラミング言語の中で、なぜ自分がRubyを学ぶのか? しっかりと把握した上で学習に取り組んでいきたいと考え、『Rubyとは何か?』調べました。 超基礎的なこと …

TypeScriptについてまとめてみた

はじめに JavaScript がとりあえずそのまま動くので、雰囲気で使ってしまいがちな TypeScript。初心者向けに基本的なことをまとめてみました。 TypeScript って何? TypeScript はマイクロソフトが開発したプログラミング言語で、オープンソースでメンテナンスされています …

トレジャーデータの新機能「Data Connector」でクライアントレスなビッグデータ連携を実現する

トレジャーデータは、スキーマレスな大量のデータ(ビッグデータ)をパブリッククラウド上に保管して集計や抽出をするためのサービスなのですが、他システムからの連携データをトレジャーデータのテーブルに格納するまでが一苦労でした。 他システムとの外部連携を行う場合、一般的にローカルサーバー内のストレージを外部 …