定点模型转换

在经过前文所述的一系列过程,如果伪量化精度已经满足要求,便可执行模型部署的相关流程, 主要包括导出 HBIR 模型(export)以及转定点模型(convert)操作。

您可以先把这两个步骤理解为:

  • export,负责把 torch 侧的伪量化模型导出为 HBIR 表达。

  • convert,负责把导出的 HBIR 模型进一步转为真正的定点模型。

阶段主要输入主要输出负责内容是否已经进入真正定点
Exportqat_model / calib_model
和 example_inputs
qat.bc按部署所需的 forward 逻辑导出 HBIR 计算图否,仍处于导出阶段
Convertqat.bcquantized.bc将伪量化 HBIR 进一步转为真正的定点模型是,已进入真正定点

在 export 和 convert 阶段,比较常见且容易混淆的几个产物关系如下:

产物类型获取阶段说明常见用途
qat.pttorch 模型prepare / calibration / qat 后torch 侧的伪量化模型继续执行 Calibration、QAT、Export
qat.export.pttorch 模型pre_export 后仅完成查表转定点的 torch 模型,计算逻辑与 qat.bc 更接近用于 export 一致性分析
以及查表问题定位
qat.bcHBIR 模型export 后qat.pt 导出的 HBIR 模型,仍属于导出阶段产物用于 export 结果验证
以及 convert 输入
quantized.bcHBIR 模型convert 后qat.bc 定点化得到的模型用于 compile 前的定点精度验证

本章节下方介绍中,统一使用 qat_model 作为示例输入。如果您当前走的是 Calibration-only 路线,也可以直接将这里的 qat_model 替换为 calib_model

Export:导出 HBIR 模型

在真正转为定点模型之前,需要先将伪量化模型导出为 HBIR 模型。 在 export 时,您需要提供一组 example_inputs。工具会使用这组 inputs 执行模型的完整 forward 逻辑,并将执行到的算子逐个转写为 HBIR 结点或子图。

示例如下:

from horizon_plugin_pytorch.quantization import FakeQuantState, set_fake_quantize
from horizon_plugin_pytorch.quantization.hbdk4 import export

base_model = qat_model

base_model.eval()
set_fake_quantize(base_model, FakeQuantState.VALIDATION)

hbir_qat_model = export(base_model, (example_input,))
注意
  • 导出的 HBIR 模型中不仅仅包含量化的算子,而是会包含模型 forward 中实际执行到的所有算子。因此在导出 HBIR 时,请确保模型的 forward 逻辑与最终所需的部署逻辑一致。

  • HBIR 不支持动态 shape。计算图中各处的 shape 均由导出时模型中 Tensor 的 shape 决定。若您需要在仿真和上板使用不同的 batch size,请使用不同的数据分别导出 HBIR 模型。

  • 如果您当前主要想先验证部署链路是否能走通,您也可以选择跳过量化精度调优的过程,Calibration 初步完成之后先直接执行 Export / Convert 流程,尽早确认模型中是否存在无法导出或编译的操作。

注解

精度说明

Export 后得到的 HBIR 模型理论上计算逻辑和 torch 模型一致,但存在以下区别,可能会造成数值无法对齐:

  1. torch 模型中的大部分非线性 elementwise 算子,在 HBIR 中转为查表的实现方式。

  2. reduce_sumgemm 等带有累加计算的算子,可能会因为累加顺序不同而出现数值波动。

如果您发现 qat.pt / qat_model 正常,但 qat.bc 结果异常,通常应优先怀疑问题发生在 export 阶段。

Convert:转定点模型

得到导出的 HBIR 模型后,便可继续将模型转为定点模型。Convert 是真正进入定点阶段的步骤,输出产物为 quantized.bc。 一般我们认为精度方面,定点模型的结果和编译后模型的结果是完全一致的。

注解

Convert 前后,模型由浮点伪量化计算变为真正的定点计算,因此数值波动是正常现象。

一般来说,在进入 compile 之前,quantized.bc 是最值得优先关注的定点精度基线。

示例如下:

from hbdk4.compiler import convert

quantized_bc = convert(
    qat_bc,
    "nash-e",
)
注意
  • HBIR 模型的输入仅支持单个 TensorTuple[Tensor], 输出仅支持 Tuple[Tensor]

  • 定点模型和伪量化模型之间无法做到完全数值一致,所以请以定点模型 quantized.bc 的精度为准。若 quantized.bc 精度不达标,需要继续进行量化感知训练或者进入一致性分析,直到精度满足您的要求。

定点模型精度验证

完成 convert 后,建议您先对 quantized.bc 做精度验证,再决定是否继续 compile。

在验证时,建议您重点注意下面几点:

  • eval_hbir_data_loader 的 batch size 需要与 export 时使用的 example_inputs 保持一致。

  • 默认输入输出名称通常为 _input_{n}_output_{n}。如果您在 export 时做了自定义,这里也需要同步修改。

示例如下:

示例如下(使用上方 convert 得到的 quantized_bc):

from typing import Tuple

import hbdk4.compiler as hb4
import torch.utils.data as data

# hbir 精度测试使用的 dataloader,注意此处的 batch_size 必须和 export hbir 时
# 使用的 example_input 相同
_, eval_hbir_data_loader = prepare_data_loaders(
    data_path, train_batch_size, 1
)

def evaluate_hbir(
    model: hb4.Module, data_loader: data.DataLoader
) -> Tuple[AverageMeter, AverageMeter]:
    top1 = AverageMeter("Acc@1", ":6.2f")
    top5 = AverageMeter("Acc@5", ":6.2f")

    for image, target in data_loader:
        image, target = image.cpu(), target.cpu()

        # 默认输入输出名字为 _input_{n} / _output_{n} 的形式
        # 如果 export 时做了自定义,这里也需要同步修改
        output = model["forward"].feed({"_input_0": image})["_output_0"]
        acc1, acc5 = accuracy(output, target, topk=(1, 5))
        top1.update(acc1, image.size(0))
        top5.update(acc5, image.size(0))

    return top1, top5


# 测试定点模型精度
top1, top5 = evaluate_hbir(
    quantized_bc,
    eval_hbir_data_loader,
)
print(
    "Quantized model: evaluation Acc@1 {:.3f} Acc@5 {:.3f}".format(
        top1.avg, top5.avg
    )
)

如果 quantized.bc 精度已经满足要求,您可以继续阅读 模型编译及性能评测 章节。

一致性风险提示

在 Export / Convert 阶段,如果结果和预期不一致,建议您优先按下面的方式快速判断问题发生在哪一段:

  • 如果 qat.pt / qat_model 正常,但 qat.bc 异常,优先判断问题发生在 export 阶段,重点关注查表转定点、导出图是否一致,以及部署逻辑是否与训练侧一致。

  • 如果 qat.bc 正常,但 quantized.bc 异常,优先判断问题发生在 convert 阶段,重点关注定点化过程中引入的数值差异。

  • 如果 quantized.bc 正常,但 hbm 异常,优先判断问题发生在 compile / 部署阶段,重点关注输入输出处理、前后处理适配和板端部署差异。

如果您需要继续做 export / convert / compile 阶段的一致性排查,可继续参考部署一致性分析说明章节。