一、量化基础回顾:什么是模型量化?量化的类型(PTQ与QAT)、量化精度损失的根源分析
各位同学好,我是老张。今天咱们正式开始聊模型量化这个主题。说实话,量化这个话题我讲了不下几十次,但每次讲都有新感悟。尤其是当你亲手把一个32位的浮点模型压到8位甚至4位,看着推理速度翻倍、内存占用砍半,那种成就感,嗯,只有做过的人才知道。
但别高兴太早。量化最让人头疼的是什么?精度回退。模型跑得快了,但结果不准了,这谁受得了?所以咱们这门课的核心,就是教你怎么把精度“救回来”。
在动手修复之前,得先把基础打牢。今天这一讲,我们就来聊聊:量化到底是什么?有哪些类型?精度损失又是怎么来的?
1.1 什么是模型量化?
说白了,模型量化就是把模型里的参数和计算,从高精度(比如32位浮点,FP32)换成低精度(比如8位整数,INT8)。
你想想看,一个FP32的数值占4个字节,换成INT8只占1个字节。模型大小直接缩到四分之一。推理时用整数运算,比浮点运算快得多,尤其是在手机、嵌入式设备这些资源受限的地方。
我刚开始接触量化时,总觉得这玩意儿有点“玄学”。把好好的浮点数硬塞进整数里,信息肯定有损失啊。没错,确实有损失,但关键在于——我们能不能让这个损失不影响最终结果。
核心思想:量化不是“无损压缩”,而是“有损压缩”。我们的目标不是让量化后的模型和原模型一模一样,而是让它们在任务指标(比如分类准确率、检测mAP)上尽可能接近。
量化的一般公式长这样:
# 量化公式
q = round(r / scale) + zero_point
# 反量化公式
r = (q - zero_point) * scale
# 其中:
# r 是原始浮点值
# q 是量化后的整数值
# scale 是缩放因子(浮点)
# zero_point 是零点偏移(整数)
这个公式看着简单,但里面的门道可不少。scale和zero_point怎么选?不同的选法,精度损失天差地别。后面我们会详细讲。
1.2 量化的类型:PTQ 与 QAT
量化主要分两大类:训练后量化(PTQ)和量化感知训练(QAT)。这两者的区别,我打个比方你就明白了。
PTQ 就像你买了一件成衣,直接穿上。合不合身看运气,但胜在快、省事。
QAT 就像你找裁缝量身定制。过程慢一点,但穿上去服服帖帖。
咱们来具体看看:
1.2.1 训练后量化(PTQ)
PTQ 是最简单、最常用的量化方式。你有一个训练好的FP32模型,直接拿过来,跑一小部分校准数据,统计出每层激活值和权重的分布范围,然后算出scale和zero_point,完成量化。
优点很明显:
- 不需要重新训练,省时间省算力
- 操作简单,几行代码就能搞定
- 通用性强,大部分模型都能用
缺点也很突出:
- 精度损失可能较大,尤其是小模型或敏感任务
- 对校准数据依赖强,数据选不好,量化效果就崩
我的经验:PTQ 适合大模型(比如ResNet-50以上)或者对精度要求不那么苛刻的场景。我曾经在一个目标检测项目里用PTQ,模型从FP32压到INT8,mAP只掉了0.3%,推理速度提升了2.5倍。这种“白捡”的收益,谁不爱?
1.2.2 量化感知训练(QAT)
QAT 就复杂一些了。它在训练过程中就“模拟”了量化的效果。具体来说,在前向传播时,把权重和激活值“伪量化”(先量化再反量化),让模型提前适应量化带来的误差。反向传播时,用直通估计器(STE)来近似梯度,让模型学会“对抗”量化误差。
优点:
- 精度更高,通常能接近甚至达到FP32的水平
- 更鲁棒,对校准数据不那么敏感
缺点:
- 需要重新训练,费时费力
- 训练技巧多,学习率调整、BN层处理等都有讲究
注意:QAT 不是万能的。我曾经在一个超小模型(MobileNetV2)上试过QAT,精度反而比PTQ还差。后来发现是学习率没调好,模型在量化模拟中“过拟合”了。所以,QAT 需要经验,不是跑起来就完事的。
为了让你更直观地理解两者的区别,我画了一张流程图:
1.3 量化精度损失的根源分析
好了,现在咱们进入最核心的部分——精度损失到底是怎么来的?
我把它归结为三个根源:
1.3.1 信息损失:量化误差
这是最直观的。把32位浮点数映射到8位整数,能表示的数字范围从约10^38缩小到256个。这中间必然有信息丢失。
量化误差主要分两种:
- 舍入误差:浮点数映射到最近的整数,这个“四舍五入”的过程会引入误差
- 截断误差:超出量化范围的值被“截断”到边界值,比如大于127的浮点数被强行变成127
关键点:量化误差的大小取决于两个因素:
- 量化位宽:8位比4位精度高,这是显然的
- 量化粒度:逐层量化 vs 逐通道量化,后者更精细,误差更小
1.3.2 分布偏移:校准数据与真实数据不匹配
这个坑我踩过好几次。PTQ需要校准数据来统计分布,但如果你选的校准数据跟实际推理时的数据分布不一样,那量化参数就“偏”了。
举个例子:
- 你用ImageNet的图片做校准,但实际部署时全是监控摄像头拍的夜间图像
- 你用干净的数据做校准,但实际输入有噪声
这种情况下,量化后的模型在真实场景下表现会很差。我建议:校准数据一定要尽可能贴近真实部署场景。
1.3.3 累积误差:层间传播
这是最隐蔽、也最致命的问题。单层的量化误差可能很小,但经过多层传播后,误差会不断累积、放大。
你想想看:
- 第1层的输出有0.1%的误差
- 第2层把误差放大到0.5%
- 到了第10层,误差可能已经到5%了
- 到了输出层,结果可能完全不对
尤其是那些对数值敏感的网络结构,比如:
- 有shortcut连接的残差网络(ResNet)
- 有大量concat操作的网络(如DenseNet)
- 注意力机制(Transformer)
这些结构里,误差会沿着多条路径传播,互相叠加,最终导致精度雪崩。
避坑指南:我曾经在一个BERT模型上做量化,单层误差只有0.2%,但最终GLUE分数掉了5个点。排查了三天才发现,是第6层的self-attention模块对误差特别敏感,把一个小误差放大了100倍。从那以后,我每次做量化都会逐层检查误差传播情况。
1.4 总结:一张表看懂
| 维度 | PTQ | QAT |
|---|---|---|
| 是否需要训练 | 否 | 是 |
| 数据需求 | 少量校准数据 | 大量训练数据 |
| 精度表现 | 中等,可能下降1-3% | 优秀,接近FP32 |
| 部署速度 | 快(几小时) | 慢(几天到几周) |
| 适用场景 | 大模型、精度要求不高 | 小模型、精度敏感任务 |
| 精度损失根源 | 量化误差 + 分布偏移 | 量化误差 + 训练不充分 |
好了,这一讲的内容就到这里。量化基础打牢了,后面我们才能谈修复。下一讲,我会带你看看量化精度回退的常见模式——哪些层最容易出问题?哪些结构是“重灾区”?这些都是我实战中总结出来的经验,保证让你少走弯路。
公众号:蓝海资料掘金营,微信deep3321