嵌入式AI模型量化与MCU推理优化部署调试实战 - 第1节
1.1 什么是模型量化?
模型量化,说白了就是把模型里的高精度数字(通常是 float32)换成低精度数字(比如 int8)。你想想看,一个 float32 是 32 位,一个 int8 只有 8 位,这一下就压缩了 4 倍。
我刚开始接触量化时,总觉得这玩意儿会掉精度。后来在 STM32F4 上跑一个 2MB 的模型,死活塞不进 256KB 的 RAM。量化成 int8 后,模型直接缩到 500KB,跑起来了。嗯,从那以后我就再也不敢小看量化了。
量化的本质
量化的数学本质,就是一个映射关系:
// 浮点值 → 整数值
q = round(r / S) + Z
// 整数值 → 浮点值
r = (q - Z) * S
其中:
- r — 原始浮点值(float32)
- q — 量化后的整数值(int8/uint8)
- S — 缩放因子(scale),一个浮点数
- Z — 零点偏移(zero point),一个整数
就这么简单。一个线性映射,把无限连续的浮点空间,映射到有限离散的整数空间。
1.2 为什么需要量化?
这个问题我经常被问到。答案其实很直接:MCU 的资源太有限了。
三个硬理由
| 维度 | float32 | int8 | 优势 |
|---|---|---|---|
| 模型体积 | 100 MB | 25 MB | 缩小 4 倍 |
| 内存占用 | 256 KB | 64 KB | 缩小 4 倍 |
| 推理速度 | 100 ms | 25 ms | 快 2~4 倍 |
| 功耗 | 高 | 低 | 降低 30%~50% |
我在一个智能门锁项目里遇到过这种情况:客户要求人脸识别延迟小于 200ms,MCU 是 Cortex-M4,只有 128KB RAM。float32 模型跑一次要 350ms,直接超时。量化到 int8 后,延迟降到 80ms,还省出一半内存做其他功能。
1.3 量化的数学原理
量化分两种:对称量化和非对称量化。我一个个讲。
对称量化
对称量化的特点是:零点 Z = 0。也就是说,浮点 0 映射到整数 0。
// 对称量化公式
q = round(r / S)
r = q * S
// 缩放因子计算
S = max(|r_max|, |r_min|) / 127
举个例子:
// 假设浮点范围 [-3.0, 3.0]
S = max(3.0, 3.0) / 127 = 0.02362
// 浮点 1.5 → 整数
q = round(1.5 / 0.02362) = round(63.5) = 64
// 整数 64 → 浮点
r = 64 * 0.02362 = 1.5118
对称量化有个问题:如果数据分布不对称(比如全是正数),会浪费一半的整数范围。我踩过这个坑,一个 ReLU 后的激活值全是正的,用对称量化后精度掉了 5%。
非对称量化
非对称量化允许零点 Z 不为 0,可以偏移到任意位置。
// 非对称量化公式
q = round(r / S) + Z
r = (q - Z) * S
// 缩放因子计算
S = (r_max - r_min) / 255
Z = round(-r_min / S)
还是刚才的例子:
// 浮点范围 [0.0, 3.0]
S = (3.0 - 0.0) / 255 = 0.01176
Z = round(-0.0 / 0.01176) = 0
// 浮点 1.5 → 整数
q = round(1.5 / 0.01176) + 0 = round(127.5) = 128
// 整数 128 → 浮点
r = (128 - 0) * 0.01176 = 1.5053
你看,非对称量化把整个整数范围 [0, 255] 都用上了,精度比对称量化高了一倍。
两种量化对比
| 特性 | 对称量化 | 非对称量化 |
|---|---|---|
| 零点 Z | 固定为 0 | 可偏移 |
| 整数范围 | [-128, 127] | [0, 255] |
| 适用场景 | 权重(正负对称) | 激活值(分布任意) |
| 计算复杂度 | 低(无零点偏移) | 高(需处理 Z) |
| 精度损失 | 分布不对称时较大 | 较小 |
1.4 量化误差分析
量化一定会引入误差。为什么?因为从连续到离散,信息必然丢失。
误差来源
- 舍入误差:round() 操作会丢失小数部分
- 截断误差:超出量化范围的值被截断
- 量化噪声:整体精度下降导致的随机误差
我记得有一次调试一个语音识别模型,量化后准确率从 95% 掉到 82%。查了半天,发现是某个层的激活值范围特别大(-100 到 100),量化后大部分值都被截断了。后来做了范围裁剪,准确率回到了 93%。
1.5 知识体系总览
下面这张图把本章的核心知识点串起来了。我建议你多看几遍,把量化这件事的全局脉络理清楚。
1.6 本章小结
量化这件事,说难不难,说简单也不简单。核心就三句话:
- 量化是映射:把 float32 映射到 int8,用 S 和 Z 两个参数控制
- 量化是取舍:用精度换体积、速度、功耗
- 量化有套路:权重对称、激活非对称,这是工业标准