TensorFlow量化训练

简介: 前段时间研究了tflite和量化相关的操作, 经测试量化尤其在具有专门DSP加速的硬件上(比如MTK8183)有着很好的加速效果,大约3X的提升; tensorflow提供了tflite转化工具toco,使用命令大致如下: bazel-bin/tensorflow/contrib/lite/toco/toco --input_file=mobilenet_v1_1.0_128_froz
前段时间研究了tflite和量化相关的操作, 经测试量化尤其在具有专门DSP加速的硬件上(比如MTK8183)有着很好的加速效果,大约3X的提升;
tensorflow提供了tflite转化工具toco,使用命令大致如下:
bazel-bin/tensorflow/contrib/lite/toco/toco --input_file=mobilenet_v1_1.0_128_frozen.pb \
  --input_format=TENSORFLOW_GRAPHDEF \
  --output_format=TFLITE \
  --output_file=/tmp/mobilenet_v1_1.0_128.tflite \
  --inference_type=FLOAT \
  --input_data_types=FLOAT \
  --input_arrays=input \
  --output_arrays=MobilenetV1/Predictions/Reshape_1 \
  --input_shapes=1,128,128,3 \
  --logtostderr
这里面遇到的一个坑是,发现用pip直接安装的tensorflow, 运行这个命令会包error:, 因为option的名字不一样,那是用python重新封装的,而从源码编译toco(用官方的bazel工具)是C++的;
上述命令只是转化为tflite的格式,如果需要量化,只需要改成这样:
bazel-bin/tensorflow/contrib/lite/toco/toco --input_file=mobilenet_v1_1.0_128_frozen.pb \
  --input_format=TENSORFLOW_GRAPHDEF \
  --output_format=TFLITE \
  --output_file=/tmp/mobilenet_v1_1.0_128.tflite \
  --inference_type=QUANTIZED_UINT8 \
  --input_data_types=QUANTIZED_UINT8 \
  --input_arrays=input \
  --output_arrays=MobilenetV1/Predictions/Reshape_1 \
  --input_shapes=1,128,128,3 \
  --logtostderr
对于, 一般的模型, 它会报错, 原因是没有提供MinMax的范围(量化需要这两个值进行缩放), 对于不同的类型,这两个值的获取方式不一样,对于里面的weights比较好办,只要统计一下最大最小值就好了,但是对于graph里面的其他tensor,因为输入的不同,所以每层输出的值也会不同,这里就需要在训练的时候去统计每个node的[Min, Max]; 当然你可以用这个语句去手动制定范围,但是精度可能就会收到很大影响.
tf.quantization.fake_quant_with_min_max_args
而且使用toco的时候需要加上:
--reorder_across_fake_quant=true
或者你也可以在使用toco的时候加上:
--default_ranges_min=0 \
--default_ranges_max=1
但是这样就更加糟糕了,它会给所有没有[Min,Max]的node,使用这两个值作为默认值
 
所以,由此我们知道:
1) 我们需要在训练的时候统计[Min, Max]
2) 为了量化能有更好的精度,我们希望[Min, Max]最好在一个比较小的范围内, 所以一些best practise包括: a)使用relu6作为激励函数; b) 使用batch normalization
 
Google提供了 quantization-aware的训练方法,可以参考 https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/quantize
简单总结下:
1) 在你定义好网络结构之后, 加上
tf.contrib.quantize.create_training_graph(input_graph=g,
                                          quant_delay=2000000)
它会把网络重新改造,具体可以看tensorboar;
这里面,要注意quant_delay这个参数, 这个参数的意思的在此之前,网络会使用float进行正常的训练,收敛到一个比较好的水平;之后,会执行一个fake-quant的操作.
改造之前的一个卷积层:
改造之后的一个卷积层:
关键的操作就在于这个act_quant节点,统计了最大最小的值,然后执行量化操作,最上面的delay_quant里面有两个switch op, 就用根据设置的quant_delay来决定是否使用量化的结果进行forward
2) 按照正常的方式保存你的checkpoint;
3) 导出用于eval的网络,这个最好是在另外一个文件里面(否则可能会有这个问题 https://github.com/tensorflow/tensorflow/issues/19936),同样的方式创建网络结构后,调用:
tf.contrib.quantize.create_eval_graph(input_graph=g)
然后load checkpoint,最后保存graph和新的checkpoint.
tf.train.write_graph(sess.graph_def, output_dir, 'graph.pb', as_text=True)
saver = tf.train.Saver(max_to_keep=100)
saver.save(sess, './workspace/'+args.model+'/chk', global_step=1)
4) freeze graph
python3 -m tensorflow.python.tools.freeze_graph \
--input_graph=./graph.pb \
--output_graph=exported_freezed_inference_graph.pb \
--input_checkpoint=./chk-1 \
--output_node_names="your_output_name"
5) 现在就可以使用toco命令导出量化的模型了;
 
也许等你执行完以上操作,发现自己的模型里面仍然会报某些node还是没有[Min, Max], 根据我的观察,在某些情况下(具体不明),发现只有添加了BatchNorm的层在调用cerate_train_graph的时候才会添加fake_quant; 但是有的时候不需要BatchNorm也可以,很奇怪~
 
最后,你还可以用这个命令查看你到处tflite量化模型的op和[Min,Max]的范围
bazel-bin/tensorflow/contrib/lite/toco/toco \
--input_file=exported_freezed_inference_graph.pb \
--input_format=TENSORFLOW_GRAPHDEF   \
--output_format=GRAPHVIZ_DOT   \
--output_file=exported_freezed_inference_graph_opt.dot   \
--inference_type=QUANTIZED_UINT8 \
--input_data_types=QUANTIZED_UINT8  \
--input_arrays=image   \
--output_arrays=Openpose/MConv_Stage1_L_5_pointwise/Conv2D \
--input_shapes=1,128,128,3   \
--logtostderr \
--default_ranges_min=0 \
--default_ranges_max=1

dot -Tpdf exported_freezed_inference_graph_opt.dot -o exported_freezed_inference_graph_opt.pdf
 
 
 
目录
相关文章
|
7月前
|
机器学习/深度学习 算法 TensorFlow
文本分类识别Python+卷积神经网络算法+TensorFlow模型训练+Django可视化界面
文本分类识别Python+卷积神经网络算法+TensorFlow模型训练+Django可视化界面
121 0
文本分类识别Python+卷积神经网络算法+TensorFlow模型训练+Django可视化界面
|
TensorFlow 算法框架/工具
tensorflow/train训练指令
tensorflow/train训练指令
71 0
|
机器学习/深度学习 监控 算法
【tensorflow】连续输入的神经网络模型训练代码
【tensorflow】连续输入的神经网络模型训练代码
|
2月前
|
并行计算 Shell TensorFlow
Tensorflow-GPU训练MTCNN出现错误-Could not create cudnn handle: CUDNN_STATUS_NOT_INITIALIZED
在使用TensorFlow-GPU训练MTCNN时,如果遇到“Could not create cudnn handle: CUDNN_STATUS_NOT_INITIALIZED”错误,通常是由于TensorFlow、CUDA和cuDNN版本不兼容或显存分配问题导致的,可以通过安装匹配的版本或在代码中设置动态显存分配来解决。
50 1
Tensorflow-GPU训练MTCNN出现错误-Could not create cudnn handle: CUDNN_STATUS_NOT_INITIALIZED
|
2月前
|
数据采集 TensorFlow 算法框架/工具
【大作业-03】手把手教你用tensorflow2.3训练自己的分类数据集
本教程详细介绍了如何使用TensorFlow 2.3训练自定义图像分类数据集,涵盖数据集收集、整理、划分及模型训练与测试全过程。提供完整代码示例及图形界面应用开发指导,适合初学者快速上手。[教程链接](https://www.bilibili.com/video/BV1rX4y1A7N8/),配套视频更易理解。
43 0
【大作业-03】手把手教你用tensorflow2.3训练自己的分类数据集
|
4月前
|
机器学习/深度学习 API 算法框架/工具
【Tensorflow+keras】Keras API两种训练GAN网络的方式
使用Keras API以两种不同方式训练条件生成对抗网络(CGAN)的示例代码:一种是使用train_on_batch方法,另一种是使用tf.GradientTape进行自定义训练循环。
47 5
|
4月前
|
UED 存储 数据管理
深度解析 Uno Platform 离线状态处理技巧:从网络检测到本地存储同步,全方位提升跨平台应用在无网环境下的用户体验与数据管理策略
【8月更文挑战第31天】处理离线状态下的用户体验是现代应用开发的关键。本文通过在线笔记应用案例,介绍如何使用 Uno Platform 优雅地应对离线状态。首先,利用 `NetworkInformation` 类检测网络状态;其次,使用 SQLite 实现离线存储;然后,在网络恢复时同步数据;最后,通过 UI 反馈提升用户体验。
98 0
|
4月前
|
安全 Apache 数据安全/隐私保护
你的Wicket应用安全吗?揭秘在Apache Wicket中实现坚不可摧的安全认证策略
【8月更文挑战第31天】在当前的网络环境中,安全性是任何应用程序的关键考量。Apache Wicket 是一个强大的 Java Web 框架,提供了丰富的工具和组件,帮助开发者构建安全的 Web 应用程序。本文介绍了如何在 Wicket 中实现安全认证,
46 0
|
4月前
|
机器学习/深度学习 数据采集 TensorFlow
从零到精通:TensorFlow与卷积神经网络(CNN)助你成为图像识别高手的终极指南——深入浅出教你搭建首个猫狗分类器,附带实战代码与训练技巧揭秘
【8月更文挑战第31天】本文通过杂文形式介绍了如何利用 TensorFlow 和卷积神经网络(CNN)构建图像识别系统,详细演示了从数据准备、模型构建到训练与评估的全过程。通过具体示例代码,展示了使用 Keras API 训练猫狗分类器的步骤,旨在帮助读者掌握图像识别的核心技术。此外,还探讨了图像识别在物体检测、语义分割等领域的广泛应用前景。
31 0
|
4月前
|
API 算法框架/工具
【Tensorflow+keras】使用keras API保存模型权重、plot画loss损失函数、保存训练loss值
使用keras API保存模型权重、plot画loss损失函数、保存训练loss值
33 0