原文地址:http://nilhcem.com/android/custom-tensorflow-classifier
TensorFlow是一個(gè)開源的用于機(jī)器學(xué)習(xí)的庫,是由谷歌開發(fā)的并用在他們的多個(gè)項(xiàng)目中。
一個(gè)簡(jiǎn)單、快捷、并且有趣的開始TensorFlow的方法就是創(chuàng)建一個(gè)圖像分類器,我們的Android設(shè)備可以直接檢測(cè)和識(shí)別圖片中的對(duì)象。
在這篇文章中,我們將會(huì)創(chuàng)建一個(gè)Android應(yīng)用程序,可以識(shí)別視頻游戲人物。

首先,運(yùn)行Android分類示例
Github上提供了官方的TensorFlow android 圖片分類示例代碼,如果你想要build他,需要花費(fèi)一些時(shí)間,你需要安裝NDK,Bazel,用Android studio將會(huì)花費(fèi)40分鐘左右的build時(shí)間。
如果你想導(dǎo)入TensorFlow安卓示例代碼到你的項(xiàng)目中,你需要做:
- 導(dǎo)入原始的TensorFlow Android 示例代碼
- 創(chuàng)建一個(gè)新的Android Studio項(xiàng)目(applicationId:org.tensorflow.demo),以便已經(jīng)設(shè)置了gradle配置。
- 將TensorFlow的android示例代碼移動(dòng)到新的gralde項(xiàng)目。
- 移除DetectorActivity和StylizeActivity,我們今天只需要ClassifierActivity。
- 下載CI與構(gòu)建NDK庫,并將它們放入到項(xiàng)目的gradle中。
- 將預(yù)訓(xùn)練的ImageNet模型放到項(xiàng)目中的assets文件夾中。
一旦你導(dǎo)入了TensorFlow android示例代碼,運(yùn)行一下并且開始檢測(cè)東西。
創(chuàng)建自己的圖片分類器
TensorFlow示例使用“Inception”,這是一個(gè)經(jīng)過預(yù)訓(xùn)練用以從ImageNet 2012 Chanllenge圖像數(shù)據(jù)集中檢測(cè)1000個(gè)對(duì)象的模型。
我們要轉(zhuǎn)移學(xué)習(xí),這意味著我們從一個(gè)已經(jīng)在另一個(gè)問題上訓(xùn)練的模型開始,然后我們將用它訓(xùn)練另外一個(gè)類似的問題,從頭開始深入學(xué)習(xí)可能需要花費(fèi)幾天的時(shí)間,但是類似的學(xué)習(xí)卻可以在短期內(nèi)完成。
1、收集大量的圖像
Inception適用于各種圖像(至少30張圖片),我們將創(chuàng)建一個(gè)/tf_files/games/mario,/tf_files/games/bomberman等
一次下載多張圖片的快速方法就是在Google圖片上搜索內(nèi)容,并使用Chrome擴(kuò)展程序進(jìn)行批量下載。

2、重新訓(xùn)練模型,以從圖像學(xué)習(xí)
現(xiàn)在我們有了所有的圖像,我們將重新訓(xùn)練模型。
我們可以使用docker容器開設(shè)置TensorFlow環(huán)境:
docker run -it -v $HOME/tf_files:/tf_files \
gcr.io/tensorflow/tensorflow:latest-devel
cd /tensorflow
git pull
git checkout v1.0.1
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/games
不要停止你的容器,你很快會(huì)再需要他。
此操作可能需要幾分鐘,取決于你擁有多少圖像和有多少指定的訓(xùn)練步驟.
這些命令將使用TensorFlow下載初始模型并重新訓(xùn)練他以檢測(cè)~/tf_files/ 游戲中的圖像。
該腳本將申城兩個(gè)文件:protobuf文件中的模型(retrained_graph.pb)和他可以識(shí)別的所有對(duì)象的標(biāo)簽列表(retrained_labels.txt).
優(yōu)化模型
我們有自己的模型,然而,如果你嘗試把他導(dǎo)入到Android項(xiàng)目中,將會(huì)得到如下錯(cuò)誤:
Op BatchNormWithGlobalNormalization is not avaliable in GraphDef version 21. it has been removed in version 9.Use tf.nn.batch_normalization.
我們首先需要優(yōu)化他,使用一個(gè)工具optimize_for_inference
./configure
bazel build tensorflow/python/tools:optimize_for_inference
構(gòu)建工具需要花費(fèi)20分鐘的時(shí)間。
優(yōu)化
在這一點(diǎn)上,一件最值得做的就是,為了節(jié)省時(shí)間,將目前docker進(jìn)程提交到一個(gè)新的鏡像,你就不需要重建optimeze_for_inference工具。
exit
docker ps -a
docker commit <container ID> <new_name>
docker run -it $HOME/tf_files:/tf_files <new_name>
cd /tensorflow
現(xiàn)在工具已經(jīng)構(gòu)建了,你可以優(yōu)化你的模型了。
bazel-bin/tensorflow/python/tools/optimize_for_inference \
--input=/tf_files/retrained_graph.pb \
--output=/tf_files/retrained_graph_optimized.pb \
--input_names=Mul \
--output_names=final_result
現(xiàn)在可以退出docker容器,此腳本將生成一個(gè)~/tf_files/retrained_graph_optimized.pb文件,現(xiàn)在可以在你的Android項(xiàng)目中導(dǎo)入。
導(dǎo)入新的模型到你的Android應(yīng)用中
我們有已經(jīng)重新訓(xùn)練的模型,我們現(xiàn)在可以刪除Android項(xiàng)目的assets下面的ImageNet模型,并且替換成新的模型~/tf_files/retrained_graph_optimized.pb和~/tf_files/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/retrained_graph_optimized.pb";
private static final String LABEL_FILE =
"file:///android_asset/retrained_labels.txt";
測(cè)試已經(jīng)訓(xùn)練過的AI
我們安裝新的AI模型,我們可以運(yùn)行項(xiàng)目到Android設(shè)備上,并且使用我們的新的訓(xùn)練過的AI來檢測(cè)對(duì)象。
Android Things怎么樣
在Android Things上使用TensorFlow比在Android上使用簡(jiǎn)單一點(diǎn),已經(jīng)有一個(gè)官方的gradle示例,他與ImageNet模型一起使用,可以快速部署:androidthings.
如果你想使用你自定義的模型,你只需要做這篇文章中相同的步驟就可以了。
- 替換assets文件夾中的你的自定義模型
- 移除.aar庫并用TensorFlow最新的庫替代
- 修改TensorFlowImageClassfier.java文件中的常量。

在這篇文章中,你看到了一些完全無用的東西:使用深度學(xué)習(xí)來分類視頻游戲角色,但你可以做一些有趣的事情。