一、量化基础回顾:什么是模型量化?量化的类型(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 需要经验,不是跑起来就完事的。

为了让你更直观地理解两者的区别,我画了一张流程图:

PTQ vs QAT 流程对比 PTQ 训练后量化 FP32 预训练模型 校准数据(少量) 统计分布 → 计算 scale/zero_point INT8 量化模型 QAT 量化感知训练 FP32 预训练模型 训练数据(大量) 前向:伪量化(Fake Quant) INT8 量化模型 vs 数据量不同 核心差异 PTQ:快但精度可能损失 | QAT:慢但精度更高

1.3 量化精度损失的根源分析

好了,现在咱们进入最核心的部分——精度损失到底是怎么来的?

我把它归结为三个根源:

1.3.1 信息损失:量化误差

这是最直观的。把32位浮点数映射到8位整数,能表示的数字范围从约10^38缩小到256个。这中间必然有信息丢失。

量化误差主要分两种:

  • 舍入误差:浮点数映射到最近的整数,这个“四舍五入”的过程会引入误差
  • 截断误差:超出量化范围的值被“截断”到边界值,比如大于127的浮点数被强行变成127

关键点:量化误差的大小取决于两个因素:

  1. 量化位宽:8位比4位精度高,这是显然的
  2. 量化粒度:逐层量化 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