【避坑指南】ONNX导出Resize算子版本适配失败?一文解决No Adapter To Version 17错误与.numpy()陷阱
【避坑指南】ONNX导出Resize算子版本适配失败?一文解决No Adapter To Version 17错误与.numpy()陷阱
摘要:在将PyTorch模型导出为ONNX时,你是否遇到过“No Adapter To Version 17 for Resize”和“.numpy() not supported for tensor subclasses”的诡异报错?本文将深入剖析该问题的根因(ONNX版本转换器缺失+PyTorch内部numpy调用冲突),并提供一套经过验证的终极解决方案(升级ONNX库、固定opset版本、规避numpy调用)。适合所有使用PyTorch模型部署到ONNX/ONNX Runtime的开发者,尤其针对包含Resize算子(如Upsample)的模型。
引言
深夜加班,你满心欢喜地训练好一个超级棒的PyTorch模型,准备导出ONNX部署上线。结果终端里突然刷出一串红色报错:“No Adapter To Version 17 for Resize”,紧接着又来一句“.numpy() not supported for tensor subclasses”。是不是瞬间心态就崩了?别急,你不是一个人。这个组合错误坑了无数人,今天我们就来彻底把它“按在地上摩擦”。
环境说明
| 项目 | 内容 |
|---|---|
| 操作系统 | Windows |
| Python环境 | Anaconda |
| 深度学习框架 | PyTorch |
| 相关库 | ONNX、onnxruntime、onnxscript、onnx_ir |
| 问题场景 | PyTorch模型导出为ONNX(包含nn.Upsample或F.interpolate——底层对应Resize算子) |
注意:该问题的出现与库的具体版本关系密切,但即使版本较新也可能触发。下文提供的解决方案适用性较广。
错误现场
假设我们尝试用以下代码导出模型:
import torch
import torch.onnx
# 假设 model 是一个包含 Upsample 层的模型
model = MyModel()
dummy_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(model, dummy_input, "model.onnx", verbose=True)
# 或指定了 opset_version=17
终端输出的错误信息如下:
RuntimeError: Exporting the operator 'aten::upsample_nearest2d' to ONNX opset version 17 is not supported. Please open a bug to request ONNX export support for the missing operation. Or try opset version lower than 17 to export the model.
...
During handling of the above exception, another exception occurred:
...
onnx_ir.passes.PassError: No adapter to version $17 for Resize
...
AttributeError: '.numpy()' is not supported for tensor subclasses. Use .detach().numpy() instead.
简单解读一下:
No adapter to version $17 for Resize:ONNX 内部版本转换器(adapter)在处理Resize算子时,找不到从当前 opset 转换到 opset 17 的适配函数。.numpy() not supported for tensor subclasses:在优化或转换过程中,某处对torch.Tensor调用了.numpy(),但该 Tensor 是一个子类(如torch.nn.Parameter或某些自定义子类),导致调用失败。- 最终
onnx_ir.passes.PassError表明优化 pass 崩溃,导出流程直接中断。
排查思路
由于我们无法直接复现用户的每一个尝试,我将常见的排查方向分享给大家,并说明为什么它们可能无效或不够彻底:
-
尝试降低 opset 版本:将
opset_version从 17 降至 11 或 13。- 结果:
Resize适配错误消失,但新错误可能随之而来(其他算子不兼容低版本)。 - 为什么不行:治标不治本。opset 17 引入了更丰富的
Resize属性(如coordinate_transformation_mode、nearest_mode等),如果模型利用了这些新特性,降版本会导致语义丢失或失败。
- 结果:
-
升级 onnx 和 onnxruntime:
pip install --upgrade onnx onnxruntime- 结果:有时能解决
No Adapter问题,但.numpy()错误依旧。 - 为什么不行:
.numpy()问题是 PyTorch 内部实现与 onnx 导出脚本的交互问题,与 onnx 库版本无关;且 onnx 升级后,某些 adapter 仍未覆盖 opset 17 的Resize。
- 结果:有时能解决
-
检查输入张量形状与动态轴:确保
dynamic_axes参数正确,且输入输出张量不是torch.nn.Parameter。- 结果:无改善。
- 为什么不行:根源不在动态轴参数,而在 PyTorch 导出过程中的内部调用。
-
替换自定义 Resize 算子:自己重写一个 ONNX 算子实现。
- 结果:工作量巨大,且易出错。
- 太笨重:这不是通用解法。
终极解决方案
经过大量测试与源码追踪,我总结出一套最可靠、最精准的解决方案,只需四步即可彻底解决。
Step 1:升级 ONNX 与相关库至最新稳定版
这是基础,但必须做。请在你的 Anaconda 环境中执行:
pip install --upgrade onnx onnxruntime onnxscript
注意:onnx 可以升级,但 onnxruntime 和 onnxscript 也可能需要同步更新以避免兼容性问题。
Step 2:指定 opset 版本为 17(保留最新特性)
不要在代码中降版本。请像这样导出:
torch.onnx.export(
model,
dummy_input,
"model.onnx",
opset_version=17, # 明确指定 17
input_names=['input'],
output_names=['output'],
dynamic_axes={'input': {0: 'batch_size'}, 'output': {0: 'batch_size'}}
)
为什么指定 17? 因为升级后的 ONNX(≥1.14)已经补全了 opset 17 的
Resizeadapter,但你必须显式告诉 PyTorch 使用 opset 17,否则它可能自动选择较低版本(如 9 或 13)。
Step 3:手动规避 .numpy() 调用陷阱
PyTorch 内部在导出时(尤其是在 _export_onnx::_get_numpy_style_axes 等函数中)会对 torch.Tensor 的子类(如 Parameter)调用 .numpy()。解决方法是在导出前将模型中的所有 Parameter 转换为普通 Tensor。可以在 export 之前执行:
def convert_parameters_to_tensors(model):
for name, param in model.named_parameters():
# 将 Parameter 变为普通 Tensor,但 retain 数据
setattr
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)