Tensorflow模型优化
文章目录
模型优化官方页面说明
感谢TFLITE中文兴趣小组干货满满的分享。本博客为分享内容的整理,供大家参考,欢迎批评指正。
首先我们要回答一个问题:
为什么要模型优化
官方页面开宗明义,分享开门见山
首先回答的就是为什么要模型优化:
在端侧部署部署我们不得不考虑端侧设备在算力、内存、耗电量、网络带宽和模型存储空间方面存在限制。模型优化核心解决的就是部署和执行的问题。(大佬的PPT很简洁但是直切重点)
而Tensorflow 模型优化工具包就是这样一套工具。
- 降低云和边缘设备(例如移动设备和 IoT 设备)的延迟时间和推断成本。
- 将模型部署到边缘设备,这些设备在处理、内存、耗电量、网络连接和模型存储空间方面存在限制。
- 在现有硬件或新的专用加速器上执行模型并进行优化。
这里的“优化”,个人认为一方面是基于硬件支持限制的”无奈之举“。(边缘设备——不得不作)
另一方面是对更低延迟的追求。(服务器——锦上添花)
“优化”理解为“改造”更为贴切一点。综合算力、内存、耗电量、网络带宽和模型存储空间等方面限制的一个改造。
”改造“(模型改造)往往是以牺牲模型精度为代价的,不同的优化方式精度的损失不同,如何决定优化方式就是平衡的艺术,需要针对项目本身。
ps:
比如在工业检测这个对模型精度和模型延迟要求都比较较高的场景,我们在优化中,不得不考虑在降低延迟的同时也要保证模型精度在合适水平。
一个典型的(tradeoff problem)
端侧部署
模型优化方式
模型优化常用的两种方式
-
Quantization
降低模型精度
-
Sparsity
减少模型连接
模型蒸馏,因为难以普遍化到各种任务,需要case-by-case的调试,所以没有特别好的工具支持,比较看应用场景
Quantization
深度学习模型中的主要就是矩阵运算
量化的思路很简单,就是将32位的float数映映射到8位的int数区间中,将float操作替换为int 的操作
而映射本质就是一个线性变换。
但是我们接着去想,就会发现新的问题,就是8位int数在运算之后,会得到一个16位,32位的数。
而运算结果向前传播到下一个算子时,算子要求为8位int输入。
所以rescale是模型量化中不可少的工作,而这个scale操作可以理解为,我们在原有模型基础上加了scale操作,对模型结构的小修改,在前向传输过程中增加了一个scale算子。
大家细看前后两张图的对比
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
这是一个有损的变换,优化本身改变了模型,改变的内容上面都有提到就不多赘述
CPU上可以混合整型和浮点型设备。但是DSP设备如果不能全部转为整形操作,那么就无法运行模型。回到开头所提到的就是——硬件支持限制的**”无奈之举“**
难点
- 模型量化优化,精度损失的如何产出和解释性是一个难的问题。
- 量化过程本身需要数据(比如动态数据范围的确定)
工具包支持
32 bit float ->16 bit float
GPU推荐和普遍,目前CPU不支持,未来会。
● Reducedfloat
○ float16 parameters
○ float16 computations
混合优化
只量化常量的tensor,动态的保留,一般只应用在CPU中
● Hybrid quantization
○ 8-bit integer weights
○32-bit float biases &activations
○ Integer and floating point computations
整形优化
全部都是8bit,精度损失比较大。不推荐,笔者自己开始尝试过,最后精度损失劝退。一定要自己evaluate。
● Integer quantization
○ 8-bit integer weights
○ 8 & 16-bit biases &activations
○ Only integer computations
Post-training API
32 bit float ->16 bit float
GPU推荐和普遍,目前CPU不支持,未来会。
混合量化
只量化常量的tensor,动态的保留,一般只应用在CPU中
整形量化
全部都是8bit,精度损失比较大。不推荐,笔者自己开始尝试过,最后精度损失劝退。一定要自己evaluate。
During training API
针对Interger-only quantization
这个非常灵活,非常的黑科技。大家有兴趣,可以自己去看,就不作赘述。
可以整体量化,可以只量化某一层,可以自定义。
如何选择合适的量化方式
见以下表格
但都是一些general的建议,具体情况还是要具体分析,需要自己evaluate。
Sparsity
通过模型剪枝技术删掉模型中不必要的连接。
首先简单介绍一下模型剪枝
简单的说就是
先排序 再置0
工具包支持
非常友好,只需要定义一个剪枝的schedule,指定什么时候开始,什么时候结束,最后的稀疏度就可以。
注意block_size
这个参数,在CPU上加速一般需要有一定的结构。
没有structure的全稀疏的加速比较困难
目前是experimental阶段
目前对稀疏模型的支持