量化基础回顾:FP16、INT8、INT4、FP8量化原理及其对精度的影响
聊精度损失排查,咱们得先把量化这件事儿掰扯清楚。说实话,我见过太多同学一上来就调校准集、试各种算法,结果精度崩了都不知道问题出在哪。根本原因?就是没搞懂每种量化格式到底在干什么。
今天这一章,咱们就把FP16、INT8、INT4、FP8这四种主流量化格式的底裤扒干净。我会结合我在实际部署中踩过的坑,帮你建立起对量化精度的直觉。
1. 量化到底在做什么?
说白了,量化就是用更少的比特数去表示一个数值。你想想看,FP32用32位存一个数,INT8只用8位。这中间差了4倍的内存带宽和存储开销。但代价呢?精度会损失。
为什么会这样?因为比特数少了,能表示的数值范围和精度都变小了。就好比用一把厘米尺去量头发丝,你只能估个大概。
核心公式:量化过程本质上是一个映射——把浮点数的范围压缩到整数范围里。
量化值 = round(浮点值 / scale) + zero_point
其中scale是缩放因子,zero_point是零点偏移。这两个参数决定了量化精度。
我在项目中遇到过一件事:有同学把scale算错了,结果模型输出全是NaN。排查了两天,最后发现是校准集里有一个异常大值把scale撑爆了。嗯,这种坑踩过一次就记住了。
2. FP16:半精度浮点
FP16是FP32的"小弟"。它用16位表示一个数:1位符号位,5位指数位,10位尾数位。
| 格式 | 总位数 | 指数位 | 尾数位 | 动态范围 |
|---|---|---|---|---|
| FP32 | 32 | 8 | 23 | ~10^38 |
| FP16 | 16 | 5 | 10 | ~10^4 |
FP16最大的问题是什么?动态范围太小。FP32能表示到10^38,FP16只能到10^4。这意味着什么?如果你的模型权重里有大于65504的数,直接溢出变成Inf。
我建议你在做FP16推理时,先检查一下权重的最大值。如果超过6万,就要小心了。我记得有一次部署BERT-large,有个层的权重最大值到了7万,FP16推理直接崩了。后来加了层归一化才解决。
个人经验:FP16对大多数CV模型是安全的,但对一些NLP模型(尤其是大模型)要格外小心。LayerNorm和Softmax的输出范围容易超标。
3. INT8:整数量化的主力
INT8是目前工业界最常用的量化格式。它用8位有符号整数表示数值,范围是[-128, 127]。你没看错,就这么窄。
所以INT8量化的关键就在于——怎么把浮点数范围压缩到这个小区间里。常用的方法有两种:
- 对称量化:zero_point=0,只计算scale。适合权重分布对称的情况。
- 非对称量化:有zero_point,可以处理偏移的分布。适合激活值。
你想想看,如果原始浮点数的范围是[-10, 10],那scale就是20/255≈0.078。每个浮点值乘以这个scale再取整,就变成INT8了。但问题是,如果有个离群值是100,那scale就变成200/255≈0.78,整个量化精度就全毁了。
避坑指南:我曾经因为没做离群值处理,INT8量化后的模型准确率从95%掉到了60%。后来用饱和截断法(saturation clipping)把离群值截掉,才恢复到93%。记住:INT8量化最怕离群值。
4. INT4:极致压缩的代价
INT4,每个数只用4位。范围是[-8, 7](有符号)或[0, 15](无符号)。这精度损失有多大?你自己算算,原来FP32有23位尾数,现在只剩4位了。
INT4量化通常用在什么地方?
- 模型权重存储(减少显存占用)
- 对精度不敏感的任务(比如某些推荐系统)
- 配合FP16混合使用(部分层INT4,部分层FP16)
说实话,我不建议在精度敏感的任务上直接用INT4。我在一个图像分类项目里试过,Top-1准确率掉了8个点。后来改用INT8+INT4混合量化,才把损失控制在2个点以内。
关键点:INT4量化通常需要分组量化(group-wise quantization)。比如每32个权重共享一个scale,这样能减少量化误差。TensorRT-LLM里默认就是这种策略。
5. FP8:新秀登场
FP8是最近两年才火起来的格式。它有两种变体:
- E4M3:4位指数,3位尾数。动态范围大,精度低。
- E5M2:5位指数,2位尾数。动态范围更大,精度更低。
FP8的好处是,它比INT8更灵活。因为是指数格式,它能表示更大的范围,同时在小数值区域保持一定精度。这在处理大模型的激活值时特别有用。
我记得在部署LLaMA-70B时,用FP8量化比INT8量化精度高了0.5个点。原因就是LLaMA的激活值分布很广,INT8的均匀量化搞不定,FP8的非均匀量化反而更合适。
我的建议:如果你在部署大模型(70B以上),优先考虑FP8。它比INT8精度好,比FP16省一半显存。但要注意,FP8的硬件支持还不完善,目前只有H100和B200原生支持。
6. 精度损失的核心原因
聊了这么多格式,咱们总结一下精度损失到底从哪来:
- 截断误差:量化时取整操作导致的误差。这是不可避免的。
- 溢出误差:数值超出表示范围,变成Inf或NaN。这是最致命的。
- 累积误差:多层量化误差叠加,导致最终输出偏差越来越大。
- 分布失配:校准集和实际推理数据的分布不一致,导致scale选错。
你想想看,一个100层的Transformer,每层损失0.1%的精度,累积下来就是10%的损失。这就是为什么有时候单层量化看起来没问题,但整个模型就崩了。
7. 知识体系总览
下面这张图是我自己整理的量化知识体系,帮你建立全局视角:
这张图把四种格式和精度损失原因串起来了。你从中心出发,根据模型类型和精度要求,选择合适的分支。然后对照底部的四大原因,逐一排查。
8. 实战建议
最后,给你几个我在项目中总结出来的实操建议:
- 先跑FP16基线:任何量化项目,先确保FP16推理精度没问题。FP16都崩了,就别谈INT8了。
- 检查权重分布:用histogram看一下权重的分布。如果有长尾,考虑饱和截断或分组量化。
- 逐层对比:量化后,逐层对比输出和FP32的差异。哪层偏差大,就重点处理哪层。
- 校准集要覆盖:校准集的数据分布要和实际推理数据一致。我见过有人用ImageNet校准集去量化一个医学影像模型,结果精度掉了15个点。
好了,这一章的内容就到这儿。量化原理是基础,但也是排查精度损失的起点。下一章咱们会深入校准集的选择和优化,到时候再聊。
公众号:蓝海资料掘金营,微信deep3321