1. 程式人生 > >Tensorflow lite for 移動端安卓開發(二)——完整詳細過程訓練自己的模型

Tensorflow lite for 移動端安卓開發(二)——完整詳細過程訓練自己的模型

官方給的Tensorflow lite demo是ImageNet 中訓練的1000類物體識別,基於移動端的專案需要,現在要用模型訓練自己的資料,提供兩種訓練方法,這也是自己在摸索Tensorflow過程中,嘗試的兩種方法。
一)利用examples中的retrain.py 指令碼進行遷移學習
https://github.com/tensorflow/tensorflow/tree/r1.8/tensorflow/examples/image_retraining
遷移學習指的是將訓練好的模型通過簡單的訓練使其適用於一個新的問題,該指令碼利用已有訓練好的模型(mobilenet,inceptionv3等)來重新訓練新的資料,固定模型的特徵提取層(瓶頸層,bottleneck),對新資料,直接利用這個訓練好的神經網路對影象進行特徵提取得到每張圖片的特徵向量,將該向量作為輸入來訓練一個新的單層全連線神經網路處理新的分類問題。
該指令碼的README.md如下:特意強調該指令碼產生的計算流圖相容Tensorflow Tite轉化器,能直接轉化成TFlite格式的模型

retrain.py is an example script that shows how one can adapt a pretrained
network for other classification problems. A detailed overview of this script
can be found at:
https://codelabs.developers.google.com/codelabs/tensorflow-for-poets/#0

The script also shows how one can train layers
with quantized weights and
activations instead of taking a pre-trained floating point model and then quantizing weights and activations. The output graphdef produced by this script is compatible with the TensorFlow Lite Optimizing Converter and can be converted to TFLite format.

按照指令碼要求準備資料,將資料按照每個類別存放在各自的資料夾下:
這裡寫圖片描述
閱讀原始碼,檢視指令碼中幾個重要的輸入引數
‘–image_dir’
標記影象資料夾的路徑
‘output_graph’
存放訓練好的計算圖(該計算圖已經進行了變數固化,可以直接轉化為TFlite)
‘–output_labels’
輸出標籤
‘–summaries_dir’
存放訓練日誌,用TensorfBord開啟,可以檢視訓練過程
‘–how_many_training_steps’
訓練次數
‘–bottleneck_dir’
存放瓶頸層輸出的特徵向量
‘–architecture’
預訓練好的用於提取影象特徵的模型
‘–saved_model_dir’
存放匯出的模型,含有計算流圖和變數值
‘–final_tensor_name’
輸出層的節點名字

1) 生成output_graph.pb檔案

python /home/liuli/tensorflow-r1.8/tensorflow/examples/image_retraining/retrain.py     --image_dir /home/liuli/work/Tensorflow/car_classification/data/     --learning_rate=0.0005     --testing_percentage=10     --validation_percentage=10     --train_batch_size=32     --validation_batch_size=-1     --flip_left_right True     --random_scale=30     --random_brightness=30     --eval_step_interval=200     --how_many_training_steps=6000   --architecture=mobilenet_1.0_224_quant   ----model_dir=/home/liuli/work/Tensorflow/car_classification/imagenet

2) 轉化成.tflite檔案

cd /home/liuli/tensorflow
bazel build tensorflow/contrib/lite/toco:toco
bazel run --config=opt tensorflow/contrib/lite/toco:toco -- \
  --input_file=/home/liuli/work/Tensorflow/output_graph.pb \
  --input_format=TENSORFLOW_GRAPHDEF \
  --output_format=TFLITE \
  --output_file=/home/liuli/work/Tensorflow/5.tflite \
  --inference_type=QUANTIZED_UINT8 \
  --input_array=input \
  --output_array=final_result \ 
  --input_shape=1,224,224,3 \
  --mean_value=128 \
  --std_value=127

其中output_array 為模型的輸出節點,和 retrain.py 中的 final_tensor_name對應。
使用retrain.py遷移學習,能很快達到收斂,但精度不夠,我用mobilenet float型介面訓練完後準確率只有0.82

DATASET_DIR=/home/liuli/work/Tensorflow/cars
TRAIN_DIR=/home/liuli/work/Tensorflow/car_train_logs
python train_image_classifier.py \
    --train_dir=${TRAIN_DIR} \
    --dataset_name=car \
    --dataset_split_name=train \
    --dataset_dir=${DATASET_DIR} \
    --model_name=mobilenet_v1

微調現有模型:

DATASET_DIR=/home/liuli/work/Tensorflow/cars
TRAIN_DIR=/home/liuli/work/Tensorflow/car_train_logs
CHECKPOINT_PATH=/home/liuli/work/Tensorflow/mobilenet_v1_1.0_224/mobilenet_v1_1.0_224.ckpt
python train_image_classifier.py \
    --train_dir=${TRAIN_DIR} \
    --dataset_name=car \
    --dataset_split_name=train \
    --dataset_dir=${DATASET_DIR} \
    --model_name=mobilenet_v1 \
    --checkpoint_path=${CHECKPOINT_PATH} \
    --checkpoint_exclude_scopes=MobilenetV1/Logits,MobilenetV1/AuxLogits \
    --trainable_scopes=MobilenetV1/Logits,MobilenetV1/AuxLogits

3)測試模型效能

DATASET_DIR=/home/liuli/work/Tensorflow/cars
CHECKPOINT_FILE=/home/liuli/work/Tensorflow/car_train_logs/model.ckpt-89078

python eval_image_classifier.py \
    --alsologtostderr \
    --checkpoint_path=${CHECKPOINT_FILE} \
    --dataset_name=car \
    --dataset_split_name=validation \
    --dataset_dir=${DATASET_DIR} \
    --model_name=mobilenet_v1

重新訓練的方法,迭代了將近90000次,花費了10個小時,最後模型收斂的準確率為0.881,通過對比方法一中的準確率,發現重新訓練準確率提升很明顯

4)匯出計算圖

python export_inference_graph.py \
    --alsologtostderr \
    --model_name=mobilenet_v1 \
    --image_size=224 \
    --dataset_name=car \
    --output_file=/tmp/mobilenet_v1_224.pb

5)將變數值儲存成常量,固化計算圖

cd /home/liuli/tensorflow
freeze_graph --input_graph=/tmp/mobilenet_v1_224.pb \
  --input_checkpoint=/home/liuli/work/Tensorflow/car_train_logs/model.ckpt-89078 \
  --input_binary=true \
  --output_graph=/home/liuli/work/Tensorflow/1_frozen.pb \
  --output_node_names=MobilenetV1/Predictions/Reshape_1

6)轉化成.tflite
生成float inference模型

cd /home/liuli/tensorflow
bazel build tensorflow/contrib/lite/toco:toco
bazel run --config=opt tensorflow/contrib/lite/toco:toco -- \
  --input_file=/home/liuli/work/Tensorflow/1_frozen.pb \
  --output_file=/home/liuli/work/Tensorflow/7_float.tflite \
  --inference_type=FLOAT \
  --input_shape=1,224,224,3 \
  --input_array=input \
  --output_array=MobilenetV1/Predictions/Reshape_1

生成Quant inference模型

cd /home/liuli/tensorflow
bazel build tensorflow/contrib/lite/toco:toco
bazel run --config=opt tensorflow/contrib/lite/toco:toco -- \
  --input_file=/home/liuli/work/Tensorflow/1_frozen.pb \
  --output_file=/home/liuli/work/Tensorflow/7.tflite \
  --input_format=TENSORFLOW_GRAPHDEF \
  --output_format=TFLITE \
  --inference_type=QUANTIZED_UINT8 \
  --input_shape=1,224,224,3 \
  --input_array=input \
  --output_array=MobilenetV1/Predictions/Reshape_1 \
  --default_ranges_min=0 \
  --default_ranges_max=6 \
  --std_value=127.5 \
  --mean_value=127.5

相比Float inference(浮點型)模型,Quant inference(量化)模型的精度很低,在下一篇部落格中介紹了在移動端進行模型測試的方法
https://blog.csdn.net/u011092156/article/details/80639811
總結:
以上介紹了兩種方法訓練自己的資料,大家可以結合自己的需求,以及硬體配置進行選擇,在計算資源受限,沒有GPU的機器上訓練時,可以優先考慮使用遷移學習,雖然精度不高,但是訓練時間短,當計算資源充足時,則考慮重新訓練,此時還可以對模型進行調參,達到最佳效能。