ONNX中Conv算子输出形状为None,yolov7转TensorFlow报错求助
我训练了一个PyTorch版YOLOv7模型,使用以下脚本导出为ONNX格式:
!git clone https://github.com/WongKinYiu/yolov7 !pip install -r yolov7/requirements.txt ... !python3 yolov7/export.py --weights {my_checkpoint_path} --grid --simplify
之后用onnx2tf转换为TensorFlow格式时触发报错,关键日志如下:
Model convertion started ============================================================ INFO: input_op_name: images shape: [1, 3, 640, 640] dtype: float32 INFO: onnx_op_type: Conv onnx_op_name: /model.0/conv/Conv INFO: input_name.1: images shape: [1, 3, 640, 640] dtype: float32 INFO: input_name.2: model.0.conv.weight shape: [32, 3, 3, 3] dtype: <class 'numpy.float32'> INFO: input_name.3: model.0.conv.bias shape: [32] dtype: <class 'numpy.float32'> INFO: output_name.1: /model.0/conv/Conv_output_0 shape: None dtype: None ERROR: The trace log is below. Traceback (most recent call last): File "/usr/local/google/home/huiliukeith/pytorchenv/lib/python3.10/site-packages/onnx2tf/utils/common_functions.py", line 267, in print_wrapper_func result = func(*args, **kwargs) File "/usr/local/google/home/huiliukeith/pytorchenv/lib/python3.10/site-packages/onnx2tf/utils/common_functions.py", line 329, in inverted_operation_enable_disable_wrapper_func result = func(*args, **kwargs) File "/usr/local/google/home/huiliukeith/pytorchenv/lib/python3.10/site-packages/onnx2tf/ops/Conv.py", line 111, in make_node and graph_node.inputs[0].shape[2:] == output_tensor_shape[2:]: TypeError: 'NoneType' object is not subscriptable
我认为问题不在onnx2tf,而是ONNX导出时Conv层的输出形状被标记为None,想知道torch.onnx.export的哪些参数会导致这种情况?
解答
确实,torch.onnx.export的多个参数会影响ONNX模型的形状推断结果,导致输出形状被标记为None,关键参数及调整方案如下:
1. 动态维度设置(dynamic_axes)
如果导出时设置了dynamic_axes(比如允许batch size、输入尺寸动态变化),但未明确固定静态维度,ONNX会将可变维度标记为None。如果你的场景不需要动态维度,直接注释或删除这个参数即可;若必须保留动态性,也要明确指定哪些维度是动态的,避免全维度动态化。
2. opset版本(opset_version)
过低的opset版本(比如低于12)对形状推断的支持有限,建议使用opset 13及以上版本,YOLOv7的导出脚本默认可能使用较低版本,手动修改可提升形状推断准确性。
3. 常量折叠(do_constant_folding)
启用常量折叠(默认值为True)可以优化计算图,让ONNX更好地推断静态形状。如果导出时被设置为False,可能导致部分层的形状无法被正确解析。
4. 输入/输出名称指定(input_names/output_names)
明确指定输入输出张量名称,能帮助ONNX工具更清晰地解析图结构,避免因张量标识模糊导致的形状推断失败。
针对YOLOv7导出脚本的修改示例
找到YOLOv7的export.py中torch.onnx.export的调用代码,修改为如下配置:
torch.onnx.export(model, img, f, verbose=False, opset_version=13, training=torch.onnx.TrainingMode.EVAL, do_constant_folding=True, input_names=['images'], output_names=['output'], # 若不需要动态维度,注释掉下面的dynamic_axes # dynamic_axes={'images': {0: 'batch_size'}, # 'output': {0: 'batch_size'}} )
验证ONNX模型的形状
导出后可通过onnxruntime快速检查输出形状是否为静态值:
pip install onnxruntime
import onnxruntime as ort sess = ort.InferenceSession("your_exported_model.onnx") print(f"输入形状: {sess.get_inputs()[0].shape}") print(f"输出形状: {sess.get_outputs()[0].shape}")
如果输出形状仍为None,说明模型内部存在可变尺寸的操作,此时可在onnx2tf转换时用-ois参数强制指定静态输入形状(如onnx2tf -i your_model.onnx -ois "[1,3,640,640]"),但优先建议从导出阶段解决形状问题。
内容的提问来源于stack exchange,提问作者Hui Liu

