目录
前言
一、混合量化
1.1 概念介绍
1.1.1 hybrid_quantization_step1
1.1.2 hybrid_quantization_step2
二、实际编写程序
2.1混合量化第一阶段
2.2 混合量化第二阶段
三、混合量化第一步接口参数proposal
前言
为什么要进行混合量化?
答案:提高模型每一层精度,提高模型精度
从博文:
RKNPU2从入门到实践 --- 【6】模型评估----量化精度分析-CSDN博客我们得到了量化精度,如下图所示,下图表示的是连板推理时模型的量化精度,我们以input.25这一层为例,发现该层的runtime_error中的golden_err【计算的是上一层的输出层,也即input.25当前层的精度】只有0.930068,这是比较小的。
那对于这种问题,该如何处理呢?
这就需要混合量化来优化这个精度了。
一、混合量化
1.1 概念介绍
1.1.1 hybrid_quantization_step1
使用混合量化功能时,第一阶段调用的主要接口是 hybrid_quantization_step1,用于生成临时 模 型 文 件 ( {model_name}.model ) 、 数 据 文 件 ( {model_name}.data ) 和 量 化 配 置 文 件({model_name}.quantization.cfg)。接口详情如下:
1.1.2 hybrid_quantization_step2
用于使用混合量化功能时生成 RKNN 模型,接口详情如下:
举例如下:
二、实际编写程序
创建项目文件夹,以及相应的文件,并将相关资料放入项目文件夹中,如下图所示。
在step1.py文件中,先写入如下代码:
from rknn.api import RKNN
if __name__ == '__main__':
# 第一步:创建RKNN对象
rknn = RKNN()
# 第二步:配置RKNN对象参数
rknn.config(
mean_values=[[123.675,116.28,103.53]],
std_values=[[58.395,58.395,58.395]],
target_platform='rk3588'
# 其余参数保持默认即可
)
# 第三步:调用load_pytorch接口导入pt模型
rknn.load_pytorch(model='./resnet18.pt',input_size_list=[[1, 3, 224, 224]])
# 最后一步:释放RKNN对象
rknn.release()
2.1混合量化第一阶段
根据流程图,第四步为混合量化的step1,对应的代码为:
添入step1代码后的整体代码如下:
from rknn.api import RKNN
if __name__ == '__main__':
# 第一步:创建RKNN对象
rknn = RKNN()
# 第二步:配置RKNN对象参数
rknn.config(
mean_values=[[123.675,116.28,103.53]],
std_values=[[58.395,58.395,58.395]],
target_platform='rk3588'
# 其余参数保持默认即可
)
# 第三步:调用load_pytorch接口导入pt模型
rknn.load_pytorch(model='./resnet18.pt',input_size_list=[[1, 3, 224, 224]])
# 使用hybrid_quantization_step1 接口进行混合量化的第一步
rknn.hybrid_quantization_step1(
dataset='dataset.txt', # 表示模型量化所需要的数据集
rknn_batch_size=-1, # 表示自动调整模型输入batch数量
proposal=False, # 默认为False。设置为True,可以自动产生混合量化的配置建议值
proposal_dataset_size=1
)
# 最后一步:释放RKNN对象
rknn.release()
接下来运行该程序:
得到如下图:
我们要对得到的resnet18.quantization.cfg文件进行修改。 该文件内容如下所示:
修改的地方为该文件的第一行,即custom_quantize_layers:{},将input.25层由量化层转换为非量化层,如下所示:
2.2 混合量化第二阶段
在step2.py文件中编写程序:
from rknn.api import RKNN
if __name__ == '__main__':
# 创建RKNN对象
rknn = RKNN()
# 直接调用hybrid_quantization_step2接口进行混合量化的第二个步骤
rknn.hybrid_quantization_step2(
model_input='resnet18.model',# 表示第一步生成的模型文件
data_input='resnet18.data', #表示第一步生成的配置文件
model_quantization_cfg='resnet18.quantization.cfg' # 表示第一步生成的量化配置文件
)
# 使用量化精度分析接口评估混合量化后的RKNN模型
rknn.accuracy_analysis(
inputs=['./space_shuttle_224.jpg'],
output_dir='./snapshot',
target='rk3588'
)
# 调用RKNN模型导出接口(方便后续模型部署)
rknn.export_rknn(
export_path='./resnet18.rknn'
)
#释放RKNN对象
rknn.release()
运行step2.py程序:
此处有bug,后续更新!!
上图来自于:06_RKNN 模型评估-量化精度分析_哔哩哔哩_bilibili
可以看到,input.25层的golden_err从原来的0.930068变为了现在的0.999746。精度变高。
将经过混合量化和没有经过混合量化的进行对比,这里贴出没有经过混合量化的精度信息截图。
我们从上图中可以看到,input.25这一层的下一层是142层,但是在经过混合量化之后,我们发现input.25层的下一层并不是142层,而是input.25__int8,这一层在input.25层和142层中间,这是为什么呢?这会带来什么样的后果呢?
由于142层的输入类型为int8类型,而input.25已经变为float16类型,故浮点数转换为int8类型,因此才会有input.25__int8这一层的出现。我们看到,input.25__int8层的golden_err只有0.930005。因此,这么一操作,精度不增反减了,那该如何补救呢?
我们干脆直接跳过input.25__int8这一层,因此修改.cfg文件,如下图所示:
加入的 '142': float16 表示将input.25层的输出层,即142层由量化层变为非量化层。
然后重新运行step2.py程序,得到(下图是将终端打印信息拷贝到记事本中,便于观察):
可以看到,input.25 层周围的精度值都变高了,这也就证明了混合量化效果有效。
以上是对 resnet18.pt 模型的某一层进行混合量化。若对模型进行更多层的混合量化,那么模型的效果会大大提高。
三、混合量化第一步接口参数proposal
在上面,proposal这个参数的取值为False,导致了我们在混合量化第二阶段修改.cfg文件时需要手动去修改。
那么我们将这个参数取值设置为True,又会有怎样的变化呢?
随后运行step1.py程序,得到:
我们来看看.cfg文件有什么变化:
我们发现.cfg文件中的custom_quantize_layers由proposal取值为False时的空变为了proposal取值为True时的好多内容。
这相当于是手动筛选精度差的层变为了自动筛选精度差的层。何乐而不为呢?