本节摘要:一次真实的 INT8 掉点事故:货架检测模型量化后平均精度掉了近七个点。本节按「背景、排查、定位、修复、复盘」完整还原处理过程,沉淀出一条可复用的掉点排错路径——本章前三节的方法论,在这单工单里全部派上了用场。
理论讲完,看一次实战。这单工单的价值不在结果(修复本身不难),而在排查路径的每一步「为什么先查这里」——把顺序学走,你遇到掉点时就不会从重装环境开始浪费时间。
场景是零售货架分析:检测模型负责识别SKU(单品包装盒),部署在门店边缘盒子的核显上。FP32 基线平均精度 52.4,用 4.1 节的标准 PTQ 流程压到 INT8 后,同一测试集掉到 45.7——掉了 6.7 个点。按第 4.1 节的经验表,检测模型通常掉点在一个点以内,这个数字明显出格。
工单里还有两条被忽视的线索,事后看都是关键:一是团队「顺手」用了公开数据集的图片当校准集,因为业务数据标注还没批下来;二是验收时只看了总平均精度,没看分类别指标。两条线索分别指向数据分布与故障定位两个排查方向。
掉点排查的第一原则是别盯着总指标。平均数会把结构性问题摊平——六个点的掉法,可能是所有类别均匀退化(数值路径问题),也可能是个别类别崩盘(数据分布问题)。两种病因的药方完全不同,所以第一步是拆指标:
| 排查步骤 | 动作 | 本案的发现 |
|---|---|---|
| 1. 拆分类别 | 分类别算精度,与 FP32 对比 | 三个类合计掉了五个点,其余正常 |
| 2. 拆场景 | 把掉点类别按图片来源分组 | 掉的样本几乎全是夜班光照图片 |
| 3. 逐层对质 | 逐层比较 FP32 与 INT8 输出偏差 | 某检测头的卷积层偏差显著偏大 |
| 4. 对账归因 | 把数据线索与层线索合议 | 敏感层恰好对夜班暗光激活范围敏感 |
第一步就锁定了「个别类别崩盘」,方向从数值算法问题转向数据问题。第二步实锤:掉点样本九成来自夜班时段。第三步从模型侧交叉验证——逐层对质的代码很朴素:
# 逐层对质思路:在相同输入下比较两版模型各层输出 fp32_req = fp32_compiled.create_infer_request() int8_req = int8_compiled.create_infer_request() for name in intermediate_names: # 按需注册中间输出 a = fp32_req.get_tensor(name).data b = int8_req.get_tensor(name).data rel = abs(a - b).max() / (abs(a).max() + 1e-9) if rel > 0.05: # 相对偏差阈值 print(name, round(rel, 3))
输出里那层「显眼包」卷积,正好位于三个掉点类别的特征通路上。数据线索与模型线索在此会合:校准集全是白天门店图,夜班光照下的激活范围超出了按白天数据定出的量化刻度——刻度不够用,数值被压扁,特征失真,三个类别应声掉队。
修复分两步,按成本从低到高执行。第一步换校准集:从业务数据里按时段分层抽样,白天与夜班按真实比例混合,重跑量化——总掉点从 6.7 收窄到 2.1。第二步处理残余:把对质暴露的敏感层排除在量化外(NNCF 支持按算子类型或名称忽略指定层),代价是该层回退高精度、吞吐小幅下降——最终掉点 0.8,性能实测收益保住了八成,工单关闭。
验证环节照搬 2.1 节的对拍纪律:FP32 与修复后 INT8 在含夜班的完整测试集上全量对拍,另加三天的门店灰度真实流量观察。灰度期间没有新增掉点类别,才正式推送全量。
这单工单的复盘沉淀出四条通用结论,值得贴在团队看板上。
掉点先拆指标再动手。总平均精度是给管理层看的,排错要用分类别、分场景的细粒度指标——平均数会撒谎,分布不会。
校准集是量化的一半生命。它必须来自目标部署环境,时段、光照、设备差异都要覆盖。用「手边现成」的数据集校准,等于替模型签了一份自己没读过的合同。💡 校准集不用大,几百条分层抽样的样本常常够用——要点在覆盖度,不在数量。
逐层对质是模型侧的听诊器。数据侧线索与模型侧线索要交叉验证:本案若只有数据线索,可能换完校准集就止步于 2.1;若只有层线索,可能误入调参的死胡同。
修复按成本排序。换数据、调预设、排除敏感层、混合精度、QAT——每一步都比下一步便宜一个量级,别跳级。⚠️ 唯独「重装环境换版本碰运气」不在清单上:那不是排查,是拖延。
把这四条与 4.1 节的工作流图拼起来,就得到本节的最终交付——一条掉点排错的标准路径:拆指标定方向、查数据找分布、逐层对质定位、按成本梯度修复、全量对拍加灰度收尾。下次遇到掉点,照着走即可。
这单工单还有一个值得单列的教训:最初的验收指标选错了。团队用总平均精度做唯一验收线,而货架分析的业务价值恰恰集中在「高价品类识别准确率」上——本案掉队的三个类别里有两个正是高价品类。也就是说,按业务口径看,这次量化的实际伤害比 6.7 个点更大。事故之后团队把验收指标改成双层:全局指标(平均精度)防系统性退化,业务重点指标(高价品类召回)防局部塌方,双层都要过线才算达标。指标设计的这一课与量化无关、与所有模型变更有关:验收指标是业务价值的投影,投影选错,工程再严谨也在守一个错的东西。把它写进 7.3 节工作流的阶段一——约束与验收线,就从源头对了。
修复的第二步「排除敏感层」在实战里有一笔容易漏算的账。被排除的层回退到高精度执行,意味着该层的输入输出要在整型与浮点格式间往返,插入额外的量化解量化节点——这些节点的开销发生在热路径上。本案排除两层后吞吐下降约一成五,在可接受范围;但如果为了抢救精度把敏感层排除到两位数,性能优势可能被蚕食到「不如不量化」。所以排除动作要有纪律:每次只排除当前对质确认的层,排除一轮测一轮性能与精度,用数据找平衡点;「先全排除保精度、再逐层放回来」是反向的稳妥玩法,适合精度压力特别大的场景。两种玩法都成立,共同的底线是排除清单要进版本管理——它是量化配置的一部分,丢了这个清单,下次重转就全部返工。
实录收尾,把评审时被问得最多的三个问题留给读者。追问一:为什么不直接上 QAT 一步到位?——QAT 需要训练管线与全量数据,本案 PTQ 修复只花了半天,为半天能解决的事动用训练资源是资源错配;QAT 的正确位置在 PTQ 排查到头仍不达标之后。追问二:掉点会不会是量化工具的问题?——可能性存在但优先级最低,工具问题在社区反馈里占的比例远小于数据问题;先查自己校准集与敏感层,最后才怀疑工具。追问三:这套排查路径对大模型权重压缩适用吗?——思路完全同构:拆指标(按任务类型)、查数据(提示分布)、逐层对质、按成本修复,5.2 节的混合位宽策略就是「排除敏感层」在大模型上的对应物。方法的复用性,正是把它写成实录的理由。
量化的事到此闭环。下一章换一个量级完全不同的对象:十亿参数起步的大语言模型怎么塞进边缘设备——你会看到本章的思路在那里以另一种形式重生。