PyTorch 到 ONNX 导出,不支持 ATen 运算符,onnxruntime 挂起
PyTorch to ONNX export, ATen operators not supported, onnxruntime hangs out
我想将基于 roberta-base
的语言模型导出为 ONNX
格式。该模型使用 ROBERTA
嵌入并执行文本分类任务。
from torch import nn
import torch.onnx
import onnx
import onnxruntime
import torch
import transformers
来自日志:
17: pytorch: 1.10.2+cu113
18: CUDA: False
21: device: cpu
26: onnxruntime: 1.10.0
27: onnx: 1.11.0
PyTorch
导出
batch_size = 3
model_input = {
'input_ids': torch.empty(batch_size, 256, dtype=torch.int).random_(32000),
'attention_mask': torch.empty(batch_size, 256, dtype=torch.int).random_(2),
'seq_len': torch.empty(batch_size, 1, dtype=torch.int).random_(256)
}
model_file_path = os.path.join("checkpoints", 'model.onnx')
torch.onnx.export(da_inference.model, # model being run
model_input, # model input (or a tuple for multiple inputs)
model_file_path, # where to save the model (can be a file or file-like object)
export_params=True, # store the trained parameter weights inside the model file
opset_version=11, # the ONNX version to export the model to
operator_export_type=torch.onnx.OperatorExportTypes.ONNX_ATEN_FALLBACK,
do_constant_folding=True, # whether to execute constant folding for optimization
input_names = ['input_ids', 'attention_mask', 'seq_len'], # the model's input names
output_names = ['output'], # the model's output names
dynamic_axes={'input_ids': {0 : 'batch_size'},
'attention_mask': {0 : 'batch_size'},
'seq_len': {0 : 'batch_size'},
'output' : {0 : 'batch_size'}},
verbose=True)
我知道如果包含在模型架构中,从 ATen(C++11 的张量库)转换某些运算符可能会出现问题 PyTorch Model Export to ONNX Failed Due to ATen。
如果我设置参数 operator_export_type=torch.onnx.OperatorExportTypes.ONNX_ATEN_FALLBACK
则导出成功,这意味着 'leave as is ATen operators if not supported in ONNX'.
PyTorch 导出函数给我以下警告:
Warning: Unsupported operator ATen. No schema registered for this operator.
Warning: Shape inference does not support models with experimental operators: ATen
看起来模型中唯一未转换为 ONNX 的 ATen 运算符位于层 LayerNorm.weight 和 LayerNorm.bias 内(我有几个这样的层):
%1266 : Float(3, 256, 768, strides=[196608, 768, 1], requires_grad=0, device=cpu) =
onnx::ATen[cudnn_enable=1, eps=1.0000000000000001e-05, normalized_shape=[768], operator="layer_norm"]
(%1265, %model.utterance_rnn.base.encoder.layer.11.output.LayerNorm.weight,
%model.utterance_rnn.base.encoder.layer.11.output.LayerNorm.bias)
# /opt/conda/lib/python3.9/site-packages/torch/nn/functional.py:2347:0
比模型检查通过 OK:
model = onnx.load(model_file_path)
# Check that the model is well formed
onnx.checker.check_model(model)
# Print a human readable representation of the graph
print(onnx.helper.printable_graph(model.graph))
我还可以使用 Netron 可视化计算图。
但是当我尝试使用导出的 ONNX 模型执行推理时,它停止了,没有日志或标准输出。所以这段代码会挂掉系统:
model_file_path = os.path.join("checkpoints", "model.onnx")
sess_options = onnxruntime.SessionOptions()
sess_options.log_severity_level = 0
ort_providers: List[str] = ["CUDAExecutionProvider"] if use_gpu else ['CPUExecutionProvider']
session = InferenceSession(model_file_path, providers=ort_providers, sess_options=sess_options)
有没有解决这个问题的建议?从官方文档中我看到 torch.onnx 以这种方式导出的模型可能只能由 Caffe2
.
运行
这些层不在基础冷冻 roberta 模型中,所以这是我自己添加的附加层。是否可以用相似层替换有问题的层并重新训练模型?
或者 Caffe2
是这里的最佳选择并且 onnxruntime 不会进行推理?
更新:我在BERT cased embeddings的基础上重新训练了模型,但是问题依旧。相同的 ATen 运算符不会在 ONNX 中转换。
看起来层 LayerNorm.weight 和 LayerNorm.bias 仅在 BERT 之上的模型中。那么,您对更改此层并启用 ONNX 导出有何建议?
您是否尝试过在为 onnx 定义运算符后导出?类似于以下内容 code by Huawei.
另一方面,加载模型时,从技术上讲,您可以覆盖任何您想要的内容。放置一个特定层等于您修改后的 class 继承原始层,保持相同的行为(输入和输出)但可以修改它的执行。
您可以尝试使用它来保存更改后有问题的运算符的模型,在 onnx 中对其进行转换,并以这种形式(甚至在 pytorch 中)进行微调。
这通常似乎最好由 onnx 团队解决,因此长期解决方案可能是 post 在 github issues page 上对特定运算符的请求(但可能很慢)。
最好的方法是重写模型中使用这些运算符的地方,以某种方式转换查看 this 以供参考。
例如,如果问题是层规范,那么您可以自己编写。有时有帮助的另一件事是不要将轴设置为动态的,因为有些操作还不支持它
我想将基于 roberta-base
的语言模型导出为 ONNX
格式。该模型使用 ROBERTA
嵌入并执行文本分类任务。
from torch import nn
import torch.onnx
import onnx
import onnxruntime
import torch
import transformers
来自日志:
17: pytorch: 1.10.2+cu113
18: CUDA: False
21: device: cpu
26: onnxruntime: 1.10.0
27: onnx: 1.11.0
PyTorch
导出
batch_size = 3
model_input = {
'input_ids': torch.empty(batch_size, 256, dtype=torch.int).random_(32000),
'attention_mask': torch.empty(batch_size, 256, dtype=torch.int).random_(2),
'seq_len': torch.empty(batch_size, 1, dtype=torch.int).random_(256)
}
model_file_path = os.path.join("checkpoints", 'model.onnx')
torch.onnx.export(da_inference.model, # model being run
model_input, # model input (or a tuple for multiple inputs)
model_file_path, # where to save the model (can be a file or file-like object)
export_params=True, # store the trained parameter weights inside the model file
opset_version=11, # the ONNX version to export the model to
operator_export_type=torch.onnx.OperatorExportTypes.ONNX_ATEN_FALLBACK,
do_constant_folding=True, # whether to execute constant folding for optimization
input_names = ['input_ids', 'attention_mask', 'seq_len'], # the model's input names
output_names = ['output'], # the model's output names
dynamic_axes={'input_ids': {0 : 'batch_size'},
'attention_mask': {0 : 'batch_size'},
'seq_len': {0 : 'batch_size'},
'output' : {0 : 'batch_size'}},
verbose=True)
我知道如果包含在模型架构中,从 ATen(C++11 的张量库)转换某些运算符可能会出现问题 PyTorch Model Export to ONNX Failed Due to ATen。
如果我设置参数 operator_export_type=torch.onnx.OperatorExportTypes.ONNX_ATEN_FALLBACK
则导出成功,这意味着 'leave as is ATen operators if not supported in ONNX'.
PyTorch 导出函数给我以下警告:
Warning: Unsupported operator ATen. No schema registered for this operator.
Warning: Shape inference does not support models with experimental operators: ATen
看起来模型中唯一未转换为 ONNX 的 ATen 运算符位于层 LayerNorm.weight 和 LayerNorm.bias 内(我有几个这样的层):
%1266 : Float(3, 256, 768, strides=[196608, 768, 1], requires_grad=0, device=cpu) =
onnx::ATen[cudnn_enable=1, eps=1.0000000000000001e-05, normalized_shape=[768], operator="layer_norm"]
(%1265, %model.utterance_rnn.base.encoder.layer.11.output.LayerNorm.weight,
%model.utterance_rnn.base.encoder.layer.11.output.LayerNorm.bias)
# /opt/conda/lib/python3.9/site-packages/torch/nn/functional.py:2347:0
比模型检查通过 OK:
model = onnx.load(model_file_path)
# Check that the model is well formed
onnx.checker.check_model(model)
# Print a human readable representation of the graph
print(onnx.helper.printable_graph(model.graph))
我还可以使用 Netron 可视化计算图。
但是当我尝试使用导出的 ONNX 模型执行推理时,它停止了,没有日志或标准输出。所以这段代码会挂掉系统:
model_file_path = os.path.join("checkpoints", "model.onnx")
sess_options = onnxruntime.SessionOptions()
sess_options.log_severity_level = 0
ort_providers: List[str] = ["CUDAExecutionProvider"] if use_gpu else ['CPUExecutionProvider']
session = InferenceSession(model_file_path, providers=ort_providers, sess_options=sess_options)
有没有解决这个问题的建议?从官方文档中我看到 torch.onnx 以这种方式导出的模型可能只能由 Caffe2
.
这些层不在基础冷冻 roberta 模型中,所以这是我自己添加的附加层。是否可以用相似层替换有问题的层并重新训练模型?
或者 Caffe2
是这里的最佳选择并且 onnxruntime 不会进行推理?
更新:我在BERT cased embeddings的基础上重新训练了模型,但是问题依旧。相同的 ATen 运算符不会在 ONNX 中转换。 看起来层 LayerNorm.weight 和 LayerNorm.bias 仅在 BERT 之上的模型中。那么,您对更改此层并启用 ONNX 导出有何建议?
您是否尝试过在为 onnx 定义运算符后导出?类似于以下内容 code by Huawei.
另一方面,加载模型时,从技术上讲,您可以覆盖任何您想要的内容。放置一个特定层等于您修改后的 class 继承原始层,保持相同的行为(输入和输出)但可以修改它的执行。 您可以尝试使用它来保存更改后有问题的运算符的模型,在 onnx 中对其进行转换,并以这种形式(甚至在 pytorch 中)进行微调。
这通常似乎最好由 onnx 团队解决,因此长期解决方案可能是 post 在 github issues page 上对特定运算符的请求(但可能很慢)。
最好的方法是重写模型中使用这些运算符的地方,以某种方式转换查看 this 以供参考。 例如,如果问题是层规范,那么您可以自己编写。有时有帮助的另一件事是不要将轴设置为动态的,因为有些操作还不支持它