模型量化基础:从浮点到整数的“压缩术”
各位同学,咱们今天聊点实在的——模型量化。
说白了,量化就是把模型里那些又大又慢的浮点数(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,忘了考虑负半轴。结果量化后的权重全偏了,模型直接输出乱码。记住,对称量化要用绝对值最大的那个值。
量化误差的来源
量化一定会丢精度,关键是要知道丢在哪。我总结了三个主要来源:
- 舍入误差:
round()操作会丢掉小数部分。比如浮点值0.7,量化后可能变成1或0,误差0.3。 - 截断误差:超出量化范围的值会被截断。比如int8最大127,浮点值128.0量化后还是127,误差1.0。
- 量化粒度误差:量化步长S越大,精度越低。比如S=0.1时,相邻整数代表的值差0.1;S=0.01时,差0.01。
为什么会这样?说白了,你用8位整数去表示32位浮点的信息,信息量本身就少了4倍。误差是必然的,我们要做的是控制误差在可接受范围内。
注意:量化误差会逐层累积。第一层误差0.1%,经过50层卷积,可能变成5%。所以量化后一定要做精度验证,别偷懒。
知识结构总览
下面这张图,把量化的核心逻辑串起来了:
量化误差的实测影响
我拿一个实际项目的数据给大家看看:
| 量化方式 | 模型精度(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倍,推理速度从“跑不动”变成“实时”。这就是量化的价值。
我的建议:刚开始做量化,先用对称量化试权重,非对称量化试激活。如果精度掉得厉害,再考虑混合精度或量化感知训练。别一上来就搞复杂的,先跑通再说。