PyTorch 模型量化常见问题
训练环境
Docker 容器无法使用 Nvidia 资源?
可能原因:GPU Docker 环境未正确配置。
优先排查:优先检查 环境部署 中 GPU Docker 部分的说明。
处理建议:建议确认 Docker 启动方式、GPU 设备映射和驱动环境是否符合文档要求。
QAT 量化训练
Calibration 精度差,是否说明 QAT 精度大概率也会偏低?
可能原因:
-
对同一模型而言,Calibration 精度与 QAT 精度通常呈正相关关系。
-
不同模型对量化误差的敏感程度不同,因此这种相关性没有统一的判断指标。
优先排查:
-
优先检查 Calibration 精度是否已经明显低于预期。
-
进一步检查模型是否存在量化不友好的结构,例如高风险算子、共享模块或多输入分布差异过大。
-
如果已经开始 QAT,还应同步检查 quantized model 的精度,而不是仅观察 QAT model。
处理建议:如果 Calibration 精度已经明显偏低,建议优先回到 Calibration 阶段排查,不宜直接寄希望于 QAT 完全修复问题。
Calibration 做到什么程度,可以开始 QAT?
可能原因:
-
单纯调整校准参数,通常只能带来有限提升。
-
是否继续停留在 Calibration 阶段,应结合当前精度和一次小规模 QAT 试跑的结果共同判断。
优先排查:
-
优先检查 Calibration 精度与目标精度之间的差距。
-
可进一步进行一次小规模 QAT 训练,同时观察 QAT model 和 quantized model 的结果。
处理建议:
-
如果 Calibration 精度已经非常接近目标,继续调整校准参数通常仍有价值。
-
如果 QAT 精度高于 Calibration,但离目标仍有明显差距,建议继续留在 Calibration 阶段排查量化不友好的问题。
-
如果 QAT 精度反而低于 Calibration,建议优先检查 QAT pipeline 和训练策略,而不是继续盲目训练。
QAT 训练时的现象,是否应与 float 训练基本一致?
可能原因:
-
一般情况下,loss、精度等整体趋势应与浮点训练基本一致。
-
如果差异较大,通常说明 QAT pipeline、训练状态控制或量化配置存在问题。
优先排查:
-
优先检查 loss 曲线是否与 float 训练末期差异过大。
-
进一步检查
train() / eval()和set_fake_quantize()的状态切换是否正确。 -
同时确认是否正确加载了 Calibration 阶段的初始化参数,以及
prepare后的模型是否又被继续修改。
处理建议:如果训练现象与 float 明显不一致,建议优先排查 QAT pipeline 本身,而不是直接调整大量训练超参数。
量化模型精度异常,应优先查看哪些专题?
可能原因:QAT model 或 HBIR 模型精度不符合预期,往往涉及量化配置、训练策略或训练部署一致性中的一个或多个环节。
优先排查:
-
如果表现为精度下降、bad case 增多或定位范围不清晰,可优先查看 PyTorch 模型精度调优工具。
-
如果需要进一步进行量化调优,可继续查看 精度调优指导。
-
如果问题主要发生在导出、convert、compile 或上板阶段,可继续查看 部署一致性分析说明。
处理建议:建议先判断问题发生在训练阶段、导出阶段还是部署阶段,再选择对应专题继续排查。
QAT 初始 loss 很大、训练中出现 NAN / INF,应如何处理?
可能原因:
-
输入数据本身存在 NAN。
-
浮点模型尚未收敛。
-
未正确执行 Calibration 初始化。
-
学习率过大、训练策略不合适,或 fake quant / observer 状态配置异常。
优先排查:
-
优先检查输入数据是否含有 NAN / INF。
-
进一步检查浮点模型是否已经收敛。
-
进一步检查是否开启了 Calibration,以及是否正确加载了 Calibration 模型参数。
-
同时检查
model_check_result.txt和qconfig_dtypes.pt.py,确认图结构和 dtype 没有明显异常。 -
必要时再检查训练策略,例如学习率、优化器和梯度裁剪方式。
处理建议:
-
建议先确认输入数据没有异常值。
-
建议先确认浮点模型已经收敛,否则微小量化误差也可能放大成明显波动。
-
建议先完成 Calibration,以获得更稳定的初始系数。
-
如果学习率过大,可优先调低学习率,必要时增加梯度裁剪。
-
如果浮点训练使用了 OneCycle 等对学习率影响较大的策略,QAT 阶段通常更适合先切换为较稳定的 SGD 策略再验证。
QAT 精度不升反降,甚至比 Calibration 更差,应如何处理?
可能原因:
-
训练策略不合适。
-
BN 处理方式不匹配。
-
scale 更新方式不合理。
-
quantized model 精度也在同步下降。
优先排查:
-
优先同步检查 QAT model 和 quantized model 的精度,不要只观察 QAT model。
-
进一步检查 BN 策略是否与当前浮点训练方式一致。
-
进一步检查量化参数应固定还是继续更新。
-
如果问题在导出后进一步放大,可继续查看 部署一致性分析说明。
处理建议:
-
如果 QAT 精度低于 Calibration,建议优先检查训练策略、BN 处理方式和 scale 更新方式。
-
如果 quantized model 精度也同步下降,说明问题通常不只是训练表象,而是会真实影响后续部署效果。
开启多机训练后精度变差,应如何处理?
可能原因:开启多机训练后,总 batch size 成倍增大,但学习率等超参数未同步调整。
优先排查:
-
优先检查总 batch size 是否发生明显变化。
-
进一步检查 LR、weight decay 等超参数是否仍沿用单机配置。
处理建议:开启多机训练后,建议同步调整 LR 等超参数进行平衡,而不是直接沿用原配置。
Qconfig 是否需要用户干预?
可能原因:Qconfig 直接定义 activation 和 weight 的量化方式,如果对其基本作用缺少判断,后续排查容易失去依据。
优先排查:
-
优先确认当前使用的 qconfig 模板、量化算法和最终 dtype 配置是否符合模型与平台要求。
-
如需进一步了解配置方法,可参考 构建 QConfig。
处理建议:建议至少明确 activation 和 weight 的量化方式,以及当前使用的核心模板配置。当前支持 FakeQuantize、LSQ、PACT 等量化算法。
如何导出各阶段的 ONNX 模型?
确认当前需要导出的对象是 qat_model 还是 quantized_model,确认后可按如下方式分别导出 QAT 模型和 quantized model 的 ONNX:
int16 / fp16 配置没有按预期生效,应如何处理?
可能原因:
-
module_name配置错误。 -
配置被后续模板覆盖。
-
算子发生回退,导致最终 dtype 与预期不一致。
优先排查:
-
优先检查
module_name是否正确。该字段只支持 string,不支持按 index 索引。 -
进一步检查
model_check_result.txt、qconfig_dtypes.pt.py和qconfig_changelogs.txt,确认最终算子 dtype 是否符合预期。 -
如果平台策略本身仍不明确,可继续查看 构建 QConfig。
处理建议:
-
建议先确认配置命中的是正确模块。
-
如果已经配置 int16 / fp16,但最终结果没有生效,建议优先检查模板覆盖顺序和回退日志,而不是仅查看配置代码本身。
如何确认某一层是否开启了高精度输出?
可能原因:模型输出节点未正确配置为高精度输出。
优先排查:打印 qat_model 中对应层,检查该层是否包含 (activation_post_process): FakeQuantize。
例如 int32 高精度 conv 打印如下:
int8 低精度 conv 打印如下:
处理建议:
-
若没有
activation_post_process: FakeQuantize,通常说明该层为高精度输出。 -
若本应高精度输出却仍显示为低精度,建议优先检查 qconfig 配置和输出模板是否正确设置。
-
如果配置看起来正确但最终 dtype 仍不符合预期,建议继续检查
qconfig_dtypes.pt.py和qconfig_changelogs.txt。
QAT 与 quantized 模型精度不一致,应如何处理?
可能原因:
-
QAT 阶段无法完全模拟 HBIR 中的纯定点计算逻辑。
-
导出、convert 或查表转定点过程引入了额外误差。
优先排查:
-
优先验证 quantized HBIR 模型精度,而不是仅观察 QAT torch module。
-
如果导出后精度掉点,可先用
pre_export判断问题是否出在查表转定点阶段。 -
进一步查看 部署一致性分析说明 和量化精度调优工具中的逐层对比结果,例如
compare_per_layer_out.txt。
处理建议:
-
建议在 QAT 之后至少验证一次 quantized model 的精度。
-
如果 QAT 精度正常但 quantized 精度异常,建议优先按导出一致性问题处理,而不是继续盲目训练。
上板后出现掉点,应优先排查哪些环节?
可能原因:
-
quantized.bc 与 hbm 之间存在一致性问题。
-
前处理、输入域、颜色空间转换或部署链路引入了额外误差。
优先排查:
-
优先确认 quantized.bc 精度是否正常。
-
如果 quantized.bc 正常而 hbm 或上板结果掉点,优先查看 部署一致性分析说明。
-
同时检查输入数据格式是否与训练阶段一致,例如是否从 RGB 变成了 centered YUV444 / nv12。
-
如果更偏向部署侧问题,还应继续检查前处理、后处理、插入节点和板端输入输出适配是否一致。
处理建议:不宜直接将上板掉点归因于 QAT 训练本身,应先区分问题发生在 QAT、导出、convert、compile 还是板端输入准备阶段。
load calibration 之后,QAT 训练为什么权重参数不更新?
可能原因:
-
prepare放在 optimizer 定义之后。 -
fake_quant_enabled或observe_enabled状态不正确。 -
module 的
training状态不正确。
优先排查:
-
优先检查
prepare是否在 optimizer 定义之前。 -
进一步检查
fake_quant_enabled和observe_enabled是否为 1。 -
进一步检查 module 中的
training变量是否为True。
处理建议:
-
建议优先确认 QAT 模型结构和 optimizer 绑定的是同一份 prepare 后模型,再继续检查训练状态切换是否正确。
-
如果仍无法定位,可回看 Prepare 章节确认模型替换和训练状态是否符合预期。
辅助分支能否插入伪量化节点?
可能原因:辅助分支不用于部署,但却被一并纳入了全局 QAT 训练。
优先排查:
-
优先确认该分支是否确实属于部署上板路径。
-
进一步检查该分支的数据分布是否与主干其他分支存在明显差异。
处理建议:
-
一般仅建议对需要部署上板的模型部分插入伪量化节点。
-
辅助分支通常会增加训练难度,如果该分支与其他分支的数据分布差异较大,还会进一步增加精度风险,通常建议去除。
如何将地平线 gridsample 算子改写为 torch 公版实现?
可能原因:horizon_plugin_pytorch 中的 gridsample 算子与 torch 公版实现的 grid 定义方式不同。
优先排查:
-
优先确认当前
grid输入是否为 int16 类型的绝对坐标。 -
如果计划切换为
torch.nn.functional.grid_sample,还需确认是否已完成坐标归一化。
处理建议:horizon_plugin_pytorch 中的 gridsample 算子使用 int16 类型的绝对坐标作为 grid 输入,torch 公版实现使用 float32 类型的归一化坐标,取值范围为 [-1, 1]。从 torch.nn.functional.grid_sample 路径导入算子后,可通过如下方式完成归一化。
设置类错误
模型输出节点未设置为高精度输出,导致量化精度不符合预期,应如何处理?
可能原因:模型输出节点仍按默认低精度配置执行,导致结果不符合预期。
优先排查:优先检查输出节点对应的 qconfig 设置,以及是否启用了输出高精度相关模板优化。
错误示例如下。
假设模型定义如下:
处理建议:如果希望模型输出节点保持高精度,可通过 QconfigSetter 和模板优化方式进行配置,例如:
为什么某些模块无需量化,却设置了非 None 的 qconfig?
可能原因:前后处理、loss function 等本不需要量化的模块,被错误设置了 qconfig。
优先排查:优先检查这些模块是否确实属于部署路径。
处理建议:建议仅对需要量化的模块设置 qconfig。
没有正确设置 march,会带来什么问题?
可能原因:march 设置与实际部署处理器不一致。
优先排查:优先检查当前目标平台对应的 BPU 架构。
处理建议:应根据目标处理器选择正确的 march,例如 J6 需要使用 Nash。
方法类错误
模型输入使用 RGB 等非 centered YUV444 格式,为什么可能导致部署精度不一致?
可能原因:训练输入格式与 Horizon 硬件支持的输入格式不一致。
优先排查:优先检查训练输入格式是否与部署侧保持一致。
处理建议:建议从模型训练开始即直接使用 centered YUV444 作为网络输入。
为什么仅使用 qat model 做精测和训练监控,可能无法及时发现部署侧精度异常?
可能原因:QAT 阶段无法完全模拟 HBIR 中的纯定点计算逻辑,仅观察 qat model 结果可能掩盖后续部署侧误差。
优先排查:
-
优先补充 quantized model 或 quantized HBIR 模型的精度验证结果。
-
如果两者结果不一致,可回到 部署一致性分析说明 继续定位。
处理建议:建议在 QAT 训练过程中同步观察 quantized 方向的验证结果,而不是仅以 qat model 作为精测和监控依据。
算子类错误
为什么多次调用同一个 FloatFunctional() 成员会有问题?
可能原因:同一个 FloatFunctional 被多次调用时,会共享同一组量化参数,容易引入额外误差。
优先排查:优先检查 forward 中是否多次调用同一个通过 FloatFunctional() 定义的成员。
错误示例如下:
处理建议:不建议在 forward 中多次调用同一个 FloatFunctional() 变量,通常应拆分为多个独立成员。
Quantized 模型中部分算子未经过 calibration 或 QAT,为什么可能导致推理失败或部署精度异常?
可能原因:部分算子在定点阶段需要依赖 Calibration 或 QAT 获得真实量化参数。如果缺少前期量化过程,可能无法保证推理正确性和精度稳定性。
优先排查:
-
优先确认新增算子是否已在 Calibration 或 QAT 阶段参与量化。
-
如果该算子属于后处理或部署阶段新增节点,还需确认它是否属于允许直接添加的算子类型。
处理建议:Quantized 阶段并非完全不能直接添加算子,例如颜色空间转换等算子可按文档要求处理。但并非所有算子都适合直接添加,例如 cat 这类算子通常需要依赖 Calibration 或 QAT 阶段统计得到的真实量化参数。若需要在网络中增加类似算子,建议优先评估其量化路径是否完整。
模型类错误
浮点模型过拟合会影响 QAT 吗?
可能原因:浮点模型本身过拟合,导致输入稍有扰动就会引起明显输出变化,量化误差更容易被放大。
模型过拟合常见判定方法:
优先排查:
-
优先检查输入稍作变化后输出是否变化很大。
-
进一步检查模型参数赋值是否较大。
-
进一步检查模型 activation 是否较大。
处理建议:建议优先解决浮点模型过拟合问题,再继续进行 QAT。
模型导出
导出为什么会导致精度损失?
可能原因:QAT 阶段的查表仍然是前后带伪量化的浮点算子,导出后才真正转换为查表定点实现。
优先排查:
-
优先用
pre_export验证是否为查表转定点导致的精度损失。 -
进一步查看 部署一致性分析说明 章节,区分问题发生在 export、convert 还是 compile 之后。
可通过如下代码验证是否是查表算子导致了精度损失:
处理建议:如果导出后精度下降,建议先确认问题出现在 export 前后,还是出现在 convert / compile 之后,再决定下一步排查方向。
导出和训练代码不一致时,怎样减少代码侵入?
可能原因:模型中同时包含训练逻辑、验证逻辑和部署逻辑,导致 forward 路径不一致。
优先排查:
-
优先检查模型是否只包含部署逻辑。
-
如果不是,再检查 forward 是否已通过
training变量或部署标志做区分。
如果模型只包含部署逻辑,就不存在导出和训练代码不一致的问题。否则,可通过下面的方法处理:
处理建议:一般更建议通过 module 的 training 变量和自定义部署标志控制 forward 路径,而不是拆分为多个独立 forward。
