【yolov5】pytorch模型导出为onnx模型

博主想拿官网的yolov5训练好pt模型,然后转换成rknn模型,然后在瑞芯微开发板上调用模型检测。但是官网的版本对npu不友好,所以采用改进结构的版本:

  1. 将Focus层改成Conv层
  2. 将Swish激活函数改成Relu激活函数

自带的预训练模型是预测80类CoCo数据集的yolov5s改进结构,下面就带大家一起转换模型!

1、首先部署好yolov5的环境,保证可以运行detect.py进行检测,将自己训练好的pt模型放到weights目录下,我这里命名是best.pt。

在这里插入图片描述

2、pip install onnx安装好onnx库

在这里插入图片描述
3、输入下面命令导出模型(后面的weights、img和batch参数可以不加,设置下默认参数即可)

python models/export.py --weights ./weights/best.pt --img 640 --batch 1

然后会分解网络层,预览模型层数和参数量,最后保存为./weights/best.onnx

(yolov5) dzh@dzh-Lenovo-Legion-Y7000:~/airockchip-yolov5$ python models/export.py --weights ./weights/best.pt --img 640 --batch 1
Namespace(batch_size=1, img_size=[640, 640], weights='./weights/best.pt')
Fusing layers... 
Model Summary: 140 layers, 7.2627e+06 parameters, 0 gradients

Starting TorchScript export with torch 1.12.1+cu102...
/home/dzh/anaconda3/envs/yolov5/lib/python3.8/site-packages/torch/jit/_trace.py:967: TracerWarning: Encountering a list at the output of the tracer might cause the trace to be incorrect, this is only valid if the container structure does not change based on the module's inputs. Consider using a constant container instead (e.g. for `list`, use a `tuple` instead. for `dict`, use a `NamedTuple` instead). If you absolutely need this and know the side effects, pass strict=False to trace() to allow this behavior.
  module._c._create_method_from_trace(
TorchScript export success, saved as ./weights/best.torchscript.pt

Starting ONNX export with onnx 1.12.0...
/home/dzh/airockchip-yolov5/./models/yolo.py:103: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!
  if augment:
/home/dzh/airockchip-yolov5/./models/yolo.py:128: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!
  if profile:
/home/dzh/airockchip-yolov5/./models/yolo.py:143: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!
  if profile:
/home/dzh/anaconda3/envs/yolov5/lib/python3.8/site-packages/torch/onnx/symbolic_helper.py:621: UserWarning: You are trying to export the model with onnx:Resize for ONNX opset version 10. This operator might cause results to not match the expected results by PyTorch.
ONNX's Upsample/Resize operator did not match Pytorch's Interpolation until opset 11. Attributes to determine how to transform the input were added in onnx:Resize in opset 11 to support Pytorch's behavior (like coordinate_transformation_mode and nearest_mode).
We recommend using opset 11 and above for models using this operator.
  warnings.warn(
ONNX export success, saved as ./weights/best.onnx

Export complete (4.98s). Visualize with https://github.com/lutzroeder/netron.
(yolov5) dzh@dzh-Lenovo-Legion-Y7000:~/airockchip-yolov5$ 

4、导出的onnx模型可以用Netron网站查看网络结构:

在这里插入图片描述
可以看到转换后的结构比较乱,有些结点其实可以跳过,减小模型。这里可以使用修改onnx模型的工具,说明都在Readme中。

在这里插入图片描述

这里我们使用深度学习的库onnx-simplifier,通过pip安装即可。

Collecting onnx-simplifier
  Downloading onnx_simplifier-0.4.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.0 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.0/2.0 MB 203.7 kB/s eta 0:00:00
Requirement already satisfied: onnx in /home/dzh/anaconda3/envs/yolov5/lib/python3.8/site-packages (from onnx-simplifier) (1.12.0)
Collecting rich
  Downloading rich-12.6.0-py3-none-any.whl (237 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 237.5/237.5 kB 191.1 kB/s eta 0:00:00
Requirement already satisfied: numpy>=1.16.6 in /home/dzh/anaconda3/envs/yolov5/lib/python3.8/site-packages (from onnx->onnx-simplifier) (1.23.3)
Requirement already satisfied: protobuf<=3.20.1,>=3.12.2 in /home/dzh/anaconda3/envs/yolov5/lib/python3.8/site-packages (from onnx->onnx-simplifier) (3.19.6)
Requirement already satisfied: typing-extensions>=3.6.2.1 in /home/dzh/anaconda3/envs/yolov5/lib/python3.8/site-packages (from onnx->onnx-simplifier) (4.4.0)
Collecting commonmark<0.10.0,>=0.9.0
  Downloading commonmark-0.9.1-py2.py3-none-any.whl (51 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 51.1/51.1 kB 215.0 kB/s eta 0:00:00
Collecting pygments<3.0.0,>=2.6.0
  Downloading Pygments-2.13.0-py3-none-any.whl (1.1 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.1/1.1 MB 142.8 kB/s eta 0:00:00
Installing collected packages: commonmark, pygments, rich, onnx-simplifier
Successfully installed commonmark-0.9.1 onnx-simplifier-0.4.8 pygments-2.13.0 rich-12.6.0
(yolov5) dzh@dzh-Lenovo-Legion-Y7000:~/airockchip-yolov5$ python -m onnxsim ./weights/red.onnx ./weights/red2.onnx
Installing onnxruntime by `/home/dzh/anaconda3/envs/yolov5/bin/python -m pip install --user onnxruntime`, 
please wait for a moment..
Collecting onnxruntime
  Downloading onnxruntime-1.12.1-cp38-cp38-manylinux_2_27_x86_64.whl (4.9 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.9/4.9 MB 52.8 kB/s eta 0:00:00
Collecting coloredlogs
  Downloading coloredlogs-15.0.1-py2.py3-none-any.whl (46 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 46.0/46.0 kB 74.5 kB/s eta 0:00:00
Requirement already satisfied: protobuf in /home/dzh/anaconda3/envs/yolov5/lib/python3.8/site-packages (from onnxruntime) (3.19.6)
Collecting sympy
  Downloading sympy-1.11.1-py3-none-any.whl (6.5 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.5/6.5 MB 72.3 kB/s eta 0:00:00
Requirement already satisfied: packaging in /home/dzh/anaconda3/envs/yolov5/lib/python3.8/site-packages (from onnxruntime) (21.3)
Requirement already satisfied: numpy>=1.21.0 in /home/dzh/anaconda3/envs/yolov5/lib/python3.8/site-packages (from onnxruntime) (1.23.3)
Collecting flatbuffers
  Downloading flatbuffers-22.9.24-py2.py3-none-any.whl (26 kB)
Collecting humanfriendly>=9.1
  Downloading humanfriendly-10.0-py2.py3-none-any.whl (86 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 86.8/86.8 kB 129.3 kB/s eta 0:00:00
Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /home/dzh/anaconda3/envs/yolov5/lib/python3.8/site-packages (from packaging->onnxruntime) (3.0.9)
Collecting mpmath>=0.19
  Downloading mpmath-1.2.1-py3-none-any.whl (532 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 532.6/532.6 kB 128.3 kB/s eta 0:00:00
Installing collected packages: mpmath, flatbuffers, sympy, humanfriendly, coloredlogs, onnxruntime

然后输入python -m onnxsim ./weights/red.onnx ./weights/red2.onnx优化onnx模型。可以看到优化前后的表。

在这里插入图片描述


总结可能遇到的问题:

ONNX export failure: No module named ‘onnx’
原因:没有安装onnx库导致找不到该模块
RuntimeError: Given groups=1, weight of size [32, 12, 3, 3], expected input[1, 3, 640, 640] to have 12 channels, but got 3 channels instead
模型预期的图像通道是12,但是现在输入是3个通道的图像,所以在图片输入之前改成模型需要的通道数
<think>嗯,用户想了解YOLO模型中调试通道数的方法或解决相关问题,还有相关的报错解决方案。首先,我得回忆一下YOLO的结构,尤其是关于通道数的部分。YOLO的不同版本,比如v3、v5、v8,可能在通道数的处理上有些差异,所以得先明确用户用的是哪个版本。不过可能用户没具体说明,所以需要覆盖通用情况。 首先,通道数的问题通常出现在模型定义、数据预处理或权重加载时。比如,在定义模型时,卷积层的输入输出通道数不匹配会导致错误。这时候需要检查各层的通道数是否正确衔接。比如,如果某一层的输出通道是256,下一层的输入也应该是256,否则会报错。举个例子,用户可能在修改模型结构时调整了某层的通道数,但后续层没相应调整,导致维度不匹配。这时候需要逐层检查,特别是卷积层和上采样层之间的连接。 另外,数据预处理部分,输入图像的通道数一般是3(RGB),但如果用户误用了灰度图像或者数据加载时处理不当,可能会导致通道数错误。比如,如果数据加载器将图像转换为单通道,但模型期望的是三通道输入,就会出问题。这时候需要检查数据集的加载和处理代码,确保输入张量的形状是(batch_size, 3, height, width)。 然后是报错信息分析。常见的错误如“shape mismatch”或“expected input channels M, got N”这类,通常指向通道数不匹配。例如,在加载预训练权重时,如果用户修改了模型的通道数但没有重新训练或调整权重,就会导致权重形状不匹配。这时候可能需要冻结部分层,或者重新定义模型结构以匹配权重。 另外,用户提到的引用中有关于CUDA错误和模型推理的问题,比如AttributeError,这可能和模型加载失败有关。比如,使用engine模型(可能是TensorRT转换后的模型)时,如果输入通道数与engine期望的不一致,就会报错。这时候需要检查导出模型时的配置,确保输入尺寸和通道数正确。 还有用户可能在使用某些自定义模块时,比如SPP或FPN结构,通道数的调整不当也会引发问题。例如,在特征金字塔网络中,各层的通道数需要对齐才能进行融合,否则会导致相加或拼接时的维度错误。这时候需要确保各分支的输出通道数相同,或者使用1x1卷积进行调整。 此外,激活函数或归一化层的参数也可能与通道数相关。比如,BatchNorm层的num_features参数必须等于输入通道数,如果这里设置错误,会导致运行时错误。需要检查所有BN层的参数是否正确对应前一层的输出通道数。 解决方案方面,逐步调试是关键。可以使用调试工具或打印各层的输入输出形状,跟踪数据流,找出维度变化的位置。例如,在PyTorch中,可以在forward方法里添加print语句,输出各层的形状,帮助定位问题层。 对于YOLO的特定结构,比如Darknet中的残差块,通道数的变化需要遵循特定的模式。如果用户自行添加或删减了某些层,可能会破坏这种模式,导致后续层的计算出错。这时候参考官方模型定义,对比自己的修改部分,确保通道数变化符合预期。 还有可能的问题是在模型转换导出时,比如将PyTorch模型转换ONNX或TensorRT格式时,输入尺寸或通道数设置错误。需要确保在转换时指定正确的输入形状,包括通道数。例如,使用torch.onnx.export时,input_names和dynamic_axes参数需要正确设置,特别是对于通道数部分。 另外,用户可能在训练时调整了输入图像的尺寸,但没有相应调整模型中的锚点(anchors)或检测头的参数,导致通道数或特征图尺寸不匹配。例如,YOLO的检测头通常会预测边界框相对于网格的位置,如果特征图的尺寸变化,而锚点未调整,可能会引发维度错误。 总结一下,调试通道数的方法包括:检查模型定义中各层的通道数衔接,验证输入数据的通道数是否正确,确保预训练权重与模型结构匹配,使用调试工具跟踪张量形状,以及在模型转换时正确配置参数。对于报错,需要根据错误信息定位到具体层,逐步排查可能的通道数不匹配问题。</think>### YOLO模型中调试通道数的方法与解决方案 #### 1. **通道数错误的原因分析** - **模型结构定义错误**:在修改YOLO网络结构(如调整卷积层、特征金字塔层数)时,若未正确计算输入输出通道数,会导致张量维度不匹配。例如,若某层输出通道为$C_{out}$,下一层输入通道必须也为$C_{out}$[^1]。 - **输入数据格式错误**:输入图像的通道数必须与模型定义一致(通常为3通道RGB)。若数据预处理错误(如单通道灰度图),会触发类似`expected 3 channels but got 1`的报错[^2]。 - **预训练权重不匹配**:加载预训练权重时,若模型结构被修改(如增减通道数),会导致权重形状与模型参数不匹配,出现`shape mismatch`错误[^3]。 #### 2. **调试方法** - **逐层打印张量形状**:在模型前向传播中插入调试代码,输出各层输入输出形状: ```python class YOLOLayer(nn.Module): def forward(self, x): print(f"输入形状: {x.shape}") # 输出形状信息 # ... 原操作 ``` - **检查关键模块**: - **卷积层**:验证`nn.Conv2d(in_channels, out_channels, kernel_size)`的参数是否与前后层匹配。 - **特征融合层**:在FPN(特征金字塔)中,确保上采样和拼接操作的通道数对齐,必要时使用$1 \times 1$卷积调整通道数。 - **检测头**:YOLO检测头的输出通道数需满足$C = (5 + \text{num\_classes}) \times \text{num\_anchors}$,例如COCO数据集为$3 \times (5 + 80) = 255$。 #### 3. **常见报错与解决方案** - **报错示例1**:`RuntimeError: Given groups=1, weight of size [64, 256, 1, 1], expected input[16, 128, 256, 256] to have 256 channels, but got 128 channels` **原因**:前一层的输出通道为128,但当前卷积层的输入通道被设置为256。 **解决**:调整卷积层的`in_channels`参数为128,或修正前一层的输出通道数。 - **报错示例2**:`AttributeError: 'NoneType' object has no attribute 'create_execution_context'` **原因**:使用TensorRT的engine模型时,输入通道数与模型定义不符[^4]。 **解决**:检查模型导出时的输入配置,确保与推理代码一致,例如: ```python # ONNX导出代码示例 torch.onnx.export(model, dummy_input, "model.onnx", input_names=["input"], output_names=["output"]) ``` #### 4. **验证与优化** - **单元测试**:对修改后的模型进行前向传播测试: ```python dummy_input = torch.randn(1, 3, 640, 640) # 模拟输入 output = model(dummy_input) # 验证是否报错 ``` - **可视化工具**:使用Netron等工具查看模型结构,确认各层通道数逻辑正确。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

振华OPPO

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值