定点模型转换

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

导出 HBIR 模型

模型部署首先需要将伪量化模型导出为 HBIR 模型。需提供一组 example_inputs,工具利用此 inputs 执行模型的完整 forward 逻辑,并将执行到的算子逐个转义为 hbir 结点或子图。

注意
  • 导出的 hbir 中不仅仅包含量化的算子,而是会包含模型 forward 中执行到的所有算子。因此在导出 hbir 时请确保模型的 forward 逻辑与所需的部署逻辑一致。
  • hbir 不支持动态 shape,计算图中各处的 shape 均由导出时模型中 Tensor 的 shape 决定。若需要在仿真和上板使用不同的 batch size,请使用不同的数据分别导出 HBIR 模型。
  • 您也可以选择跳过量化精度调优的过程,Calib 初步完成之后先直接验证模型部署的流程,以保证模型中不存在无法导出或编译的操作。
注解

精度说明

导出的 hbir 模型理论上计算逻辑和 torch 模型一致,但存在以下区别,会造成数值无法对齐:

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

  2. 存在累加计算的算子如 reduce_sum, gemm 等,会由于累加的顺序不同导致数值波动。

######################################################################
# 可根据需要修改以下参数
# 1. 使用哪个模型作为流程的输入,可以选择 calib_model 或 qat_model
base_model = qat_model
######################################################################

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

qat_model.eval()
set_fake_quantize(qat_model, FakeQuantState.VALIDATION)
hbir_qat_model = export(base_model, (example_input,))

转定点模型

导出为 HBIR 模型后,便可将模型转为定点模型。一般我们认为精度方面,定点模型的结果和编译后模型的结果是完全一致的。

注意
  • HBIR 模型的输入仅支持单个 TensorTuple[Tensor], 输出仅支持 Tuple[Tensor]
  • 定点模型和伪量化模型之间无法做到完全数值一致,所以请以定点模型的精度为准。若定点模型精度不达标,需要继续进行量化感知训练直到精度满足您的要求。
注解

精度说明

convert 前后,模型由浮点伪量化计算变为定点计算,会导致数值波动。

from hbdk4.compiler import convert

# 将模型转为定点状态,注意此处的 march 需要区分 nash-e/m/p
hbir_quantized_model = convert(
    hbir_qat_model,
    "nash-e",
)

# 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(
    hbir_quantized_model,
    eval_hbir_data_loader,
)
print(
    "Quantized model: evaluation Acc@1 {:.3f} Acc@5 {:.3f}".format(
        top1.avg, top5.avg
    )
)