欢迎学习RKNN系列相关文章,从模型转换、精度分析,评估到部署,推荐好资源:
一、Ubuntu系统上安装rknn-toolkit
二、使用rknn-toolkit将Pytorch模型转为RKNN模型
三、RKNN模型的评估和推理测试
四、RKNN模型量化精度分析及混合量化提高精度
五、RKNN模型性能评估和内存评估
六、rknn-toolkit-lite2部署RKNN模型到开发板上(python版)
七、RKNN C API开发板上落地部署RKNN模型
八、RKNN零拷贝API开发板落地部署RKNN模型
一、量化精度分析及混合量化的必要性
由于在RKNN模型构建的过程中,对模型进行了量化,会无可避免的造成精度损失,使用精度分析接口,可以查看每一层的精度损失情况。通过混合量化,将某些损失较大的层,从量化层转为非量化层,从而提高模型的精度。
二、源码包获取
本教程配套的源码包获取方法为文章末扫码到公众号中回复关键字:RKNN精度分析与混合量化。获取下载链接。
下载解压源码包后的样子如下:
三、量化精度分析
3.1 量化精度分析流程
计算不同情况下,同一层网络输入值的余弦距离,来近似的查看每一层精度损失的情况。具体量化精度分析的流程如下:
3.2 量化精度分析accuracy_analysis接口
量化精度分析调用accuracy_analysis接口,推理并产生快照,也就是dump出每一层的tensor数据。会dump出包括fp32和quant两种数据类型的快照,用于计算量化误差。
注:
该接口只能在 build或 hybrid_quantization_step2之后调用,并且原始模型应该为非量化的模型,否则会调用失败。
该接口使用的量化方式与config_中指定的一致。
3.3 测量模拟器推理精度代码
3.3.1 参数修改
量化精度分析代码对应于源码包中accuracy_analysis.py脚本,需要修改的地方如下:
3.3.2 代码
具体代码如下:
from rknn.api import RKNN
import cv2
import numpy as np
if __name__=='__main__':
rknn = RKNN(verbose=True) # 打印详细日志
# 调用config接口设置模型的预处理、量化方法等参数
rknn.config(
mean_values = [[123.675,116.28,103.53]], # mean_values表示预处理要减去的均值化参数
std_values = [[58.395,58.395,58.395]], # std_values 表示预处理要除的标准化参数
target_platform = "rk3588" # target_platform表示生成的RKNN模型要运行在哪个RKNPU平台上。通常有rk3588,rk3566,rv1126等
)
# 添加load_xxx接口,进行常用深度学习模型的导入 将深度学习模型导入
rknn.load_pytorch(
model = "./resnet18.pt",
input_size_list = [[1, 3,224,224]]
)
# 使用build接口来构建RKNN模型
rknn.build(
do_quantization = True,
dataset = "dataset.txt",
rknn_batch_size = -1
)
# 调用export_rknn接口导出RKNN模型
rknn.export_rknn(export_path="resnet18.rknn")
# 使用accuracy_analysis 接口进行模型量化精度分析
rknn.accuracy_analysis(
inputs = ["space_shuttle_224.jpg"], # inputs 表示进行推理的图像
output_dir = 'snapshot', # 表示精度分析的输出目录
target = None, # 表示目标硬件平台
device_id = None, # 表示设备的编号
)
rknn.release()
3.3.3 测试结果
运行上面脚本后的结果如下:
3.4 测量开发板推理精度代码
3.4.1 参数修改
量化精度分析代码同样对应于源码包中accuracy_analysis.py脚本,需要修改的地方如下:
3.4.2 代码
具体代码见下:
from rknn.api import RKNN
import cv2
import numpy as np
if __name__=='__main__':
rknn = RKNN(verbose=True) # 打印详细日志
# 调用config接口设置模型的预处理、量化方法等参数
rknn.config(
mean_values = [[123.675,116.28,103.53]], # mean_values表示预处理要减去的均值化参数
std_values = [[58.395,58.395,58.395]], # std_values 表示预处理要除的标准化参数
target_platform = "rk3588" # target_platform表示生成的RKNN模型要运行在哪个RKNPU平台上。通常有rk3588,rk3566,rv1126等
)
# 添加load_xxx接口,进行常用深度学习模型的导入 将深度学习模型导入
rknn.load_pytorch(
model = "./resnet18.pt",
input_size_list = [[1, 3,224,224]]
)
# 使用build接口来构建RKNN模型
rknn.build(
do_quantization = True,
dataset = "dataset.txt",
rknn_batch_size = -1
)
# 调用export_rknn接口导出RKNN模型
rknn.export_rknn(export_path="resnet18.rknn")
# 使用accuracy_analysis 接口进行模型量化精度分析
rknn.accuracy_analysis(
inputs = ["space_shuttle_224.jpg"], # inputs 表示进行推理的图像
output_dir = 'snapshot', # 表示精度分析的输出目录
target = "rk3588", # 表示目标硬件平台
# target=None, # 表示目标硬件平台
device_id = None, # 表示设备的编号
)
rknn.release()
3.4.3 测试结果
开发版的测试结果多了计算运行时的误差(runtime_error),如下:
在文件夹snapshot文件夹中查看保存下来的输入值,如下:
四、混合量化
4.1 RKNN-Toolkit混合量化功能
RKNN-Toolkit支持混合量化功能。混合量化是指在一个模型中,部分层使用浮点数表示,部分层使用定点数表示。这种方式可以在保证模型精度的同时,降低模型的存储和计算需求,提高推理速度。
RKNN-Toolkit的量化功能支持将浮点模型转成量化模型,目前支持的量化方法有非对称量化(asymmetric_quantized-u8),动态定点量化(dynamic_fixed_point-8 和 dynamic_fixed_point-16)。
4.2 混合量化第一阶段
RKNN混合量化的第一阶段主要是生成临时模型文件、数据文件及量化配置参数文件。这个阶段需要准备一组量化图片(图片原图,而且大小要和模型的输入相同),以及一个dataset.txt文件。
在这个阶段,RKNN-Toolkit会对模型进行初步的量化处理,生成一个量化配置文件,这个文件中包含了模型中每个tensor的量化参数。这个文件可以用来修改混合精度,比如可以在这个文件中设置哪些层需要进行量化,哪些层不需要。
这个阶段的目标是为第二阶段的混合量化做好准备,使得在第二阶段可以根据第一阶段生成的文件进行更精细的量化处理。
4.2.1 第一阶段流程图
第一阶段的具体流程图见下:
4.2.2 手动修改量化层转非量化层
4.2.2.1 参数修改
代码脚本中具体要修改的地方如下:
4.2.2.2 代码
具体代码对应于源码包中hrhrid_quantization文件夹中的setp1.py脚本,具体代码如下:
from rknn.api import RKNN
import cv2
import numpy as np
if __name__=='__main__':
rknn = RKNN(verbose=True) # 打印详细日志
# 调用config接口设置模型的预处理、量化方法等参数
rknn.config(
mean_values = [[123.675,116.28,103.53]], # mean_values表示预处理要减去的均值化参数
std_values = [[58.395,58.395,58.395]], # std_values 表示预处理要除的标准化参数
target_platform = "rk3588" # target_platform表示生成的RKNN模型要运行在哪个RKNPU平台上。通常有rk3588,rk3566,rv1126等
)
# 添加load_xxx接口,进行常用深度学习模型的导入 将深度学习模型导入
rknn.load_pytorch(
model = "./resnet18.pt",
input_size_list = [[1, 3,224,224]]
)
# 使用hybrid_quantization_step 接口进行混合量化第一步
rknn.hybrid_quantization_step1(
dataset="dataset.txt", # 表示模型量化所需要的数据集
rknn_batch_size=-1, # 表示自动调整模型输入batch数量
proposal=False, # 设置为True,可以自动产生混合量化的配置建议,比较耗时
# proposal= True, # 设置为True,可以自动产生混合量化的配置建议,比较耗时
proposal_dataset_size=1, # 第三步骤所用的图片
)
rknn.release()
4.2.2.3 运行结果
运行上面脚本后会在更目录下生成三个新的文件,如下:
4.2.2.4 查看精度损失较大层
运行上面脚本后会输出如下的误差,找到哪些层的损失较多,就将损失较多的层从量化层转为非量化层。
4.2.2.5 添加量化层
从上面可以看出25层,33层,43层,51层等损失较大,这里举例选取其中input.25层,将该层从量化层转为非量化层,在resnet18.quantization.cfg文件夹添加,如下:
4.2.2.6 混合量化结果
接下来进行第二阶段混合量化,直接调转到4.3 混合量化第二阶段。运行4.3.3中的代码后,得到下面的结果:
从上面的输出结果可以看出,input.25层的精度得到提高,但是其它层的精度损失了,还需要对其它损失层继续量化层转非量化层,如下:
4.2.2.6 混合量化测试结果
上面二次添加后的运行结果如下,可以看出精度提高了:
4.2.3 自动生成配置文件修改量化层转非量化层
4.2.3.1 参数修改
将源码包中step1.py脚本中的proposal参数设置为True,如下:
4.2.3.2 自动生成的配置文件
修改好后运行上面脚本,同样会在根目录下生成三个文件,同4.2.2.3。
其中在.cfg文件中,自动添加了精度损失大,需要将量化层转为非量化层的对应层,如下:
4.2.3.3 测试结果
下面进行第二阶段,运行step2.py脚本,代码见4.3.3。
4.3 混合量化第二阶段
RKNN混合量化的第二阶段主要是生成RKNN模型。在这个阶段,RKNN-Toolkit会根据第一阶段生成的临时模型文件、数据文件及量化配置参数文件,进行更精细的量化处理。
这个阶段的目标是生成一个可以在硬件平台上运行的RKNN模型。
4.3.1 第二阶段流程图
下面是混合量化的第二阶段,将第一步生成的3个临时文件合并为一个文件。具体流程图见下:
4.3.2 参数修改
参数需要修改的地方如下:
4.3.3 代码
代码对应源码包中的step2.py,具体代码如下:
from rknn.api import RKNN
if __name__=="__main__":
rknn = RKNN(verbose=True)
# 调用hyborid_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模型
rknn.export_rknn(export_path="./resnet18.rknn")
rknn.release()
五、可视化RKNN模型
通过上面的转换导出,会在根目录下得到RKNN模型,通过netron.app可以将RKNN模型结构可视化出来,netron.app的网址为:netron.app
打开网址后直接将RKNN模型拖到网页中,或者通过打开文件夹方式导入,如下:
打开后的样子如下:
六、总结
以上就是RKNN模型量化精度分析及混合量化提高精度的详细方法,希望能帮到你!
关于RKNN模型的相关其它教程,看我前面博文,此系列持续更新中。
总结不易,多多支持,谢谢!