tensorflowを使ってうなぎと寿司の判別するClassifier(分類器)を作ってみました.
(今の季節に旬なものを分類したいというのが今回の記事のきっかけです.)
おおまかな流れとしては,コンピュータでモデルの学習を行って完成したモデルをandroidに入れて使用するという感じです.
記事の内容は任天堂のキャラを分類するこの記事をかなり参考にさせてもらいました.記事では多クラスですが,今回はtensorflowの理解を深めることが目的なので,2クラス分類問題としました.
(もちろん2つ以上のものを学習させることは可能です.3個でも100個でも200個でも...)
では早速やっていきましょう!
##まずは分類したいものの画像を集めましょう!
だいたい40〜60枚ぐらいだといいですね.最低でも30枚は必要です.
多い分には問題はないのが深層学習ですが,極端に多い枚数20000枚とかだと精度はいいけど,学習に時間がかかってしまうということが起きます.
また少なすぎても,学習させた画像しか分類できなくなります.(過少適合)
それとノイズ(イラストや関係ない画像)があると分類器が極端に機能が低下すると思うのでそこらへんは目grepで適当に除去してください.
画像の集め方はGoogle検索で一枚一枚ダウンロードしてもいいのですが,それは大変なので画像検索した画面で以下のクローム拡張を使うと簡単にダウンロードできます.(使い方はフィーリングで覚えてください.)
https://chrome.google.com/webstore/detail/fatkun-batch-download-ima/nnjjahlikiabnchcpehcpkdeckfgnohf
うなぎと寿司の画像を集めたら以下のディレクトリに保存します.
~/tf_files/food/unagi # うなぎの画像
~/tf_files/food/sushi # 寿司の画像
次にandroidのファイルを編集していくのですが,ベースはtensorflowのリポジトリのサンプルです.
https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android
このデフォルトのモデルを自分で作ってみるというのが今回の一番の目的であり目標です.
cd ~/
git clone https://github.com/tensorflow/tensorflow.git
cd ~/tensorflow
git checkout v1.2.1
# dockerでやる場合.環境があるならこの部分は不要です.
docker run -it \
--volume ~/tf_files:/tf_files \
--volume ~/tensorflow:/tensorflow \
--workdir /tensorflow tensorflow/tensorflow:1.2.1 bash
# 学習のメイン部分4000回のトレーニングをします.ハードの性能によって調整してください.
# dockerでやらない人はこの部分を適宜書き換えてください.
python tensorflow/examples/image_retraining/retrain.py \
--bottleneck_dir=/tf_files/bottlenecks \
--how_many_training_steps 4000 \
--model_dir=/tf_files/inception \
--output_graph=/tf_files/retrained_graph.pb \
--output_labels=/tf_files/retrained_labels.txt \
--image_dir /tf_files/food
このままでは,Androidでモデルを使用できないのでAndroidようにモデルの最適化を行います.
python tensorflow/python/tools/optimize_for_inference.py \
--input=/tf_files/retrained_graph.pb \
--output=/tf_files/optimized_graph.pb \
--input_names="Mul" \
--output_names="final_result"
以下を実行すると容量が少しマシになるようです.私の環境では2MBほどしか減りませんでした.
python tensorflow/tools/quantization/quantize_graph.py \
--input=/tf_files/optimized_graph.pb \
--output=/tf_files/rounded_graph.pb \
--output_node_names=final_result \
--mode=weights_rounded
元からあるassetフォルダーのモデルは削除しても構いませんが,ビルドすると復活してしまうのでほっといても構いません.
先ほど作ったrounded_graph.pb(またはoptimized_graph.pb)とretrained_labels.txtをassetフォルダーにコピーします.
retrained_labels.txtは分類するラベル(うなぎと寿司)を表す文字列のデータですが,現在のラベルがフォルダ名の英語のままなので順番を保ったまま日本語にしましょう.
寿司
うなぎ
ClassifierActivity.javaを追加したモデル名に合わせて編集します.
// ここも以下のように書き換えてください.
private static final int INPUT_SIZE = 299;
private static final int IMAGE_MEAN = 128;
private static final float IMAGE_STD = 128;
private static final String INPUT_NAME = "Mul";
private static final String OUTPUT_NAME = "final_result";
// ここをファイル名に合わせて編集
private static final String MODEL_FILE =
"file:///android_asset/rounded_graph.pb"; // または optimized_graph.pb
private static final String LABEL_FILE =
"file:///android_asset/retrained_labels.txt";
build.gradle(app)を一部書き換えて完成です.
def nativeBuildSystem = 'cmake'
あとは実行してみましょう!!
##実際の動作画面です.
ラグがありますが,寿司とうなぎをしっかりと判別できています.精度も高いです.(twiiterの誰かの適当な画像で検証済み)
(gifアニメの中の画像の著作権は金銭目的の記事じゃないので許してください.)
###制作物のソースコードは以下です.
https://github.com/Ooshita/Unagi_or_sushi
##まとめ
Google Cloud Vision API とかあるのになんで自前で作るんだ,と言う方がいるかもしれませんが,
まず有料だし,オンライン環境じゃなきゃ死にます.
うなぎと寿司を絶対にオフラインで分類したいということは多分あんまりないですが,命に関わるシステムはオフラインじゃなきゃ仕方がないです.
あとはいくら使っても無料っていうのがいいですよね.あとは自分で好きなだけ調整できるということでしょう.
あとはもっと複雑なアフォーダンスを解析するとかのモデルも自分で試してAndroidに組み込むこともできます.
自分の好きなように深層学習を使えるというのが最高の楽しさですね.
参考
Android - Add some machine learning to your apps, with TensorFlow
http://nilhcem.com/android/custom-tensorflow-classifier
人工知能の基礎の理解に良いサイト
人工知能の学習理論 渡辺澄夫先生
http://watanabe-www.math.dis.titech.ac.jp/users/swatanab/joho-gakushu.html
##深層学習について理解を深めたいときに読んだらいい書籍も紹介してます.
深層学習をやるならこれを読め!
http://qiita.com/NoriakiOshita/items/ef360cf13cf2969aab71