模型量化基础:PTQ与QAT——从调试现场的浮点误差说起
上周调一个端侧检测模型推理时发现某个关键层的输出张量在FP32和INT8版本下差异超过15%直接导致后续NMS误删了本该保留的边界框。盯着量化前后的权重分布直方图看了半小时突然意识到问题出在校准数据集的采样方式上——我们用了训练集的随机子集但里面恰好缺少了极端光照条件下的样本。这个坑让我决定系统梳理量化技术的底层逻辑毕竟在嵌入式场景里模型不仅要跑得快更要跑得稳。量化到底在量化什么模型量化的核心思想很简单用低精度数据类型通常是INT8近似表示高精度数据FP32。但魔鬼在细节里。以卷积层为例原始计算是FP32权重与FP32输入相乘量化后变成INT8权重与INT8输入相乘最后再通过反量化系数还原到FP32空间。这里的关键在于找到合适的缩放系数scale和零点zero point让INT8的256个离散值尽可能覆盖FP32数据的实际分布范围。常见的对称量化公式长这样# 量化过程scalemax(abs(weight_range))/127# 127是INT8正半轴最大值quantized_weightround(weight/scale)# 这里要四舍五入到最近整数# 反量化过程dequantized_weightquantized_weight*scale# 必然损失精度注意scale的计算方式如果直接取最大绝对值那些分布在外围的离群值会挤占主要数值区间的分辨率。去年我们在某款安防芯片上就遇到过这个问题某个注意力层的权重存在少量±10以上的极端值导致95%的权重被压缩到INT8的不到50个离散值里。PTQ静态量化的快与痛后训练量化PTQ不需要重新训练直接拿训练好的模型跑一批校准数据统计各层的输入输出范围。听起来很美好但实际工程中至少要处理三个难题第一是校准数据的选择。早期我们图省事直接用验证集的前100张结果部署到真实场景发现某类小目标的召回率暴跌。后来改成按场景类别分层采样确保每类至少有5个代表性样本。更稳妥的做法是收集实际场景的未标注数据虽然标注成本高但能避免分布偏移带来的量化误差。第二是量化粒度。逐层量化per-layer实现简单但精度损失明显逐通道量化per-channel对深度可分离卷积特别有效不过有些推理引擎不支持。去年给某款物联网设备做优化时发现其NPU只支持逐张量量化被迫调整了网络结构中的通道数分配。第三是敏感层处理。通常网络的首尾层对量化误差更敏感尤其是检测模型的预测头。我们的经验是保留最后三个卷积层为FP16在RK3588平台上实测精度只下降0.3%推理速度仍比全FP32快2.1倍。别迷信某些论文说的“全部INT8”实际部署时要看芯片指令集的支持情况。QAT动态量化的训练技巧量化感知训练QAT把量化误差纳入训练过程让模型提前适应低精度表示。PyTorch的torch.quantization模块提供了现成的QAT流程但有几个细节容易踩坑# 错误示例直接对预训练模型开启QATmodel.qconfigtorch.quantization.get_default_qat_qconfig(fbgemm)torch.quantization.prepare_qat(model,inplaceTrue)# 这样会导致第一个epoch的精度崩盘因为BN层的统计量还没稳定# 建议分三步走model.train()# 第一步先跑2-3个epoch不启用量化让BN层重新统计参数# 第二步插入伪量化节点但前向传播仍用FP32torch.quantization.prepare_qat(model,inplaceTrue)# 第三步微调5-10个epoch这时梯度会穿过量化模拟器QAT阶段的学习率要设得比原始训练小一个数量级我们通常用初始学习率的1/10。另外注意评估时一定要先调用convert方法转换模型曾经有同事忘记转换拿着带伪量化节点的模型测速度结果比FP32还慢。工程实践中的混合策略实际项目里很少纯用PTQ或QAT。我们的标准流程是先用PTQ快速验证基线精度如果关键指标下降超过2%就对敏感层启动QAT微调。对于资源受限的嵌入式设备还会加入以下策略权重聚类分析用K-means分析各层权重分布对均匀分布的层使用线性量化对双峰分布的层尝试对数量化部分DSP支持。激活值监控在校准阶段记录每层激活值的峰度kurtosis峰度高的层适当扩大量化范围避免截断过多尾部信息。交叉层补偿某层量化后误差较大时微调其前后层的缩放系数在相邻层间做误差分配。这个方法在MobileNetV3上把mAP提升了0.7%。写给刚入门的量化工程师量化不是魔法它本质是在速度、精度和硬件限制之间做权衡。刚开始建议从PTQ入手用TensorRT或OpenVINO的工具链快速走通全流程建立对量化误差的直觉。遇到精度损失大的情况先别急着调参画出每层权重的分布直方图看看是不是离群值在捣乱。芯片选型阶段就要考虑量化支持程度有些国产NPU只支持特定的量化格式比如非对称量化必须带zero point提前了解能省掉后期移植的麻烦。最后记住量化后的模型一定要在真实场景数据上测试实验室的干净数据会掩盖很多问题。模型量化像给网络做“瘦身手术”既要减掉冗余的精度脂肪又不能伤及功能筋骨。每次量化前多问自己这个模型最终跑在什么设备上部署环境的温度范围是多少内存带宽的瓶颈在哪里把这些工程约束考虑进去量化方案才能落地生根。