TensorFlow Mobilenet SSD模型压缩并移植安卓上以达到实时检测效果

        以前使用TensorFlow object detect API实现了目标检测(14个手势的识别),使用的是轻量级模型Mobilenet-ssd,Mobilenet-ssd自己检测速率相较于其余模型会更快。使用模型配置文件未对参数修改时,训练后的模型经过TensorFlow lite移植安卓上检测发现,速率达到了200-300ms(用的红米5A手机性能较差),模型大小5M(有点忘了)。200-300ms一帧的检测速率在安卓机上仍是能感受到明显的卡顿,于是想对模型进行优化,目标将模型大小压缩到1M如下,一帧检测速率优化至20ms左右。在模型优化的过程当中尝试了不少方法,以下:python

  • 查了不少方法,有对模型进行剪枝的,大体思路是将模型中不重要的权值置零以减小非零权值的数量,官方的实现方法说明是在tensorflow/contrib/model_pruning/目录下。但实际根据此方法进行模型剪枝后经过TensorFlow lite转换后的tflite模型并未有明显的提高,彷佛没有提高(多是姿式不对,望大神可以指点)。
  • 决定使用粗暴的方法直接修改模型结构。于是我查看了源码找到了mobilenet-ssd模型设置的文件,我将mobilenet中第三层直接删除(由于mobilenet-ssd提取特征的层级运算耗时会大些,想删除一层看看会不会提高效率),模型训练完成后移植安卓中发现目标检测会不许,速率也没明显提高。此时有点失落。
  • 查看源码时无心间看到mobilenet_v1.py时,

                 https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet_v1.pygit

      发现结果以下: github

100% Mobilenet V1 (base) with input size 224x224:mobilenet_v1模型未对模型压缩,输入大小为224x224此时模型参数总个数为3,185,088性能

75% Mobilenet V1 (base) with input size 128x128:mobilenet_v1模型压缩至原来的模型75%,输入大小不变,此时模型参数总个数为1,800,144测试

从模型参数总个数发现75% Mobilenet V1 (base)减小了不少,进而速率也获得了提高。在该源码文件中发现下图代码,进而能够肯定设置模型参数压缩的值是depth_multiplier这个参数。优化

此压缩方法原理即经过设置depth_multiplier,模型每层深度depth与depth_multiplier相乘进而减小原有的深度(我的理解,若是有误望指出)。Mobilenet_v1模型结构以下:spa

下面开始介绍如何修改配置文件进行模型压缩。.net

此处省略TensorFlow下载步骤,直接从配置文件参数修改开始。3d

一、首先拷贝配置文件code

ssd_mobilenet_v1_0.75_depth_300x300_coco14_sync.config至本身的目录中;配置文件位置:

https://github.com/tensorflow/models/tree/master/research/object_detection/samples/configs(根据下载的TensorFlow工程位置查找)

打开配置文件,找到depth_multiplier修改参数值(这里我将模型压缩至30%)

配置文件中可修改输入模型训练的图像大小以下(下降图像输入的模型中的分辨率一样可提升模型推理效率):

二、下载预训练模型(若不使用预训练模型可将该两行注释

#fine_tune_checkpoint: "PATH_TO_BE_CONFIGURED/model.ckpt"
#from_detection_checkpoint: true

网址:

https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md

能够看到

能够下载第一个红框的模型,第二个红框用于须要对模型进行量化处理的(后面再详细介绍)。

若须要训练后模型可量化处理,在配置文件最后加上红框部分代码以下图。

三、第三步假设配置文件参数都设置完(模型地址、训练图像地址、训练标签,测试图像地址、测试标签),该配置的环境变量都配置完成(export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim)再也不描述。开始运行程序进行训练。

python object_detection/model_main.py \
--logtostderr \
--pipeline_config_path=xxxxxxx/ssd_mobilenet_v1_030_14_1119.config \
--model_dir=xxxxxxxx \
--num_train_steps=50000 \
--num_eval_steps=2000

四、模型训练完则开始使用TensorFlow lite将模型进行转换成安卓可用的模型。具体步骤可见我上一个博客

http://www.javashuo.com/article/p-curabuju-no.html

此时以上步骤是使用的非量化模型,将depth_multiplier设置成0.25时,最终模型经过TensorFlow lite转成tflite文件,文件大小为1.5M,在安卓上速率达到了25-40ms(红米5A手机跳动较大只能粗略一个范围),这样的速率仍是达到了实时。

 

下面介绍使用量化模型,量化模型的大小仅为非量化模型的1/4,速率也能获得较大提高而且不影响精度(官方说不影响精度,但在我手机上测试时没有非量化模型精准,不懂为什么)

一、拷贝配置文件并修改其内容,配置文件使用的地址如上,可以使用文件:

ssd_mobilenet_v1_0.75_depth_quantized_300x300_pets_sync.config

二、下载量化模型,见上面步骤2,可下载第二个红框的模型。

三、步骤3如上步骤3;

四、在第四步时见上面的第四步,须要将命令中inference_type设置为QUANTIZED_UINT8;

以下:

bazel run --config=opt tensorflow/contrib/lite/toco:toco -- \
--input_file=$OUTPUT_DIR/tflite_graph.pb \
--output_file=$OUTPUT_DIR/detect.tflite \
--input_shapes=1,192,192,3 \     (根据实际训练的模型大小修改)
--input_arrays=normalized_input_image_tensor \
--output_arrays='TFLite_Detection_PostProcess','TFLite_Detection_PostProcess:1','TFLite_Detection_PostProcess:2','TFLite_Detection_PostProcess:3' \
--inference_type=QUANTIZED_UINT8 \
--mean_values=128 \
--std_values=128 \
--change_concat_input_ranges=false \
--allow_custom_ops

以上步骤完成则从完成了经过TensorFlow API进行目标检测并经过修改配置文件以达到模型压缩的目的。上面步骤中省略了一些使用TensorFlow API进行目标检测的步骤方法,网上资料较多可自行查找,这里重点介绍如何进行模型压缩。下面将列举一些模型压缩后在安卓上测试的效率(具体值我没记录,只记得大概,下次认真点记录)。

手机型号

是否量化

Depth_multiplier

Size(模型大小)

速率(一帧/ms)

红米5A

1.0

5M

200-300ms

红米5A

0.25

1.5M

25-40ms

红米5A

0.25

433K

15-30ms

华为P9

0.25

433K

8-20ms

华为P9

0.35

700+K

12-25ms