3、模型量化基础:为什么需要量化、量化的原理(FP32->INT8)、对称量化与非对称量化、量化感知训练(QAT)与训练后量化(PTQ)
大家好,我是你们的老朋友。今天我们来聊聊模型量化。
说实话,量化这个话题,在深度学习部署里属于「绕不过去的坎」。你想想看,一个模型在 GPU 上跑得飞快,一上手机或者边缘设备,立马卡成 PPT。为什么?说白了,就是计算资源和存储资源不够用了。这时候,量化就是那个「救火队员」。
为什么需要量化?
我刚开始做部署的时候,也天真地以为直接拿 FP32 模型跑就行。结果呢?一个 ResNet-50 在 Jetson Nano 上推理一次要 200 多毫秒,帧率连 5fps 都不到。这哪行?
量化的核心价值,其实就三点:
- 模型变小:FP32 转 INT8,体积直接缩到原来的 1/4。一个 100MB 的模型,量化完只有 25MB。这对移动端和嵌入式设备来说,太关键了。
- 推理变快:INT8 的计算比 FP32 快得多。很多硬件(比如手机上的 NPU、DSP)对 INT8 有专门的加速指令。我实测过,量化后推理速度能提升 2-4 倍。
- 功耗降低:计算量小了,内存访问少了,功耗自然就降下来了。这对电池供电的设备来说,是刚需。
一句话总结:量化就是用一点点精度损失,换取体积、速度和功耗的巨大收益。在工程落地中,这几乎是必选项。
量化的原理:FP32 -> INT8
量化到底是怎么做的?别把它想得太玄乎。
本质上,量化就是一个映射过程。我们把 FP32 的浮点数范围,映射到 INT8 的整数范围(-128 到 127,或者 0 到 255)。
数学公式很简单:
INT8_value = round(FP32_value / scale) + zero_point
其中:
- scale(缩放因子):决定了每个整数步长代表多大的浮点数。
- zero_point(零点):浮点数 0 映射到哪个整数。
反量化就是逆过程:
FP32_value = (INT8_value - zero_point) * scale
嗯,这里要注意:round 操作会带来精度损失。这就是量化误差的来源。我在项目中遇到过,有些模型对精度特别敏感,量化后准确率掉了 5 个点,那就得想办法了。
对称量化 vs 非对称量化
这两种方式,说白了就是 zero_point 怎么处理。
对称量化
对称量化要求 zero_point = 0。也就是说,浮点数的 0 精确映射到整数的 0。
它的映射范围是对称的:[-max_abs, max_abs] 映射到 [-127, 127](INT8 的 -128 通常不用,为了对称)。
优点:实现简单,计算效率高。很多硬件(比如 TensorRT)默认就用对称量化。
缺点:如果数据分布不对称(比如全是正数),那有一半的整数范围就浪费了。精度会受影响。
非对称量化
非对称量化允许 zero_point 不为 0。它把 [min, max] 映射到 [0, 255](或者 [-128, 127])。
优点:能充分利用整个整数范围,精度通常比对称量化好一点。
缺点:计算时多了一个 zero_point 的偏移,稍微复杂一些。
| 特性 | 对称量化 | 非对称量化 |
|---|---|---|
| zero_point | 固定为 0 | 不固定,需计算 |
| 映射范围 | [-max_abs, max_abs] | [min, max] |
| 计算复杂度 | 低 | 稍高 |
| 精度 | 数据对称时好 | 通常更好 |
| 硬件支持 | 广泛 | 部分硬件不支持 |
我的建议:如果硬件支持,优先试对称量化。如果精度不够,再换非对称。我在部署 MobileNet 时,对称量化掉点 0.3%,非对称量化只掉 0.1%,但速度慢了 5%。这就要看你的取舍了。
量化感知训练(QAT)与训练后量化(PTQ)
这两种方法,是量化的「两条腿」。走哪条,取决于你的场景。
训练后量化(PTQ)
PTQ 是最简单粗暴的方式。模型训练完,直接拿来做量化。
步骤:
- 拿一小部分校准数据(几百张图片就行)。
- 跑一遍推理,统计每层激活值的 min、max 分布。
- 根据统计结果,计算 scale 和 zero_point。
- 把权重和激活值都量化成 INT8。
优点:快!不需要重新训练,几分钟就搞定。
缺点:精度损失可能比较大。尤其是对激活值分布敏感的模型。
我曾经在一个检测模型上试 PTQ,mAP 直接从 0.75 掉到 0.68。客户当场就不干了。嗯,这时候就得请出 QAT 了。
量化感知训练(QAT)
QAT 的思路是:在训练过程中,就模拟量化带来的误差,让模型学会「适应」量化。
具体做法:
- 在训练图中插入伪量化节点(FakeQuantize)。
- 前向传播时,用伪量化模拟 INT8 的计算。
- 反向传播时,用直通估计器(STE)来近似梯度,让量化操作可导。
- 训练完成后,去掉伪量化节点,导出真正的 INT8 模型。
优点:精度损失极小,甚至有时比 FP32 还好(因为量化起到了正则化的作用)。
缺点:需要重新训练,耗时。而且需要修改训练代码。
避坑指南:我曾经在 QAT 训练时,学习率没调好,模型直接不收敛了。后来发现,QAT 的学习率要比正常训练小 10 倍左右。另外,校准数据集的选择也很关键,一定要覆盖真实场景的数据分布。
怎么选?
我个人的经验是:
- 先试 PTQ:如果精度损失在可接受范围内(比如 0.5% 以内),那就用 PTQ。省时省力。
- 精度不够,上 QAT:如果 PTQ 掉点太多,或者模型对精度要求极高(比如医疗、自动驾驶),那就老老实实做 QAT。
- 混合使用:有些层对量化敏感(比如第一层、最后一层),可以保持 FP32,其他层量化。这叫混合精度量化。
好了,关于量化的基础,我们就聊到这里。下一章,我会带大家手撸一个 PTQ 的代码实现。到时候你就知道,量化其实没那么神秘。