5. 模型转换进阶指南
5.1. 概述
pulsar2 build
用于模型 图优化、 量化、 编译 等操作. 其运行示意图如下:
pulsar2 build
利用输入模型(model.onnx
)、PTQ校准数据(calibration.tar
)和配置文件(config.json
), 生成输出模型(axmodel
).pulsar2 build
的命令行参数将会覆盖配置文件中的某些对应部分, 并使pulsar2 build
将覆盖过后得到的配置文件输出出来. 配置文件的详细介绍参见 《配置文件详细说明》.
5.2. 模型编译详解
本节介绍 pulsar2 build
命令完整使用方法.
pulsar2 build -h
可显示详细命令行参数:
1 usage: main.py build [-h] [--config] [--input] [--output_dir] [--output_name]
2 [--work_dir] [--model_type] [--target_hardware]
3 [--npu_mode] [--input_shapes]
4 [--onnx_opt.disable_onnx_optimization]
5 [--onnx_opt.enable_onnxsim] [--onnx_opt.model_check]
6 [--onnx_opt.disable_transformation_check]
7 [--onnx_opt.save_tensors_data]
8 [--quant.calibration_method] [--quant.precision_analysis]
9 [--quant.precision_analysis_method]
10 [--quant.precision_analysis_mode]
11 [--quant.highest_mix_precision]
12 [--quant.conv_bias_data_type]
13 [--quant.refine_weight_threshold]
14 [--quant.enable_smooth_quant]
15 [--quant.transformer_opt_level]
16 [--quant.input_sample_dir] [--quant.ln_scale_data_type]
17 [--quant.check] [--quant.disable_auto_refine_scale]
18 [--compiler.static_batch_sizes [...]]
19 [--compiler.max_dynamic_batch_size]
20 [--compiler.disable_ir_fix] [--compiler.check]
21 [--compiler.check_mode] [--compiler.debug]
22 [--compiler.input_sample_dir]
23 optional arguments:
24 -h, --help show this help message and exit
25 --config config file path, supported formats: json / yaml /
26 toml / prototxt. type: string. required: false.
27 default:.
28 --input input model file path. type: string. required: true.
29 --output_dir axmodel output directory. type: string. required:
30 true.
31 --output_name rename output axmodel. type: string. required: false.
32 default: compiled.axmodel.
33 --work_dir temporary data output directory. type: string.
34 required: false. default: same with ${output_dir}.
35 --model_type input model type. type: enum. required: false.
36 default: ONNX. option: ONNX, QuantAxModel, QuantONNX.
37 --target_hardware target hardware. type: enum. required: false. default:
38 AX650. option: AX650, AX620E, M76H.
39 --npu_mode npu mode. while ${target_hardware} is AX650, npu mode
40 can be NPU1 / NPU2 / NPU3. while ${target_hardware} is
41 AX620E, npu mode can be NPU1 / NPU2. type: enum.
42 required: false. default: NPU1.
43 --input_shapes modify model input shape of input model, this feature
44 will take effect before the `input_processors`
45 configuration. format:
46 input1:1x3x224x224;input2:1x1x112x112. type: string.
47 required: false. default: .
48 --onnx_opt.disable_onnx_optimization
49 disable onnx optimization. type: bool. required:
50 false. default: false.
51 --onnx_opt.enable_onnxsim
52 enable onnx simplify by
53 https://github.com/daquexian/onnx-simplifier. type:
54 bool. required: false. default: false.
55 --onnx_opt.model_check
56 enable model check. type: bool. required: false.
57 default: false.
58 --onnx_opt.disable_transformation_check
59 disable transformation check. type: bool. required:
60 false. default: false.
61 --onnx_opt.save_tensors_data
62 save tensors data to optimize memory footprint. type:
63 bool. required: false. default: false.
64 --quant.calibration_method
65 quantize calibration method. type: enum. required:
66 false. default: MinMax. option: MinMax, Percentile,
67 MSE.
68 --quant.precision_analysis
69 enable quantization precision analysis. type: bool.
70 required: false. default: false.
71 --quant.precision_analysis_method
72 precision analysis method. type: enum. required:
73 false. default: PerLayer. option: PerLayer, EndToEnd.
74 --quant.precision_analysis_mode
75 precision analysis mode. type: enum. required: false.
76 default: Reference. option: Reference, NPUBackend.
77 --quant.highest_mix_precision
78 enable highest mix precision quantization. type: bool.
79 required: false. default: false.
80 --quant.conv_bias_data_type
81 conv bias data type. type: enum. required: false.
82 default: S32. option: S32, FP32.
83 --quant.refine_weight_threshold
84 refine weight threshold, should be a legal float
85 number, like 1e-6. -1 means disable this feature.
86 type: float. required: false. default: 1e-6.
87 limitation: 0 or less than 0.0001.
88 --quant.enable_smooth_quant
89 enalbe smooth quant strategy for conv 1x1. type: bool.
90 required: false. default: false.
91 --quant.transformer_opt_level
92 tranformer opt level. type: int. required: false.
93 default: 0. limitation: 0~2.
94 --quant.input_sample_dir
95 input sample data dir for precision analysis. type:
96 string. required: false. default: .
97 --quant.ln_scale_data_type
98 LayerNormalization scale data type. type: enum.
99 required: false. default: FP32. option: FP32, S32,
100 U32.
101 --quant.check quant check level, 0: no check; 1: check node dtype.
102 type: int. required: false. default: 0.
103 --quant.disable_auto_refine_scale
104 refine weight scale and input scale, type: bool.
105 required: false. default: false.
106 --compiler.static_batch_sizes [ ...]
107 static batch sizes. type: int array. required: false.
108 default: [].
109 --compiler.max_dynamic_batch_size
110 max dynamic batch. type: int, required: false.
111 default: 0.
112 --compiler.disable_ir_fix
113 disable ir fix, only work in multi-batch compilation.
114 type: bool. required: false. default: false.
115 --compiler.check compiler check level, 0: no check; 1: assert all close;
116 2: assert all equal. type: int. required: false.
117 default: 0.
118 --compiler.check_mode
119 compiler check mode, CheckOutput: only check model
120 output; CheckPerLayer: check model intermediate tensor
121 and output. type: enum. required: false. default:
122 CheckOutput. option: CheckOutput, CheckPerLayer.
123 --compiler.debug compiler debug level. type: int. required: false.
124 default: 0.
125 --compiler.input_sample_dir
126 input sample data dir for compiler check. type:
127 string. required: false. default: .
提示
用户可以根据参数规格编写
json / yaml / toml / prototxt
格式的配置文件,通过命令行参数--config
指向配置文件部分编译参数支持命令行传入,且优先级高于配置文件,通过
pulsar2 build -h
查看支持的命令行编译参数,比如命令行参数--quant.calibration_method
相当于配置了QuantConfig
结构体的calibration_method
字段
5.2.1. 参数详解
- pulsar2 build 参数解释
- --config
数据类型:string
是否必选:是
描述:配置文件路径,支持
json / yaml / toml / prototxt
格式,结构体见 《配置文件详细说明》
- --work_dir
数据类型:string
是否必选:否
默认值:与 output_dir 相同
描述:中间结果输出目录
- --input
数据类型:string
是否必选:是
描述:输入模型路径
- --output_dir
数据类型:string
是否必选:是
描述:编译结果输出目录,编译后的模型命名为 compiled.axmodel
- --model_type
数据类型:enum
是否必选:否
默认值:ONNX
描述:输入模型类型,支持枚举:
ONNX
,QuantAxModel
,QuantONNX
- --target_hardware
数据类型:enum
是否必选:否
默认值:AX650
描述:模型编译的目标 soc 平台类型,支持
AX650
,AX620E
,M76H
- --npu_mode
数据类型:enum
是否必选:否
默认值:NPU1
描述:模型编译模式
soc 平台为
AX650
时,支持枚举:NPU1
,NPU2
,NPU3
soc 平台为
AX620E
时,支持枚举:NPU1
,NPU2
警告
npu_mode 指的是使用的 NPU 核数,而不是 vNPU 编号,请不要混淆。
- --input_shapes
数据类型:string
是否必选:否
默认值:空
描述:模型编译过程中,修改模型的输入尺寸,格式为:
input1:1x3x224x224;input2:1x1x112x112
。
- --onnx_opt
disable_onnx_optimization
数据类型:bool
是否必选:否
默认值:false
描述:是否使能浮点 ONNX 模型图优化模块。
enable_onnxsim
数据类型:bool
是否必选:否
默认值:false
描述:是否使用 onnxsim 工具简化浮点 ONNX,https://github.com/daquexian/onnx-simplifier。
model_check
数据类型:bool
是否必选:否
默认值:false
描述:是否使能浮点 ONNX 模型图优化结束后与原始 ONNX 模型的对分功能。
disable_transformation_check
数据类型:bool
是否必选:否
默认值:false
描述:在浮点 ONNX 模型图优化过程中,是否禁用每次子图变换后的子图对分功能。
- --quant
在 BuildConfig 中是名为 quant 的成员变量
calibration_method
数据类型:enum
是否必选:否
默认值:MinMax
描述:量化算法,支持的枚举
MinMax
,Percentile
,MSE
, 结构体见 《配置文件详细说明》
precision_analysis
数据类型:bool
是否必选:否
默认值:false
描述:是否逐层分析 Quant AXModel 的量化精度
precision_analysis_method
数据类型:enum
是否必选:否
默认值:PerLayer
描述:精度分析方法,可选 PerLayer / EndToEnd。PerLayer 意味着每一层都采用浮点模型对应的层输入,计算每一层的输出与浮点模型输出的相似度。EndToEnd 代表首层采用浮点模型输入,然后进行完整模型的仿真,计算最终输出结果与浮点模型输出的相似度。
precision_analysis_mode
数据类型:enum
是否必选:否
默认值:Reference
描述:逐层仿真的实现,可选 Reference / NPUBackend。Reference 可以运行编译器支持的全部模型(支持包含 CPU 及 NPU 子图的模型),但是计算结果相比于最终上板结果会有少量误差(基本上差距在正负 1 内,且无系统性误差)。NPUBackend 可以运行仅包含 NPU 子图的模型,但是计算结果与上板结果比特对齐。
highest_mix_precision
数据类型:bool
是否必选:否
默认值:false
描述:是否使能最高精度量化模式。
conv_bias_data_type
数据类型:enum
是否必选:否
默认值:S32
描述:量化时 Conv 算子 Bias 属性保存的数据类型,可选 S32 / FP32。
refine_weight_threshold
数据类型:float
是否必选:否
默认值:1e-6
描述:将权重量化阈值调整至指定值。
enable_smooth_quant
数据类型:bool
是否必选:否
默认值:false
描述:使能 smooth quant 量化策略以提升量化精度。
transformer_opt_level
数据类型:int
是否必选:否
默认值:0
描述:Transformer 网络的量化方式配置。
input_sample_dir
数据类型:string
是否必选:否
默认值:空
描述:配置用于量化精度分析的输入数据目录,如果未指定,则采用量化校准集中的数据。
备注
注意
--quant.input_sample_dir
中的输入数据的格式应与原模型相同。
- --compiler
在 BuildConfig 中是名为 compiler 的成员变量
static_batch_sizes
数据类型:list of int
是否必选:否
默认值:0
描述:编译器按照用户提供 batch 组合进行编译,基于这一组 batch 模型,可以在运行时支持任意 batch_size 输入的高效推理。详情参考:《静态多 batch 模式》。
max_dynamic_batch_size
数据类型:int
是否必选:否
默认值:0
描述:编译器自动推导出 NPU 可高效运行且不大于 max_dynamic_batch_size 的 batch 模型组合,基于这一组 batch 模型,可以在运行时支持任意 batch_size 输入的高效推理。详情参考:《动态多 batch 模式》。
disable_ir_fix
数据类型:bool
是否必选:否
默认值:false
描述:多 batch 编译时,是否禁止编译器默认的 Reshape 算子属性修改行为。
check
数据类型:int
是否必选:否
默认值:0
描述:是否通过仿真检查编译结果的正确性,0 代表不做任何检查;1 代表 all close 检查;2 代表 all equal 检查。
check_mode
数据类型:enum
是否必选:否
默认值:0
描述:对分模式,CheckOutput 代表只对结果进行对分。CheckPerLayer 代表逐层对分。
input_sample_dir
数据类型:string
是否必选:否
默认值:空
描述:配置用于编译器检查的输入数据目录,如果未指定,则会优先使用量化校准数据。
备注
注意
--compiler.input_sample_dir
中的输入数据的格式应与编译后的模型相同(包含预处理)。
5.3. 多核编译详解
用户可通过修改 pulsar2 build
中的 --npu_mode
选项灵活配置 NPU编译模式,充分利用算力。
5.3.1. NPU 单核模式
--npu_mode
默认配置是 NPU1
,即 1 个 NPU core
模式。之前的 《模型编译》 章节中均采用 NPU1
默认配置进行说明。
5.3.2. NPU 双核模式
--npu_mode
配置修改为 NPU2
,即 2 个 NPU core
模式。以转换 mobilenetv2
模型举例,修改配置文件如下所示:
{
"model_type": "ONNX",
"npu_mode": "NPU2", # 只需要修改这里,默认配置是 NPU1
"quant": {
"input_configs": [
{
"tensor_name": "input",
"calibration_dataset": "./dataset/imagenet-32-images.tar",
"calibration_size": 32,
"calibration_mean": [103.939, 116.779, 123.68],
"calibration_std": [58.0, 58.0, 58.0]
}
],
"calibration_method": "MinMax",
"precision_analysis": false
},
"input_processors": [
{
"tensor_name": "input",
"tensor_format": "BGR",
"src_format": "BGR",
"src_dtype": "U8",
"src_layout": "NHWC",
"csc_mode": "NoCSC"
}
],
"compiler": {
"check": 0
}
}
pulsar2 build
编译命令如下:
root@xxx:/data# pulsar2 build --input model/mobilenetv2-sim.onnx --output_dir output --config config/mobilenet_v2_build_config.json
5.4. 多 batch 编译详解
pulsar2 build
支持用户配置模型的 batch_size,分为静态多 batch 及动态多 batch 编译两种模式,这两种模式互斥。本章节以 AX650
举例。
5.4.1. 静态多 batch 模式
编译器按照用户提供 batch 组合进行编译,支持命令行参数 --compiler.static_batch_sizes
配置以及修改配置文件中的 compiler.static_batch_sizes
两种方式。
设置静态多 batch 编译后,通过
onnx inspect -m -n -t
查看compiled.axmodel
时,输入输出 shape 的 batch 维将变为用户指定的最大 batch。batch 之间将尽可能的复用权重数据,因此模型大小相比于单独编译各个 batch 的模型大小总和更小。
提示
以 mobilenetv2 模型为例,原模型输入 input
shape 为 [1, 224, 224, 3]
,
进行 static_batch_sizes
等于 [1, 2, 4] 的静态多 batch 编译后,shape 将变为 [4, 224, 224, 3]
。
5.4.2. 动态多 batch 模式
编译器自动推导出 NPU 可高效运行且不大于 max_dynamic_batch_size
的 batch 模型组合,基于这一组 batch 模型,可以在运行时支持任意 batch_size 输入的高效推理。支持命令行参数 --compiler.max_dynamic_batch_size
配置以及修改配置文件中的 compiler.max_dynamic_batch_size
两种方式。
编译器会从 batch 1 开始,2 倍递增进行编译,当 batch 大于设置的
max_dynamic_batch_size
或者当前 batch 理论推理效率低于前一个 batch 时停止。batch 理论推理效率:理论推理耗时 / batch_size。
batch 之间将尽可能的复用权重数据,因此模型大小相比于单独编译各个 batch 的模型大小总和更小。
设置动态多 batch 编译后,通过
onnx inspect -m -n -t
查看compiled.axmodel
时,输入输出 shape 的 batch 维将变为max_dynamic_batch_size
。
提示
以 mobilenetv2 模型为例,原模型输入 input
shape 为 [1, 224, 224, 3]
,
进行 max_dynamic_batch_size
等于 4 的动态多 batch 编译后,shape 将变为 [4, 224, 224, 3]
。
运行时,会根据调用者在推理时设置的动态 batch 大小,寻找合适的 batch 组合,进行多次推理。
提示
当一个模型理论推理效率随着 batch 数增加而提高并且编译后仅有一个 NPU 子图,max_dynamic_batch_size
设置为 4 时,编译后的 compiled.axmodel
中会包含 [1, 2, 4] 三个 batch 的模型。
推理或仿真时:
如果设置动态 batch 的值为 3 时,
axengine 推理框架
及pulsar2 run 仿真器
会在内部进行 batch 2 + batch 1 两次 NPU 推理或仿真。如果设置动态 batch 的值为 9 时,
axengine 推理框架
及pulsar2 run 仿真器
会在内部进行 batch 4 + batch 4 + batch 1 三次 NPU 推理或仿真。
动态多 batch 编译时,会有以下日志展示出编译出的 batch 组合:
...
2023-07-09 20:06:02.690 | INFO | yamain.command.build:compile_npu_subgraph:985 - QuantAxModel macs: 280,262,480
2023-07-09 20:06:06.786 | WARNING | yamain.command.build:compile_npu_subgraph:1035 - graph [subgraph_npu_0] batchs [1, 2]
2023-07-09 20:06:06.795 | INFO | yamain.command.build:compile_ptq_model:924 - fuse 1 subgraph(s)
5.4.3. 包含 Reshape 算子的模型多 batch 编译
如果模型中包含 Reshape
算子,在执行多 batch 编译时 pulsar2
可能无法正确的推测出 Reshape
算子的输出 shape。
此时用户可以通过 《常量数据修改》 功能,修改 Reshape
算子的 shape
输入数据,使得 pulsar2
在多 batch 编译过程中正确推导出输出 shape。
比如存在一个 shape 为 [2, 1, 64]
的 Reshape
算子,假设第 1 维为 batch,则通过常量数据修改功能,将 shape 对应的常量 tensor 修改为 [2, -1, 64]
或者 [2, 0, 64]
后,即可支持多 batch 编译。
除此之外,如果用户没有显式的配置算子属性修改,那么 pulsar2
会将 Reshape
算子 shape 的第 0 维修改为 -1,尝试进行多 batch 编译。
提示
pulsar2 支持在 Reshape
的 shape 中配置 0
或者 -1
。0
代表与输入 tensor 对应维度的值相同;-1
代表根据输入 tensor 计算得出的未知维度大小。
5.5. 逐层对分详解
pulsar2 build
提供了一套浮点模型与量化后模型的逐层精度对比工具。有如下两种方式配置,任选其一即可:
在命令行中配置
--quant.precision_analysis 1
开启精度对比功能;如下为一个示例:
root@xxx:/data/quick_start_example# pulsar2 build --input model/mobilenetv2-sim.onnx --output_dir output --config config/config_mobilenet_v2_onnx.json --quant.precision_analysis 1
编译命令不变,在配置文件中将
"precision_analysis": false
修改为"precision_analysis": true
:
{
"model_type": "ONNX",
"npu_mode": "NPU1",
"quant": {
"input_configs": [
{
"tensor_name": "input",
"calibration_dataset": "./dataset/imagenet-32-images.tar",
"calibration_size": 32,
"calibration_mean": [103.939, 116.779, 123.68],
"calibration_std": [58.0, 58.0, 58.0]
}
],
"calibration_method": "MinMax",
"precision_analysis": true # 这里修改为 true, 默认是 false
},
"input_processors": [
{
"tensor_name": "input",
"tensor_format": "BGR",
"src_format": "BGR",
"src_dtype": "U8",
"src_layout": "NHWC",
"csc_mode": "NoCSC"
}
],
"compiler": {
"check": 0
}
}
重新执行编译过程后,可得到如下带有 Quant Precision Table
的输出信息,包含了 节点名、类型、输出名、数据类型、输出形状、余弦相似度 等:
root@xxx:/data# pulsar2 build --input model/mobilenetv2-sim.onnx --output_dir output --config config/mobilenet_v2_build_config.json
...
Building native ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
Quant Precision Table 【PerLayer Reference】
┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓
┃ Operator ┃ Type ┃ Output Tensor ┃ Data Type ┃ Shape ┃ Cosin Distance ┃
┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩
│ Conv_0 │ AxQuantizedConv │ 474 │ FP32 │ (1, 32, 112, 112) │ 0.999932050704956 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_2 │ AxQuantizedConv │ 477 │ FP32 │ (1, 32, 112, 112) │ 0.9994480609893799 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_4 │ AxQuantizedConv │ 480 │ FP32 │ (1, 16, 112, 112) │ 0.9990373849868774 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_5 │ AxQuantizedConv │ 483 │ FP32 │ (1, 96, 112, 112) │ 0.9993898272514343 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_7 │ AxQuantizedConv │ 486 │ FP32 │ (1, 96, 56, 56) │ 0.9991888999938965 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_9 │ AxQuantizedConv │ 489 │ FP32 │ (1, 24, 56, 56) │ 0.9991229772567749 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_10 │ AxQuantizedConv │ 492 │ FP32 │ (1, 144, 56, 56) │ 0.999823272228241 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_12 │ AxQuantizedConv │ 495 │ FP32 │ (1, 144, 56, 56) │ 0.9995720386505127 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_14 │ AxQuantizedConv │ 498 │ FP32 │ (1, 24, 56, 56) │ 0.9993237853050232 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Add_15 │ AxQuantizedAdd │ 339 │ FP32 │ (1, 24, 56, 56) │ 0.9992991089820862 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_16 │ AxQuantizedConv │ 501 │ FP32 │ (1, 144, 56, 56) │ 0.9996923208236694 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_18 │ AxQuantizedConv │ 504 │ FP32 │ (1, 144, 28, 28) │ 0.9997930526733398 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_20 │ AxQuantizedConv │ 507 │ FP32 │ (1, 32, 28, 28) │ 0.9997037053108215 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_21 │ AxQuantizedConv │ 510 │ FP32 │ (1, 192, 28, 28) │ 0.9998888373374939 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_23 │ AxQuantizedConv │ 513 │ FP32 │ (1, 192, 28, 28) │ 0.9993594884872437 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_25 │ AxQuantizedConv │ 516 │ FP32 │ (1, 32, 28, 28) │ 0.9995540976524353 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Add_26 │ AxQuantizedAdd │ 356 │ FP32 │ (1, 32, 28, 28) │ 0.999687135219574 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_27 │ AxQuantizedConv │ 519 │ FP32 │ (1, 192, 28, 28) │ 0.9998943209648132 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_29 │ AxQuantizedConv │ 522 │ FP32 │ (1, 192, 28, 28) │ 0.9997372031211853 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_31 │ AxQuantizedConv │ 525 │ FP32 │ (1, 32, 28, 28) │ 0.9995033144950867 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Add_32 │ AxQuantizedAdd │ 365 │ FP32 │ (1, 32, 28, 28) │ 0.9996601343154907 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_33 │ AxQuantizedConv │ 528 │ FP32 │ (1, 192, 28, 28) │ 0.9998391270637512 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_35 │ AxQuantizedConv │ 531 │ FP32 │ (1, 192, 14, 14) │ 0.999911367893219 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_37 │ AxQuantizedConv │ 534 │ FP32 │ (1, 64, 14, 14) │ 0.9996770024299622 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_38 │ AxQuantizedConv │ 537 │ FP32 │ (1, 384, 14, 14) │ 0.9999406337738037 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_40 │ AxQuantizedConv │ 540 │ FP32 │ (1, 384, 14, 14) │ 0.9997537136077881 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_42 │ AxQuantizedConv │ 543 │ FP32 │ (1, 64, 14, 14) │ 0.9997888207435608 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Add_43 │ AxQuantizedAdd │ 382 │ FP32 │ (1, 64, 14, 14) │ 0.9997644424438477 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_44 │ AxQuantizedConv │ 546 │ FP32 │ (1, 384, 14, 14) │ 0.9999357461929321 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_46 │ AxQuantizedConv │ 549 │ FP32 │ (1, 384, 14, 14) │ 0.9998541474342346 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_48 │ AxQuantizedConv │ 552 │ FP32 │ (1, 64, 14, 14) │ 0.9997283816337585 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Add_49 │ AxQuantizedAdd │ 391 │ FP32 │ (1, 64, 14, 14) │ 0.9997260570526123 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_50 │ AxQuantizedConv │ 555 │ FP32 │ (1, 384, 14, 14) │ 0.9998891353607178 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_52 │ AxQuantizedConv │ 558 │ FP32 │ (1, 384, 14, 14) │ 0.9995425939559937 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_54 │ AxQuantizedConv │ 561 │ FP32 │ (1, 64, 14, 14) │ 0.9989281892776489 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Add_55 │ AxQuantizedAdd │ 400 │ FP32 │ (1, 64, 14, 14) │ 0.9995357394218445 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_56 │ AxQuantizedConv │ 564 │ FP32 │ (1, 384, 14, 14) │ 0.9998661875724792 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_58 │ AxQuantizedConv │ 567 │ FP32 │ (1, 384, 14, 14) │ 0.9998401999473572 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_60 │ AxQuantizedConv │ 570 │ FP32 │ (1, 96, 14, 14) │ 0.9996302723884583 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_61 │ AxQuantizedConv │ 573 │ FP32 │ (1, 576, 14, 14) │ 0.9998155832290649 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_63 │ AxQuantizedConv │ 576 │ FP32 │ (1, 576, 14, 14) │ 0.9993364810943604 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_65 │ AxQuantizedConv │ 579 │ FP32 │ (1, 96, 14, 14) │ 0.9981837868690491 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Add_66 │ AxQuantizedAdd │ 417 │ FP32 │ (1, 96, 14, 14) │ 0.9994098544120789 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_67 │ AxQuantizedConv │ 582 │ FP32 │ (1, 576, 14, 14) │ 0.998947262763977 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_69 │ AxQuantizedConv │ 585 │ FP32 │ (1, 576, 14, 14) │ 0.9985659718513489 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_71 │ AxQuantizedConv │ 588 │ FP32 │ (1, 96, 14, 14) │ 0.9961519241333008 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Add_72 │ AxQuantizedAdd │ 426 │ FP32 │ (1, 96, 14, 14) │ 0.998038113117218 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_73 │ AxQuantizedConv │ 591 │ FP32 │ (1, 576, 14, 14) │ 0.9991413950920105 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_75 │ AxQuantizedConv │ 594 │ FP32 │ (1, 576, 7, 7) │ 0.9995304346084595 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_77 │ AxQuantizedConv │ 597 │ FP32 │ (1, 160, 7, 7) │ 0.9926491379737854 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_78 │ AxQuantizedConv │ 600 │ FP32 │ (1, 960, 7, 7) │ 0.9965869784355164 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_80 │ AxQuantizedConv │ 603 │ FP32 │ (1, 960, 7, 7) │ 0.9980652332305908 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_82 │ AxQuantizedConv │ 606 │ FP32 │ (1, 160, 7, 7) │ 0.9920080900192261 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Add_83 │ AxQuantizedAdd │ 443 │ FP32 │ (1, 160, 7, 7) │ 0.9830436706542969 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_84 │ AxQuantizedConv │ 609 │ FP32 │ (1, 960, 7, 7) │ 0.99485182762146 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_86 │ AxQuantizedConv │ 612 │ FP32 │ (1, 960, 7, 7) │ 0.9986639022827148 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_88 │ AxQuantizedConv │ 615 │ FP32 │ (1, 160, 7, 7) │ 0.9871683716773987 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Add_89 │ AxQuantizedAdd │ 452 │ FP32 │ (1, 160, 7, 7) │ 0.9710026383399963 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_90 │ AxQuantizedConv │ 618 │ FP32 │ (1, 960, 7, 7) │ 0.9886921048164368 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_92 │ AxQuantizedConv │ 621 │ FP32 │ (1, 960, 7, 7) │ 0.9995152950286865 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_94 │ AxQuantizedConv │ 624 │ FP32 │ (1, 320, 7, 7) │ 0.9987302422523499 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Conv_95 │ AxQuantizedConv │ 627 │ FP32 │ (1, 1280, 7, 7) │ 0.9998956918716431 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ GlobalAveragePool_97 │ AxQuantizedAvgPool │ 464 │ FP32 │ (1, 1280, 1, 1) │ 0.9999791979789734 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Reshape_103 │ AxReshape │ 472 │ FP32 │ (1, 1280) │ 0.9999794960021973 │
├──────────────────────┼───────────────────────────┼───────────────┼───────────┼───────────────────┼────────────────────┤
│ Gemm_104 │ AxQuantizedFullyConnected │ output │ FP32 │ (1, 1000) │ 0.99989914894104 │
└──────────────────────┴───────────────────────────┴───────────────┴───────────┴───────────────────┴────────────────────┘
...
提示
更加详细的内容,请参考 《量化精度分析参数说明》.
备注
如果配置文件中 "precision_analysis": false
,编译命令包含 --quant.precision_analysis 1
,此时依然会开启精度对比功能。
5.6. 加载自定义数据集详解
pulsar2 build
支持加载用户自定义的数据集用于量化,支持 .npy
以及 .bin
为后缀名的文件格式。
5.6.1. 准备数据集
建议在处理图片时,尽量与推理时的预处理相同,尽量避免使用训练时的数据增强,一些参考步骤如下:
读取图片
将图片
rbg channel
顺序对齐到模型输入缩放图片
归一化
上述步骤仅供参考,可以根据实际情况进行调整与删减。如有些模型并不要求图片做归一化,对此类模型即可省去归一化的步骤。
处理好图片后,将相应格式文件打包成压缩文件。
备注
npy
后缀名文件指以 Numpy
数组格式保存的文件,使用该文件格式时,需要保证保存时数组的数据类型、形状与相应的模型输入一致,后缀名为 .npy
。
bin
后缀名文件指以二进制格式保存的文件,使用该文件格式时,数据应以二进制保存,后缀名为 .bin
。
5.6.2. 配置与编译
修改 quant.input_configs.calibration_format
字段为 Numpy
或者 Binary
, 一个完整的示例如下:
{
"model_type": "ONNX",
"npu_mode": "NPU1",
"quant": {
"input_configs": [
{
"tensor_name": "input",
"calibration_dataset": "./dataset/npy_dataset.tar",
"calibration_size": 10,
"calibration_format": "Numpy", # 修改为 Numpy 或者 Binary, 默认是Image
}
],
"calibration_method": "MinMax",
},
"input_processors": [
{
"tensor_name": "input",
"tensor_format": "BGR",
"src_format": "BGR",
"src_dtype": "U8",
"src_layout": "NHWC",
"csc_mode": "NoCSC"
}
],
"compiler": {
"check": 0
}
}
执行编译,Quant Config Table
中的 Data Format
字段变更为了 Numpy
,结果参考如下:
root@aa:/data/quick_start_example# pulsar2 build --input model/mobilenetv2-sim.onnx --output_dir npy_output/ --config config/npy_config_mobilenet_v2_onnx.json
...
Quant Config Table
┏━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓
┃ Input ┃ Shape ┃ Dataset Directory ┃ Data Format ┃ Tensor Format ┃ Mean ┃ Std ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩
│ input │ [1, 3, 224, 224] │ input │ Numpy │ BGR │ [103.93900299072266, 116.77899932861328, 123.68000030517578] │ [58.0, 58.0, 58.0] │
└───────┴──────────────────┴───────────────────┴─────────────┴───────────────┴──────────────────────────────────────────────────────────────┴────────────────────┘
...
5.7. 多输入模型配置量化数据集
多输入的模型,不同输入需要不同的校准集,可以通过修改配置实现。
字段 input_configs
支持配置多个输入, 通过 tensor_name
指定模型的输入名,以下为一个配置示例:
{
"quant": {
"input_configs": [
{
"tensor_name": "input1", # 输入 1
"calibration_dataset": "input1_dataset.tar",
"calibration_size": 10,
"calibration_mean": [103.939, 116.779, 123.68],
"calibration_std": [58.0, 58.0, 58.0],
"calibration_format": "Image", #
},
{
"tensor_name": "input2", # 输入 2
"calibration_dataset": "input2_dataset.tar",
"calibration_size": 10,
"calibration_mean": [103.939, 116.779, 123.68],
"calibration_std": [58.0, 58.0, 58.0],
"calibration_format": "Image",
},
],
}
}
5.8. 多输入模型配置量化数据集(NumpyObject)
多输入的模型,不同输入需要不同的校准集,也可以通过使用 NumpyObject 实现,
字段 input_configs
支持配置多个输入, 通过 tensor_name
指定模型的输入名,以下为一个配置示例:
{
"quant": {
"input_configs": [
{
"tensor_name": "DEFUALT",
"calibration_dataset": "dataset.tar",
"calibration_size": -1,
"calibration_format": "NumpyObject", # 数据类型
},
],
}
}
5.8.1. 准备数据集
NumpyObject 是 Numpy 提供的一种字典数据类型。 字典数据与模型中 input 对应,其中 key 为模型的 input 名。 value 为较准数据,类型和形状要与相应的 input 相同,即做完预处理后直接输入到模型的数据, 格式为 numpy.ndarray 。 value 的数据处理与 《加载自定义数据集详解》 相同。
假设模型有两个输入如下图:
下面是一个最简单的生成示例代码:
import numpy as np
calib_data = {}
calib_data["rgb"] = np.random.randn(1, 2, 3, 224, 224).astype(np.float32)
calib_data["inst_emb"] = np.random.randn(1, 384).astype(np.float32)
np.save("data.npy", calib_data)
在生产环境中,建议调用推理代码的 dataloader , 对其进行遍历, 将遍历得到的数据转成 Numpy.ndarray 类型后按照字典保存为 NumpyObject , 就可以直接获取到做完预处理后的数据。
5.9. 混合精度量化详解
pulsar2 build
支持混合精度量化,可以对指定 算子
或者 一类算子
或者 某个子图
设置量化精度。
5.9.1. 配置
修改 quant.layer_configs
字段,目前量化精度支持的枚举: U8
, U16
, FP32
。
以下为一个配置示例:
{
"model_type": "ONNX",
"npu_mode": "NPU1",
"quant": {
"input_configs": [
{
"tensor_name": "DEFAULT",
"calibration_dataset": "./dataset/imagenet-32-images.tar",
"calibration_size": 32,
"calibration_mean": [103.939, 116.779, 123.68],
"calibration_std": [58.0, 58.0, 58.0]
}
],
"layer_configs": [
{
"op_type": "Add", # 指定 Add 类型的算子的量化精度
"data_type": "U16"
},
{
"layer_name": "conv6_4", # 指定 conv6_4 算子的量化精度
"data_type": "U16"
},
{
# 指定 conv2_1_linear_bn 与 relu2_2_dwise 之间子图内包含的算子量化精度
"start_tensor_names": ["conv2_1_linear_bn"], # string of list
"end_tensor_names": ["relu2_2_dwise"], # string of list
"data_type": "U16"
}
],
"calibration_method": "MinMax",
"precision_analysis": false
},
"input_processors": [
{
"tensor_name": "input",
"tensor_format": "BGR",
"src_format": "BGR",
"src_dtype": "U8",
"src_layout": "NHWC",
"csc_mode": "NoCSC"
}
],
"compiler": {
"check": 0
}
}
5.9.2. 子图配置说明
配置 某个子图
为指定的类型时,需要注意 start_tensor_names
和 end_tensor_names
指定的是 tensor_name
, 而非 node_name
。
如果想配置整个模型为某个量化类型,可以将 start_tensor_names
和 end_tensor_names
设置成 [''DEFAULT'']
,下面是一个示例:
{
"layer_configs": [
{
"start_tensor_names": ["DEFAULT"], # string of list
"end_tensor_names": ["DEFAULT"], # string of list
"data_type": "U16"
}
]
}
Conv
类型算子,不支持配置 data_type
为 FP32
,但是可以单独配置其输出支持 FP32
,通过如下配置实现:
{
"layer_configs": [
{
"op_type": "Conv",
"data_type": "U8",
"output_data_type": "FP32", # 配置输出为FP32, 该配置目前只对Conv算子生效
}
]
}
下面是配置整个模型除了 Conv
外其余算子为 FP32
量化类型的config:
{
"layer_configs": [
{
"op_type": "Conv",
"data_type": "U8",
"output_data_type": "FP32", # 配置输出为FP32, 该配置目前只对Conv算子生效
},
{
"start_tensor_names": ["DEFAULT"], # string of list
"end_tensor_names": ["DEFAULT"], # string of list
"data_type": "FP32"
}
]
}
备注
对于一个算子来说,可能同时存在 指定算子
或者 一类算子
或者 某个子图
三个量化精度配置,优先级为:
指定算子
> 一类算子
> 某个子图
注意
目前 FP32
配置支持的算子有限,已经验证过的算子有 LeayRelu
Sigmoid
Relu
Add
Mul
Div
Sub
Concat
Softmax
。
5.9.3. 编译与结果
编译时会有 Layer Config Table
展示当前layer_configs的配置。
root@aa:/data/quick_start_example# pulsar2 build --input model/mobilenetv2-sim.onnx --output_dir output --config config/mobilenet_v2_mix_precision_config.json
...
Quant Config Table
┏━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓
┃ Input ┃ Shape ┃ Dataset Directory ┃ Data Format ┃ Tensor Format ┃ Mean ┃ Std ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩
│ input │ [1, 3, 224, 224] │ input │ Image │ BGR │ [103.93900299072266, 116.77899932861328, 123.68000030517578] │ [58.0, 58.0, 58.0] │
└───────┴──────────────────┴───────────────────┴─────────────┴───────────────┴──────────────────────────────────────────────────────────────┴────────────────────┘
Layer Config Table
┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Op Type / Layer name ┃ Precision ┃
┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Add │ U16 │
├──────────────────────┼───────────┤
│ conv6_4 │ U16 │
└──────────────────────┴───────────┘
...
编译结束后会在 output/quant
目录下生成一个 quant_axmodel.json
文件,里面记录了每个算子的量化配置信息,下面节选了其中一部分用作示例。
"Add_26": {
"507": {
"bit_width": 16,
"policy": {
"PER_TENSOR": true,
"PER_CHANNEL": false,
"LINEAR": true,
"EXPONENTIAL": false,
"SYMMETRICAL": false,
"ASYMMETRICAL": true,
"POWER_OF_2": false
},
"state": "ACTIVATED",
"quant_min": 0,
"quant_max": 65535,
"hash": 762206185,
"dominator": 762206185
},
"516": {
"bit_width": 16,
"policy": {
"PER_TENSOR": true,
"PER_CHANNEL": false,
"LINEAR": true,
"EXPONENTIAL": false,
"SYMMETRICAL": false,
"ASYMMETRICAL": true,
"POWER_OF_2": false
},
"state": "OVERLAPPED",
"quant_min": 0,
"quant_max": 65535,
"hash": 3471866632,
"dominator": 4099361028
}
}
5.10. 修改原始模型输入尺寸
通过修改配置文件,可以在模型转换过程中修改各输入的尺寸。
接下来以 mobilenetv2
为基础,将模型输入修改为 384*384
命令行方式,增加参数:
--input_shapes data:1x3x384x384
配置文件方式,在根节点增加参数:
{
...
"input_shapes": "data:1x3x384x384",
...
}
转换模型过程中会出现以下日志,说明模型输入尺寸已修改成功:
INFO[0006] 2023-08-24 20:04:59.530 | WARNING | yamain.command.load_model:optimize_onnx_model:640 - change input shape to {'data': (1, 3, 384, 384)}
备注
模型输入尺寸修改作用在量化之前,量化数据集的尺寸需要与修改后的尺寸保持一致。
多组输入之间用半角分号分隔,详情参考参数详解部分。
5.11. 配置模型额外输入尺寸
通过配置在模型编译过程中,除原始模型的主尺寸之外,可以输出额外其他若干组尺寸。这些尺寸都会保存在同一个 compiled.axmodel
中。
多组尺寸之间会复用同一组权重数据(量化工具将会在模型原始尺寸的基础上进行量化),用户需要自行评估量化时尺寸与推理时尺寸不同而可能导致的精度问题。
接下来将以 mobilenetv2
为例,在原输入尺寸 224*224
的基础上,额外增加一个尺寸 384*384
,然后通过 pulsar2 run
工具选择尺寸进行仿真。
修改配置文件,在
input_processors
节点中,对输入配置一个src_extra_shapes
子节点:
{
...
"input_processors": [
{
"tensor_name": "DEFAULT",
"tensor_format": "BGR",
"src_format": "BGR",
"src_dtype": "U8",
"src_layout": "NHWC",
"src_extra_shapes": [
{
"shape": [1, 3, 384, 384]
}
],
"csc_mode": "NoCSC",
"csc_mat": [
1.164, 2.017, 0, -276.8, 1.164, -0.392, -0.813, 135.616, 1.164, 0,
1.596, -221.912
]
}
],
...
}
模型编译编译过程中,出现以下日志可以确认配置生效:
2024-01-01 21:27:02.082 | INFO | yamain.command.build:compile_ptq_model:973 - extra input shape, index: 1, shape: {'data': (1, 3, 384, 384)}
编译结束以后,
compiled.axmodel
中将会包含两个独立尺寸的子图,可以单独进行推理。
pulsar2 run
包含--group_index
参数,用于选择不同尺寸的子图进行仿真,该参数默认值为 0,对应原始分辨率的子图(224*224)。1 对应额外分辨率的子图(384*384)。AXEngine
推理包含额外输入尺寸的模型时选择不同尺寸的方式,请参考AXEngine 文档
。
5.12. 算子属性修改
通过修改配置文件,可以在模型转换过程中修改特定算子的属性。
接下来以 mobilenetv2
为基础,将其中名为 pool6
的 AveragePool
算子的 ceil_mode
修改为 1
,在配置文件中增加以下内容:
"op_processors": [
{
"op_name": "pool6",
"attrs": {
"ceil_mode": 1
}
}
],
使用 pulsar2 build
转换模型会出现以下日志,说明算子属性已修改成功:
2023-05-07 18:47:34.274 | INFO | yamain.command.load_model:op_attr_patch:488 - set op [pool6] attr [ceil_mode] to 1
5.13. 常量数据修改
通过修改配置文件,可以在模型转换过程中修改特定常量数据。
假设某个模型中包含一个名为 reshape_0
的 Reshape
算子,此算子的 shape
输入为名为 reshape_0_shape
的常量数据,原始数据为 [1, 96, 48]
。
在配置文件中增加以下内容,可以将该常量数据修改为 [-1, 96, 48]
。
"const_processors": [
{
"name": "reshape_0_shape",
"data": [-1, 96, 48]
}
],
使用 pulsar2 build
转换模型会出现以下日志,说明常量数据已修改成功:
2023-05-07 18:15:41.464 | WARNING | yamain.command.load_model:const_patch:512 - update data of const tensor [reshape_0_shape], (-1,, 96, 48), S64
5.14. Transformer模型配置详解
针对Transformer模型,可以通过 quant.transformer_opt_level
来设置不同等级的优化。
目前支持设置 0
, 1
, 2
三个等级。
下面以 Swin-T
模型示例,配置如下:
"quant": {
"input_configs": [
{
"tensor_name": "DEFAULT",
"calibration_dataset": "dataset.tar",
"calibration_format": "Image",
"calibration_size": 32,
"calibration_mean": [123.68, 116.779, 103.939],
"calibration_std": [58.62, 57.34, 57.6]
}
],
"calibration_method": "MSE",
"transformer_opt_level": 2 # 设置transformer优化等级为2
},
使用 pulsar2 build
转换模型会出现以下日志,说明配置修改成功:
INFO[0176] Transformer optimize level: 2
下表是 Swin-T
在不同优化等级下的精度和性能表现 ,该模型浮点精度(acc1)为 81.2%
优化等级 |
精度(acc1) |
耗时 |
---|---|---|
1 |
80.488% |
7.266ms |
2 |
80.446% |
7.114ms |
备注
当前版本建议设置等级 1
, 在实测中等级 2
较等级 1
的性能提升幅度较小,而等级 1
的精度要略优。
备注
目前已经验证过的模型有 Swin
系列, SwinV2
系列, Deit
系列, Vit
系列。
5.15. Quantized ONNX 模型导入
为了支持客户自行量化的模型(包括 4 bit QAT 量化),AX650
M76H
支持量化后的 Quantized ONNX 格式的模型作为输入。模型格式采用了 ONNX QDQ 格式。
下面以 resnet50 和 yolov5s 4w8f 模型为例,演示如何对 Quantized ONNX 格式的模型进行编译。
首先请下载我们已经转换好的模型,点击下载 resnet50
,点击下载 yolov5s
然后对 resnet50 使用如下的配置文件:
{
"model_type": "QuantONNX",
"npu_mode": "NPU1",
"quant": {
"input_configs": [
{
"tensor_name": "DEFAULT",
"calibration_dataset": "s3://npu-ci/data/dataset_v04.zip",
"calibration_size": 64,
"calibration_mean": [103.939, 116.779, 123.68],
"calibration_std": [1.0, 1.0, 1.0]
}
],
"calibration_method": "MinMax"
},
"input_processors": [
{
"tensor_name": "data",
"src_format": "BGR",
"src_dtype": "U8",
"src_layout": "NHWC"
}
],
"compiler": {
"check": 0
}
}
最后使用 pulsar2 build 命令进行编译,即可得到 compiled.axmodel
文件。
pulsar2 build --target_hardware AX650 --input path/to/model.onnx --config path/to/config.json --output_dir output
提示
在配置文件中通过 "model_type": "QuantONNX"
指定输入模型的类型为 Quantized ONNX。
使用类似的方法,我们可以对 yolov5s Quantized ONNX 格式的模型进行编译,只需要替换成如下的配置文件进行编译即可:
{
"model_type": "QuantONNX",
"npu_mode": "NPU1",
"quant": {
"input_configs": [
{
"tensor_name": "DEFAULT",
"calibration_dataset": "s3://npu-ci/data/coco_calib_image.tar",
"calibration_size": 32,
"calibration_mean": [0, 0, 0],
"calibration_std": [255.0, 255.0, 255.0]
}
],
"layer_configs": [
{
"op_type": "Silu",
"data_type": "U16"
}
],
"calibration_method": "MSE"
},
"input_processors": [
{
"tensor_name": "DEFAULT",
"tensor_format": "RGB",
"tensor_layout": "NCHW",
"src_format": "BGR",
"src_layout": "NHWC",
"src_dtype": "U8"
}
],
"compiler": {
"check": 0
}
}
5.16. 色彩空间转换配置
支持客户通过配置在模型中添加色彩空间转换功能,由 NPU
完成从 YUV
色彩空间到 RGB
色彩空间的转换。详细配置请参考 《预处理、后处理参数说明》
{
"input_processors": [
{
"tensor_name": "DEFAULT",
"tensor_format": "BGR",
"src_format": "YUV420SP", # 指定编译后模型的输入色彩空间
"src_dtype": "U8",
"src_layout": "NHWC",
"csc_mode": "LimitedRange"
}
]
}