模型量化入门:FP32 vs FP16 vs INT8
各位同学好,我是你们的老朋友。今天咱们聊聊模型量化——这个在NPU推理优化里绕不开的话题。
说实话,我刚接触量化那会儿,也觉得不就是把精度降一降嘛,有啥好讲的?后来在项目里踩了不少坑,才明白这里面门道很深。今天我就把这几年的经验掰开了揉碎了讲给你听。
为什么需要量化?
先问个问题:你想想看,一个FP32的模型跑在NPU上,跟跑在GPU上有什么区别?
其实核心就两点——带宽和算力。
NPU的片上存储很有限,一般就几MB到几十MB。你一个ResNet-50的模型,FP32权重大概98MB,根本放不下。每次推理都要从DDR搬数据,带宽就成了瓶颈。
我做过一个实验:同样的模型,FP32推理延迟是15ms,换成INT8后直接降到4ms。为什么?因为数据量小了4倍,搬运时间少了,计算单元也能跑得更快。
核心结论:量化就是用更少的比特数表示数值,换来更快的推理速度和更低的功耗。
FP32 vs FP16 vs INT8:到底差在哪?
咱们先看一张表,直观感受一下差异:
| 数据类型 | 位宽 | 表示范围 | 精度 | 典型场景 |
|---|---|---|---|---|
| FP32 | 32位 | ±3.4×10³⁸ | 约7位有效数字 | 训练、高精度推理 |
| FP16 | 16位 | ±6.5×10⁴ | 约3位有效数字 | 混合精度训练、部分推理 |
| INT8 | 8位 | -128~127 | 整数精度 | NPU推理主力 |
你看,FP32范围最大,精度最高。但NPU上跑FP32,就像开着一辆大卡车在胡同里掉头——费劲。
FP16呢?范围小了很多,但精度还行。我有个项目做语音识别,FP16推理精度只掉了0.1%,速度却快了1.8倍。嗯,这个性价比挺划算。
INT8就更狠了。数据量直接压缩到原来的1/4,NPU的乘累加单元跑得飞起。但代价是——精度损失需要仔细处理。
我的经验:如果模型对精度不敏感(比如分类任务),直接上INT8。如果是检测或分割,建议先做FP16,再逐步压到INT8。
量化原理:到底是怎么压缩的?
量化说白了,就是找一个映射关系,把浮点数映射到整数上。
数学上很简单:
Q = round(r / S) + Z
其中:
- r 是原始浮点数
- Q 是量化后的整数
- S 是缩放因子(scale)
- Z 是零点偏移(zero point)
反量化就是反过来:
r = (Q - Z) × S
你看,就这么简单。但实际工程里,麻烦事全在怎么选S和Z上。
我曾经在一个项目里,直接用了全局的min/max来算S,结果模型精度掉了5%。后来改成逐通道量化,精度只掉了0.3%。
注意:量化不是简单的四舍五入。你想想看,如果原始数据分布不均匀,直接量化会导致大量信息丢失。
对称量化 vs 非对称量化
这两个概念,我建议你从零点位置来理解。
对称量化
对称量化里,零点Z=0。也就是说,浮点数的0映射到整数的0。
公式变成:
Q = round(r / S)
好处是计算简单,硬件实现方便。坏处是——如果数据分布不对称,比如ReLU后的激活值全是正数,那负数那半边就浪费了。
我记得有一次做MobileNet的量化,激活值全是0到6之间。用对称量化,量化步长S=6/127≈0.047,精度损失很小。但如果是权重,分布可能正负对称,对称量化就很合适。
非对称量化
非对称量化允许零点Z不为0。这样就能把浮点数的min/max完整映射到整数的min/max。
公式就是前面那个:
Q = round(r / S) + Z
好处是数据利用率高,精度损失小。坏处是计算稍微复杂一点,硬件上要多算一个偏移。
我建议你记住这个原则:
经验法则:
- 权重:用对称量化(分布通常对称)
- 激活值:用非对称量化(分布通常偏斜)
- 如果硬件支持,优先用非对称量化
一张图看懂量化流程
下面这张图是我自己画的,把整个量化流程串起来了:
实际项目中的避坑指南
讲完理论,咱们聊聊实战中容易踩的坑。
我曾经踩过的坑:
- 校准数据太少:有一次我只用了50张图片做校准,结果模型在测试集上精度掉了3%。后来改成500张,精度只掉了0.5%。建议至少用几百张有代表性的数据。
- 忽略异常值:数据里偶尔会有几个特别大或特别小的值,直接取min/max会导致量化步长过大。我习惯用百分位法,比如取1%和99%分位点。
- 逐层量化 vs 逐通道量化:逐层量化省事但精度差,逐通道量化精度好但计算量大。我的建议是——权重用逐通道,激活值用逐层。
一个小技巧:量化后一定要做精度验证。我一般会跑完整验证集,对比FP32和INT8的精度差异。如果差异超过1%,就要调整量化参数了。
总结一下
量化这件事,说白了就是用精度换速度。但怎么换、换多少,需要你根据实际场景来权衡。
我个人习惯的做法是:
- 先用FP32跑一遍,拿到精度基线
- 转FP16,看看精度损失
- 如果没问题,再压到INT8
- INT8精度不够?试试逐通道量化或混合精度
嗯,今天就先聊到这儿。量化这块内容很多,后面咱们还会讲到量化感知训练、混合精度量化这些进阶话题。你先把基础打牢,后面学起来就轻松了。
想要更多资料,联系可可