昇腾部署onnx模型问题总结
使用ATC转换onnx模型出错
报错信息
ERROR:edge_agent:Run command return fail, COMMAND="atc --framework=5 --model=/deploy/in/fastsam/FastSAM-x.onnx --soc-version=Ascend910B4 --output=/deploy/models/modelname/1/model", RET=255, STDOUT="ATC start working now, please wait for a moment.
...
ATC run failed, Please check the detail log, Try 'atc --help' for more information
E19010: 2024-12-30-02:55:37.701.083 No parser is registered for Op [/model.0/conv/Conv, optype [ai.onnx::19::Conv]].
Solution: Check the version of the installation package and reinstall the package. For details, see the operator specifications.
TraceBack (most recent call last):
No parser is registered for Op [/model.0/act/Sigmoid, optype [ai.onnx::19::Sigmoid]].
No parser is registered for Op [/model.0/act/Mul, optype [ai.onnx::19::Mul]].
No parser is registered for Op [/model.1/conv/Conv, optype [ai.onnx::19::Conv]].
No parser is registered for Op [/model.1/act/Sigmoid, optype [ai.onnx::19::Sigmoid]].
No parser is registered for Op [/model.1/act/Mul, optype [ai.onnx::19::Mul]].
问题分析
通过netron来看onnx,发现是opset19的模型。
而我用的atc版本比较旧,猜测是opset版本太高导致atc不支持。
解决办法
在export onnx的时候,指定opset 12。再用atc转换为om模型就不报错了。
如果没有原始的pt模型,只能直接改onnx模型,可以试试这个方法:
import onnx
model = onnx.load("./in/my.onnx")
for opset in model.opset_import:
if opset.domain == "":
opset.version = 12 #
onnx.save(model, "output_model.onnx")
ACL加载om模型出错
在acl获取输出tensor名称时报错了
I1231 02:46:09.580177 6318 pb_stub.cc:366] "Failed to initialize Python stub: NameError: name 'output_tensor_name' is not defined\n\nAt:\n /deploy/models/modelname/1/model.py(175): initialize\n"
[INFO] INIT: input name[0] = images
[INFO] INIT: input datatype[0] = 0
[INFO] INIT: input dims[0] = {'name': 'images', 'dimCount': 4, 'dims': [1, 3, 1024, 1024]}
[INFO] INIT: output name[0] = output0
[INFO] INIT: output datatype[0] = 0
[INFO] INIT: output dims[0] = {'name': '/model.22/Concat_11:0:output0', 'dimCount': 3, 'dims': [1, 37, 21504]}
[INFO] INIT: output name[1] = output1
[INFO] INIT: output datatype[1] = 0
[INFO] INIT: output dims[1] = {'name': '/model.22/Concat_1:0:output1', 'dimCount': 4, 'dims': [1, 105, 128, 128]}
E1231 02:46:12.922687 6318 backend_model.cc:692] "ERROR: Failed to create instance: NameError: name 'output_tensor_name' is not defined\n\nAt:\n /deploy/models/modelname/1/model.py(175): initialize\n"
E1231 02:46:12.922926 6318 model_lifecycle.cc:642] "failed to load 'modelname' version 1: Internal: NameError: name 'output_tensor_name' is not defined\n\nAt:\n /deploy/models/modelname/1/model.py(175): initialize\n"
I1231 02:46:12.922969 6318 model_lifecycle.cc:777] "failed to load 'modelname'"
解析输出tensor出错了。前两个输出Tensor名字分别是output0和output1,第三个是onnx::Reshape_1276。
我猜测和名字里的前缀有关,可能是“::”导致解析失败。后来测试印证了我的猜想。
解决办法
修改onnx模式输出节点名称,将输出节点中包含“onnx::”前缀去掉。
import onnx
# 1. 加载 ONNX 模型
model_path = "my.onnx" # 替换为你的 ONNX 模型路径
model = onnx.load(model_path)
# 2. 定义需要去掉的前缀
prefix = "onnx::"
# 3. 遍历所有输出节点,修改名称并更新前一级节点
for output in model.graph.output:
if output.name.startswith(prefix):
# 去掉前缀,生成新的输出节点名称
new_output_name = output.name[len(prefix):]
old_output_name = output.name
# 修改输出节点名称
output.name = new_output_name
print(f"Output node name changed from '{old_output_name}' to '{new_output_name}'")
# 4. 查找并更新所有相关节点的输入和输出
for node in model.graph.node:
# 更新节点的输入
for i, node_input in enumerate(node.input):
if node_input == old_output_name:
node.input[i] = new_output_name
print(f"Updated node '{node.name}' input from '{old_output_name}' to '{new_output_name}'")
# 更新节点的输出
for i, node_output in enumerate(node.output):
if node_output == old_output_name:
node.output[i] = new_output_name
print(f"Updated node '{node.name}' output from '{old_output_name}' to '{new_output_name}'")
# 5. 更新模型的元数据(可选)
model.model_version = 1 # 更新模型版本
model.doc_string = "Modified model with updated output node names (removed 'onnx::' prefix)" # 更新描述信息
# 6. 验证模型是否有效
try:
onnx.checker.check_model(model)
print("Model is valid!")
except onnx.checker.ValidationError as e:
print(f"Model is invalid: {e}")
# 7. 保存修改后的模型
new_model_path = "my_out.onnx" # 替换为保存路径
onnx.save(model, new_model_path)
print(f"Modified model saved to '{new_model_path}'")