ResNet50 MNIST 量化示例
OE 包在 samples/onnx_ptq 路径下为您提供了一个 ONNX 模型的训练后量化 PTQ(Post-Training Quantization)转换示例,即位于 samples/onnx_ptq/resnet50_mnist 路径下的 ResNet50 MNIST 示例。
该示例以 MNIST 手写数字数据集上训练得到的 ResNet50 模型为对象,提供了从模型验证、校准数据准备、量化编译到单张推理和数据集精度评测的完整脚本。除第 5 步的数据集精度评测需要您自行准备 MNIST 测试集并在脚本中填写路径外,其余脚本无需改动即可直接运行。 如果您的模型输入是特征图、雷达点云特征、频谱数据这类非图像数据,可以直接参考本示例的配置方式。
在进行以下操作前,请确认您已经参考 环境部署 章节完成了开发机环境安装。
示例内容说明
示例位于 OE 包的 samples/onnx_ptq/resnet50_mnist 路径下,浮点模型、校准图片和测试图片都随包提供,无需额外下载。目录内容如下:
五个编号脚本对应完整的转换链路,按 01 到 05 的顺序依次执行即可。四个 Python 文件由编号脚本内部调用,各自的分工如下:
-
preprocess.py,负责校准数据预处理、单张推理前处理和测试集数据加载。 -
postprocess.py,负责分类后处理、精度统计和评测报告生成。 -
infer.py,单张推理脚本,由04_inference.sh调用。 -
eval.py,数据集评测脚本,由05_evaluate.sh调用。
本示例中的 infer.py 和 eval.py 仅适配此示例,对其他模型不通用。
使用流程
环境准备
开始执行编号脚本前,请先参考 Docker 容器部署 一节完成 Docker 环境的安装和配置并进入容器,再进入示例目录:
示例本身自带浮点模型、校准图片和测试图片,无需额外准备。
准备评测数据集
唯一需要自行准备的是一份 MNIST 官方 IDX 格式测试集,供第 5 步的数据集精度评测使用。请准备好 t10k-images-idx3-ubyte 和 t10k-labels-idx1-ubyte 两个文件并放在同一目录下,具体配置方式见 第 5 步:评测数据集精度。
如果您暂时只想跑通链路、确认前处理和推理是否正确,可以先跳过 IDX 测试集的准备,执行到第 4 步的单张推理为止。
准备完成后,即可按 01 到 05 的顺序依次执行五个脚本。
第 1 步:验证浮点模型
执行 01_check.sh 完成模型检查:
脚本内部调用 hb_compile 对 resnet50_mnist.onnx 做检查,示例默认按 J6E 平台验证,因此 --march 取值为 nash-e。如果您的目标平台不同,请改为对应取值,不同平台的量化策略差异见 平台差异说明 章节。
检查通过时,终端会逐层打印算子的部署情况。如果检查不通过,请根据终端打印或当前路径下生成的 hb_compile.log 确认报错信息,更多说明见 模型验证 章节。
第 2 步:准备校准数据
执行 02_preprocess.sh 生成校准数据:
脚本内部调用 preprocess.py,从 calibration_data 目录读取校准图片,处理后存放到 calibration_data_float32 目录,默认取 100 张参与校准。这三项分别由 --src_dir、--dst_dir 和 --cal_img_num 参数控制,可以按需修改。
预处理步骤与训练前处理完全一致,即先读成单通道灰度图,再把像素值除以 255 缩放到 0~1,最后按 MNIST_MEAN 和 MNIST_STD 做标准化。这两个数值在 preprocess.py 中定义,均值取 0.1307,标准差取 0.3081,与模型训练时的取值一致,校准、单张推理和数据集评测三处共用同一份取值。
处理后每张图片保存为一个 .npy 文件,文件名形如 xxx.cali.npy,数据类型为 float32,形状为 (1, 28, 28),与配置文件中 input_shape 去掉 batch 维后的形状一致。脚本执行结束时会打印一份校验信息,包含首个样本的形状、数据类型和数值范围,可用来确认预处理结果是否符合预期。
校准数据必须与训练时的前处理保持一致。本示例把归一化放在了 Python 侧,因此校准数据是已经归一化后的浮点数据,而不是 0~255 的原始像素值。如果这一步漏做归一化,校准得到的量化参数会明显偏离真实数据分布,进而影响量化模型精度。
校准数据准备的通用说明见 数据准备 章节。
第 3 步:量化编译
本步依据 resnet50_mnist_config.yaml 完成量化编译,执行前建议先确认配置文件内容与您的模型一致。
配置文件说明
resnet50_mnist_config.yaml 的主要参数如下:
其中需要重点关注的是输入信息参数组,这也是本示例与图像输入模型配置差异最大的地方。input_type_rt 与 input_type_train 均配置为 featuremap,表示上板模型接收的数据格式和原始浮点模型的数据格式都按 float32 特征图处理,转换工具不会在模型前端插入颜色空间转换节点。norm_type 配置为 no_preprocess,表示不由转换工具执行归一化,归一化改由 preprocess.py 在 Python 侧完成。
-
input_type_train为featuremap时,input_type_rt只能同样配置为featuremap,不支持与 nv12、rgb、bgr、yuv444、gray 组合。完整的组合支持关系见 配置文件具体参数信息 章节。 -
模型输入类型为
featuremap时,input_layout_train配置不生效。示例中仍保留NCHW取值,是为了与浮点模型的实际数据排布保持一致,便于对照阅读。
calibration_parameters 中 cal_data_dir 指向第 2 步生成的 calibration_data_float32 目录,calibration_type 取 default。如果量化后精度不满足要求,可以按 mix、kl、max 的顺序依次尝试。
其余参数的取值范围和填写方式见 配置文件具体参数信息 章节,完整模板见 配置文件模板 章节。
执行编译
确认配置无误后,执行 03_build.sh:
转换产物存放在配置文件 working_dir 指定的 model_output 目录下,文件名前缀由 output_model_file_prefix 指定,即 resnet50_mnist_28x28_gray。后续两步会用到其中两个产物:
-
model_output/resnet50_mnist_28x28_gray_original_float_model.onnx,用于评测浮点模型基线精度。 -
model_output/resnet50_mnist_28x28_gray_quantized_model.bc,用于评测量化模型精度。
完整的产物清单、各产物的用途以及一致性对比时应当选用哪一份,见 转换产出物 章节。
转换过程中打印的 Calibrated Cosine 和 Quantized Cosine 相似度可以作为量化后数值稳定性的参考,但与模型精度不存在绝对的直接关联。是否可以接受量化结果,仍应以第 5 步的数据集精度为准。
第 4 步:验证单张推理
执行 04_inference.sh 对单张测试图片做推理:
不带参数时脚本使用量化模型 resnet50_mnist_28x28_gray_quantized_model.bc,参数中包含 origin 时使用浮点模型 resnet50_mnist_28x28_gray_original_float_model.onnx。两种模型的输入排布都是 NCHW,推理图片默认取 ./test_data/test_0000.png。
因为 input_type_rt 配置为 featuremap,模型内部不包含预处理节点,所以 infer.py 前处理得到的归一化浮点数据可以直接送入模型,无需再做色彩空间转换或数据拆分。这一点与 nv12 输入的分类示例不同,nv12 输入需要先把数据拆分为 y 和 uv 两个输入。
推理成功时,终端会打印 top-1 的类别编号、概率和类别名称。类别名称由 postprocess.py 中的 MNIST_CLASSES 定义,取值为 digit 0 到 digit 9。如果打印结果与图片实际数字一致,说明前处理、推理和后处理链路已经打通,可以进入数据集精度评测。
第 5 步:评测数据集精度
编辑 05_evaluate.sh,把 MNIST_DATA_ROOT 修改为 IDX 测试集所在目录的实际路径:
如果您在 Docker 容器中执行本示例,请先确认测试集目录已经正确挂载进容器,并且 MNIST_DATA_ROOT 填写的是容器内路径。
修改完成后执行评测:
与单张推理一致,不带参数时评测量化模型,参数中包含 origin 时评测浮点模型。脚本调用 eval.py,由 preprocess.py 中的 MNISTIdxDataLoader 直接读取 IDX 文件并逐样本归一化,无需提前把测试集转成图片。
评测过程中,终端每处理 1000 个样本会打印一次累计准确率,评测结束时打印样本总数、正确样本数和最终准确率。同时会在当前目录生成 resnet50_mnist_eval.log,其中逐条记录了每个样本的序号、预测类别和是否正确,可以用来定位具体的错分样本。
eval.py 还提供了 --parallel_num 参数用于指定并行进程数,默认取 1。如果评测耗时较长,可以在 05_evaluate.sh 的 python3 -u ./eval.py 命令中追加该参数适当提高并行度。
示例中的浮点模型在 MNIST 全部 10000 个测试样本上的准确率为 0.9968,可以作为量化前的基线。如果量化模型精度明显低于该基线,请先确认校准数据的前处理是否与训练一致,再参考 精度调优指导 章节调整量化配置。
跑通之后下一步看什么
完成上述五步后,您已经得到了可用于部署的量化模型。接下来可以按需要选择方向:
-
需要了解每个阶段的完整说明和产物含义,参考 ONNX 模型量化原理及流程概述 章节。
-
需要评估模型的静态性能和板端实测性能,参考 模型性能评估 章节。
-
需要在开发机端验证
quantized_model.bc与hbm的输出一致性,参考 模型精度评估 章节。 -
需要把模型部署到开发板并接入上层应用,参考 ONNX 模型快速入门 章节中开发板环境验证与模型部署的说明。
