4、量化参数:Scale(缩放因子)和Zero-point(零点)的数学原理
好,咱们进入量化最核心的两个参数:Scale 和 Zero-point。
说白了,量化就是把浮点数(比如 3.14159)映射到整数(比如 128)的过程。那怎么映射?靠的就是这两个参数。我刚开始接触量化时,总觉得这俩东西很玄乎,后来自己手推了一遍公式,发现其实挺朴素的。
4.1 从数学角度看映射
假设你有一个浮点数范围 [r_min, r_max],要映射到 8 位整数的范围 [0, 255]。那这个映射就是一条直线:
r = S * (q - Z)
其中:
- r 是真实的浮点数值
- q 是量化后的整数值
- S 是 Scale(缩放因子)
- Z 是 Zero-point(零点)
反过来,从浮点到整数的公式是:
q = round(r / S + Z)
嗯,这里要注意:round 操作会带来精度损失。我在项目中遇到过,有些模型对舍入方式特别敏感,用 floor 和 round 结果能差 2% 的精度。
4.2 Scale(缩放因子)的数学本质
Scale 说白了就是「步长」。它决定了每个整数步长代表多大的浮点数变化。
计算公式很简单:
S = (r_max - r_min) / (q_max - q_min)
举个例子:
- 浮点范围:[-1.0, 1.0]
- 量化范围:[0, 255]
- 那么 S = (1.0 - (-1.0)) / (255 - 0) = 2.0 / 255 ≈ 0.00784
你想想看,这意味着每个整数步长代表约 0.00784 的浮点数变化。S 越小,精度越高,但能表示的范围也越小。
关键点:Scale 是浮点数,在推理时需要用浮点运算。但好在它是个常数,可以提前算好。
4.3 Zero-point(零点)的数学意义
Zero-point 是浮点数 0 对应的整数值。为什么需要它?
我个人的理解是:它解决了「偏移」问题。比如你的数据范围是 [-1.0, 2.0],对称范围是 [-1.0, 1.0] 的话,零点就不在中间了。
计算公式:
Z = round(q_min - r_min / S)
或者更直观的:
Z = round(-r_min / S) + q_min
举个例子:
- r_min = -1.0, r_max = 2.0
- S = (2.0 - (-1.0)) / 255 = 3.0 / 255 ≈ 0.01176
- Z = round(0 - (-1.0) / 0.01176) = round(85.0) = 85
这意味着浮点数 0 对应整数 85。如果数据是对称的,Z 通常接近 128(对于 8 位无符号)。
小技巧:我习惯在量化前先检查数据的分布。如果数据集中在 0 附近,Z 会接近 128;如果数据偏正或偏负,Z 会偏移。这个偏移量会影响量化误差。
4.4 对称量化 vs 非对称量化
这里有个重要的分支:对称量化和非对称量化。
| 类型 | 特点 | Z 值 | 适用场景 |
|---|---|---|---|
| 对称量化 | r_min = -r_max | Z = 0(或 128) | 权重(通常对称分布) |
| 非对称量化 | r_min ≠ -r_max | Z ≠ 0 | 激活值(ReLU 后全为正) |
我曾经在量化一个 MobileNet 时,对权重用了非对称量化,结果精度掉了 5%。后来改成对称量化,精度只掉了 0.5%。为什么?因为权重的分布通常是对称的,非对称量化反而引入了不必要的偏移误差。
4.5 量化误差的数学分析
量化误差主要来自两个方面:
- 舍入误差:round 操作带来的,最大误差为 0.5 * S
- 截断误差:超出 [r_min, r_max] 的值被截断,误差可能很大
举个例子:
// 假设 S = 0.01, Z = 0
// 浮点数 3.14159
q = round(3.14159 / 0.01 + 0) = round(314.159) = 314
// 反量化
r' = 0.01 * (314 - 0) = 3.14
// 误差 = 3.14159 - 3.14 = 0.00159
嗯,这个误差看起来不大。但如果你的数据范围很大,S 就会变大,误差也会变大。
避坑指南:我曾经在量化一个语音模型时,没注意输入数据的动态范围。结果有个通道的峰值是其他通道的 10 倍,导致 S 被拉得很大,其他通道的精度全毁了。后来我用了逐通道量化(per-channel quantization),才解决了这个问题。
4.6 实际应用中的选择
在 STM32 上做量化时,我一般遵循这几个原则:
- 权重:用对称量化,Z=0,计算简单
- 激活值:用非对称量化,因为 ReLU 后全是正数
- 偏置:用 32 位整数,不量化,或者用高精度量化
你想想看,如果权重和激活都用对称量化,那卷积计算就变成了整数乘加,效率极高。但激活值如果是对称的,有一半的量化范围就浪费了(因为 ReLU 后全是正数)。
所以,没有绝对的好坏,只有适合不适合。
4.7 小结
Scale 和 Zero-point 是量化的基石。理解它们的数学原理,你就能:
- 手动计算量化参数
- 分析量化误差的来源
- 选择合适的量化策略
下一章,我会讲如何在 STM32CubeAI 中实际配置这些参数,以及如何用代码验证量化效果。到时候咱们再细聊。