模型量化、感知训练以及混合精度训练的理论理解和总结

1. 深度学习模型从模型定义到模型部署

以tensorflow为例,总结一下当前遇到的一些模型部署策略。策略如下图,首先定义好fp32的模型,然后包含6条不同的线路:

  • 模型经过常规普通训练后,保存为fp32格式的pb模型,然后经过英伟达的tensorRT转换为uff模型,然后就可以在服务器端进行部署;
  • 模型经过常规普通训练后,保存为fp32格式的savel_model模型,然后经过tensorflow的api转换为经过加速的savel_model模型,然后就可以在服务器端通过tf-serving进行部署; 
  • 模型经过常规普通训练后,保存为fp32格式的h5或savel_model模型,然后经过tensorflow的api后量化为tflite模型,后量化时可以选择动态量化、fp32、fp16量化和int8量化,然后就可以在终端通过tensorflow Lite进行部署;
  • 模型经过量化感知训练后,保存为fp32格式的h5或savel_model模型,然后经过tensorflow的api后量化为tflite模型,量化时最好是选择int8量化,然后就可以在终端通过tensorflow Lite进行部署;
  • 模型经过混合精度训练后,保存为fp32格式的h5或savel_model模型,然后经过tensorflow的api后量化为tflite模型,量化时最好是选择fp16量化,然后就可以在终端通过tensorflow Lite进行部署;
  • 模型经过任何方式保存为任何格式的h5或save_model或tflite,然后经过第三方库转换为onnx格式,然后onnx格式可以转换为其它框架的模型,这里onnx是fp32、fp16还是int8格式,取决于转换前模型的数据格式;
  • 注:以上路径其实有一些无需经过中间的h5或save_model,可以直接从keras model转换为tflite;tflite可以转onnx见【7】

2. 什么是模型量化

模型量化其实就是将fp32的模型转换为fp16或者int8的模型,转换后可以达到缩小模型体积、减小内存占用和提高运算速度的目的,当然精度会受到一定程度的影响。关于提高运算速度这一点还要看硬件支持情况,否则会变得更慢或者根本不能运行。量化成int8时,一般运行在CPU、TPU或DSP上,量化成fp16时,一般运行在有Tensor Cores的GPU上,例如V100和2080ti等,其它GPU,例如P100和P40等不支持。对于不支持int8或fp16的硬件上运行模型,有可能不能运行,即使可以运行结果也是先上采样为fp32后再运行。

3. 什么是"后量化"

所谓模型的后量化,指的是在模型已经训练完成,所有参数均已固定的情况下,对模型进行量化。量化的基本原理就是将连续值映射到离散值或者将稠密的离散值映射到稀疏的离散值。直接采用后量化办法,肯定会对模型精度产生比较大的影响尤其是量化成int8,精度掉点有可能会比较多。在tf.keras中,量化采用的是转化成tflite的方式,在参数选择时可以选择量化为动态范围、fp32、fp16或int8几种格式,还可以设置输入图片是哪一种格式,当输入图片格式与内部格式不统一时,模型会自动转换格式,在参数设置时最好统一格式,这里需要着重说明的是动态范围量化,采用该方式量化后,模型尺寸变为原模型的1/4,权重为int8格式,但是实际运行时,一部分运算是int8完成的,一部分运算是fp32完成的,所以该量化方式不适合部署在仅支持int8运算的硬件上。如果要运行在仅仅支持int8的硬件上,需要采用完全int8的量化方式,包括输入输出设置等全部设为int8。在tf.keras中如何设置参数实现不同方式的量化,参见【1】【2】。

4. 什么是量化感知训练

上面讲了后量化的基本原理和实施办法,可以发现在量化为int8时,可能掉点会比较严重。量化感知训练就是用来解决这个问题的,解决方式是,在后量化为int8前,先按照接下来后量化的要求提前对模型参数进行训练,提高后量化后的精度。具体如何实现的,这个原理当前我还不太确定,但是结论是量化感知训练可以明显提升后量化为int8的模型的精度。量化感知训练时的权重等参数依然是fp32,量化感知训练结束后,如果不进行后量化而是直接保存为h5或者save_model,那模型和参数都是fp32格式的,模型体积不变。量化感知训练的方式可以参看【3】,可以对整个模型量化感知训练,也可以只是针对部分层,也可以针对自定义层。

5. 什么是混合精度训练

上面讲了如何减小后量化为int8时的掉点问题,那如何减小量化为fp16时的掉点问题呢,解决办法就是混合精度训练。上面的量化感知训练不能针对fp16进行提升,原因是量化为int8和fp16是完全不同的方式。所谓混合精度训练指的是,模型的参数始终保存为fp32的格式,但是在前向推理时,首先在内存中将fp32格式的权重转换为fp16,图片格式也是fp16,然后进行前向推理,所有中间过程和绝大部分计算全部在fp16格式下进行,最终得到fp16的loss;然后对loss进行放大,然后基于放大后的loss在fp16格式下进行反向梯度计算得到fp16格式下的梯度,然后将fp16格式的梯度转换为fp32格式,然后进行梯度缩小,缩小的倍数与之前loss放大的倍数相同,用于解决fp16的数据溢出问题;然后fp32格式的梯度乘以学习率,然后作用于fp32格式的权重上,至此结束一轮训练,之所以最终权重始终保存为fp32格式是为了解决fp16的舍入误差问题;上面说的前向推理过程中并非所有运算就采用fp16而是部分运算采用fp32是为了提高loss的计算精度。所以模型经过混合精度训练后参数依然是fp32格式,所以此时保存h5或者save_model,那依然是fp32格式,模型大小不变。之后再进行fp16格式的tflite后量化才可以得到真正量化后的模型。

这里需要说明的是首先混合精度训练似乎并不是为了fp16量化而提出的,其原本是为了解决fp32模型训练时内存占用多,耗时长的问题。所以在前向推理时,部分运算采用了fp32的运算,这样可以使得前向推理的输出尽量接近fp32的模型的输出,混合精度训练完成后可以使用正常的fp32进行推理。但是因为整个前向推理过程绝大部分运算都是在fp16下完成的,所以其可以保证训练时的前向推理输出与后量化为fp16后的模型输出相似,所以先混合精度训练,然后后量化为fp16模型,相比直接量化为fp16模型,精度会更高,实测很多模型采用该方式量化后一点精度损失也没有。根据上面所讲,似乎在前向推理过程中全部采用fp16进行运算而不是大部分采用,这样更有利于后量化为fp16模型。关于混合精度训练更多详情见【4】【5】【6】。

6. 个人总结备忘(不断矫正更新)

在【8】中有混合精度训练的官方教程,我的猜测是【8】的教程是针对tf2.4以前的版本的,在tf2.6中依然可用,但是tf2.4以后似乎有了新的方式,一句设置环境变量的代码就能搞定,见【9】教程。在【8】中的教程分两部分,第一部分是针对fit()训练方式,这个在它的教程里验证通过了,但是在自己写的模型上却没有作用,原因未知;第二部分是针对自定义训练方式,这个方式我还未验证。在【9】中的方式,在自己的模型上未验证通过,没有任何作用。所以当前对tensorflow如何实现混合精度训练还是不太清楚。

这里总结一下我当前针对硬件与运算类型关系的总结。CPU应该是支持int8、fp16和fp32运算的,而且运算单元是同一模块,不需要单独运算单元;GPU是一部分仅仅支持fp32,还有一部分支持int8、fp16和fp32,最新的GPU应该是都支持了,三种运算分别需要独立独有的运算单元,需要说明的是tensor core是新的用来加速fp16矩阵运算的模块,并不是解决支持int8和fp16运算问题的模块,虽然事实上,包含tensor core的GPU在fp16的运算能力上大幅提升。

当前tflite模型只能在CPU上运行,int8量化模型应该是按照int8运行的,但是默认情况下,float16量化模型在运行时将权重值反量化到float32,然后运行。当前onnx模型即可以选择CPU运行也可以选择GPU运行。P40GPU不支持FP16运算,2080ti和RTX6000支持FP16运算。h5模型不管采不采用混合精度训练,其保存时皆为fp32类型,但是经过混合精度训练,虽然格式是fp32,但是后面量化为fp16后能尽量保持精度;h5模型不管经不经过量化感知训练,其保存时皆为fp32类型,但是经过量化感知训练,虽然格式是fp32,但是后面量化为int8后能尽量保持精度。h5模型可以直接转换为onnx,可以训着opset参数,可以选择batch,但是不能选择量化;h5模型转换为tflite,不可以选择batch,如果h5事先定义了batch,则遵循h5的batch,如果没有定义则batchsize默认1,读取tflite后可以修改batch,h5模型转换为tflite,可以选择不同的量化模式。tflite可以转onnx,但是当前看起来没有opset参数,也没有其它参数可选。

参考

1. TensorFlow Lite量化方法介绍

2. tflite量化

3. Quantization aware training in Keras example  |  TensorFlow Model Optimization

4. 浅谈混合精度训练

5. 【PyTorch】唯快不破:基于Apex的混合精度加速

6. 混合精度训练

7. tflite2onnx的Python项目详细描述

8. 混合精度案例 tensorflow官方

9. GPU加速实战——混合精度训练

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值