量化版——TensorFlow-Slim圖像分類Mobilenet模型並移植至安卓客戶端

1. 配置

基本配置 版本號
CPU Intel® Core™ i5-8400 CPU @ 2.80GHz × 6
GPU GeForce RTX 2070 SUPER/PCIe/SSE2
OS Ubuntu18.04
openjdk 1.8.0_242
python 3.6.9
bazel 0.21.0
gcc 4.8.5
g++ 4.8.5

hint:

  1. bazel會在轉換模型的時候用到, 我的另一篇博客有講如何配置.
    https://blog.csdn.net/weixin_43056275/article/details/105124979
  2. bazel編譯時, gcc和g++版本需要一致.

2. 準備工作

2.1 下載

2.1.1 下載models-1.12.0

https://github.com/tensorflow/models/tree/v1.12.0
在~/.bashrc中加入配置
export PYTHONPATH=$PYTHONPATH:pwd:pwd/slim

2.1.2 下載模型

https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md
在這裏插入圖片描述
紅框內的模型用於需要對模型進行量化處理的

2.1.3 下載tensorflow-r1.13源碼

https://github.com/tensorflow/tensorflow/tree/r1.13

2.2 使用bazel編譯tensorflow-r1.13源碼

我的另一篇博客寫的很詳細
https://blog.csdn.net/weixin_43056275/article/details/105124979

3. 訓練Mobilenet v1 quantized 模型

3.1 製作數據集

我的數據集文件結構和生成tfrecord的代碼可供下載: https://download.csdn.net/download/weixin_43056275/12314008
我做的是二分類, 所以我的數據集只有兩個類別, bad 和 good.
以下是我製作tfrecord的文件目錄:

data_prepare/
	pic/
		train/
			bad/
			good/
		validation
			bad/
			good/
	src/
		tfrecord.py/
	data_convert.py
  1. pic裏面有train和validation兩個目錄, 分別是訓練和驗證使用的圖片. 在目錄中,分別以類別名分類保存圖像. 比如我是二分類, 標籤是bad, good. 文件名就是以這個分類.
  2. src 裏面保存tfrecord.py 這個python文件提供給data_convert.py 調用.
  3. data_convert.py, 可以調用這個文件來生成tfrecord和標籤txt, 生成的tfrecord被保存在pic目錄下.
    運行data_convert.py生成tfrecord文件
python data_convert.py -t pic/ \
    --train-shards 2 \
    --validation-shards 2 \
    --num-threads 2 \
    --dataset-name mydata

參數含義解釋:

  1. -t pic/:表示轉換pic文件夾中的數據。pic文件夾中必須有一個train目錄和一個validation目錄,分別代表訓練和驗證數據集。每個目錄下按類別存放了圖像數據。
  2. −−train-shards 2:將訓練數據集分爲兩塊,即最後的訓練數據就是兩個tfrecord格式的文件。如果讀者的數據集較大,可以考慮將其分爲更多的數據塊。
  3. −−validation-shards 2:將驗證數據集分爲兩塊。
  4. −−num-threads 2:採用兩個線程產生數據。注意線程數必須要能整除train-shards 和validation-shards,來保證每個線程處理的數據塊數是相同的。
  5. −−dataset-name mydata:給生成的數據集起一個名字。這裏將數據集起名叫“satellite”,最後生成文件的開頭就是satelite_train 和satelite_validation。

運行上述命令後,就可以在pic文件夾中找到5個新生成的文件,分別是訓練數據 mydata_train_00000-of-00002.tfrecord、mydata_train_00001-of-00002.tfrecord,以及驗證數據 mydata_validation_00000-of-00002.tfrecord、mydata_validation_00001-of-00002.tfrecord。另外,還有一個文本文件label.txt,它表示圖片的內部標籤(數字)到真實類別(字符串)之間的映射順序。如在tfrecord中的標籤爲0,那麼就對應label.txt 第一行的類別,在tfrecord的標籤爲1,就對應label.txt中第二行的類別,依此類推。

3.2 定義新的datasets文件

找到models/research/目錄中的slim文件夾, 這就是要用到的TensorFlow Slim的源代碼。這裏簡單介紹TensorFlow Slim的代碼結構,見下表。

文件夾或文件名 用途
datasets/ 定義一些訓練時使用的數據集。如果需要訓練自己的數據,必須同樣在datasets文件夾中進行定義,會在下面對此進行介紹
nets/ 定義了一些常用的網絡結構,如AlexNet、VGGl6、VGG19、Inception 系列、ResNet、MobileNet等
preprocessing/ 在模型讀入圖片前,常常需要對圖像做預處理和數據增強。這個文件夾針對不同的網絡,分別定義了它們的預處理方法
scripts 包含了一些訓練的示例腳本
train_ image_classifier.py 訓練模型的入口代碼
eval_image_classifier.py 驗證模型性能的入口代碼
download_and _convert data.py 下載並轉換數據集格式的入口代碼

首先,在datasets/目錄下新建一個文件mydata.py,並將flowers.py文件中的內容複製到satellite.py中。接下來,需要修改以下幾處內容。

  1. 第一處是_FILE_PATTERN、SPLITS_TO_SIZES、_NUM_CLASSES,將其進行以下修改:
    在這裏插入圖片描述
    _FILE_PATTERN 變量定義了數據的文件名的格式
    SPLITS_TO_SIZES變量定義訓練集、驗證集的數量
    _NUM_CLASSES 變量定義了數據集中圖片的類別數目
  2. 第二處修改爲image/format部分,將之修改爲:
    在這裏插入圖片描述
  3. 修改datasets目錄下另一個文件dataset_factory.py, 註冊自己的數據名
    在這裏插入圖片描述

3.3 修改mobilenet_v1結構參數

因爲我下載的是 mobilenet_v1_0.75_224_quant, 所以 slim/nets/mobilenet_v1.py中有兩個地方要修改.
在這裏插入圖片描述在這裏插入圖片描述

3.4 準備訓練文件夾

  1. 將上文下載的預訓練模型解壓到slim文件夾下, 作爲checkpoint_path參數
  2. 在slim新建train_dir, 作爲訓練模型後生成ckpt的存儲文件夾

3.5 開始訓練

python train_image_classifier.py \
   --train_dir=./train_dir \
   --dataset_dir=./data_prepare/pic \
   --dataset_name=mydata \
   --dataset_split_name=train \
   --model_name=mobilenet_v1 \
   --checkpoint_path=./mobilenet_v1_0.75_224_class/mobilenet_v1_0.75_224_quant.ckpt \
   --checkpoint_exclude_scopes=MobilenetV1/Logits,MobilenetV1/AuxLogits \
   --max_number_of_steps=100000 \
   --train_image_size=224 \
   --trainable_scopes=MobilenetV1/Logits,MobilenetV1/AuxLogits \
   --quantize_delay=0
  • train_dir: 存儲訓練生成的日誌和ckpt
  • dataset_dir: tfrecord和txt的目錄
  • dataset_name: 上文定義的數據集的名字
  • max_number_of_steps=100000: 最大的執行步數

3.6 驗證模型

python eval_image_classifier.py \
    --alsologtostderr \
    --checkpoint_path=./train_dir/model.ckpt-100000 \
    --dataset_dir=./data_prepare/pic \
    --dataset_name=mydata \
    --dataset_split_name=validation \
    --model_name=mobilenet_v1 \
    --eval_image_size=224

4. 將訓練結果轉換爲tflite量化模型

4.1 導出推理圖

python export_inference_graph.py \
  --alsologtostderr \
  --model_name=mobilenet_v1 \
  --dataset_dir=./data_prepare/pic \   #數據集路徑
  --dataset_name=mydata \  #數據集名字
  --image_size=224 \
  --output_file=./test.pb \
  --quantize=True

如果不設置好數據集路徑和名字會導致 Assign requires shapes of both tensors to match. lhs shape= [1001] rhs shape= [2].
如何解決請看, https://blog.csdn.net/weixin_43056275/article/details/105405751

4.2 獲取pb文件的輸入輸出

有兩種方式

4.2.1 通過netron

https://lutzroeder.github.io/netron/
可以在線上傳模型, 得到輸入輸出
輸入:
在這裏插入圖片描述輸出:
在這裏插入圖片描述

4.2.2 通過summarize_graph命令

在./tensorflow-r1.13運行

bazel build tensorflow/tools/graph_transforms:summarize_graph
bazel-bin/tensorflow/tools/graph_transforms/summarize_graph \
  --in_graph=/home/ying/usb/models/models-1.12.0/research/slim/test.pb

4.3 凍結導出的模型

在./tensorflow-r1.13運行

bazel build tensorflow/python/tools:freeze_graph
bazel-bin/tensorflow/python/tools/freeze_graph \
  --input_graph=/home/ying/usb/models/models-1.12.0/research/slim/test.pb \
  --input_checkpoint=/home/ying/usb/models/models-1.12.0/research/slim/train_dir/model.ckpt-100000 \
  --input_binary=true --output_graph=/home/ying/usb/models/models-1.12.0/research/slim/frozen1.pb \
  --output_node_names=MobilenetV1/Predictions/Reshape_1

4.4 轉換pb模型爲tflite模型

在./tensorflow-r1.13運行

bazel build tensorflow/lite/toco:toco
bazel-bin/tensorflow/lite/toco/toco --input_file=/home/ying/usb/models/models-1.12.0/research/slim/frozen1.pb \
  --input_format=TENSORFLOW_GRAPHDEF \
  --output_format=TFLITE \
  --output_file=/home/ying/usb/models/models-1.12.0/research/slim/frozen1.tflite \
  --inference_type=QUANTIZED_UINT8 \
  --input_arrays=input \
  --output_arrays=MobilenetV1/Predictions/Reshape_1 \
  --input_shapes=1,224,224,3

4.5 測試tflite模型

在./tensorflow-r1.13運行

bazel build tensorflow/lite/examples/label_image:label_image
bazel-bin/tensorflow/lite/examples/label_image/label_image 
  --tflite_model=/home/ying/usb/models/models-1.12.0/research/slim/frozen1.tflite 
  --input_mean=128 
  --input_std=128 
  --labels="/home/ying/usb/models/models-1.12.0/research/slim/data_prepare/pic/label.txt" 
  --image="/home/ying/usb/deep-learning-for-image-processing-master/deep-learning-for-image-processing-master/pytorch_learning/Test5_resnet/test1/bad15.bmp"

結果:
在這裏插入圖片描述
根據tensorflow版本不同, 參數可能也會有所不同, 請根據情況進行調整.

5. 部署到Android

打開./tensorflow-r1.13/tensorflow/lite/examples/android
將tflite和txt放到./tensorflow-r1.13/tensorflow/lite/examples/android/app/src/main/assets文件下

5.1 修改ClassifierActivity

在這裏插入圖片描述

5.2 修改RecognitionScoreView(可改可不改)

修改之後, 在運行app時, 屏幕上只會顯示最相似的一類. 不修改之前會顯示多項分類, 有不同的分數, 根據需求進行修改.
在這裏插入圖片描述
以下爲配置文件的更改

5.2 配置文件的更改

5.2.1 build.gradle(Project: android)

在這裏插入圖片描述

5.2.2 build.gradle(Module: app)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    buildToolsVersion '28.0.3'
    defaultConfig {
        applicationId "org.tensorflow.lite.demo"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        // Remove this block.
//        jackOptions {
//            enabled true
//        }
    }
    lintOptions {
        abortOnError false
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    aaptOptions {
        noCompress "tflite"
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

repositories {
    maven {
        url 'https://google.bintray.com/tensorflow'
    }
}

// import DownloadModels task
project.ext.ASSET_DIR = projectDir.toString() + '/src/main/assets'
project.ext.TMP_DIR   = project.buildDir.toString() + '/downloads'

// Download default models; if you wish to use your own models then
// place them in the "assets" directory and comment out this line.
apply from: "download-models.gradle"

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'org.tensorflow:tensorflow-lite:0.1.2-nightly'
    implementation 'org.tensorflow:tensorflow-lite:2.0.0'
}

5.2.3 配置文件的更改 AndroidManifest.xml

在這裏插入圖片描述
註釋掉目標檢測和語音的app的內容, 只留下分類.

參考:
https://blog.csdn.net/qq_33200967/article/details/82773677#commentBox
https://www.cnblogs.com/Terrypython/p/10858803.html
https://zhuanlan.zhihu.com/p/44437031
https://www.imooc.com/article/details/id/28871

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章