一、背景:为什么大家几乎都会从 base_int16 开始?
在 QAT 项目中,只要遇到精度问题,工程师的第一反应通常是:
先上全 int16,看精度上限。
这是完全合理的。
原因:
int16 动态范围更大
量化误差更小
更接近浮点
能快速验证“模型是否具备量化可行性”
如果全 int16 精度仍不好,问题往往不在 bit-width,而在:
scale 分布异常
observer 未收敛
插桩位置不合理
数据分布问题
因此:
base_int16 是“精度上限探测工具”。
这一步是科学且必要的。
二、工程现实:最终目标往往是性能
但真实部署环境通常是:
延时受限
带宽受限
片上存储受限
在这种前提下:
全 int16 基本不可能成为最终部署形态。
所以工程上更合理的路径应该是:
以 base_int8 作为默认底座
对精度敏感区域做局部升级
这意味着:
int16 用来探上限
int8 用来做工程
这两个阶段目标不同。
三、真正的困难:从 base_int16 切回 base_int8
问题往往出现在这里。
当我们在 base_int16 下完成精度探索后,会得到大量细节信息:
哪些 layer 敏感
哪些 layer 需要 fix_scale
哪些模块 output 必须 int16
哪些 Conv / Matmul 必须 int16 输入
但当切换到 base_int8 时,会发现:
默认 ModuleNameTemplate 不同
默认 ConvDtypeTemplate 不同
默认 MatmulDtypeTemplate 不同
输出 dtype 传播链改变
结果:
相同 prefix 写法,生效行为完全不同。
这就意味着:
base_int16 的配置不能直接复制到 base_int8。
四、问题的本质:不要让 base 决定量化形态
量化系统本质是“分层覆盖系统”。
如果让 base 决定形态,你就会被 base 牵着走。
真正应该控制的是:
每个模块最终生效的 dtype 拓扑。
五、方法论框架:量化拓扑设计
整个方法可以抽象为五个阶段:
我们逐步展开。
六、第一阶段:全 int16 精度上限探测
典型配置:
目标:
验证量化可行性
建立精度上限参考
七、第二阶段:使用 GlobalFakequantSwitch 定位问题
无论哪种路径,都建议使用:
典型使用思路:
全局关闭 FakeQuant
单模块开启
或单模块关闭
确认:
精度损失是否来自 bit-width
是否来自 scale 更新
是否来自某个具体模块
这一步可以避免盲目升位宽。
八、第三阶段:基于模型结构识别敏感模块
量化配置必须依赖模型结构。
例如:
backbone 多为线性卷积 → int8 风险低
head 中 aggregation / attention → 敏感
必须回答:
哪些模块属于 backbone?
哪些属于 neck?
哪些属于 head?
哪些包含 matmul?
哪些包含 feature aggregation?
没有结构分析,就没有精准升级。
九、第四阶段:构建“等效量化拓扑”
核心思想:
默认 int8 + 精准 prefix 升级
Step 1:统一默认 base_int8
这是性能底座。
Step 2:定义敏感模块列表
Step 3:输出 dtype 升级
Step 4:Conv 输入升级
Step 5:Matmul 输入升级
十、等效性的关键点
如果你在 base_int16 下:
backbone output=int8
head output=int16
那么你必须保证:
在 base_int8 下通过 prefix 升级后,
每个模块最终 output dtype 完全一致。
验证方法:
打印每层最终 dtype
单层剔除测试
对比精度曲线
十一、fix_scale 的位置
fix_scale 与 dtype 是两个维度:
dtype 控制动态范围
fix_scale 控制 scale 是否锁定
某些 head 模块:
可能必须 int16
也可能必须 fix_scale
但不要把 fix_scale 当成“精度万能补丁”。
十二、工程调优路径建议
推荐流程:
全 int8 → 测性能
全 int16 → 测精度上限
GlobalFakequantSwitch 定位问题
结构分析敏感模块
构建统一 int8 base
prefix 升级
单层剔除
构建精度-性能 Pareto 曲线
十三、常见误区
❌ 误区1:int16 一定比 int8 精度高
实际很多 backbone 层 int8 几乎无损。
❌ 误区2:回退法可以长期维护
回退法适合探测上限,不适合工程维护。
❌ 误区3:忽略输出 dtype 传播
输出 dtype 会影响下游模块。
十四、最终总结
量化优化不是:
从 int16 往下退
从 int8 往上加
而是:
设计一个清晰、可迁移、可验证的量化拓扑结构。
当我们做到:
base 可替换
prefix 可迁移
最终 dtype 可验证
FakeQuant 可局部控制
我们就掌握了 QAT 的量化配置体系。
