PPOCRV3文本识别模型精度损失问题解决

1. 得到可用的ncnn模型

paddleocr文本识别模型(ch_PPOCRv3_rec_infer)转ncnn模型,我参考了这位大神的博客,基本包括了我遇到的所有问题,是一篇很好的文章:https://blog.csdn.net/qq_29543997/article/details/128923330,博客中提到转换的模型存在精度损失,也是基于该问题引出这篇博客。

2. 先看问题

在得到ncnn模型后,使用同一张图像,使用onnx模型和ncnn模型分别在paddleocr工程和ncnn工程上运行看识别结果, 发现精度损失在10-4,按理说onnx转ncnn仅是数据架构的转换,误差不会这么大:
在这里插入图片描述

3. 快速解决

尝试更换ncnn编译库,重新测试模型精度损失。下面内容是个人排查问题的方法,有兴趣的可以看看。

4. 问题分析

分析方法:分析onnx模型和ncnn模型各层的输入结果,比对损失(过程还是蛮痛苦的)。

  1. onnx模型各层输出打印:https://blog.csdn.net/xefei/article/details/126489861
  2. ncnn模型各层输出打印:这个挺简单的,改一下输出blob名称就好。

最终发现ncnn模型中将paddle推理模型中的AdaptiveAvgPool层(onnx不支持)和其之后的卷积层替换为了GlogalAvgPool和InnerProduct层,对ncnn的.param文件修改后,该部分的精度损失由[10-4,10-3],降到[0,10-6]。

  1. paddle推理模型对应源码:PaddleOCR/ppocr/modeling/backbones/det_mobilenet_v3.py中的"class SEModule(nn.Layer):"
  2. param文件文件介绍:https://blog.csdn.net/m0_37264397/article/details/124184227#t1
  3. ncnn官网各层参数介绍:https://github.com/Tencent/ncnn/wiki/operators

param文件修改内容如下:

# 前两行
# 修改前
7767517
251 289
# 修改后
7767517
253 291

# 修改GlogalAvgPool和InnerProduct层(2处)
# 修改前
Pooling                         p2o.GlobalAveragePool.0  1 1 batch_norm_50.tmp_4_splitncnn_1 p2o.GlobalAveragePool.1 0=1 4=1
InnerProduct             p2o.Conv.24              				1 1 p2o.GlobalAveragePool.1 relu_2.tmp_0 0=64 1=1 2=16384 9=1
InnerProduct             p2o.Conv.25             				1 1 relu_2.tmp_0 conv2d_110.tmp_0 0=256 1=1 2=16384
# 修改后
Pooling                  		p2o.GlobalAveragePool.0  1 1 batch_norm_50.tmp_4_splitncnn_1 p2o.GlobalAveragePool.1 0=1 7=1 8=1 5=1
Convolution              p2o.Conv.24              			  1 1 p2o.GlobalAveragePool.1 conv2d_120.tmp_0 0=64 1=1 5=1 6=16384 9=1
ReLU                     		p20.ReLU.1               				  1 1 conv2d_120.tmp_0 relu_2.tmp_0
Convolution              p2o.Conv.25            				  1 1 relu_2.tmp_0 conv2d_110.tmp_0 0=256 1=1 5=1 6=16384

# 修改前
Pooling                  		p2o.GlobalAveragePool.2  1 1 batch_norm_52.tmp_4_splitncnn_1 p2o.GlobalAveragePool.3 0=1 4=1
InnerProduct             p2o.Conv.28              			  1 1 p2o.GlobalAveragePool.3 relu_3.tmp_0 0=128 1=1 2=65536 9=1
InnerProduct             p2o.Conv.29           				  1 1 relu_3.tmp_0 conv2d_113.tmp_0 0=512 1=1 2=65536
# 修改后
Pooling                  		p2o.GlobalAveragePool.2  1 1 batch_norm_52.tmp_4_splitncnn_1 p2o.GlobalAveragePool.3 0=1 7=1 8=1 5=1
Convolution              p2o.Conv.28              			  1 1 p2o.GlobalAveragePool.3 conv2d_121.tmp_0 0=128 1=1 5=1 6=65536 9=1
ReLU                     		p20.ReLU.2               			  	  1 1 conv2d_121.tmp_0 relu_3.tmp_0
Convolution              p2o.Conv.29              			  1 1 relu_3.tmp_0 conv2d_113.tmp_0 0=512 1=1 5=1 6=65536

修改前后param的网络结构如下:
在这里插入图片描述
经过以上修改得到的模型仍有误差,接着往下逐层分析,最终确认注意力机制中的InnerProduct层(全连接层)导致的精度损失,经过分析,甚至手动计算ncnn模型该层的输出,得到的输出结果与onnx结果精度损失很小。直接怀疑ncnn编译库内部计算存在问题,实在没办法了,尝试更换一版ncnn的编译库,没想到精度损失直接降到0~10-5。至于到底是ncnn版本问题,还是编译过程中出了问题就不得而知。

  1. 获取ncnn模型各层权重:https://github.com/Tencent/ncnn/issues/4666#issuecomment-1521638902
  2. 获取onnx模型各层权重: 直接用netron打开,点击某一层,右侧可以看到其weights和bias, 且能够保存下来。

5. 最终效果

在这里插入图片描述

上面是对短文本的识别效果,误差还是有10-5,不过对于长文本误差则是在0到10-7,可能是因为短文本图像补边造成的差异,需要进一步确认。

6. 结语

至此来看,自己前面改AdaptiveAvgPool层和InnerProduct层好像没用,白折腾了,直接换ncnn编译库可能就好了。不过经过这么折腾学了不多东西,记录下来作为后备之需。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值