0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Pytorch量化感知训练的详解

电子设计 来源:电子设计 作者:电子设计 2020-12-08 22:57 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

文章转载于微信公众号:GiantPandaCV
作者: Pui_Yeung

前言

  量化感知训练(Quantization Aware Training )是在模型中插入伪量化模块(fake/_quant module)模拟量化模型在推理过程中进行的舍入(rounding)和钳位(clamping)操作,从而在训练过程中提高模型对量化效应的适应能力,获得更高的量化模型精度 。在这个过程中,所有计算(包括模型正反向传播计算和伪量化节点计算)都是以浮点计算实现的,在训练完成后才量化为真正的int8模型。  

Pytorch官方从1.3版本开始提供量化感知训练API,只需修改少量代码即可实现量化感知训练。目前torch.quantization仍处于beta阶段,不保证API前向、后向兼容性。以下介绍基于Pytorch 1.7,其他版本可能会有差异。

Pytorch量化感知训练流程

  首先给出提供一个可运行demo,直观了解量化感知训练的6个步骤,再进行详细的介绍

importtorchfromtorch.quantizationimportprepare_qat,get_default_qat_qconfig,convertfromtorchvision.modelsimportquantization# Step1:修改模型#这里直接使用官方修改好的MobileNetV2,下文会对修改点进行介绍model=quantization.mobilenet_v2()print("originalmodel:")print(model)# Step2:折叠算子#fuse_model()在training或evaluate模式下算子折叠结果不同,#对于QAT,需确保在training状态下进行算子折叠assertmodel.trainingmodel.fuse_model()print("fusedmodel:")print(model)#Step3:指定量化方案#通过给模型实例增加一个名为"qconfig"的成员变量实现量化方案的指定#backend目前支持fbgemm和qnnpackBACKEND="fbgemm"model.qconfig=get_default_qat_qconfig(BACKEND)# Step4:插入伪量化模块prepare_qat(model,inplace=True)print("modelwithobservers:")print(model)#正常的模型训练,无需修改代码# Step5:实施量化model.eval()#执行convert函数前,需确保模型在evaluate模式model_int8=convert(model)print("quantizedmodel:")print(model_int8)# Step6:int8模型推理#指定与qconfig相同的backend,在推理时使用正确的算子torch.backends.quantized.engine=BACKEND#目前Pytorch的int8算子只支持CPU推理,需确保输入和模型都在CPU侧#输入输出仍为浮点数fp32_input=torch.randn(1,3,224,224)y=model_int8(fp32_input)print("output:")print(y)

Step1:修改模型

  Pytorch下需要适当修改模型才能进行量化感知训练,以下以常用的MobileNetV2为例。官方已修改好的MobileNetV2的代码,详见这里(https://github.com/pytorch/vi...

修改主要包括3点,以下摘取相应的代码进行介绍:

(1)在模型输入前加入QuantStub(),在模型输出后加入DeQuantStub()。目的是将输入从fp32量化为int8,将输出从int8反量化为fp32。模型的/_/_init/_/_()和forward()修改为:

classQuantizableMobileNetV2(MobileNetV2):def__init__(self,*args,**kwargs):"""MobileNetV2mainclassArgs:InheritsargsfromfloatingpointMobileNetV2"""super(QuantizableMobileNetV2,self).__init__(*args,**kwargs)self.quant=QuantStub()self.dequant=DeQuantStub()defforward(self,x):x=self.quant(x)x=self._forward_impl(x)x=self.dequant(x)returnx

(2)对加法等操作加入伪量化节点。因为int8数值进行加法运算容易超出数值范围,所以不是直接进行计算,而是进行反量化->计算->量化的操作。以InvertedResidual的修改为例:

classQuantizableInvertedResidual(InvertedResidual):def__init__(self,*args,**kwargs):super(QuantizableInvertedResidual,self).__init__(*args,**kwargs)#加法的伪量化节点需要记录所经过该节点的数值的范围,因此需要实例化一个对象self.skip_add=nn.quantized.FloatFunctional()defforward(self,x):ifself.use_res_connect:#普通版本MobileNetV2的加法#returnx+self.conv(x)#量化版本MobileNetV2的加法returnself.skip_add.add(x,self.conv(x))else:returnself.conv(x)

(3)将ReLU6替换为ReLU。MobileNet V2使用ReLU6的原因是对ReLU的输出范围进行截断以缓解量化为fp16模型时的精度下降。因为int8量化本身就能确定截断阈值,所以将ReLU6替换为ReLU以去掉截断阈值固定为6的限制。官方的修改代码在建立网络后通过/_replace/_relu()将MobileNetV2中的ReLU6替换为ReLU:

model=QuantizableMobileNetV2(block=QuantizableInvertedResidual,**kwargs)_replace_relu(model)

Step2:算子折叠

  算子折叠是将模型的多个层合并成一个层,一般用来减少计算量和加速推理。对于量化感知训练而言,算子折叠作用是将模型变“薄”,减少中间计算过程的误差积累。

  以下比较有无算子折叠的结果(上:无算子折叠,下:有算子折叠,打印执行prepare/_qat()后的模型)

 如果不进行算子折叠,每个Conv-BN-ReLU单元一共会插入4个FakeQuantize模块。而进行算子折叠后,原来Conv2d()被ConvBnReLU2d()代替(3层合并到了第1层),BatchNorm2d()和ReLU()被Inentity()代替(仅作为占位),最终只插入了2个FakeQuantize模块。

FakeQuantize模块的减少意味着推理过程中进行的量化-反量化的次数减少,有利于减少量化带来的性能损失。

  算子折叠由实现torch.quantization.fuse/_modules()。目前存在的比较遗憾的2点:

  算子折叠不能自动完成,只能由程序员手工指定要折叠的子模型。以torchvision.models.quantization.mobilenet/_v2()中实现的算子折叠函数为例:

deffuse_model(self):#遍历模型内的每个子模型,判断类型并进行相应的算子折叠forminself.modules():iftype(m)==ConvBNReLU:fuse_modules(m,['0','1','2'],inplace=True)iftype(m)==QuantizableInvertedResidual:#调用子模块实现的fuse_model(),间接调用fuse_modules()m.fuse_model()

  能折叠的算子组合有限。目前支持的算子组合为:ConV + BN、ConV + BN + ReLU、Conv + ReLU、Linear + ReLU、BN + ReLU。如果尝试折叠ConvTranspose2d、ReLU6等不支持的算子则会报错。

Step3:指定量化方案

  目前支持fbgemm和qnnpack两种backend方案。官方推荐x86平台使用fbgemm方案,ARM平台使用qnnpack方案。  量化方案通过如下方法指定

model.qconfig=get_default_qat_qconfig(backen)#或model.qconfig=get_default_qat_qconfig(backen)

  即通过给model增加一个名为qconfig为成员变量并赋值。

  量化方案可通过设置qconfig自定义,本文暂不讨论。

Step4:插入伪量化模块  

通过执行prepare/_qat(),实现按qconfig的配置方案给每个层增加FakeQuantize()模块 每个FakeQuantize()模块内包含相应的Observer()模块,在模型执行forward()时自动记录数值,供实施量化时使用。

Step5:实施量化  

完成训练后,通过执行convert()转换为真正的int8量化模型。 完成转换后,FakeQuantize()模块被去掉,原来的ConvBNReLU2d()算子被替换为QuantizedConvReLU2d()算子。

Step6:int8模型推理

  int8模型的调用方法与普通的fp32模型的调用无异。需要注意的是,目前量化算子仅支持CPU计算,故须确保输入和模型都在CPU侧。

  若模型推理中出现报错,一般是前面的步骤存在设置不当,参考常见问题第1点。

常见问题

(1) RuntimeError: Could not run XX with arguments from the YY backend. XX is only available for these backends ZZ  

虽然fp32模型和int8模型都能在CPU上推理,但fp32算子仅接受tensor作为输入,int8算子仅接受quantedtensor作为输入,输入和算子的类型不一致导致上述错误。

  一般排查方向为:是否完成了模型修改,将加法等操作替换为量化版本;是否正确添加了QuantStub()和DeQuantStub();是否在执行convert()前是否执行了model.eval()(在traning模型下,dropout无int8实现但没有被去掉,然而在执行推理时会报错)。

(2) 是否支持GPU训练,是否支持DistributedDataParallel训练?  

支持。官方有一个完整的量化感知训练的实现,使用了GPU和DistributedDataParallel,可惜在文档和教程中未提及,参考这里(https://github.com/pytorch/vi.../_quantization.py)。

(3) 是否支持混合精度模型(例如一部分fp32推理,一部分int8推理)?  

官方没有明确说明,但经实践是可以的。

  模型是否进行量化取决于是否带qconfig。因此可以将模型定义修改为

classMixModel(nn.Module):def__init__(self):super(MixModel,self).__init__()self.fp32_part=Fp32Model()self.int8_part=Int8Model()defforward(self,x):x=self.int8_part(x)x=self.fp32(x)returnxmix_model=MixModel()mix_model.int8_part.qconfig=get_default_qat_qconfig(BACKEND)prepare_qat(mix_model,inplace=True)

  由此可实现所需的功能。注意将QuantStub()、Dequant()模块移到Int8Model()中。

(4)精度保持效果如何,如何提升精度?  

笔者进行的实验不多,在做过的简单的OCR任务中,可以做到文字检测和识别模型的指标下降均不超过1个点(量化的int8模型对比正常训练的fp32模型)。官方教程中提供了分类例子的效果和提升精度的技巧,可供参考。

总结

  Pytorch官方提供的量化感知训练API,上手较为简单,易于集成到现有训练代码中。但目前手动修改模型和算子折叠增加了一定的工作量,期待在未来版本的改进。

- END -

推荐阅读

更多嵌入式AI技术干货请关注嵌入式AI专栏。

审核编辑:符乾江
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 深度学习
    +关注

    关注

    73

    文章

    5590

    浏览量

    123905
  • pytorch
    +关注

    关注

    2

    文章

    813

    浏览量

    14699
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    瑞芯微模型量化文件构建

    模型是一张图片输入时,量化文件如上图所示。但是我现在想量化deepprivacy人脸匿名模型,他的输入是四个输入。该模型训练时数据集只标注了人脸框和关键点,该模型的预处理是放到模型外的,不在模型
    发表于 06-13 09:07

    OCR识别训练完成后给的是空压缩包,为什么?

    OCR识别 一共弄了26张图片,都标注好了,点击开始训练,显示训练成功了,也将压缩包发到邮箱了,下载下来后,压缩包里面是空的 OCR图片20几张图太少了。麻烦您多添加点,参考我们的ocr识别训练数据集 请问
    发表于 05-28 06:46

    技术分享 | 高逼真合成数据助力智驾“看得更准、学得更快”

    自动驾驶研发如何高效获取海量训练数据?高逼真合成数据技术正在提供新解法。通过仿真平台可生成多场景、多传感器的精准标注数据。文章详解如何构建符合nuScenes标准的数据集,覆盖复杂交通场景,为感知模型
    的头像 发表于 04-29 10:47 3293次阅读
    技术分享 | 高逼真合成数据助力智驾“看得更准、学得更快”

    海思SD3403边缘计算AI数据训练概述

    AI数据训练:基于用户特定应用场景,用户采集照片或视频,通过AI数据训练工程师**(用户公司****员工)** ,进行特征标定后,将标定好的训练样本,通过AI训练服务器,进行AI学习
    发表于 04-28 11:11

    NVIDIA技术驱动帕西尼触觉感知与人形机器人智能突破

    感知科技实现了从接触仿真、触觉信号产生、仿真数据生成,再到触觉模态模型训练的全流程 GPU 加速,提升标定和训练效率 100 倍,完成触觉传感器的批量标定和触觉模态规模化实机部署。
    的头像 发表于 04-21 09:15 1199次阅读

    从安防到元宇宙:RK3588如何重塑视觉感知边界?

    示例: 多模态AI融合:支持TensorFlow、PyTorch等主流框架模型部署,可应用于智能零售中的行为识别系统,通过摄像头+红外传感器数据融合,精准分析顾客停留热点。 七屏异显与8K编解码:在数
    发表于 04-07 16:11

    如何排除深度学习工作台上量化OpenVINO™的特定层?

    无法确定如何排除要在深度学习工作台上量化OpenVINO™特定层
    发表于 03-06 07:31

    是否可以输入随机数据集来生成INT8训练量化模型?

    无法确定是否可以输入随机数据集来生成 INT8 训练量化模型。
    发表于 03-06 06:45

    使用OpenVINO™ 2021.4将经过训练的自定义PyTorch模型加载为IR格式时遇到错误怎么解决?

    使用 OpenVINO™ 2021.4 将经过训练的自定义 PyTorch 模型加载为 IR 格式时遇到错误: RuntimeError: [ GENERAL_ERROR ] Failed
    发表于 03-05 08:40

    详解RAD端到端强化学习后训练范式

    受限于算力和数据,大语言模型预训练的 scalinglaw 已经趋近于极限。DeepSeekR1/OpenAl01通过强化学习后训练涌现了强大的推理能力,掀起新一轮技术革新。
    的头像 发表于 02-25 14:06 1020次阅读
    <b class='flag-5'>详解</b>RAD端到端强化学习后<b class='flag-5'>训练</b>范式

    操作指南:pytorch云服务器怎么设置?

    设置PyTorch云服务器需选择云平台,创建合适的GPU实例,安装操作系统、Python及Anaconda,创建虚拟环境,根据CUDA版本安装PyTorch,配置环境变量,最后验证安装。过程中需考虑
    的头像 发表于 02-08 10:33 606次阅读

    大模型训练框架(五)之Accelerate

    轻松切换不同的并行策略,同时它还支持混合精度训练,可以进一步提升训练效率。 1. 导入 Accelerate只需添加四行代码,即可在任何分布式配置中运行相同的 PyTorch 代码!让大规模
    的头像 发表于 01-14 14:24 1767次阅读

    【「具身智能机器人系统」阅读体验】+两本互为支持的书

    之极。 《计算机视觉之PyTorch数字图像处理》为《具身智能机器人系统》提供了感知和识别能力,而《具身智能机器人系统》则为《计算机视觉之PyTorch数字图像处理》提供了执行体。读好这两本书,无疑为了解和追随新技术潮流提供了助
    发表于 01-01 15:50

    利用Arm Kleidi技术实现PyTorch优化

    PyTorch 是一个广泛应用的开源机器学习 (ML) 库。近年来,Arm 与合作伙伴通力协作,持续改进 PyTorch 的推理性能。本文将详细介绍如何利用 Arm Kleidi 技术提升 Arm
    的头像 发表于 12-23 09:19 1619次阅读
    利用Arm Kleidi技术实现<b class='flag-5'>PyTorch</b>优化

    使用英特尔AI PC为YOLO模型训练加速

    在以往的实践中,当我们针对 ultralytics 的 YOLO 模型开展训练工作时,可供选择的计算设备通常局限于 CPU、mps 以及 cuda 这几种。然而,自 PyTorch2.5 版本发布
    的头像 发表于 12-09 16:14 2104次阅读
    使用英特尔AI PC为YOLO模型<b class='flag-5'>训练</b>加速