模型量化基础:从FP32到INT8的实战之路
各位同学,今天我们来聊聊模型量化。说实话,这可能是整个嵌入式AI部署中最关键的一环。我刚开始接触量化时,也觉得不就是把精度降低嘛,有什么难的?直到我在一个语音唤醒项目上栽了跟头——模型量化后精度掉了5个点,怎么调都回不来。后来才明白,量化不是简单的精度取舍,而是一门平衡艺术。
为什么需要量化?
先看一组数据。一个ResNet-50模型,FP32版本大概98MB。你把它量化到INT8,直接变成25MB。这还没完——推理速度能快2-4倍,功耗降低一大截。在嵌入式设备上,这差别就是「能跑」和「跑不动」的区别。
我个人的习惯是,拿到一个模型先看它的部署目标。如果是服务器端,FP16就够了。但如果是Cortex-M系列芯片,不好意思,INT8是唯一选择。你想想看,一个STM32只有几百KB的RAM,连FP32模型都装不下,不量化怎么玩?
FP32、FP16、INT8:精度与范围的博弈
先看一张表,直观感受下差异:
| 数据类型 | 位宽 | 表示范围 | 精度 | 典型场景 |
|---|---|---|---|---|
| FP32 | 32位 | ±3.4×10³⁸ | ~7位小数 | 训练、高精度推理 |
| FP16 | 16位 | ±6.5×10⁴ | ~3位小数 | GPU推理、移动端 |
| INT8 | 8位 | -128~127 | 整数 | 嵌入式、边缘设备 |
FP32的精度高,但代价是存储和计算开销大。FP16是折中方案,很多GPU原生支持,推理速度能翻倍。INT8则是最极端的压缩——把浮点数硬生生映射到256个整数上。
这里有个坑,我曾经踩过:FP16虽然位宽减半,但它的表示范围其实比FP32小很多。如果你的模型权重分布很广,直接转FP16可能会溢出。嗯,这时候就需要做范围裁剪了。
量化原理:从浮点到整数的映射
说白了,量化就是找一个映射函数,把浮点数x变成整数q:
q = round(x / scale) + zero_point
其中scale是缩放因子,zero_point是零点偏移。反量化就是:
x = (q - zero_point) × scale
就这么简单?对,核心逻辑就这么简单。但难点在于——scale和zero_point怎么选?
对称量化 vs 非对称量化
这是量化策略的两大流派。我画了张图,帮你理解:
对称量化:zero_point固定为0,浮点数的0映射到整数的0。好处是计算简单,很多硬件(比如NPU)原生支持。但问题是——如果数据分布不对称,比如ReLU后的激活值全是正数,那负数那半边就浪费了。
非对称量化:zero_point可以偏移,能覆盖[min, max]整个范围。对于ReLU后的激活值,非对称量化能把所有256个值都用在正数上,精度更高。
我在项目中遇到过这种情况:一个MobileNetV2模型,用对称量化精度掉了2%,换成非对称量化只掉了0.5%。但非对称量化在有些硬件上不支持,所以选型时一定要先看目标芯片的文档。
校准数据集:量化成败的关键
校准数据集是什么?说白了,就是用来「摸清模型脾气」的一批数据。量化时我们需要知道每一层激活值的分布范围,才能算出合适的scale和zero_point。
具体做法是:
- 准备几百到几千张有代表性的图片(或数据样本)
- 用FP32模型跑一遍推理,记录每一层的输出分布
- 根据分布统计出min、max、均值等统计量
- 用这些统计量计算量化参数
核心要点:校准数据集必须覆盖真实场景的数据分布。如果你用猫的图片做校准,然后去量化一个识别人脸的模型,那精度肯定崩。
我踩过的一个坑:有一次做语音关键词识别,校准集用了1000条干净录音。结果量化后模型在嘈杂环境下完全失效。后来我把校准集换成了带噪声的录音,问题就解决了。所以校准数据集的质量,直接决定了量化后的模型能不能用。
量化误差的来源
量化不是无损的,误差主要来自三个方面:
- 舍入误差:round操作会丢失小数部分
- 截断误差:超出表示范围的值被强行截断
- 累积误差:每一层的误差会逐层放大
实战技巧:我一般会先做一次「模拟量化」——在FP32模型上模拟INT8的计算过程,观察每一层的输出差异。如果某层误差特别大,就单独处理这层,比如保留FP16或者调整量化参数。
量化策略的选择建议
根据我的经验,可以这样选:
| 场景 | 推荐策略 | 原因 |
|---|---|---|
| 权重分布对称(如卷积层) | 对称量化 | 计算快,硬件支持好 |
| 激活值全正(如ReLU后) | 非对称量化 | 充分利用表示范围 |
| 硬件不支持非对称 | 对称量化+范围裁剪 | 兼容性优先 |
| 精度要求极高 | 混合精度(部分层FP16) | 关键层保留精度 |
注意:不要盲目追求INT8。如果你的模型在FP16下精度已经崩了,那INT8只会更糟。我建议先做FP16量化,确认精度可接受后再尝试INT8。
好了,这一章的内容就到这里。量化是个实践性很强的工作,光看理论是不够的。下一章我会带大家动手,用TensorRT和ONNX Runtime做一次完整的量化部署。到时候你们会发现,纸上谈兵和真刀真枪的差距有多大。