PTQ&QAT

前言

模型量化是一种流行的深度学习优化方法,它将模型数据(包括网络参数和激活)从浮点表示转换为低精度表示,通常使用 8 位整数。这样做有几个好处:

  • 在处理 8 位整数数据时,GPU(如英伟达)采用速度更快、成本更低的 8 位张量核心来计算卷积和矩阵乘法运算。这将产生更多的计算吞吐量,对计算受限的层尤其有效。
  • 将数据从内存移动到计算元件(GPU 的流式多处理器)需要时间和能量,还会产生热量。将激活数据和参数数据的精度从 32 位浮点数降低到 8 位整数,可减少 4 倍的数据量,从而节省能耗并降低发热量。
  • 有些层受限于带宽(内存限制)。这意味着其实现过程中大部分时间都在读写数据,因此减少其计算时间并不会减少其整体运行时间。带宽需求的减少,带宽受限层最为受益。
  • 内存占用减少意味着模型所需的存储空间更少、参数更新更小、缓存利用率更高,等等。

要将浮点张量转换为 8 位表示,需要使用比例因子将浮点张量的动态范围映射为 [-128, 127]。为了解决精度损失对任务精度的影响,人们开发了各种量化技术。这些技术可分为两类:训练后量化(post-training quantization ,PTQ)或量化感知训练(quantization-aware training, QAT)。

PTQ与QAT

  1. PTQ是在高精度模型训练完成后进行的。使用 PTQ,量化权重很容易。您可以访问权重张量并测量它们的分布。量化激活更具挑战性,因为必须使用真实的输入数据来测量激活分布。为此,使用代表任务真实输入数据的小数据集来评估经过训练的浮点模型,并收集有关层间激活分布的统计数据。最后一步,使用几个优化目标之一确定模型激活张量的量化尺度。这个过程就是校准,所使用的代表性数据集是校准数据集。
  2. QAT 背后的想法很简单:如果在训练阶段包含量化误差,则可以提高量化模型的准确性。它使网络能够适应量化的权重和激活。
  3. PTQ 是这两种方法中更受欢迎的一种,因为它简单,不涉及训练pipeline,因此也是更快的方法。不过,QAT 几乎总是能产生更好的准确性,有时这也是唯一可以接受的方法。

QAT

处理流程

1. fp32模型训练得到一个baseline

2. 在baseline模型中插入伪量化节点,得到qat模型,在数据集上进行finetune

3. 在finetune的过程中,伪量化节点模拟量化误差, 更新参数

4. 量化qat模型得到int8模型,进行端侧部署

5. 伪量化节点一般插入在输入输出、dense、conv、mutmul、act等算子

伪量化节点

伪量化实际上是quantization+dequantization的结合,实际上就是模拟量化round引起的误差

 伪量化的操作看起来输入输出没变,但是实际上在其中模拟了量化round操作,将这种误差当做一种训练的噪声,在QAT finetune的同时,模型会去适应这种噪声,从而在最后量化为INT8时,减少精度的损失, torch的实现如下

import torch import torch.nn as nn import torch.optim as optim import torchvision.datasets as datasets import torchvision.transforms as transforms from torch.quantization import QuantStub, DeQuantStub, \ quantize_dynamic, prepare_qat, convert # Define the model class MyModel(nn.Module): def __init__(self): super(MyModel, self).__init__() self.quant = QuantStub() self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1) self.relu = nn.ReLU(inplace=True) self.conv2 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1) self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) self.fc = nn.Linear(128, 10) self.dequant = DeQuantStub() def forward(self, x): x = self.quant(x) x = self.conv1(x) x = self.relu(x) x = self.conv2(x) x = self.relu(x) x = self.avgpool(x) x = x.view(x.size(0), -1) x = self.fc(x) x = self.dequant(x) return x

onnx如图所示

 

 

待更新

除了量化, 深度学习领域还有其他的模型压缩与加速的方法如下:

  • 剪枝(Parameter pruning)
  • 低秩分解(Low-rank factorization)
  • 知识蒸馏(Knowledge distillation)

reference:

https://zhuanlan.zhihu.com/p/548174416

https://developer.nvidia.com/blog/achieving-fp32-accuracy-for-int8-inference-using-quantization-aware-training-with-tensorrt/


__EOF__

本文作者xle97
本文链接https://www.cnblogs.com/xle97/p/17804834.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   xle97  阅读(212)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
点击右上角即可分享
微信分享提示