量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端

TensorFlow-Slim图像分类Mobilenet量化模型并移植至安卓客户端

  • 1. 配置
  • 2. 准备工作
    • 2.1 下载
      • 2.1.1 下载models-1.12.0
      • 2.1.2 下载模型
      • 2.1.3 下载tensorflow-r1.13源码
    • 2.2 使用bazel编译tensorflow-r1.13源码
  • 3. 训练Mobilenet v1 quantized 模型
    • 3.1 制作数据集
    • 3.2 定义新的datasets文件
    • 3.3 修改mobilenet_v1结构参数
    • 3.4 准备训练文件夹
    • 3.5 开始训练
    • 3.6 验证模型
  • 4. 将训练结果转换为tflite量化模型
    • 4.1 导出推理图
    • 4.2 获取pb文件的输入输出
      • 4.2.1 通过netron
      • 4.2.2 通过summarize_graph命令
    • 4.3 冻结导出的模型
    • 4.4 转换pb模型为tflite模型
    • 4.5 测试tflite模型
  • 5. 部署到Android
    • 5.1 修改ClassifierActivity
    • 5.2 修改RecognitionScoreView(可改可不改)
    • 5.2 配置文件的更改
      • 5.2.1 build.gradle(Project: android)
      • 5.2.2 build.gradle(Module: app)
      • 5.2.3 配置文件的更改 AndroidManifest.xml

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
量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第1张图片
红框内的模型用于需要对模型进行量化处理的

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,将其进行以下修改:
    量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第2张图片
    _FILE_PATTERN 变量定义了数据的文件名的格式
    SPLITS_TO_SIZES变量定义训练集、验证集的数量
    _NUM_CLASSES 变量定义了数据集中图片的类别数目
  2. 第二处修改为image/format部分,将之修改为:
    量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第3张图片
  3. 修改datasets目录下另一个文件dataset_factory.py, 注册自己的数据名
    量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第4张图片

3.3 修改mobilenet_v1结构参数

因为我下载的是 mobilenet_v1_0.75_224_quant, 所以 slim/nets/mobilenet_v1.py中有两个地方要修改.
量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第5张图片量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第6张图片

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/
可以在线上传模型, 得到输入输出
输入:
量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第7张图片输出:
量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第8张图片

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=FLOAT \
  --input_type=FLOAT \
  --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-Slim图像分类Mobilenet模型并移植至安卓客户端_第9张图片
根据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

量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第10张图片

5.2 修改RecognitionScoreView(可改可不改)

修改之后, 在运行app时, 屏幕上只会显示最相似的一类. 不修改之前会显示多项分类, 有不同的分数, 根据需求进行修改.
量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第11张图片
以下为配置文件的更改

5.2 配置文件的更改

5.2.1 build.gradle(Project: android)

量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第12张图片

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

量化版——TensorFlow-Slim图像分类Mobilenet模型并移植至安卓客户端_第13张图片
注释掉目标检测和语音的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

你可能感兴趣的:(图像算法,#图像分类,机器学习,tensorflow,图像分类)