3、模型量化入门:什么是量化、量化的数学原理(对称/非对称量化)、量化精度与性能的权衡

好,咱们进入第三章。量化。

说实话,很多做AI的同行一听到「量化」两个字,第一反应就是「掉精度」。我刚开始接触嵌入式AI时也这么想——好好的FP32模型,干嘛非要折腾成INT8?这不是自找麻烦吗?

后来我在一个智能门锁项目上被现实狠狠教育了一回。模型跑在Cortex-M4上,推理一次要3秒,用户都按第二遍指纹了,结果还没算完。嗯,从那以后,我再也不敢小看量化了。

3.1 什么是量化?说白了就是「省着算」

量化,本质上就是把连续的浮点数,映射到离散的整数上。

你想想看,神经网络里那些权重和激活值,大部分都是FP32的。每个数占4个字节。一个MobileNetV2大概有3.5M个参数,光权重就14MB。很多MCU的Flash才512KB,根本塞不下。

量化之后呢?INT8每个数只占1个字节。模型体积直接缩到1/4。更关键的是,整数运算比浮点运算快得多——很多硬件有专用的SIMD指令,一条指令能同时算4个、8个甚至16个数据。

核心思想:用更少的比特数表示数值,换取更小的模型体积和更快的推理速度。

我在项目中遇到过最极端的例子:一个3MB的模型量化到INT8后只有750KB,跑在H7系列芯片上,推理时间从1.2秒降到了180毫秒。精度只掉了0.3%。值不值?你自己判断。

3.2 量化的数学原理

量化不是随便把浮点数四舍五入成整数。它有一套严谨的数学映射关系。

3.2.1 基本公式

假设我们有一个浮点数 r,要量化成整数 q。公式长这样:

q = round(r / S + Z)

反过来,反量化公式:

r = (q - Z) * S

这里有两个关键参数:

  • S(Scale,缩放因子):决定每个整数步长代表多大的浮点范围
  • Z(Zero Point,零点):浮点0映射到哪个整数

我习惯把S想象成「尺子的刻度」,Z就是「尺子的起点」。你想想看,一把尺子,刻度粗细和起点位置决定了它能量什么范围的东西。

3.2.2 对称量化 vs 非对称量化

这里有个重要的分岔路口——对称还是非对称?

特性 对称量化 非对称量化
零点Z 固定为0 可以不为0
映射范围 [-max, +max] [min, max]
计算复杂度 低(无零点偏移) 高(需处理零点)
适用场景 权重(通常对称分布) 激活值(ReLU后全为正)

对称量化:

Z固定为0。公式简化为:

q = round(r / S)
r = q * S

说白了,就是把浮点范围[-a, a]映射到[-127, 127](INT8)。

我个人的习惯是:权重用对称量化。为什么?因为训练好的权重分布通常以0为中心,左右对称。你硬要加个非零的零点,反而浪费了整数的表示能力。

非对称量化:

Z可以不为0。公式就是最前面那个带Z的版本。

激活值我建议用非对称量化。你想想看,ReLU之后全是正数,范围可能是[0, 6.7]。如果用对称量化,负半轴那部分表示能力全浪费了。非对称量化可以把整个整数范围[0, 255]都用来表示正数,精度更高。

我的经验:权重用对称,激活用非对称。这是最稳妥的搭配。我曾经试过全用对称量化,结果某个层的激活值分布偏得厉害,精度直接掉了2%。后来改成非对称,精度就回来了。

3.2.3 量化参数的计算

S和Z怎么算?需要先知道浮点数的范围[min, max]。

# 对称量化
S = max(|min|, |max|) / 127
Z = 0

# 非对称量化
S = (max - min) / 255
Z = round(-min / S)

这里有个坑——min和max怎么确定?

  • 权重:直接取训练好的权重值,min和max是确定的
  • 激活值:需要跑一批校准数据(calibration dataset),统计每层的输出范围

我曾经犯过一个错误:随便拿了10张图片做校准,结果激活值范围没覆盖全。模型在测试集上精度还行,一到实际场景就崩了。后来我学乖了,至少用500-1000张有代表性的数据做校准。

3.3 量化精度与性能的权衡

量化不是免费的午餐。你省了算力和存储,就得付出精度的代价。

3.3.1 精度损失从哪来?

说白了就两个原因:

  1. 截断误差:浮点范围太大,超出整数能表示的范围,直接截断
  2. 舍入误差:浮点数落在两个整数之间,四舍五入时丢失精度

你想想看,INT8只有256个取值。FP32有40多亿个。用256个值去近似40亿个值,怎么可能没损失?

3.3.2 量化到什么程度合适?

我整理了一个表格,方便你快速决策:

量化位宽 模型体积缩减 推理加速比 典型精度损失 推荐场景
FP32→INT8 4x 2-4x <1% 大部分嵌入式场景
FP32→INT4 8x 4-8x 1-5% 对精度要求不高的场景
FP32→INT2/1 16-32x 8-16x 5-15% 极端资源受限,且任务简单

注意:以上数据是典型值,实际效果取决于模型结构和数据分布。我见过某些模型INT8量化后精度反而提升了(因为量化起到了正则化作用),也见过掉3%的。一定要实测验证。

3.3.3 如何平衡?我的实战建议

嗯,这里分享几条我踩过坑之后总结的经验:

  • 先做INT8:90%的嵌入式场景,INT8就够了。别一上来就追求INT4或二值化
  • 逐层分析:不是所有层对精度都敏感。第一层和最后一层通常最敏感,可以保留FP32。中间层大胆量化
  • 混合精度:敏感层用INT8,不敏感层用INT4。我有个项目就是这么干的,模型体积缩小了6倍,精度只掉了0.5%
  • 量化感知训练(QAT):如果后训练量化(PTQ)精度掉太多,就用QAT。在训练过程中模拟量化误差,让模型自己适应

我记得有一次做语音唤醒词检测,模型很小,PTQ量化后精度掉了3%。我换成QAT,精度只掉了0.2%。虽然训练时间多了30%,但效果值得。

3.4 小结

量化是嵌入式AI推理加速的基石。说白了,就是用精度换速度、换体积。对称量化适合权重,非对称量化适合激活值。INT8是性价比最高的选择,但具体用哪种方案,一定要结合你的模型和硬件实测。

下一章,我们会深入代码,手把手教你用TensorRT和TFLite做量化。到时候你会看到,理论落地到代码其实没那么复杂。