Rspress

# #精度debug工具

模型转换工具链会基于您提供的校准样本对模型进行校准量化并保障模型高效的部署在地平线计算平台上。而在模型转换的过程中，难免会因为浮点到定点的量化过程而引入精度损失，通常情况下造成精度损失的主要原因可能有以下几点：

1. 模型中的一部分节点对量化比较敏感会引入较大误差，即敏感节点量化问题。

2. 模型中各个节点的误差累积导致模型整体出现较大的校准误差，主要包含：权重量化导致的误差累积、激活量化导致的误差累积以及全量量化导致的误差累积。

针对该情况，地平线提供了精度debug工具用以协助您自主定位模型量化过程中产生的精度问题。该工具能够协助您对校准模型进行节点粒度的量化误差分析，最终帮助您快速定位出现精度异常的节点。

精度debug工具提供多种分析功能供您使用，例如：

- 获取节点量化敏感度。

- 获取模型累积误差曲线。

- 获取指定节点的数据分布。

- 获取指定节点输入数据通道间数据分布箱线图等。

## #快速上手

使用精度debug工具主要有以下几个步骤：

1. 在yaml中的 模型参数组(model_parameters) 配置参数 `debug_mode: "dump_calibration_data"` ，保存校准数据。

2. 导入debug模块，加载校准模型和数据。

3. 通过精度debug工具提供的API或命令行，对精度损失明显的模型进行分析。

整体流程如下图所示：

- 确认单独量化激活/权重的累积误差情况，详见：plot_acc_error 章节。

- 激活敏感度排序，详见：get_sensitivity_of_nodes 章节。

- 权重敏感度排序，详见：get_sensitivity_of_nodes 章节。

- 节点敏感度排序，详见：get_sensitivity_of_nodes 章节。

- 查看敏感激活层分布情况，详见：plot_distribution 章节以及 get_channelwise_data_distribution 章节。

- 查看敏感权重分布情况，详见：plot_distribution 章节以及 get_channelwise_data_distribution 章节。

- 敏感节点单独量化及部份量化测试，详见：sensitivity_analysis 章节。

### #校准模型与数据的保存

首先需要在yaml文件中配置 `debug_mode: "dump_calibration_data"`，以开启精度debug功能，并保存校准数据(calibration_data)，对应的校准模型(calibrated_model.onnx)为常态化保存。其中：

- 校准数据(calibration_data)：在校准阶段，模型通过对这些数据进行前向推理来获取每个被量化节点的量化参数，包括：缩放因子(scale)和阈值(threshold)。

- 校准模型(calibrated_model.onnx)：将在校准阶段计算得到的每个被量化节点的量化参数保存在校准节点中，从而得到校准模型。

注解

此处保存的校准数据与02_preprocess.sh生成的校准数据的区别？

在工具链中，`02_preprocess.sh` 得到的校准数据与此处保存的校准数据相同，均为.npy格式，可直接用于debug工具测试模型精度。需要注意的是，在送入debug工具之前需要确认 `02_preprocess.sh` 得到的校准数据文件夹结构与此处保存的校准数据文件夹结构需要一致。

注解

校准模型(calibrated_model.onnx)解读

校准模型是模型转换工具链将浮点模型经过结构优化后，通过校准数据计算得到的每个节点对应的量化参数并将其保存在校准节点中得到的中间产物。校准模型的主要特点是模型中包含校准节点，校准节点的节点类型为HzCalibration。这些校准节点主要分为两类： 激活(activation)校准节点 和 权重(weight)校准节点 。

激活校准节点 的输入是当前节点的上一个节点的输出，并基于当前激活校准节点中保存的量化参数(scales和thresholds)对输入数据进行量化及反量化后输出。

权重校准节点 的输入为模型的原始浮点权重，基于当前权重校准节点中保存的量化参数(scales和thresholds)对输入的原始浮点权重进行量化及反量化后输出。

除却上述的校准节点，校准模型中的其他节点，精度debug工具将其称为 普通节点(node) 。 普通节点 的类型包括：Conv、Mul、Add等。

calibration_data的文件夹结构如下：

`|--calibration_data ：校准数据 |----input.1 ：文件夹名为模型的输入节点并保存对应的输入数据 |--------0.npy |--------1.npy |-------- ... |----input.2 ：对于多输入模型将保存多个文件夹 |--------0.npy |--------1.npy |-------- ...`

### #精度debug模块导入与使用

接下来需要在代码中导入debug模块，并通过 `get_sensitivity_of_nodes` 接口获取节点量化敏感度（默认使用模型输出的余弦相似度）。`get_sensitivity_of_nodes` 的详细参数说明可见 get_sensitivity_of_nodes 章节。

`# 导入debug模块 import hmct.quantizer.debugger as dbg # 导入log日志模块 import logging # 若verbose=True时，需要先设置log level为INFO logging.getLogger().setLevel(logging.INFO) # 获取节点量化敏感度 node_message = dbg.get_sensitivity_of_nodes( model_or_file='./calibrated_model.onnx', metrics=['cosine-similarity', 'mse'], calibrated_data='./calibration_data/', output_node=None, node_type='node', data_num=None, verbose=True, interested_nodes=None)`

### #分析结果展示

下方为 `verbose=True` 时的打印结果：

`=================node sensitivity================= node cosine-similarity mse --------------------------------------------------- Conv_60 0.77795 68.02103 Conv_48 0.78428 64.36318 Conv_82 0.80394 61.09268 Conv_94 0.80499 65.05224 Conv_42 0.83787 49.4949 Conv_88 0.84614 49.81132 Conv_54 0.86602 41.69972 Conv_71 0.87148 39.96296 Conv_65 0.87495 40.45997 Conv_25 0.89214 34.30351 Conv_20 0.89829 32.35053 Conv_77 0.89916 31.9907 Conv_14 0.90058 32.40179 Conv_9 0.90107 34.08191 Conv_37 0.91162 28.21194 Conv_31 0.91637 28.79291`

除此之外，该API会以字典(Dict)的形式将节点量化敏感度信息返回给您以供后续使用分析。

`Out: {'Conv_60': {'cosine-similarity': 0.77795, 'mse': 68.02103}, 'Conv_48': {'cosine-similarity': 0.78428, 'mse': 64.36318}, 'Conv_82': {'cosine-similarity': 0.80394, 'mse': 61.09268}, 'Conv_94': {'cosine-similarity': 0.80499, 'mse': 65.05224}, 'Conv_42': {'cosine-similarity': 0.83787, 'mse': 49.4949}, 'Conv_88': {'cosine-similarity': 0.84614, 'mse': 49.81132}, 'Conv_54': {'cosine-similarity': 0.86602, 'mse': 41.69972}, 'Conv_71': {'cosine-similarity': 0.87148, 'mse': 39.96296}, 'Conv_65': {'cosine-similarity': 0.87495, 'mse': 40.45997}, 'Conv_25': {'cosine-similarity': 0.89214, 'mse': 34.30351}, 'Conv_20': {'cosine-similarity': 0.89829, 'mse': 32.35053}, 'Conv_77': {'cosine-similarity': 0.89916, 'mse': 31.9907}, 'Conv_14': {'cosine-similarity': 0.90058, 'mse': 32.40179}, 'Conv_9': {'cosine-similarity': 0.90107, 'mse': 34.08191}, 'Conv_37': {'cosine-similarity': 0.91162, 'mse': 28.21194}, 'Conv_31': {'cosine-similarity': 0.91637, 'mse': 28.79291}}`

更多功能详见 功能说明文档 章节。

为了方便您使用，精度debug工具还支持通过命令行进行使用，可通过 `hmct-debugger -h/--help` 查看每个功能对应的子命令。各个子命令的详细参数和用法详见 功能说明文档 章节。

## #功能说明文档

### #get_sensitivity_of_nodes

功能：获取节点量化敏感度。

命令行格式：

`hmct-debugger get-sensitivity-of-nodes MODEL_OR_FILE CALIBRATION_DATA --other options`

可通过 `hmct-debugger get-sensitivity-of-nodes -h/--help` 查看相关参数。

参数组：

参数名称 | 命令行参数缩写 | 参数配置说明 | 可选/必选
--- | --- | --- | ---
`model_or_file` | 固定参数 | 参数作用：指定校准模型。 取值范围：无。 默认配置：无。 参数说明：必选，指定需要分析的校准模型。 | 必选
`metrics` | `-m` | 参数作用：节点量化敏感度的度量方式。 取值范围： `'cosine-similarity'` , `'mse'` , `'mae'` , `'mre'` , `'sqnr'` , `'chebyshev'` 。 默认配置： `'cosine-similarity'`。 参数说明：指定节点量化敏感度的计算方式，该参数可以为列表(List)，即以多种方式计算量化敏感度，但是输出结果仅以列表中第一位的计算方式进行排序，排名越靠前说明量化该节点引入的误差越大。 | 可选
`calibrated_data` | 固定参数 | 参数作用：指定校准数据。 取值范围：无。 默认配置：无。 参数说明：必选，指定分析所需要的校准数据。 | 必选
`output_node` | `-o` | 参数作用：指定输出节点。 取值范围：校准模型中的具有对应校准节点的普通节点。 默认配置：None。 参数说明：此参数支持您指定中间节点作为输出并计算节点量化敏感度。若保持默认参数，则精度debug工具会获取模型的最终输出并在此基础上计算节点的量化敏感度。 | 可选
`node_type` | `-n` | 参数作用：节点类型。 取值范围： `'node'` , `'weight'` ,`'activation'`。 默认配置： `'node'`。 参数说明：需要计算量化敏感度的节点类型，包括：node（普通节点）、weight（权重校准节点）、activation（激活校准节点）。 | 可选
`data_num` | `-d` | 参数作用：计算量化敏感度需要的数据数量。 取值范围：大于0，小于等于calibration_data中数据的总数。 默认配置：1 参数说明：设置计算节点量化敏感度时所需要的数据数量。默认为1，此时使用calibration_data中的第一组数据进行计算。最小设置为1，最大为calibration_data中的数据数量。 | 可选
`verbose` | `-v` | 参数作用：选择是否将信息打印在终端上。 取值范围： `True` 、 `False`。 默认配置： `False`。 参数说明：若为True，则将量化敏感度信息打印在终端上。若metrics包含多种度量方式，则按照第一位进行排序。 | 可选
`interested_nodes` | `-i` | 参数作用：设置感兴趣节点。 取值范围：校准模型中的所有节点。 默认配置：None。 参数说明：若指定则只获取该节点的量化敏感度，其余节点不获取。同时，若该参数被指定，将忽视node_type指定的节点类型，也就是说该参数的优先级要高于node_type。若保持默认参数None，则计算模型中所有可被量化节点的量化敏感度。 | 可选
`save_dir` | `-s` | 参数作用：保存路径。 取值范围： 无。 默认配置： `None`。 参数说明：可选，指定分析结果的保存路径。 | 可选

API使用方法：

`# 导入debug模块 import hmct.quantizer.debugger as dbg # 导入log日志模块 import logging # 若verbose=True时，需要先设置log level为INFO logging.getLogger().setLevel(logging.INFO) # 获取节点量化敏感度 node_message = dbg.get_sensitivity_of_nodes( model_or_file='./calibrated_model.onnx', metrics=['cosine-similarity', 'mse'], calibrated_data='./calibration_data/', output_node=None, node_type='node', data_num=None, verbose=True, interested_nodes=None, save_dir="./debug_result")`

命令行使用方法：

`hmct-debugger get-sensitivity-of-nodes calibrated_model.onnx calibration_data -m ['cosine-similarity','mse'] -v True -s ./debug_result`

分析结果展示：

描述：首先您通过node_type设置需要计算敏感度的节点类型，然后工具获取校准模型中所有符合node_type的节点，并获取这些节点的量化敏感度。当verbose设置为True时，工具会将节点量化敏感度进行排序后打印在终端，排序越靠前，说明该节点量化引入的量化误差越大。同时对于不同的node_type，工具会显示不同的节点量化敏感度信息。

verbose=True且node_type='node'时，打印结果如下：

`=================node sensitivity================= node cosine-similarity mse --------------------------------------------------- Conv_60 0.77795 68.02103 Conv_48 0.78428 64.36318 Conv_82 0.80394 61.09268 Conv_94 0.80499 65.05224 Conv_42 0.83787 49.4949 Conv_88 0.84614 49.81132 Conv_54 0.86602 41.69972 Conv_71 0.87148 39.96296 Conv_65 0.87495 40.45997 Conv_25 0.89214 34.30351 Conv_20 0.89829 32.35053 Conv_77 0.89916 31.9907 Conv_14 0.90058 32.40179 Conv_9 0.90107 34.08191 Conv_37 0.91162 28.21194 Conv_31 0.91637 28.79291`

其中：

- node：节点名。

- cosine-similarity、mse：各个节点的量化敏感度数值。

verbose=True且node_type='weight'时，打印结果如下：

`====================================node sensitivity==================================== weight node cosine-similarity mse ----------------------------------------------------------------------------------------- 471_HzCalibration Conv_2 0.99978 0.07519 480_HzCalibration Conv_7 0.99986 0.04823 609_HzCalibration Conv_88 0.99997 0.01145 573_HzCalibration Conv_65 0.99997 0.00984 474_HzCalibration Conv_4 0.99997 0.00963 468_HzCalibration Conv_0 0.99997 0.0091 612_HzCalibration Conv_90 0.99997 0.00871 585_HzCalibration Conv_73 0.99997 0.0095 483_HzCalibration Conv_9 0.99998 0.00818 600_HzCalibration Conv_82 0.99998 0.00717 582_HzCalibration Conv_71 0.99998 0.00659 603_HzCalibration Conv_84 0.99998 0.00614 591_HzCalibration Conv_77 0.99998 0.00558 489_HzCalibration Conv_12 0.99998 0.00515 564_HzCalibration Conv_60 0.99999 0.00495 618_HzCalibration Conv_94 0.99999 0.00498 543_HzCalibration Conv_46 0.99999 0.00502 552_HzCalibration Conv_52 0.99999 0.00501 594_HzCalibration Conv_78 0.99999 0.00451 555_HzCalibration Conv_54 0.99999 0.00452 ...99classifier.1.weight_conv_weight_HzCalibration Gemm_99 0.99999 0.00359 558_HzCalibration Conv_56 0.99999 0.00369`

其中：

- weight：权重校准节点名。

- node：权重校准节点对应的普通节点名，即权重校准节点的输出为其输入。

- cosine-similarity、mse：各个节点的量化敏感度数值。

verbose=True且node_type='activation'时，打印结果如下：

`===================================node sensitivity=================================== activation node threshold bit cosine-similarity mse --------------------------------------------------------------------------------------- 406_HzCalibration Conv_60 0.91501 8 0.77851 67.82422 388_HzCalibration Conv_48 0.55422 8 0.78501 64.16379 440_HzCalibration Conv_82 2.01577 8 0.8041 61.0322 458_HzCalibration Conv_94 0.51507 8 0.80466 65.14515 379_HzCalibration Conv_42 0.53759 8 0.83837 49.35648 449_HzCalibration Conv_88 2.34071 8 0.84447 50.29965 397_HzCalibration Conv_54 0.81528 8 0.86499 41.99234 423_HzCalibration Conv_71 0.84753 8 0.87104 40.09385 414_HzCalibration Conv_65 0.80155 8 0.87443 40.63319 353_HzCalibration Conv_25 0.67858 8 0.89199 34.34844 345_HzCalibration Conv_20 1.06324 8 0.8984 32.31664 432_HzCalibration Conv_77 2.54515 16 0.89895 32.0417 336_HzCalibration Conv_14 1.01407 8 0.90091 32.30325 328_HzCalibration Conv_9 1.61622 8 0.90163 33.78012 371_HzCalibration Conv_37 0.91038 8 0.91277 27.84864 362_HzCalibration Conv_31 0.65606 8 0.91683 28.65791 403_HzCalibration Conv_58 0.95119 8 0.93365 21.32314 391_HzCalibration Conv_50;Add_55 2.92598 8 0.93984 19.72109 382_HzCalibration Conv_44;Add_49 2.75416 8 0.95122 17.74137 417_HzCalibration Conv_67;Add_72 2.85463 8 0.95139 15.81864`

其中：

- activation：激活校准节点名。

- node：在模型结构中在激活校准节点后的普通节点，即激活校准节点的输出为其输入。

- threshold：校准阈值，若有多个阈值则取最大值。

- bit：量化比特。

- cosine-similarity、mse：各个节点的量化敏感度数值。

API返回值：

API返回值为以字典格式（Key为节点名称，Value为节点的量化敏感度信息）保存的量化敏感度，格式如下：

`Out: {'Conv_60': {'cosine-similarity': 0.77795, 'mse': 68.02103}, 'Conv_48': {'cosine-similarity': 0.78428, 'mse': 64.36318}, 'Conv_82': {'cosine-similarity': 0.80394, 'mse': 61.09268}, 'Conv_94': {'cosine-similarity': 0.80499, 'mse': 65.05224}, 'Conv_42': {'cosine-similarity': 0.83787, 'mse': 49.4949}, 'Conv_88': {'cosine-similarity': 0.84614, 'mse': 49.81132}, 'Conv_54': {'cosine-similarity': 0.86602, 'mse': 41.69972}, 'Conv_71': {'cosine-similarity': 0.87148, 'mse': 39.96296}, 'Conv_65': {'cosine-similarity': 0.87495, 'mse': 40.45997}, 'Conv_25': {'cosine-similarity': 0.89214, 'mse': 34.30351}, 'Conv_20': {'cosine-similarity': 0.89829, 'mse': 32.35053}, 'Conv_77': {'cosine-similarity': 0.89916, 'mse': 31.9907}, 'Conv_14': {'cosine-similarity': 0.90058, 'mse': 32.40179}, 'Conv_9': {'cosine-similarity': 0.90107, 'mse': 34.08191}, 'Conv_37': {'cosine-similarity': 0.91162, 'mse': 28.21194}, 'Conv_31': {'cosine-similarity': 0.91637, 'mse': 28.79291}}`

### #plot_acc_error

功能：只量化浮点模型中的某一个节点，并依次计算该模型与浮点模型中节点输出的误差，获得累积误差曲线。

命令行格式:

`hmct-debugger plot-acc-error MODEL_OR_FILE CALIBRATION_DATA --other options`

可通过 `hmct-debugger plot-acc-error -h/--help` 查看相关参数。

参数组：

参数名称 | 命令行参数缩写 | 参数配置说明 | 可选/必选
`save_dir` | `-s` | 参数作用：保存路径。 取值范围：无。 默认配置：无。 参数说明：可选，指定分析结果的保存路径。 | 可选
`calibrated_data` | 固定参数 | 参数作用：指定校准数据。 取值范围：无。 默认配置：无。 参数说明：必选，指定需要分析的校准数据。 | 必选
`model_or_file` | 固定参数 | 参数作用：指定校准模型。 取值范围：无。 默认配置：无。 参数说明：必选，指定需要分析的校准模型。 | 必选
`quantize_node` | `-q` | 参数作用：只量化模型中指定的节点，查看误差累积曲线。 取值范围：校准模型中的所有节点。 默认配置：None。 参数说明：可选参数。指定模型中需要量化的节点，同时保证其余节点均不量化。通过判断该参数是否为嵌套列表进而决定是单节点量化还是部分量化。 例如： quantize_node=['Conv_2','Conv_9']：分别只量化Conv_2和Conv_9，同时保证其余节点不量化。 quantize_node=[['Conv_2'],['Conv_9','Conv_2']]：只量化Conv_2以及同时量化Conv_2和Conv_9，分别测试模型累积误差。 quantize_node 包含两个特殊参数：'weight'和 'activation'。当： quantize_node = ['weight']：只量化权重，不量化激活。 quantize_node = ['activation']：只量化激活，不量化权重。 quantize_node = ['weight','activation']：权重和激活分别量化。 注：quantize_node和non_quantize_node不可同时为None，必须指定其一。 | 可选
`non_quantize_node` | `-nq` | 参数作用：指定累积误差的类型。 取值范围：校准模型中的所有节点。 默认配置：None。 参数说明：可选参数。指定模型中不量化的节点，同时保证其余节点全都量化。 通过判断该参数是否为嵌套列表进而决定是单节点不量化还是部分量化。 例如： non_quantize_node=['Conv_2','Conv_9']：分别解除Conv_2和Conv_9节点的量化，同时保证其余节点全部量化。 non_quantize_node=[['Conv_2'],['Conv_9','Conv_2']]：只解除Conv_2量化以及同时解除Conv_2和Conv_9量化，分别测试模型累积误差。 注：quantize_node和non_quantize_node不可同时为None，必须指定其一。 | 可选
`metric` | `-m` | 参数作用：误差度量方式。 取值范围：`'cosine-similarity'`，`'mse'`，`'mae'`，`'mre'`，`'sqnr'`，`'chebyshev'`。 默认配置：`'cosine-similarity'`。 参数说明：设置计算模型误差的计算方式。 | 可选
`average_mode` | `-a` | 参数作用：指定累积误差曲线的输出模式。 取值范围：`True` 、`False`。 默认配置：`False`。 参数说明：默认为False。若为True，那么获取累积误差的平均值作为结果。 | 可选

`# 导入debug模块 import hmct.quantizer.debugger as dbg dbg.plot_acc_error( save_dir: str, calibrated_data: str or CalibrationDataSet, model_or_file: ModelProto or str, quantize_node: List or str, non_quantize_node: List or str, metric: str = 'cosine-similarity', average_mode: bool = False)`

分析结果展示

1.指定节点量化累积误差测试

- 指定单节点量化

配置方式：quantize_node=['Conv_2','Conv_90']，quantize_node为单列表。

API使用方法：

`# 导入debug模块 import hmct.quantizer.debugger as dbg dbg.plot_acc_error( save_dir='./', calibrated_data='./calibration_data/', model_or_file='./calibrated_model.onnx', quantize_node=['Conv_2', 'Conv_90'], metric='cosine-similarity', average_mode=False)`

命令行使用方法：

`hmct-debugger plot-acc-error calibrated_model.onnx calibrated_data -q ['Conv_2','Conv_90']`

描述：当quantize_node为单列表时，针对您设置的quantize_node，分别单独量化quantize_node中的节点并保持模型中其他节点不量化，得到对应的模型后，对该模型中每个节点的输出计算其与浮点模型中对应节点输出的之间的误差，并得到对应的累积误差曲线。

average_mode = False时：

average_mode = True时：

注解

average_mode

average_mode默认为False。对于一些模型，此时无法通过累积误差曲线判断哪种量化策略更加有效，因此需要将average_mode设置为True，此时会对前n个节点的累积误差求均值作为第n个节点的累积误差。

具体计算方式如下，例如：

average_mode=False时，accumulate_error=[1.0, 0.9, 0.9, 0.8]。

而将average_mode=True后，accumulate_error=[1.0, 0.95, 0.933, 0.9]。

- 指定多个节点量化

配置方式：quantize_node=[['Conv_2'], ['Conv_2','Conv_90']]，quantize_node为嵌套列表

API使用方法：

`# 导入debug模块 import hmct.quantizer.debugger as dbg dbg.plot_acc_error( save_dir='./', calibrated_data='./calibration_data/', model_or_file='./calibrated_model.onnx', quantize_node=[['Conv_2'], ['Conv_2', 'Conv_90']], metric='cosine-similarity', average_mode=False)`

命令行使用方法：

`hmct-debugger plot-acc-error calibrated_model.onnx calibration_data -q [['Conv_2'],['Conv_2','Conv_90']]`

描述：当quantize_node为嵌套列表时，针对您设置的quantize_node，分别量化quantize_node中的每个单列表指定的节点并保持模型中其他节点不量化，得到对应的模型后，对该模型中每个节点的输出计算其与浮点模型中对应节点输出的之间的误差，并得到对应的累积误差曲线。

- partial_qmodel_0：只量化Conv_2节点，其余节点不量化；

- partial_qmodel_1：只量化Conv_2和Conv_90节点，其余节点不量化。

average_mode=False时：

average_mode=True时：

2.解除模型部分节点量化后累积误差测试

- 指定单节点不量化

配置方式：non_quantize_node=['Conv_2','Conv_90']，non_quantize_node为单列表。

API使用方法：

`# 导入debug模块 import hmct.quantizer.debugger as dbg dbg.plot_acc_error( save_dir='./', calibrated_data='./calibration_data/', model_or_file='./calibrated_model.onnx', non_quantize_node=['Conv_2', 'Conv_90'], metric='cosine-similarity', average_mode=True)`

命令行使用方法：

`hmct-debugger plot-acc-error calibrated_model.onnx calibration_data -nq ['Conv_2','Conv_90'] -a True`

描述：当non_quantize_node为单列表时，针对您设置的non_quantize_node，分别解除non_quantize_node中各个节点的量化同时保持其他节点全部量化，得到对应的模型后，对该模型中每个节点的输出计算其与浮点模型中对应节点输出的之间的误差，并得到对应的累积误差曲线。

average_mode = False时：

average_mode = True时：

- 指定多个节点不量化

配置方式：non_quantize_node=[['Conv_2'], ['Conv_2','Conv_90']]，non_quantize_node为嵌套列表。

API使用方法：

`# 导入debug模块 import hmct.quantizer.debugger as dbg dbg.plot_acc_error( save_dir='./', calibrated_data='./calibration_data/', model_or_file='./calibrated_model.onnx', non_quantize_node=[['Conv_2'], ['Conv_2', 'Conv_90']], metric='cosine-similarity', average_mode=False)`

命令行使用方法：

`hmct-debugger plot-acc-error calibrated_model.onnx calibration_data -nq [['Conv_2'],['Conv_2','Conv_90']]`

描述：当non_quantize_node为嵌套列表时，针对您设置的non_quantize_node，分别不量化non_quantize_node中的每个单列表指定的节点并保持模型中其他节点均量化，得到对应的模型后，对该模型中每个节点的输出计算其与浮点模型中对应节点输出的之间的误差，并得到对应的累积误差曲线。

- partial_qmodel_0：不量化Conv_2节点，其余节点量化；

- partial_qmodel_1：不量化Conv_2和Conv_90节点，其余节点量化。

average_mode = False时：

average_mode = True时：

测试技巧：

测试部分量化精度时，您可能会按照量化敏感度排序进行多组量化策略的精度对比，此时可以参考以下用法：

`# 导入debug模块 import hmct.quantizer.debugger as dbg # 首先使用量化敏感度排序函数获取模型中节点的量化敏感度排序 node_message = dbg.get_sensitivity_of_nodes( model_or_file='./calibrated_model.onnx', metrics='cosine-similarity', calibrated_data='./calibration_data/', output_node=None, node_type='node', verbose=False, interested_nodes=None) # node_message为字典类型，其key值为节点名称 nodes = list(node_message.keys()) # 通过nodes来指定不量化节点，可以方便使用 dbg.plot_acc_error( save_dir='./', calibrated_data='./calibration_data/', model_or_file='./calibrated_model.onnx', non_quantize_node=[nodes[:1],nodes[:2]], metric='cosine-similarity', average_mode=True)`

3.激活权重分别量化

配置方式：quantize_node=['weight','activation']。

API使用方法：

`import hmct.quantizer.debugger as dbg dbg.plot_acc_error( save_dir='./', calibrated_data='./calibration_data/', model_or_file='./calibrated_model.onnx', quantize_node=['weight','activation'], metric='cosine-similarity', average_mode=False)`

命令行使用方法：

`hmct-debugger plot-acc-error calibrated_model.onnx calibration_data -q ['weight','activation']`

描述：quantize_node也可直接指定'weight'或者'activation'。当：

- quantize_node = ['weight']：只量化权重，不量化激活。

- quantize_node = ['activation']：只量化激活，不量化权重。

- quantize_node = ['weight', 'activation']：权重和激活分别量化。

注解

通常情况下，建议您对累积误差曲线图中靠近模型输出位置的曲线部分多加关注。当采用某种量化方法后测试得到的累计误差曲线靠近模型输出位置的累积误差较小，即相似度较高时，我们建议您优先测试此种量化方法。

### #plot_distribution

功能：选取节点，分别获取该节点在浮点模型和校准模型中的输出，得到输出数据分布。另外，将两个输出结果做差，获取两个输出之间的误差分布。

命令行格式：

`hmct-debugger plot-distribution MODEL_OR_FILE CALIBRATION_DATA --other options`

可通过 `hmct-debugger plot-distribution -h/--help` 查看相关参数。

参数组：

参数名称 | 命令行参数缩写 | 参数配置说明 | 可选/必选
`save_dir` | `-s` | 参数作用：保存路径。 取值范围：无。 默认配置：无。 参数说明：可选，指定分析结果的保存路径。 | 可选
`model_or_file` | 固定参数 | 参数作用：指定校准模型。 取值范围：无。 默认配置：无。 参数说明：必选，指定需要分析的校准模型。 | 必选
`calibrated_data` | 固定参数 | 参数作用：指定校准数据。 取值范围：无。 默认配置：无。 参数说明：必选，指定需要分析的校准数据。 | 必选
`nodes_list` | `-n` | 参数作用：指定需要分析的节点。 取值范围：校准模型中的所有节点。 默认配置：无。 参数说明：必选，指定需要分析的节点。若nodes_list中的节点类型为： 权重校准节点：绘制原始权重和经过校准之后的权重的数据分布。 激活校准节点：绘制激活校准节点的输入数据分布。 普通节点：绘制该节点在量化前后的输出数据分布，同时绘制二者之间的误差分布。 注：nodes_list为 list 类型，可指定一系列节点，并且上述三种类型节点 可同时指定。 | 必选

`# 导入debug模块 import hmct.quantizer.debugger as dbg dbg.plot_distribution( save_dir: str, model_or_file: ModelProto or str, calibrated_data: str or CalibrationDataSet, nodes_list: List[str] or str)`

分析结果展示：

API使用方法：

`# 导入debug模块 import hmct.quantizer.debugger as dbg dbg.plot_distribution( save_dir='./', model_or_file='./calibrated_model.onnx', calibrated_data='./calibration_data', nodes_list=['317_HzCalibration', # 激活节点 '471_HzCalibration', # 权重节点 'Conv_2']) # 普通节点`

命令行使用方法：

`hmct-debugger plot-distribution calibrated_model.onnx calibration_data -n ['317_HzCalibration','471_HzCalibration','Conv_2']`

node_output：

weight：

activation：

注解

上方三幅图中，蓝色三角表示：数据绝对值的最大值。红色虚线表示：最大的校准阈值。

### #get_channelwise_data_distribution

功能：绘制指定校准节点输入数据通道间数据分布的箱线图。

命令行格式：

`hmct-debugger get-channelwise-data-distribution MODEL_OR_FILE CALIBRATION_DATA --other options`

可通过 `hmct-debugger get-channelwise-data-distribution -h/--help` 查看相关参数。

参数组：

参数名称 | 命令行参数缩写 | 参数配置说明 | 可选/必选
--- | --- | --- | ---
`save_dir` | `-s` | 参数作用：保存路径。 取值范围：无。 默认配置：无。 参数说明：可选，指定分析结果的保存路径。 | 可选
`model_or_file` | 固定参数 | 参数作用：指定校准模型。 取值范围：无。 默认配置：无。 参数说明：必选，指定分析所需要的校准模型。 | 必选
`calibrated_data` | 固定参数 | 参数作用：指定校准数据。 取值范围：无。 默认配置：无。 参数说明：必选，指定分析所需要的校准数据。 | 必选
`nodes_list` | `-n` | 参数作用：指定校准节点。 取值范围：校准模型中的所有权重校准节点和激活校准节点。 默认配置：无。 参数说明：必选，指定校准节点。 | 必选
`axis` | `-a` | 参数作用：指定channel所在的维度。 取值范围：小于节点输入数据的维度。 默认配置：None。 参数说明：channel信息所在shape中的位置。参数默认为None，此时对于激活校准节点，默认认为节点输入数据的第二个维度表示channel信息，即axis=1；对于权重校准节点，会读取该节点属性中的axis参数作为channel信息。 | 可选

`# 导入debug模块 import hmct.quantizer.debugger as dbg dbg.get_channelwise_data_distribution( save_dir: str, model_or_file: ModelProto or str, calibrated_data: str or CalibrationDataSet, nodes_list: List[str], axis: int = None)`

分析结果展示：

描述：针对您设置的校准节点列表node_list，从参数axis中获取channel所在的维度，获取节点输入数据通道间的数据分布。 其中axis默认为None，此时若节点为权重校准节点，则channel所在的维度默认为0；若节点为激活校准节点，则channel所在的维度默认为1。

权重校准节点：

激活校准节点：

输出结果如下图所示：

图中：

- 横坐标表示节点输入数据的通道数，图例中输入数据有96个通道。

- 纵坐标表示每个channel的数据分布范围，其中红色实线表示该channel数据的中位数，蓝色虚线表示均值。每个箱子的上下限分别表示上四分位数和下四分位数，上下限之外的离散点表示异常值，通过观察这些异常值绝对值的最大值来判断当前节点输入数据是否出现较大波动的情况。

关于如何通过观察箱线图判断节点是否存在量化风险，请参考PTQ精度debug示例: MobileVit_s精度问题分析。

### #sensitivity_analysis

功能：针对量化敏感节点，分别分析测试单独量化以及部分量化这些节点后的模型精度。

命令行格式：

`hmct-debugger sensitivity-analysis MODEL_OR_FILE CALIBRATION_DATA --other options`

可通过 `hmct-debugger sensitivity-analysis -h/--help` 查看相关参数。

参数组：

参数名称 | 命令行参数缩写 | 参数配置说明 | 可选/必选
--- | --- | --- | ---
`model_or_file` | 固定参数 | 参数作用：指定校准模型。 取值范围：无。 默认配置：无。 参数说明：必选，指定需要分析的校准模型。 | 必选
`calibrated_data` | 固定参数 | 参数作用：指定校准数据。 取值范围：无。 默认配置：无。 参数说明：必选，指定分析所需要的校准数据。 | 必选
`pick_threshold` | `-p` | 参数作用：设置选取节点的敏感度阈值。 取值范围：无。 默认配置：0.999。 参数说明：可选，此功能计算普通节点的量化敏感度，选择敏感度小于 pick_threshold的节点作为敏感节点进行分析测试。 注：当设置sensitive_nodes时，则直接对sensitive_nodes进行测试，不再 另行计算节点敏感度并根据pick_threshold选择敏感节点。 | 可选
`data_num` | `-d` | 参数作用：计算量化敏感度需要的数据数量。 取值范围：大于0，小于等于calibration_data中数据的总数。 默认配置：1。 参数说明：设置计算节点量化敏感度时所需要的数据数量。 | 可选
`sensitive_nodes` | `-sn` | 参数作用：指定需要分析的敏感节点。 取值范围：校准模型中的所有节点。 默认配置：无。 参数说明：可选，指定需要分析的敏感节点。 注：当设置此参数时，则直接对此参数中的节点进行测试，不再另行计算 节点敏感度并根据pick_threshold选择敏感节点。 | 可选
`qtype` | `-q` | 参数作用：敏感节点的目标qtype。 取值范围：`float32`，`int16`，`int8`。 默认配置：`float32`。 参数说明：可选，指定敏感节点的目标qtype。 | 可选
`save_dir` | `-sd` | 参数作用：保存路径。 取值范围：无。 默认配置：无。 参数说明：可选，指定分析结果的保存路径。 | 可选

API使用方法：

`# 导入debug模块 import hmct.quantizer.debugger as dbg dbg.sensitivity_analysis(model_or_file='calibrated_model.onnx', calibrated_data='calibration_data', pick_threshold=0.9999, data_num=1, qtype="float32", sensitive_nodes=[])`

命令行使用方法：

`hmct-debugger sensitivity-analysis calibrated_model.onnx calibration_data -q float32`

分析结果展示：

`==============Model output cosine-similarity analysis: float32=============== Index Node op_type original_qtype original improved_qtype improved ----------------------------------------------------------------------------- 1 Conv_2 Conv int8 0.97535 float32 0.98666 2 Conv_90 Conv int8 0.98666 float32 0.98973 3 Conv_77 Conv int8 0.98973 float32 0.99062 4 Conv_4 Conv int8 0.99062 float32 0.99331 5 Conv_7 Conv int8 0.99331 float32 0.99096 6 Conv_92 Conv int8 0.99096 float32 0.99096 7 Conv_0 Conv int8 0.99096 float32 0.99511 8 Conv_86 Conv int8 0.99511 float32 0.99597 9 Conv_78 Conv int8 0.99597 float32 0.99592 10 Add_83 Add int8 0.99592 float32 0.99592 11 Conv_84 Conv int8 0.99592 float32 0.99618 12 Conv_9 Conv int8 0.99618 float32 0.99680 13 Add_89 Add int8 0.99680 float32 0.99680 14 Conv_88 Conv int8 0.99680 float32 0.99744 15 Conv_94 Conv int8 0.99744 float32 0.99781 16 Conv_80 Conv int8 0.99781 float32 0.99823 17 Conv_82 Conv int8 0.99823 float32 0.99865 18 Conv_5 Conv int8 0.99865 float32 0.99804 19 Conv_14 Conv int8 0.99804 float32 0.99880 20 Conv_12 Conv int8 0.99880 float32 0.99890 21 Conv_60 Conv int8 0.99890 float32 0.99878 22 Conv_23 Conv int8 0.99878 float32 0.99826 23 Conv_20 Conv int8 0.99826 float32 0.99892 24 Conv_37 Conv int8 0.99892 float32 0.99866 25 Conv_75 Conv int8 0.99866 float32 0.99881`

其中：

- Index：敏感节点编号。

- Node：敏感节点名称。

- op_type：敏感节点类型。

- original_qtype, original：节点原始量化类型以及将该节点之前(不包括当前节点)的所有敏感节点的量化类型设置为qtype后的模型与浮点模型的输出相似度。

- improved_qtype, improved：节点被设置的qtype以及将该节点与之前所有节点的量化类型设置为qtype后的模型与浮点模型的输出相似度。

图中：

- 蓝色虚线：浮点模型输出与自身的输出相似度。

- 红色实线：将当前节点以及之前所有节点的量化类型设置为qtype时与浮点模型的输出相似度。 例如：上图中将敏感度排序靠前的三个节点'Conv_2', 'Conv_90', 'Conv_77'设置为float32数据类型可以将模型输出相似度恢复到约0.99。

注解

上图中横坐标为0的点表示校准模型对应的输出相似度。

### #runall

功能：一键运行原本debug工具中的所有功能。

命令行格式：

`hmct-debugger runall MODEL_OR_FILE CALIBRATION_DATA --other options`

可通过 `hmct-debugger runall -h/--help` 查看相关参数。

参数组：

参数名称 | 命令行参数缩写 | 参数配置说明 | 可选/必选
`model_or_file` | 固定参数 | 参数作用：指定校准模型。 取值范围：无。 默认配置：无。 参数说明：必选，指定需要分析的校准模型。 | 必选
`calibrated_data` | 固定参数 | 参数作用：指定校准数据。 取值范围：无。 默认配置：无。 参数说明：必选，指定需要分析的校准数据。 | 必选
`save_dir` | `-s` | 参数作用：保存路径。 取值范围：无。 默认配置：无。 参数说明：指定分析结果的保存路径。 | 可选
`ns_metrics` | `-nm` | 参数作用：节点量化敏感度的度量方式。 取值范围：`'cosine-similarity'`，`'mse'`，`'mae'`，`'mre'`，`'sqnr'`，`'chebyshev'`。 默认配置：`'cosine-similarity'`。 参数说明：指定节点量化敏感度的计算方式，该参数可以为列表(List)， 即以多种方式计算量化敏感度， 但是输出结果仅以列表中第一位的计算方式进行排序， 排名越靠前说明量化该节点引入的误差越大。 | 可选
`output_node` | `-o` | 参数作用：指定输出节点。 取值范围：校准模型中的具有对应校准节点的普通节点。 默认配置：None。 参数说明：此参数支持您指定中间节点作为输出并计算节点量化敏感度。 若保持默认参数None，则精度debug工具会获取模型的最终输出 并在此基础上计算节点的量化敏感度。 | 可选
`node_type` | `-nt` | 参数作用：节点类型。 取值范围：`'node'`，`'weight'`，`'activation'` 。 默认配置：`'node'`。 参数说明：需要计算量化敏感度的节点类型，包括：node（普通节点）、weight（权重校准节点）、activation（激活校准节点）。 | 可选
`data_num` | `-dn` | 参数作用：计算量化敏感度需要的数据数量。 取值范围：大于0，小于等于calibration_data中数据的总数。 默认配置：None。 参数说明：设置计算节点量化敏感度时所需要的数据数量。默认为None，此时默认使用calibration_data中的所有数据进行计算。最小设置为1，最大为 calibration_data 中的数据数量。 | 可选
`verbose` | `-v` | 参数作用：选择是否将信息打印在终端上。 取值范围：`True`、`False`。 默认配置：`False`。 参数说明：若为True，则将量化敏感度信息打印在终端上。 若metrics包含多种度量方式，则按照第一位进行排序。 | 可选
`interested_nodes` | `-i` | 参数作用：设置感兴趣节点。 取值范围：校准模型中的所有节点。 默认配置：None。 参数说明：若指定则只获取该节点的量化敏感度，其余节点不获取。同时，若该参数被指定，将忽视node_type指定的节点类型，也就是说该参数的优先级要高于node_type。若保持默认参数None，则计算模型中所有可被量化节点的量化敏感度。 | 可选
`dis_nodes_list` | `-dnl` | 参数作用：指定需要分析的节点。 取值范围：校准模型中的所有节点。 默认配置：无。 参数说明：指定需要分析的节点。若nodes_list中的节点类型为： 权重校准节点：绘制原始权重和经过校准之后的权重的数据分布。 激活校准节点：绘制激活校准节点的输入数据分布。 普通节点：绘制该节点在量化前后的输出数据分布，同时绘制二者之间的误差分布。 注：nodes_list为 list 类型，可指定一系列节点，并且上述三种类型节点 可同时指定。 | 可选
`cw_nodes_list` | `-cn` | 参数作用：指定校准节点。 取值范围：校准模型中的所有权重校准节点和激活校准节点。 默认配置：无。 参数说明：指定校准节点。 | 可选
`axis` | `-a` | 参数作用：指定channel所在的维度。 取值范围：小于节点输入数据的维度。 默认配置：None。 参数说明：channel信息所在shape中的位置。参数默认为None，此时对于激活校准节点，默认认为节点输入数据的第二个维度表示channel信息，即axis=1；对于权重校准节点，会读取该节点属性中的axis参数作为channel信息。 | 可选
`quantize_node` | `-qn` | 参数作用：只量化模型中指定的节点，查看误差累积曲线。 取值范围：校准模型中的所有节点。 默认配置：None。 参数说明：可选参数。指定模型中需要量化的节点，同时保证其余节点均不量化。 通过判断该参数是否为嵌套列表进而决定是单节点量化还是部分量化。 例如： quantize_node=['Conv_2','Conv_9']：分别只量化Conv_2和Conv_9， 同时保证其余节点不量化。 quantize_node=[['Conv_2'],['Conv_9','Conv_2']]：只量化Conv_2以及 同时量化Conv_2和Conv_9，分别测试模型累积误差。 quantize_node 包含两个特殊参数：'weight' 和 'activation'。当： quantize_node = ['weight']：只量化权重，不量化激活。 quantize_node = ['activation']：只量化激活，不量化权重。 quantize_node = ['weight','activation']：权重和激活分别量化。 注：quantize_node和non_quantize_node不可同时为None，必须指定其一。 | 可选
`non_quantize_node` | `-nqn` | 参数作用：指定累积误差的类型。 取值范围：校准模型中的所有节点。 默认配置：None。 参数说明：可选参数。指定模型中不量化的节点，同时保证其余节点全都量化。 通过判断该参数是否为嵌套列表进而决定是单节点不量化还是部分量化。 例如： non_quantize_node=['Conv_2','Conv_9']：分别解除Conv_2和Conv_9节点的量化，同时保证其余节点全部量化。 non_quantize_node=[['Conv_2'],['Conv_9','Conv_2']]：只解除Conv_2量化 以及同时解除Conv_2和Conv_9量化，分别测试模型累积误差。 注：quantize_node和non_quantize_node不可同时为None，必须指定其一。 | 可选
`ae_metric` | `-am` | 参数作用：累积误差度量方式。 取值范围：`'cosine-similarity'`，`'mse'`，`'mae'`，`'mre'`，`'sqnr'`，`'chebyshev'`。 默认配置：`'cosine-similarity'`。 参数说明：设置计算模型误差的计算方式。 | 可选
`average_mode` | `-avm` | 参数作用：指定累积误差曲线的输出模式。 取值范围：`True` 、`False`。 默认配置：`False`。 参数说明：默认为False。若为True，那么获取累积误差的平均值作为结果。 | 可选
`pick_threshold` | `-pt` | 参数作用：设置选取节点的敏感度阈值。 取值范围：无。 默认配置：0.999。 参数说明：可选，此功能计算普通节点的量化敏感度，选择敏感度小于 pick_threshold的节点作为敏感节点进行分析测试。 注：当设置sensitive_nodes时，则直接对sensitive_nodes进行测试，不再 另行计算节点敏感度并根据pick_threshold选择敏感节点。 | 可选
`sensitive_nodes` | `-sn` | 参数作用：指定需要分析的敏感节点。 取值范围：校准模型中的所有节点。 默认配置：无。 参数说明：可选，指定需要分析的敏感节点。 注：当设置此参数时，则直接对此参数中的节点进行测试，不再另行计算 节点敏感度并根据pick_threshold选择敏感节点。 | 可选

API使用方法：

`# 导入debug模块 import hmct.quantizer.debugger as dbg dbg.runall(model_or_file='calibrated_model.onnx', calibrated_data='calibration_data')`

命令行使用方法：

`hmct-debugger runall calibrated_model.onnx calibration_data`

runall流程：

当所有参数保持默认时，工具会依次执行以下功能：

- step1和step2：分别获取权重校准节点和激活校准节点的量化敏感度。

- step3：根据step1和step2的结果，分别取权重校准节点的top5和激活校准节点的top5绘制其数据分布。

- step4：针对step3获取的节点，分别绘制其通道间数据分布的箱线图。

- step5：绘制分别只量化权重和只量化激活的累积误差曲线。

- step6：针对敏感节点进行部分量化以及单节点量化精度分析，由于图中示例并没有指定sensitive_nodes，因此需要debug工具自行计算普通节点的量化敏感度并选取敏感度小于指定pick_threshold的节点进行测试分析。

当指定 `node_type='node'` 时，工具会获取top5节点，并分别找到每个节点对应的校准节点，并获取校准节点的数据分布和箱线图。

页面目录