征程 6 H/P 工具链 QAT 精度调优

一、QAT 调优流程

流程总览:

针对征程 6H/P 的硬件特性,以 int8+int16+fp16 的混合精度量化为主要调优配置,会增加较多的 fp16 设置来优化量化精度

注意:

征程 6H/P 上会用到更多 fp16 高精度和 GEMM 类算子双 int16 等的配置,为了配置方式更加简单灵活,QAT 量化工具提供了一套新的 qconfig 量化配置模板,具体使用方式和注意事项参考:

【地平线 J6 工具链入门教程】QAT 新版 qconfig 量化模板使用教程

调优原则:

如上是一个标准的对称量化公式,产生误差的地方主要有:

  1. round 产生的舍入误差。例如:当采用 int8 量化,scale 为 0.0078 时,浮点数值 0.0157 对应的定点值为 round(0.0157 / 0.0078) = round(2.0128) = 2,浮点数值 0.0185 对应的定点值为 round(0.0185 / 0.0078) = round(2.3718) = 2,两者均产生了舍入误差,且由于舍入误差的存在,两者的定点值一致。 对于舍入误差,可以使用更小的 scale,这样可以使得单个定点值对应的浮点值范围变小。由于直接减小 scale 会导致截断误差,所以常用的方法是使用更高的精度类型,比如:将 int8 换成 int16,由于定点值范围变大, scale 将减小。
  2. clamp 产生的截断误差。当 qmax * scale 无法覆盖需要量化的数值范围时,可能产生较大截断误差。例如:当采用 int8 量化,scale 为 0.0078 时,qmax * scale = 127 * 0.0078 = 0.9906,大于 0.9906 的值对应的定点值将被截断到 127。 对于截断误差,可以使用更大的 scale。scale 一般是由量化工具使用统计方法得到,scale 偏小的原因是校准数据不够全,校准方法不对,导致 scale 统计的不合理。比如:某一输入的理论范围为 [-1, 1],但校准或 qat 过程中,没有观测到最大值为 1 或最小值为 -1 的样本或观测到此类样本的次数太少。应该增加此类数据或者根据数值范围,手动设置固定 scale。在截断误差不大的情况下,可以调整校准参数,通过不同的校准方法和超参缓解截断误差。

因此,QAT 量化精度调优以减少上述两种误差为基本原则,下文将针对 QAT 每个阶段做调优介绍:

注意:

征程 6H/P 平台的浮点模型量化友好设计以及 QAT 模型改造等内容和征程 6E/M 一致,仍可参考该文章对应章节:

【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度调优

1.1 模型检查

完成模型改造和量化配置后,调用 Prepare 接口时会对模型做算子支持和量化配置上的检查,这些检查一定程度上反映了模型量化存在的问题。对于不支持的算子将以报错的形式提醒用户,一般有两种情况:

  1. 未正确进行模型的量化改造。Prepare 过程中 QAT 量化工具会对模型进行 trace 来获取完整的计算图,在这个过程中会完成算子替换等的优化,对于这些已替换的算子,输入输出类型如果是 torch.tensor 而非经过 QuantStub 转化后的 qtensor,则会触发不支持算子的报错,表现为 xxx is not implemented for QTensor
  2. 确实存在不支持的算子。工具链已支持业界大量的常用算子,但对于部分非常见算子的不支持情况,需考虑进行算子替换或者作为算子需求向工具链团队导入。

Prepare 运行成功后会在当前目录下自动保存模型检查文件 model_check_result.txtfx_graph.txt,建议参考下列解读顺序:

  1. 算子融合检查。算子融合作为 QAT 量化工具的标准优化手段,常见的融合组合为 Conv+ReLU+BN 和 Conv+Add 等,未融合的算子会在 txt 文件中给出,未按预期融合的算子可能是因为共享没有融合成功或者是 QAT 量化工具的融合逻辑变更(针对新版 qconfig 量化模板 enable_optimize=True 情况,见【地平线 J6 工具链入门教程】QAT 新版 qconfig 量化模板使用教程),需要检查代码,确认未融合的情况是否符合预期:
# 示例:未融合的Conv+Add算子
Fusable modules are listed below:
name       type------  -------------------------
model.view_transformation.input_proj.0.0(shared) 
<class'horizon_plugin_pytorch.nn.qat.conv2d.Conv2d'>
model.view_transformation._generated_add_0        
<class'horizon_plugin_pytorch.nn.qat.functional_modules.FloatFunctional'>

未融合的算子对模型性能会有一定影响,对于精度的影响需视量化敏感度具体分析,一般来说,Conv/Linear+ReLU+BN 可能会因为算子复用导致未融合,此时建议手动修改融合;在 OE 3.5.0 以及之后版本使用新 qconfig 模板下,Conv+Add 默认不会融合,可不修改

  1. 共享模块检查。一个 module 只有一组量化参数,多次使用将会共享同一组量化参数,多次数据分布差异较大时,会产生较大误差:
# 示例:该共享模块被调用8次
Each module called times:
name      called times
---------  --------------   
...
model.map_head.sparse_head.decoder.gen_sineembed_for_position.div.reciprocal                          
8

called times > 1 的模块可能有很多个,全部改写成非共享是一劳永逸的。对于修改简单且精度影响大的共享算子如 QuantStub,强烈建议取消共享;对于 DeQuantStub 算子,共享不会对模型精度产生影响,但是会影响 Debug 结果的分析,也建议取消共享,修改方式参考征程 6E/M“模型改造”章节。

例如下面的共享模块,量化表示的最大值为 128 * 0.0446799 ≈ 5.719,在第一次使用中,输出范围明显小于 [-5.719, 5.719],误差较小, 第二次使用中,输出范围超出 [-5.719, 5.719],数值被截断,产生了较大误差。两次数值范围的差异也造成了统计出的 scale 不准确,因此该共享模块必须修改

+-+-+-+-+-+-+--+-+-+-+-+|   | mod_name | base_op_type   | analy_op_type  | shape  | quant_dtype |  qscale |base_model_min | analy_model_min | base_model_max |   analy_model_max ||-+-+--+-+-+-+-+-+-+-+-+...| 1227 | model.map_head.sparse_head.decoder.gen_sineembed_for_position.div | horizon_plugin_pytorch.nn.div.Div  | horizon_plugin_pytorch.nn.qat.functional_modules.FloatFunctional.mul  | torch.Size([1, 1600, 128])| qint8  |  0.0446799 | 0.0002146 | 0.0000000 | 4.5935526 |  4.5567998 |...| 1520 | model.map_head.sparse_head.decoder.gen_sineembed_for_position.div | horizon_plugin_pytorch.nn.div.Div  | horizon_plugin_pytorch.nn.qat.functional_modules.FloatFunctional.mul | torch.Size([1, 1600, 128]) | qint8 |  0.0446799 | 0.0000000 | 0.0000000 |  6.2831225 |  5.7190272 |...

上面共享算子的修改方式可以参考:

class Model(nn.Module):def __init__(self, ) -> None:super().__init__()...self.steps = 2for step in range(self.steps):setattr(self, f'div{step}', FloatFunctional())def forward(self, data):...for step in range(self.steps):data = getattr(self, f'div{step}').div(x)...

对于不带权重的 function 类算子都可以参考上面的拆分方式,但是也存在部分共享算子或模块带有权重参数拆分起来比较复杂,是否需要拆分建议先根据量化敏感度进行分析。带有权重参数算子拆分时需要复制权重,拆分方式可以参考:

class Model(nn.Module):def __init__(self, ) -> None:super().__init__()...self.steps = 3self.conv0 = nn.Conv2d(...)shared_weight = self.conv0.weightshared_bias = self.conv0.biasfor step in range(1, self.steps):setattr(self, f'conv{step}', nn.Conv2d(...))getattr(self, f'conv{step}').weight = shared_weightgetattr(self, f'conv{step}').bias = shared_biasdef forward(self, data):...for step in range(self.steps):data = getattr(self, f'conv{step}')(x)...

上述共享算子修改生效后,在 model_check_result.txt 文件中可见到无该算子共享相关的信息:

# 修改生效后下面信息将不再显示
Modules below are used multi times:
name      called times
------  --------------
xxxxx                2

此外,未调用的模块也会在文件中体现,called times 为 0,当 Calibration/QAT/模型导出出现 miss_key 时,可以检查模型中是否有模块未被 trace。

  1. 量化配置检查。txt 文件中会给出模型量化精度的统计信息:
# 算子输入量化精度统计input dtype statistics:+---+--+--+--+| module type                                                                |   torch.float32 |   qint8 |   qint16 ||---+---+--+--+| <class 'horizon_plugin_pytorch.nn.qat.stubs.QuantStub'>                    |             290 |      15 |        0 || <class 'horizon_plugin_pytorch.nn.qat.linear.Linear'>                      |               5 |     117 |        9 || <class 'horizon_plugin_pytorch.nn.qat.stubs.DeQuantStub'>                  |               0 |       8 |        0 |...# 算子输出量化精度统计
output dtype statistics:+---+--+--+--+| module type                                                                |   torch.float32 |   qint8 |   qint16 ||---+--+--+--+| <class 'horizon_plugin_pytorch.nn.qat.stubs.QuantStub'>                    |               0 |     123 |      182 |...# 使用fp16量化精度的算子,量化精度统计+---+--+--+--+--+| module type                                                                |   torch.float32 |   qint8 |   qint16 |   torch.float16 ||-----+--+--+--+--|| <class 'horizon_plugin_pytorch.nn.qat.stubs.QuantStub'>                    |              34 |       0 |        0 |               0 || <class 'torch.nn.modules.padding.ZeroPad2d'>                               |               0 |      11 |        0 |               0 || <class 'horizon_plugin_pytorch.nn.qat.functional_modules.FloatFunctional'> |              48 |      14 |        9 |              50 |...

重点检查的信息有:

  • <class 'horizon_plugin_pytorch.nn.qat.stubs.QuantStub'> 的 input dtype 应为 torch.float32,对于 qint8 或者 qint16 的 input dtype,一般是冗余的 QuantStub 算子可以改掉,不会对精度产生影响但可能会对部署模型性能有影响(算子数量)
  • 正常来说模型中的算子不应出现 torch.float32 的输入精度(除下文 c 情况),如上图的 <class 'horizon_plugin_pytorch.nn.qat.linear.Linear'>,需要检查是否漏插 QuantStub 未转定点,未转定点的算子在导出部署模型时会 cpu 计算从而影响模型性能。对于模型中的一些浮点常量 tensor,工具已支持自动插入 QuantStub 转定点,建议获取最新版本
  • 对于 GEMM 类算子(Conv/Matmul/Linear)作为模型输出时支持高精度输出(征程 6E/M 支持 int32 输出,征程 6B/H/P 支持浮点输出),体现到这里则是 <class 'horizon_plugin_pytorch.nn.qat.stubs.DeQuantStub'> 的 input dtype 应为 torch.float16torch.float32,对于 qint8qint16 输入的 DeQuantStub 需要检查是否符合高精度输出的条件,符合条件但未高精度输出的需修改。此外对于下面左图的结构,也建议优化为右图结构来保证高精度输出的优化

  • qint8 和 qint16 算子的占比,可以协助判断是否配置全 int16 生效;torch.float16 算子的占比,可以协助判断是否配置 fp16 生效

txt 文件同时会给出逐层的量化配置信息:

# 激活逐层qconfig
Each layer out qconfig:+--+--+--+--+--+--+| Module Name| Module Type | Input dtype | out dtype | ch_axis | observer ||--+--+--+--+--+---|# 固定scale| quant | <class 'horizon_plugin_pytorch.nn.qat.stubs.QuantStub'>                    | [torch.float32] | ['qint16']| -1  | FixedScaleObserver(scale=tensor([3.0518e-05], device='cuda:0'),zero_point=tensor([0], device='cuda:0')) |# QAT训练激活scale更新| mod2.1.attn.q | <class 'horizon_plugin_pytorch.nn.qat.conv2d.Conv2d'>  | ['qint16']  | ['qint16'] | -1 | MinMaxObserver(averaging_constant=0.01) |# QAT训练激活scale不更新| mod2.1.FFN.out_conv.1.0| <class 'horizon_plugin_pytorch.nn.qat.conv2d.Conv2d'> | ['qint16']| ['qint16']| -1| MinMaxObserver(averaging_constant=0)  |# 激活fp16 qconfig| bev_fusion.multi_view_cross_attn.32.global_cross_window_attn._generated_add_2[add]| <class 'horizon_plugin_pytorch.nn.qat.functional_modules.FloatFunctional'> | [torch.float16, torch.float32]                     | [torch.float16] | FakeCast(dtype=torch.float16, min_val=-0.0009765625, max_val=0.0009765625)  | |# 权重逐层qconfig
Weight qconfig:+-----+----+-----+------+---+| Module Name | Module Type | weight dtype|ch_axis|observer ||---+-------+----+----+---|| mod1.0 | <class 'horizon_plugin_pytorch.nn.qat.conv2d.Conv2d'> |qint8 | 0 | MinMaxObserver(averaging_constant=0.01) |

重点检查的信息有:

  • 每层算子的输入输出 dtype、权重的 dtype,是否符合量化配置;若和量化配置不符合,比如配置了 int16,但是算子显示为 int8,则需要关注下算子回退信息,例如在旧模板下 Conv+Add 融合时 Conv 不支持 int16 输入,会导致前序算子输出回退到 int8。新的 qconfig 量化配置模板下算子回退过程需查看 qconfig_changelogs.txt,详细参考:https://developer.horizon.auto/blog/13112
  • 配置了 fix scale 的算子,是否正确显示 FixedScaleObserver 信息,scale 值是否正确
  • 逐层算子的 observer 是否正确:权重默认 MinMaxObserver,QAT 校准时激活默认 MSEObserver,QAT 训练时激活默认 MinMaxObserver
  • 若为 QAT 训练阶段且配置了固定校准的激活 scale,查看 averaging_constant,判断是否生效,生效为 averaging_constant=0(即不更新 scale),默认为 0.01(更新 scale)

对于 fx_graph.txt,可以从中获取到模型中 op/module 的上下游调用关系,例如当存在算子 called times 为 0 未被调用的情况,可以通过 Graph 定位到上下文算子从而定位未被调用的原因(通常因为在 init 函数中定义了但在 forward 中没有调用,也可能存在逻辑判断或循环次数变化的情况);此外当出现导出的部署模型(bc 模型)精度异常,也可以通过 Graph 信息来排查是否是导出计算图改变导致的

# 模型Graph图结构信息
Graph:
opcode       name        target            args           kwargs
----         -----       -------           -------        -------
placeholder    input_0    input_0              ()         {}
call_module    quant       quant            (input_0,)     {}
call_module  traj_decoder_src_proj_0_0  traj_decoder_src_proj.0.0                                             (quant,)  {}
call_function  scope_end    <function Tracer.scope_end at 0x7f4477d7dc60>   ('traj_decoder_src_proj.0',) {}
call_function  __get__    <method-wrapper '__get__' of getset_descriptor object at 0x7f460922b800>  (traj_decoder_src_proj_0_0,) {}
call_function  __getitem__       <slot wrapper '__getitem__' of 'torch.Size' objects>     (__get__, 0)   {}
call_function  __getitem___1      <slot wrapper '__getitem__' of 'torch.Size' objects>   (__get__, 1)  {}
call_function  __getitem___2     <slot wrapper '__getitem__' of 'torch.Size' objects>   (__get__, 2)   {}
call_function  __getitem___3      <slot wrapper '__getitem__' of 'torch.Size' objects>   (__get__, 3) {}
call_function  permute     <method 'permute' of 'torch._C.TensorBase' objects>   (traj_decoder_src_proj_0_0, 0, 2, 3, 1)  {}...

重点关注的 Graph 信息:

  • opcode 为算子调用类型
  • name 为当前算子名称,需注意和 model_check_result.txt 中的 module.submodule 名称区别
  • target 为算子输出
  • args 为算子输入

1.2 QAT 校准

1.2.1 int8+int16+fp16 混合精度调优

如果模型中吸收了前后处理的相关算子和操作,这部分默认需要 fp16 精度进行量化

对于 int8+int16+fp16 混合精度而言,主要的量化配置如下(配置方式参考【地平线 J6 工具链入门教程】QAT 新版 qconfig 量化模板使用教程):

  • 基础配置: TAE 算子(Conv/Matmul/Linear)双 int8、其他算子 fp16
  • 精度优化配置: TAE 算子(Conv/Matmul/Linear)单 int16(部分双 int16)、其他算子 fp16
  • 精度上限配置: TAE 算子(Conv/Matmul/Linear)双 int16、其他算子 fp16
  • 性能上限配置: 全局 int8,建议仅在测试模型最优性能(精度无保证)或作为高精度耗时优化的对比参考时配置

同样的对于较难量化的模型而言,初始应使用精度上限配置,在这个配置下解决量化流程可能的问题,优化量化风险较大的算子/模块,往往通过 Debug 工具进行定位,但在使用 Debug 工具较难定位到量化瓶颈时,可以使用分步量化的小技巧(参考本文最后章节"调优技巧"),也即对选中算子取消量化后对比精度,如定位到前后处理的算子/模块产生明显掉点,建议从模型中剥离;定位到模型中算子/模块,可以使用设置 fix_scale 和拆分共享模块等方式,或者从量化友好角度修改浮点模型(参考征程 6E/M 量化调优对应章节:【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度调优

精度上限配置下的模型较难满足部署侧的延时要求,因此解决掉上述的量化瓶颈后需要回归到基础配置。在基础配置上通过敏感度的分析结果,增加 TAE 的 int16 算子,也就是精度优化配置。在基础配置和精度优化配置下精度达标的模型,视延时情况可能需要进一步做性能优化,主要方向为:

  1. 基础配置下,回退 fp16 性能瓶颈算子到低精度 int8
  2. 精度优化配置下,回退双 int16 的 TAE 算子到单 int16,回退 fp16 性能瓶颈算子到低精度 int8

精度优化配置下如果 int16 算子比例已超出部署预期但精度仍有一定差距,则可以考虑回退部分 int16 算子后尝试 QAT 训练;基础配置下精度表现距离浮点差距较小(量化精度/浮点精度 > 90%,经验值),直接尝试 QAT 训练,在 量化精度/浮点精度 >= 95%(经验值)的情况下,建议优先尝试固定校准激活 scale 的 QAT 训练(仅调整权重感知量化误差)

对于不同精度配置下的 QAT 校准,都有一些校准超参可以调整,需要用户结合具体模型去做调参优化,其中主要的参数有校准数据的 batch size、校准的 steps,详细的参数参考:

  1. 基础调优手段:调优指南_基础调优手段
  2. 高级调优手段:调优指南_高级调优手段

由于征程 6H/P 平台使用了较多浮点 FP16 精度,该精度下数值范围超限场景有以下常见的优化方法和优缺点总结:

image

总结:

int8+int16+fp16 混合精度调优的重点应放在 TAE 双 int16+ 其他算子 fp16 的调优上,这里需要把使用问题,量化不友好模块等等各种千奇百怪的问题都解决,看到模型的精度上限,然后根据模型部署的性能要求进行 TAE int8 和 int16 混合精度的调优,最后对非 TAE 算子进行 int8+fp16 混合精度的调优,最终达成部署精度和部署性能的平衡。

1.2.2 Debug 产出物解读

征程 6H/P 平台 Debug 产出物的解读和征程 6E/M 一致,仍可参考该文章对应章节:【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度调优

Badcase 调优

对于实车或回灌反馈的可视化 badcase,利用 Debug 工具的调优流程为:

1.3 QAT 训练

大部分模型仅通过 QAT 校准就可以获得较好的量化精度,对于部分较难调优的模型,以及还需要继续优化误差类指标的模型,通常校准设置的高精度比例导致延时超过部署上限,但精度仍无法达标,这种情况可以尝试 QAT 训练来获得满足预期性能-精度平衡的量化模型。

根据前文所述,在 QAT 校准 量化精度/浮点精度 >= 95%(经验值) 的情况下,充分利用校准阶段较好的激活量化参数,优先尝试固定校准激活 scale 的 QAT 训练(仅调整权重感知量化误差),设置方式具体参考征程 6E/M 精度调优的“模型改造”章节:【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度调优

参考浮点训练,QAT 训练在大部分配置保持和浮点训练一致的基础上,也涉及到部分超参的调整来提升量化训练的精度,例如 QAT 的学习率、weight_decay、迭代次数等,详细的参数调整策略参考:

  1. 基础调优手段:调优指南_基础调优手段
  2. 高级调优手段:调优指南_高级调优手段

浮点和 QAT 训练中都涉及到对 BN 的状态控制,在浮点训练中可能会采用 FreezeBN fine-tune 的方式来提升模型精度,在多任务训练中也会采用 FreezeBN 的技巧。因此在 QAT 训练中,提供了 FuseBN 和 WithBN 两种训练方式:

  1. FuseBN 即在 Prepare 后,QAT 训练前将 BN 的 weight 和 bias 吸收到 Conv 的 weight 和 bias 中,在训练过程中不再单独更新,这一吸收过程是无损的。FuseBN 也是 QAT 默认的训练方式。
  2. WithBN 则是在 QAT 训练阶段保持 Conv+BN 不融合,带着 BN 进行训练,BN 的参数单独更新,在训练结束后转成部署模型时再做融合。浮点训练阶段如果采用了 FreezeBN 的训练方式,QAT 训练时需设置 WithBN 来对齐浮点训练方式,设置方式如下:
from horizon_plugin_pytorch.qat_mode import QATMode, set_qat_mode
set_qat_mode(QATMode.WithBN)

通过观察 QAT 训练过程的 Loss 变化来初步判断 QAT 训练的量化效果,一般来说和浮点最后的 Loss 结果越接近越好,Loss 过大可能难以收敛,Loss 过小可能影响泛化性,对于异常的 Loss 建议的优化手段:

  1. 异常 INF 和 NAN 的 Loss 值,或者初始 Loss 极大且无收敛迹象,按如下顺序排查:
    1. 去掉 prepare 模型的步骤,用 qat pipeline finetune 浮点模型,排除训练 pipeline 的问题,Loss 如果仍异常,需要检查训练链路的配置如优化器 optimizer 和 lr_updater 等
    2. 保持当前 QAT 训练配置,只关闭伪量化节点后观察训练的 Loss 现象,理论上和浮点有微小差异
from horizon_plugin_pytorch.quantization import set_fake_quantize, FakeQuantState
...
set_fake_quantize(qat_model, FakeQuantState._FLOAT)
train(qat_model, qat_dataloader)
  1. 在排查完链路问题后出现初始 Loss 较大,有收敛迹象但收敛较慢,这种情况可以尝试调整学习率,延长 QAT 迭代次数,因为 QAT 训练本质上是对已收敛浮点模型的 fine-tune,本身存在一定的随机性,用较大的学习率可以快速波动到一个理想精度(依赖一些中间权重的评测)
  2. 对于少数模型,QAT 训练以及尝试了多次超参调整后精度仍无法达标,建议回归 QAT 校准阶段增加少量高精度算子(增加 GEMM 类算子 int16,以及其他算子增加 FP16)、回归浮点结构检查是否还存在量化不友好的结构如使用了大量 GeLU 等(参考征程 6E/M 精度调优对应章节【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度调优

1.3.1 QAT 训练效率

由于 QAT 训练过程需要感知模型量化所带来的损失,因此模型中会被插入必要的量化相关的节点:数据观测节点 Observer 和伪量化节点 FakeQuant。数据观测节点会不断统计模型中数据的数值范围,伪量化节点会根据量化公式对数据做模拟量化和反量化,两者都会存在开销,此外就是 QAT 工具内部会对部分算子例如 LN 层做拆分算子的实现,因此相同配置下的 QAT 训练效率是会略低于浮点训练效率,具体还和模型参数规模、算子数量等有关。

对于用户可明显感知到的 QAT 训练效率降低,建议的优化手段有:

  1. 使用 QAT 工具提供的算子,这些算子优化了训练效率,例如 MultiScaleDeformableAttention(参考手册
  2. 更新到最新的 horizon-plugin-pytorch 版本,新版本会有持续的 bug fix 和新特性优化,如模型中某些结构或者算子训练耗时增加明显,可以向工具链团队导入

1.4. 模型导出部署

完成 QAT 精度调优后得到的模型仍是 PyTorch 模型,需要使用简单易用的接口来一步步导出编译成部署模型:PyTorch模型 -> export -> convert-> compile

export 得到 qat.bc; convert 得到 quantized.bc; compile 得到 hbm

由于导出生成物中计算差异的存在,对于每个生成物需简单验证其精度,可通过单张可视化或 mini 数据集,过程中如存在精度掉点,请参考【地平线 J6 工具链进阶教程】J6 E/M 工具链 QAT 精度一致性问题分析流程

二.调优技巧

2.1 分部量化

下面这种方式仅适用于 Calib 阶段,QAT 阶段因为模型已经适应了量化误差,关闭伪量化精度无法保证

from horizon_plugin_pytorch.utils.quant_switch import GlobalFakeQuantSwitch 
class Model(nn.Module):     def _init_(...):     def forward(self, x):         x = self.quant(x)         x = self.backbone(x)         x = self.neck(x)         GlobalFakeQuantSwitch.disable() # 使伪量化失效         # --------- float32 ---------         ​x = self.head(x)         # ---------------------------         ​GlobalFakeQuantSwitch.enable() # 重新打开伪量化         return self.dequant(x)

2.2 部分层冻结下的 QAT 训练

模型 QAT 训练时,要求模型为 train() 状态,此时若部分层冻结,则需要对应修改状态,参考代码如下:

from horizon_plugin_pytorch.quantization import (QuantStub,prepare,set_fake_quantize,FakeQuantState,)qat_model = prepare(model, example_inputs=xxx, qconfig_setter=(xxx))
qat_model.load_state_dict("calib_model_ckpt.pth")qat_model.train()# 关闭requires_grad可固定权重不更新,但Drop、BN仍然会更新for param in qat_model.backbone.parameters():param.requires_grad = False# 配置eval()可固定Drop、BN不更新,但不会固定权重,因此两者需要配合使用
qat_model.backbone.eval()
set_fake_quantize(qat_model.backbone, FakeQuantState.VALIDATION)#配置head的FakeQuant为QAT状态
set_fake_quantize(qat_model.head, FakeQuantState.QAT)

2.3 Calib/QAT 过程 NaN 值定位

出现 NaN 值可通过下面的修改在 calib/qat forward 过程中报错,从而定位到具体的算子:

from horizon_plugin_pytorch.quantization.fake_quantize import FakeQuantize
FakeQuantize.check_nan_scale='forward'#默认为save,在torch.save时检查是否有nan,有nan会报错
qat_model = prepare(model, (input), default_qat_qconfig_setter)

常见的可能出现 NaN 值的结构:

Multi-head Attention 的 attn mask,需要手动做数值的 clamp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1188899.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

即将开营 | 人工智能测试开发训练营,免费开放试听名额

关注 霍格沃兹测试学院公众号&#xff0c;回复「资料」, 领取人工智能测试开发技术合集大厂经验实战项目&#xff0c;三个月打造AI时代最稀缺的复合型测试专家“昨天刚上线的新功能&#xff0c;ChatGPT已经自动生成了完整的测试用例。”“视觉识别自动发现了UI布局的3处异常&am…

前端有多少人使用过jQuery,jQuery 近期发布重大更新4.0,快来看看更新内容是否与您有关!

2006 年 1 月 14 日&#xff0c;John Resig 在纽约市的 BarCamp 推出了一个名为 jQuery 的 JavaScript 库。 现在&#xff0c;20 年后&#xff0c;jQuery 团队正式发布了 jQuery 4.0.0 版本。 经过漫长的开发周期和几次预发布&#xff0c;jQuery 4.0.0 带来了许多改进和现代化…

太牛批了,局域网管理神器

今天给大家推荐一款不错的局域网共享软件&#xff0c;它可以帮助在局域网环境里面共享文件夹和打印机&#xff0c;有需要的小伙伴可以下载收藏一下。 局域网共享精灵企业版 无弹窗免费使用 这款软件可以帮助你快捷高效的在局域网内实现文件共享和打印机共享的操作&#xff0c;…

收藏!为什么 RAG 比微调更适配企业场景?

为什么 RAG 比微调更适合企业&#xff1f;你有没有发现&#xff0c;如今的AI早已跳出“问答机器”的范畴&#xff0c;变得愈发“懂业务”&#xff1f; 它能快速拆解公司内部的规章制度&#xff0c;精准标注法条修订的关键节点&#xff0c;甚至能从密密麻麻的财务报表中抓取核心…

2026 程序员生存指南:Cursor 跌落神坛?这 6 款 AI 编码神器,谁才配做你的主力?(附深度横评表)

摘要&#xff1a;2026 年&#xff0c;AI 编码工具已从“玩具”进化为“数字员工”。当 Cursor 不再是唯一选择&#xff0c;国产 Trae 强势崛起&#xff0c;Claude 杀入终端&#xff0c;我们该如何抉择&#xff1f;本文通过硬核参数对比表与实战决策树&#xff0c;帮你选出那个能…

2026学生党省钱降AI攻略:免费和低价工具推荐

2026学生党省钱降AI攻略&#xff1a;免费和低价工具推荐 TL;DR&#xff1a;学生党预算有限&#xff0c;但免费工具大多是坑。最省钱的正规方案是率零&#xff08;3.2元/千字&#xff09;&#xff0c;性价比最高的是嘎嘎降AI&#xff08;4.8元/千字&#xff0c;达标率99.26%&…

收藏!只为就业:纯LLM、多模态大模型、AIGC该选哪条路?

这绝对是2025年计算机应届生及算法方向求职者最焦虑的问题&#xff0c;没有之一。 过去几年&#xff0c;我从一线技术面试官做到团队负责人&#xff0c;面过的候选人从海外大厂博士到985硕士&#xff0c;累计不下八百人。聊得多了&#xff0c;也摸清了行业招聘的底层逻辑&#…

国内降AI工具 vs 国外降AI工具:中文论文选哪个?

国内降AI工具 vs 国外降AI工具&#xff1a;中文论文选哪个&#xff1f; TL;DR&#xff1a;中文论文老老实实用国产工具。国外工具&#xff08;QuillBot、Undetectable AI&#xff09;对中文支持约等于零&#xff0c;用了AI率不降反升。国内工具&#xff08;嘎嘎降AI、比话降AI&…

收藏!2026年AI行业最大机会:深耕应用层,抢占百万年薪赛道

2026年的AI行业&#xff0c;早已从“基座竞赛”迈入“应用落地”的黄金周期。据行业报告显示&#xff0c;目前超60%的企业已将AI产品落地纳入核心战略&#xff0c;但市场上能独立承接项目、打通技术与业务闭环的大模型应用开发工程师&#xff0c;却处于“供不应求”的极度稀缺状…

核心期刊AIGC检测严格?这6款工具帮你过关

核心期刊AIGC检测严格&#xff1f;这6款工具帮你过关 TL;DR&#xff1a;核心期刊对AI率要求比普通期刊严格得多&#xff0c;北大核心普遍要求15%以下&#xff0c;CSSCI更严格。推荐嘎嘎降AI&#xff08;达标率99.26%&#xff09;、比话降AI&#xff08;承诺15%以下&#xff0c;…

logioptions+软件问题解决

1.下载APP 下载旧版APP。 https://support.logi.com/hc/zh-cn/articles/4418699283607-Logi-Options 进入界面选择macos10.15 下载1.44.415778版本的 我是macos15的系统。 2.关闭自动更新 软件设置里关闭自动更新。然后在系统设置-网络-防火墙里把logioptions加上&#xff0c;不…

深度专业解析2026年企业级CMS自助建站系统有哪些

2026年&#xff0c;主流的CMS自助建站系统已从单纯的“内容展示”向“功能易扩展、互动性强、贴合业务场景”的方向发展。无论是国内企业宣传、本地化运营&#xff0c;还是搭建独立站开展跨境电商&#xff0c;均可根据需求选择合适的建站系统。以下从CMS类型与特点两个维度&…

收藏!AI Agent从入门到落地全解析,小白程序员必看的大模型进阶指南

一、前言&#xff1a;AI Agent凭啥成为科技圈顶流&#xff1f; 近年科技圈的热门技术层出不穷&#xff0c;但能让程序员、技术爱好者集体扎堆研究、上手实操的&#xff0c;AI Agent&#xff08;人工智能代理&#xff09;绝对是顶流之一。这种具备自主决策能力的智能体&#xff…

2026国内最新日用香精生产厂家top5推荐!广东广州优质品牌及厂商全面解析 - 品牌推荐2026

引言 随着消费升级与日化行业细分市场的蓬勃发展,日用香精作为提升产品附加值的核心要素,其安全性、稳定性与感官体验已成为品牌竞争的关键。据中国香料香精化妆品工业协会最新报告显示,2025年国内日用香精市场规模…

知网AIGC检测通关攻略:从0到1的保姆级教程

知网AIGC检测通关攻略&#xff1a;从0到1的保姆级教程 TL;DR&#xff1a;知网AIGC检测2026年升级后更严格&#xff0c;AI率<20%基本安全&#xff0c;>50%必须处理。通关方法&#xff1a;用嘎嘎降AI&#xff08;处理后AI率可降至7%&#xff09;或比话降AI&#xff08;承诺…

DeepSeek写的论文AI率太高?这5款工具帮你搞定

DeepSeek写的论文AI率太高&#xff1f;这5款工具帮你搞定 TL;DR&#xff1a;DeepSeek写的论文AI率通常在90%以上&#xff0c;用它自带的指令降AI基本没用。实测5款专业工具后&#xff0c;嘎嘎降AI和比话降AI效果最佳&#xff0c;可将AI率从99%降到5%以下。别折腾指令了&#xf…

vllm 调优参数之 ---enable-flash-attn

目录三、使用 --enable-flash-attn 的前提条件(很重要)✅ 硬件要求一、--enable-flash-attn 是做什么的(原理层)1️⃣ 传统 Attention 的问题2️⃣ FlashAttention 的核心思想二、在 vLLM + Qwen 14B + RTX 4090 下…

2025年值得信赖的数控4+4厂家排行,口碑为王,数控4+4/直Y/排刀机/三轴机/正交Y/36排刀机/双主轴数控4+4采购排行 - 品牌推荐师

在制造业向高端化、智能化转型的浪潮中,数控车铣复合机床,尤其是具备“4+4”轴联动能力的机型,已成为提升加工效率、实现复杂零件一次成型的核心装备。面对市场上品牌林立、技术路线各异的现状,如何甄选一家技术扎…

2026毕业季降AI避坑指南:这几款工具亲测好用

2026毕业季降AI避坑指南&#xff1a;这几款工具亲测好用 TL;DR&#xff1a;毕业季降AI工具鱼龙混杂&#xff0c;免费工具基本都是坑。亲测好用的有嘎嘎降AI&#xff08;4.8元/千字&#xff0c;达标率99.26%&#xff09;、比话降AI&#xff08;8元/千字&#xff0c;不达标退款&a…

大润发购物卡回收技巧,四种方式任你选 - 京回收小程序

大润发购物卡回收技巧,四种方式任你选"闲来无事理旧物,方觉卡券积成山。"翻出抽屉里那张沉睡已久的大润发购物卡,卡面金漆已有些斑驳,倒让我想起《长物志》里"藏之有道,用之有方"的智慧。与其…