深度學習應用系列(三)| 使用 TFLite Android構建自己的Image RecognitionApp

來源:互聯網
上載者:User

        深度學習要想落地實踐,一個少不了的路徑即是朝著智能終端、嵌入式裝置等方向發展。但終端裝置沒有GPU伺服器那樣的強大效能,那如何使得終端裝置應用上深度學習呢?

所幸Google已經推出了TFMobile,去年又更進一步,推出了TFLite,其應用思路為在GPU伺服器上利用遷移學習訓練自己的模型,然後將定製化模型移植到TFLite上,

終端裝置僅利用模型做前向推理,預測結果。本文基於以下三篇文章而成:

  • 理論篇:www.tensorflow.org/hub/tutorials/image_retraining#other_architectures
  • 實踐篇一:codelabs.developers.google.com/codelabs/tensorflow-for-poets/index.html#0
  • 實踐篇二:codelabs.developers.google.com/codelabs/tensorflow-for-poets-2-tflite/#0
  • Google提供的先行編譯模型:github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/lite/g3doc/models.md
  • TOCO官網:github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/lite/toco

      相信大家掌握後,也能輕鬆定製化自己的Image Recognition應用。

第一步. 準備資料

  資料為:http://download.tensorflow.org/example_images/flower_photos.tgz  

  這是一個關於花分類的圖片集合,下載解壓後,可以看出有5個品種分類:daisy(雛菊)、dandelion(蒲公英)、rose(玫瑰)、sunflower(向日葵)、tulip(鬱金香)。

  我們的目的即是通過重新訓練先行編譯模型,得到一個花類識別的模型。

第二步. 重新訓練  1. 挑選先行編譯模型

        從上述“Google提供的先行編譯模型”列表中,我們大體可以看出分為兩類模型,一種是Float Models(浮點數模型),一種是Quantized Models(量化模型),什麼區別呢?

  其實Float Models表示為一種高精度值的模型,該模型意味著模型size較大,識別精度更高、識別時間長度更長,適合高效能終端裝置;而Quantized Models則反之,是低精度值的模型,其精度採取固定的8位大小,故其模型size較小,識別精度低、識別時間長度較短,適合低效能終端裝置,更細的說明可以參見 www.tensorflow.org/performance/quantization  。

  我們的手機裝置更新換代很快,一般可以使用Float Models。在這個模型下,有不少先行編譯模型可選,對於本文來說,主要集中為Inception 和Mobilenet兩種架構。  

       注意Mobilenet其實也分為很多種類,如Mobilenet_V1_0.50_224,其中第三個參數為模型大小比例值(只能算是近似,不準確),分為0.25/0.50/0.75/1.0四個比例值,第四個參數為圖片大小,其值有128/160/192/224四種值。

  有興趣想觀察各模型階層的可通過以下代碼查看:  

import tensorflow as tfimport tensorflow.gfile as gfileMODEL_PATH = '/home/yourname/Documents/mobilenet_v1_1.0_224/frozen_graph.pb'def main(unusedArgv):    with tf.Graph().as_default() as graph:        with gfile.FastGFile(MODEL_PATH, 'rb') as f:            graph_def = tf.GraphDef()            graph_def.ParseFromString(f.read())            tf.import_graph_def(graph_def, name='')    for op in graph.get_operations():        for tensor in op.values():            print(tensor)if __name__ == '__main__':    tf.app.run()

  考慮到測試手機效能還不賴,我們選擇mobilenet_v1_1.0_224這個版本作為我們的先行編譯模型。

  2. 下載訓練代碼

  需要下載訓練模型代碼和android相關代碼,如下:

git clone https://github.com/googlecodelabs/tensorflow-for-poets-2cd tensorflow-for-poets-2

  其中,scripts目錄下的retrain.py是我們需要關注的,這個代碼目前僅支援Inception_v3和Mobilenet兩種先行編譯模型,預設的訓練模型為Inception_v3。

  3. 重新訓練模型

  兩種模型的訓練命令不同,若走預設的Inception_v3模型,可通過如下命令: 

python -m scripts.retrain \
--learning_rate=0.01 \ --bottleneck_dir=tf_files/bottlenecks \ --how_many_training_steps=4000 \ --model_dir=tf_files/models/ \ --output_graph=tf_files/retrained_graph.pb \ --output_labels=tf_files/retrained_labels.txt \ --image_dir=tf_files/flower_photos \

  若走Mobilenet模型,可通過如下命令:

python -m scripts.retrain \
 --learning_rate=0.01 \   --bottleneck_dir=tf_files/bottlenecks \ --how_many_training_steps=4000 \ --model_dir=tf_files/models/ \ --output_graph=tf_files/retrained_graph.pb \ --output_labels=tf_files/retrained_labels.txt \ --image_dir=tf_files/flower_photos \ --architecture=mobilenet_1.0_224

  模型命令解釋如下:

 --architecture 為架構類型,支援mobilenet和Inception_v3兩種
   --image_dir 為資料地址,假定你在tensorflow-for-poets-2目錄下建立了tflite目錄,把花圖片集放入其中
   --output_labels 最後訓練產生模型的標籤,由於花圖片集合已經按照子目錄進行了分類,故retrained_labels.txt最後包含了上述五種花的分類名稱
   --output_graph 最後訓練產生的模型
   --model_dir 命令啟動後,先行編譯模型的
   --how_many_training_steps 訓練步數,不指定的話預設為4000
   --bottleneck_dir用來把top層的訓練資料緩衝成檔案
   --learning_rate 學習率
   此外,還有些參數可以根據需要進行調整:
   --testing_percentage 把圖片按多少比例劃分出來當做test資料,預設為10
   --validation_percentage 把圖片按多少比例劃分出來當做validation資料,預設為10,這兩個值設定完後,training資料佔比80%
   --eval_step_interval 多少步訓練後進行一次評估,預設為10
   --train_batch_size 一次訓練的圖片數,預設為100
   --validation_batch_size 一次驗證的圖片數,預設為100
   --random_scale 給定一個比例值,然後隨機擴大訓練圖片的大小,預設為0
   --random_brightness 給定一個比例值,然後隨機增強或減弱訓練圖片的明亮程度,預設為0
   --random_crop 給定一個比例值,然後隨機裁剪訓練圖片的邊緣值,預設為0 

    4. 檢驗訓練效果

    我們用Mobilenet_1.0_224進行訓練,完成後找一張圖片看看是否能正確識別:

python -m scripts.label_image \  --graph=tf_files/retrained_graph.pb  \  --image=tf_files/flower_photos/daisy/3475870145_685a19116d.jpg

結果為:

Evaluation time (1-image): 1.010sdaisy (score=0.62305)tulips (score=0.22490)dandelion (score=0.14169)roses (score=0.00966)sunflowers (score=0.00071)

還是準確地識別了daisy出來。

    5. 轉換模型格式

      pb格式是不能運行在TFLite上的,TFLite吸收了Google的protobuffer優點,創造了FlatBuffer格式,具體表現就是尾碼名為.tflite的檔案。

     上述TOCO的官網已經介紹了如何通過命令列把pb格式轉成為tflite檔案,或者在代碼裡也可以轉換格式。不僅支援pb格式,也支援HDF5檔案格式轉換成tflite,實現了與其他架構的模型共用。

     那如何轉呢?本例通過命令列方式轉換。若訓練模型為Inception_v3,命令列方式如下:

toco \  --graph_def_file=tf_files/retrained_graph.pb \  --output_file=tf_files/optimized_graph.lite \  --input_format=TENSORFLOW_GRAPHDEF \  --output_format=TFLITE \  --input_shape=1,299,299,3 \  --input_array=Mul \  --output_array=final_result \  --inference_type=FLOAT \  --input_data_type=FLOAT

     若訓練模型為mobilenet,命令列方式則如下:

toco \  --graph_def_file=tf_files/retrained_graph.pb \  --output_file=tf_files/optimized_graph.lite \  --input_format=TENSORFLOW_GRAPHDEF \  --output_format=TFLITE \  --input_shape=1,224,224,3 \  --input_array=input \  --output_array=final_result \  --inference_type=FLOAT \  --input_data_type=FLOAT

  需要說明幾點:

       --input_array 參數表示模型圖結構的入口tensor op名稱,mobilenet的入口名稱為input,Inception_v3的入口名稱為Mul,為什麼這樣?可查看scripts/retrain.py代碼裡內容:

  if architecture == 'inception_v3':    # pylint: disable=line-too-long    data_url = 'http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz'    # pylint: enable=line-too-long    bottleneck_tensor_name = 'pool_3/_reshape:0'    bottleneck_tensor_size = 2048    input_width = 299    input_height = 299    input_depth = 3    resized_input_tensor_name = 'Mul:0'    model_file_name = 'classify_image_graph_def.pb'    input_mean = 128    input_std = 128elif architecture.startswith('mobilenet_'):
... data_url = 'http://download.tensorflow.org/models/mobilenet_v1_' data_url += version_string + '_' + size_string + '_frozen.tgz' bottleneck_tensor_name = 'MobilenetV1/Predictions/Reshape:0' bottleneck_tensor_size = 1001 input_width = int(size_string) input_height = int(size_string) input_depth = 3 resized_input_tensor_name = 'input:0'

  其中的resized_input_tensor_name即是新產生模型的入口名稱,大家也可以通過上面“1.挑選先行編譯模型”的代碼可視化查看新產生的模型階層。所以名稱必須正確寫對,否則運行該命令會拋出“ValueError: Invalid tensors 'input' were found” 的異常。

       --output_array則是模型的出口名稱。為什麼是final_result這個名稱,因為在scripts/retrain.py裡有:

parser.add_argument(      '--final_tensor_name',      type=str,      default='final_result',      help="""\      The name of the output classification layer in the retrained graph.\      """  )

       即出口名稱預設為final_result。

       --input_shape 需要注意的是mobilenet的訓練圖片大小為224,而Inception_v3的訓練圖片大小為299。

       最後optimized_graph.lite即是我們要移植到android上的模型檔案啦。

 

第三步. Android TFLite        1. 下載Android Studio

         這一步驟不是本文重點,請大家自行在 developer.android.com/studio/ 進行下載安裝,安裝最新的SDK和NDK。

  2. 引入工程

  從android studio上引入 tensorflow-for-poets-2/android/tflite 下的代碼,共有四個類,有三個類是跟布局打交道,而我們只需要關注ImageClassifier.java類。

        3. 匯入模型

  可通過命令列方式把產生的模型匯入上述工程的資來源目錄下:

cp tf_files/optimized_graph.lite android/tflite/app/src/main/assets/mobilenet.lite cp tf_files/retrained_labels.txt android/tflite/app/src/main/assets/mobilenet.txt
   4. 修改ImageClassifier.java類

  注意修改四個地方即可:

 /** Name of the model file stored in Assets. */  private static final String MODEL_PATH = "mobilenet.lite";  /** Name of the label file stored in Assets. */  private static final String LABEL_PATH = "mobilenet.txt";  static final int DIM_IMG_SIZE_X = 224; //若是inception,改成299  static final int DIM_IMG_SIZE_Y = 224; //若是inception,改成299
  5. 運行觀看效果

  連上手機後,點擊“Run”->"Run app"即會部署app到手機上,此時任何被網路攝影機捕獲的圖片都會按照標籤裡的5個分類進行識別排名。

       我們可以通過百度搜一些這五種類別的花進行識別,以看看其識別的正確率。

 

後記:根據我的測試結果,在花的圖片集上,mobilenet_1.0_244模型產生的新模型識別率較高,而inception_v3模型產生的新模型識別率較低或不準。

       建議大家新的資料集可在兩種模型間進行比較,以找到最適合自己的模型。

 

  

  

       

  

 

  

  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

Tags Index: