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:在训练过程中模拟量化误差,让模型学会「适应」低精度。效果好,但需要重新训练。

我画了一张图,帮你理解两者的流程差异:

FP32预训练模型 校准数据集 + 量化参数计算 INT8量化模型 PTQ:训练后量化 无需训练,速度快,精度可能下降 FP32预训练模型 插入伪量化节点(FakeQuant) 微调训练(Fine-tune) INT8量化模型 QAT:量化感知训练 需要训练,精度更高,耗时更长

我个人习惯:先PTQ,不行再QAT。PTQ几分钟搞定,QAT可能要跑几天。别一上来就搞QAT,除非你时间多。

1.4 实际落地中的量化陷阱

量化落地,坑比想象的多。我踩过的,列几个给你:

陷阱一:校准数据集选错

我曾经用ImageNet的1000张图做校准,结果模型在真实场景下精度掉了5%。后来发现,校准数据必须和实际部署场景一致。你部署的是猫狗分类,就别拿风景图做校准。

陷阱二:逐层量化 vs 逐通道量化

逐层量化省事,但精度差。逐通道量化精度好,但计算复杂。我建议:权重用逐通道,激活用逐层。这是性价比最高的方案。

陷阱三:忽略BatchNorm融合

量化前一定要把BN层融合进卷积层。否则量化后的误差会放大。我记得有个项目,BN没融合,INT8模型直接崩了,输出全是NaN。

陷阱四:对称量化遇上全正激活

ReLU后的激活值全是非负的。用对称量化,一半的表示范围浪费了。这时候非对称量化能多保留一倍精度。我踩过这个坑,后来学乖了——先看数据分布,再选量化方式。

嗯,量化这东西,纸上谈兵容易,落地才见真章。我建议你从一个小模型开始,先跑通PTQ,感受一下精度变化。然后再尝试QAT,对比效果。别一上来就搞大模型量化,容易翻车。

最后一个小技巧:量化后的模型,一定要做端到端的精度验证。别只看单层误差,有时候单层误差很小,但累积起来就炸了。