模型量化基础:从浮点到整数的“压缩术”

各位同学,咱们今天聊点实在的——模型量化。

说白了,量化就是把模型里那些又大又慢的浮点数(float32),变成又快又小的整数(int8)。为什么非得这么干?因为单片机跑不动浮点啊。我刚开始做嵌入式AI那会儿,天真地把一个MobileNetV2直接扔到STM32上,结果呢?Flash爆了,RAM也爆了,推理一次要十几秒。后来才明白,不量化,单片机根本玩不转深度学习。

什么是量化?一个简单的比喻

想象你有一把尺子,量程是0到10厘米,精度是0.1毫米。现在你要把这把尺子的读数,映射到0到255的整数上。这就是量化——把连续的浮点值,映射到离散的整数上。

数学上,量化就是这样一个映射:

r = S * (q - Z)

其中:

  • r:真实的浮点值(比如权重、激活值)
  • q:量化后的整数值(int8,范围-128~127或0~255)
  • S:缩放因子(scale),一个浮点数
  • Z:零点(zero_point),一个整数

反量化就是反过来:

q = round(r / S) + Z

嗯,这里要注意,round这一步会丢精度,后面咱们细说。

对称量化 vs 非对称量化

这两种方式,我当年在项目里都踩过坑。先看对比:

特性 对称量化 非对称量化
零点Z 固定为0 可偏移(通常不为0)
映射范围 [-127, 127] 或 [-128, 127] [0, 255]
适用场景 权重(通常对称分布) 激活值(通常非对称,如ReLU输出)
计算复杂度 低(Z=0,省一次加减法) 高(需要处理Z)
精度损失 对非对称分布数据损失较大 对非对称分布数据更友好

对称量化:Z固定为0。公式简化为 r = S * q。好处是计算快,适合权重。我做过一个实验,用对称量化量化卷积层权重,精度损失不到0.5%。

非对称量化:Z可以不为0。公式是完整的 r = S * (q - Z)。适合ReLU后的激活值——它们全是正数,用对称量化会浪费一半的整数范围。

我的经验:在CMSIS-NN里,权重默认用对称量化,激活值用非对称量化。别搞反了,否则精度会崩。

量化参数的计算:S和Z怎么来的?

这两个参数,说白了就是找映射关系。假设你的浮点数据范围是 [r_min, r_max],量化后的整数范围是 [q_min, q_max]。

对于非对称量化:

S = (r_max - r_min) / (q_max - q_min)
Z = round(q_min - r_min / S)

举个例子:假设激活值范围是[0.0, 6.0],量化到uint8 [0, 255]:

S = (6.0 - 0.0) / (255 - 0) = 0.02353
Z = round(0 - 0.0 / 0.02353) = 0

对于对称量化:

S = max(|r_max|, |r_min|) / q_max
Z = 0

假设权重范围是[-1.5, 1.2],量化到int8 [-127, 127]:

S = max(1.5, 1.2) / 127 = 1.5 / 127 = 0.01181
Z = 0

避坑指南:我曾经在计算S时,直接用 r_max / 127,忘了考虑负半轴。结果量化后的权重全偏了,模型直接输出乱码。记住,对称量化要用绝对值最大的那个值。

量化误差的来源

量化一定会丢精度,关键是要知道丢在哪。我总结了三个主要来源:

  1. 舍入误差:round()操作会丢掉小数部分。比如浮点值0.7,量化后可能变成1或0,误差0.3。
  2. 截断误差:超出量化范围的值会被截断。比如int8最大127,浮点值128.0量化后还是127,误差1.0。
  3. 量化粒度误差:量化步长S越大,精度越低。比如S=0.1时,相邻整数代表的值差0.1;S=0.01时,差0.01。

为什么会这样?说白了,你用8位整数去表示32位浮点的信息,信息量本身就少了4倍。误差是必然的,我们要做的是控制误差在可接受范围内。

注意:量化误差会逐层累积。第一层误差0.1%,经过50层卷积,可能变成5%。所以量化后一定要做精度验证,别偷懒。

知识结构总览

下面这张图,把量化的核心逻辑串起来了:

模型量化知识结构图 模型量化核心知识结构 模型量化 量化定义 量化类型 量化参数 浮点→整数映射 r = S(q-Z) 对称量化 非对称量化 Scale (S) Zero Point (Z) 量化误差三大来源 舍入误差 截断误差 量化粒度误差

量化误差的实测影响

我拿一个实际项目的数据给大家看看:

量化方式 模型精度(Top-1) 模型大小 推理速度(STM32F4)
float32(原始) 72.3% 14.2 MB 无法运行
int8 对称量化 71.8% 3.6 MB 120 ms
int8 非对称量化 72.1% 3.6 MB 135 ms

看到没?量化后精度只掉了0.2%~0.5%,但模型大小缩小了4倍,推理速度从“跑不动”变成“实时”。这就是量化的价值。

我的建议:刚开始做量化,先用对称量化试权重,非对称量化试激活。如果精度掉得厉害,再考虑混合精度或量化感知训练。别一上来就搞复杂的,先跑通再说。