6. 量化技巧¶
结合1684芯片的特点这里给出了3类优化网络量化效果的技巧:
阈值计算
混合执行
网络图优化
6.1. 阈值计算¶
6.1.1. 分布统计¶
calibration_use_pb命令行添加如下参数:
-dump_dist: 指向一个输出文件的路径。将网络各层统计的最大值及feature的分布信息保存到文件。
-load_dist: 指向一个-dump_dist参数生成的文件的路径。从-dump_dist参数生成的文件 中读取网络各个层的最大值及feature分布信息。
针对有些网络需要量化调优进行多次量化的场景,采用此参数可以只统计一次分布信息并多 次使用。可以大大加快量化调优的速度。
注:选择使用ADMM方法不支持保存和加载feature分布。
6.1.2. 阈值调整¶
阈值的选取对于网络量化效果有很大的影响,这里给出两种方式来对量化阈值进行调整。
6.1.2.1. 针对所有的层进行调整¶
calibration_use_pb命令行添加如下参数:
-th_method:可选参数,指定计算各个层量化阈值的方法,可选参数:KL,SYMKL,JSD,ADMM,ACIQ以及MAX,默认值为KL。
6.1.2.2. 针对具体的层进行调整¶
为了更精细地对某个具体层的阈值进行调整,在layer_parameter中增加了部分参数,可以通 过下面方式在prototxt文件中进行使用。
th_strategy:设置当前layer的量化阈值计算策略。
可选参数:USE_DEFAULT,USE_KL,USE_MAX,默认值为USE_DEFAULT。
USE_DEFAULT:采用calibration-tools量化程序内部定义的规则来计算当前 layer的阈值。
USE_KL:采用求KL分布的方式来计算当前layer的阈值,这里的KL是相对MAX 而言,具体的阈值计算策略可能是KL,SYMKL或者JSD。
USE_MAX:采用统计的最大值做为当前layer的最大值。
th_scale:在计算得到的阈值上面乘以缩放系数th_scale,默认值为1.0。
threshold:设置当前layer的量化阈值,无默认值。
6.2. 混合执行¶
1684芯片内部集成了浮点计算单元,可以高效地利用浮点进行计算。根据芯片的这个特点, 这里提供了一种混合执行的方式来运行网络,允许部分层用定点进行计算,部分层用浮点进 行计算。通过允许部分层用浮点进行计算,可以有效地提高网络的整体量化精度。
6.2.1. 复杂网络的前处理/ 后处理¶
Tensorflow及Pytorch等基于python的框架灵活度较大,从这些框架转过来的网络模型中可 能包含前后处理相关的算子。对于这些算子做量化将很大程度上影响网络的量化精度。这里 提供了一种方式在网络中标记出前处理、后处理相关的层,并允许这些层以浮点运行。在calibration_use_pb命令行中使用如下参数:
-fpfwd_inputs:用逗号分隔开的网络layer name,在网络中这些layer及它们之前的layer 被标记为网络前处理。网络前处理不算做正式网络的一部分,在calibration过程中不被 量化,在推理过程中保持使用浮点进行计算。
-fpfwd_outputs:用逗号分隔开的网络layer name,在网络中这些layer及它们之后的 layer被标记为网络后处理。网络后处理不算做正式网络的一部分,在calibration过程中 不被量化,在推理过程中保持使用浮点进行计算。
6.2.2. 对量化损失敏感的层¶
6.2.2.1. 通过命令行参数指定¶
在calibration_use_pb命令行中使用如下参数:
-fpfwd_blocks:用逗号分隔开的网络layer name,在网络中每个layer及它们之后直到下一 个进行数据计算的层在calibration过程中都不被量化,在推理过程中保持使用浮点进行计算。
calibration-tools程序会根据指定的layer name自动判断这个layer后面有多少个layer需 要用浮点进行计算,把网络的这个block做为一个整体用浮点进行计算,来达到提高量化精 度的目的。如下图所示在命令行中用-fpfwd_blocks指定Softmax层的layer name, calibration-tools程序会将图中红色框中的layer都标识为用浮点进行计算。 calibration-tools程序会在此block的输入处自动将输入数据转换成浮点格式,在输出位置 转换为int8数据格式。
6.2.2.2. 通过配置prototxt指定¶
forward_with_float:将当前layer用浮点进行计算,可选参数为true,false,默认值为false。
具体使用方法参考如下面图 prototxt文件中设置forward_with_float 所示,这里的*_test_fp32.prototxt文件是指 calibration_use_pb命令的输入prototxt文件,见 :ref: grenerate_fp32umodel 。
6.3. 精度优化参数¶
在calibration_use_pb命令行中可以尝试使用如下参数提高精度,其效果根据网络特点不同可能不同,以实测为准:
-accuracy_opt:将网络中depthwise卷积采用浮点推理以提高精度,默认为false,关闭。
-conv_group:将conv的输出channel按照输出幅值进行分组并拆分成不同的组分别进行量化,默认为false,关闭。
-per_channel:开启convolution计算的per_channel功能,默认为false,关闭。
为了提高精度和速度,量化过程中会进行简单的网络优化。 使用Parse-tools转换前端网络为fp32U-model的过程中会自动将batchnorm和bias转换为scale层,并且如果有相邻的scale层会合并为一个。 量化命令调用时不提前使用graph-transform参数进行网络优化直接进行量化的时候也会进行网络优化,比如打开accuracy_opt参数会触发网络优化,一些网络优化参数进行的操作如下图所示:
进行网络优化的具体操作如下图所示:
6.4. auto_cali量化优化策略¶
auto_cali可以自动尝试一些量化优化策略,提升网络量化效果,以下是自动搜索量化的例子:
Caffe框架下的MobileNet SSD自动搜索量化策略
Caffe框架下的MobileNet SSD手工配置量化策略
6.4.1. Caffe框架下的MobileNet SSD自动搜索量化策略¶
如果在 auto_cali一键量化工具 使用中出现量化效果不满足要求的情况,可配置参数postprocess_and_calc_score_class打开精度测试功能 并在阈值计算,混合执行,网络图优化等方法中搜索出最优的量化策略
$ python3 -m ufw.cali.cali_model \ --model ./test_models/caffe/MobileNetSSD_deploy.prototxt \ --weight ./test_models/caffe/MobileNetSSD_deploy.caffemodel \ --cali_image_path ./test_models/detect_pic/ \ #使用原始图片, 若使用lmdb数据配置参数:calib_lmdb_path --cali_image_preprocess='resize_h=512,resize_w=512;mean_value=127.5:127.5:127.5, scale=0.007843' \ --input_shapes '(1,3,512,512)' \ --test_iterations 10 \ --postprocess_and_calc_score_class detect_accuracy #该参数支持4类可选项[detect_accuracy、topx_accuracy_for_classify、feature_similarity、None]
6.4.2. Caffe框架下的MobileNet SSD手工配置量化策略¶
由于自动搜索量化策略较为耗时,可根据后续章节的内容,通过配置参数try_cali_accuracy_opt,在auto_cali中手工调用相应的量化优化策略, 可选量化策略均来自下文calibration_use_pb模块
$ python3 -m ufw.cali.cali_model \ --model ./test_models/caffe/MobileNetSSD_deploy.prototxt \ --weight ./test_models/caffe/MobileNetSSD_deploy.caffemodel \ --cali_image_path ./test_models/detect_pic/ \ #使用原始图片, 若使用lmdb数据配置参数:calib_lmdb_path --cali_image_preprocess='resize_h=512,resize_w=512;mean_value=127.5:127.5:127.5, scale=0.007843' \ --input_shapes '(1,3,512,512)' \ --try_cali_accuracy_opt='-per_channel=true,-th_method=ADMM' #直接指定使用-per_channel=true,-th_method=ADMM量化参数进行量化,更多策略可参考下文calibration_use_pb模块