2. 模型量化基础
量化,说白了就是把模型从「高精度」搬到「低精度」的房子里住。
我刚开始接触量化时,觉得这玩意儿挺玄乎的。FP32好好的,为什么要换成INT8?后来在部署一个BERT模型到手机端时,模型死活跑不动,我才意识到——精度换速度,这买卖划算。
1.1 量化的数学原理
先看一个核心问题:怎么把FP32的数映射到INT8?
数学上就两种方式:对称量化和非对称量化。
对称量化
对称量化,映射范围关于0对称。公式很简单:
scale = max(|x_max|, |x_min|) / 127
x_int8 = round(x_fp32 / scale)
这里有个关键点:FP32的0,映射到INT8还是0。我习惯用对称量化,因为实现起来干净利落。
但有个坑——如果数据分布严重偏斜(比如全是正数),对称量化会浪费一半的表示范围。你想想看,INT8总共256个值,对称量化只用了127个,另一半白白空着。
非对称量化
非对称量化就灵活多了:
scale = (x_max - x_min) / 255
zero_point = round(-x_min / scale)
x_int8 = round(x_fp32 / scale) + zero_point
zero_point这个偏移量,让量化范围可以「平移」。我在项目中遇到过,ReLU后的激活值全是非负的,用非对称量化能多保留一倍精度。
核心区别一句话:对称量化省计算(zero_point=0),非对称量化省精度(充分利用表示范围)。
1.2 量化精度与性能的权衡
这里有个经典问题:量化后模型到底掉不掉点?
我的经验是:大模型掉点少,小模型掉点多。为什么?因为大模型参数冗余多,量化相当于「挤水分」。小模型本来就瘦,再挤就剩骨头了。
| 量化位宽 | 理论加速比 | 典型精度损失 | 适用场景 |
|---|---|---|---|
| FP32 | 1x | 0% | 训练、高精度推理 |
| INT8 | 2-4x | 0.5-2% | 大多数推理场景 |
| INT4 | 4-8x | 1-5% | 边缘设备、大模型 |
| 二值化 | 16x+ | 5-15% | 特定场景(如人脸检测) |
嗯,这里要注意:加速比不是线性的。INT8理论上快4倍,实际可能只有2倍。因为内存带宽、计算单元利用率都会影响。
我的建议:先做INT8量化,如果精度损失在1%以内,就别折腾了。如果超过2%,再考虑QAT或者混合精度。
1.3 PTQ与QAT的区别
量化有两种主流做法:PTQ(训练后量化)和QAT(量化感知训练)。
PTQ:模型训练完,直接量化。简单粗暴,但精度损失不可控。
QAT:在训练过程中模拟量化误差,让模型学会「适应」低精度。效果好,但需要重新训练。
我画了一张图,帮你理解两者的流程差异:
我个人习惯:先PTQ,不行再QAT。PTQ几分钟搞定,QAT可能要跑几天。别一上来就搞QAT,除非你时间多。
1.4 实际落地中的量化陷阱
量化落地,坑比想象的多。我踩过的,列几个给你:
陷阱一:校准数据集选错
我曾经用ImageNet的1000张图做校准,结果模型在真实场景下精度掉了5%。后来发现,校准数据必须和实际部署场景一致。你部署的是猫狗分类,就别拿风景图做校准。
陷阱二:逐层量化 vs 逐通道量化
逐层量化省事,但精度差。逐通道量化精度好,但计算复杂。我建议:权重用逐通道,激活用逐层。这是性价比最高的方案。
陷阱三:忽略BatchNorm融合
量化前一定要把BN层融合进卷积层。否则量化后的误差会放大。我记得有个项目,BN没融合,INT8模型直接崩了,输出全是NaN。
陷阱四:对称量化遇上全正激活
ReLU后的激活值全是非负的。用对称量化,一半的表示范围浪费了。这时候非对称量化能多保留一倍精度。我踩过这个坑,后来学乖了——先看数据分布,再选量化方式。
嗯,量化这东西,纸上谈兵容易,落地才见真章。我建议你从一个小模型开始,先跑通PTQ,感受一下精度变化。然后再尝试QAT,对比效果。别一上来就搞大模型量化,容易翻车。
最后一个小技巧:量化后的模型,一定要做端到端的精度验证。别只看单层误差,有时候单层误差很小,但累积起来就炸了。