4. 模型转换工具使用

任务说明

本案例使用NPU厂商提供的模型转换工具,将一个ONNX格式的模型转换为NPU可执行的格式(如.kmodel),并验证转换产物是否生成且具备正确的模型结构信息。转换工具以onnx2npu命令行工具为例,该工具封装了NPU编译器后端。

环境与依赖

  • 已安装NPU SDK(包含onnx2npu转换工具)
  • Python 3.8+,已安装onnx库(用于验证ONNX模型有效性)
  • 示例模型:mobilenetv2.onnx(可从ONNX Model Zoo下载,或使用任意测试用ONNX模型)

完整实现

以下脚本完成三步操作:① 检查ONNX模型是否有效;② 调用转换工具生成NPU可执行文件;③ 验证输出文件是否存在且非空。

import subprocess
import os
import sys
import onnx

def validate_onnx(model_path):
    """检查ONNX模型结构是否合法"""
    try:
        model = onnx.load(model_path)
        onnx.checker.check_model(model)
        print(f"[1/3] ONNX模型验证通过: {model_path}")
        return True
    except Exception as e:
        print(f"[1/3] ONNX模型验证失败: {e}")
        return False

def convert_model(onnx_path, output_path, tool="onnx2npu"):
    """调用NPU转换工具将ONNX转为NPU可执行格式"""
    if not os.path.exists(onnx_path):
        print(f"错误: ONNX文件不存在 - {onnx_path}")
        return False
    
    # 清理旧输出
    if os.path.exists(output_path):
        os.remove(output_path)
    
    # 执行转换命令
    cmd = [tool, onnx_path, "-o", output_path]
    print(f"[2/3] 执行转换命令: {' '.join(cmd)}")
    
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
        if result.returncode != 0:
            print(f"转换失败 (exit code {result.returncode}):")
            print(result.stderr)
            return False
        print("转换命令执行成功")
        return True
    except FileNotFoundError:
        print(f"错误: 找不到转换工具 '{tool}',请确认NPU SDK已正确安装并加入PATH")
        return False
    except subprocess.TimeoutExpired:
        print("转换超时(120秒)")
        return False

def verify_output(output_path):
    """验证转换产物是否生成且非空"""
    if not os.path.exists(output_path):
        print(f"[3/3] 验证失败: 输出文件不存在 - {output_path}")
        return False
    
    file_size = os.path.getsize(output_path)
    if file_size == 0:
        print("[3/3] 验证失败: 输出文件为空")
        return False
    
    print(f"[3/3] 验证通过: 输出文件已生成 ({file_size} 字节)")
    return True

def main():
    # 配置路径
    onnx_path = "mobilenetv2.onnx"      # 输入ONNX模型
    output_path = "mobilenetv2.kmodel"  # 输出NPU可执行格式
    
    # 执行流程
    if not validate_onnx(onnx_path):
        sys.exit(1)
    
    if not convert_model(onnx_path, output_path):
        sys.exit(1)
    
    if not verify_output(output_path):
        sys.exit(1)
    
    print("\n转换流程全部完成。生成的NPU可执行文件: " + output_path)

if __name__ == "__main__":
    main()

运行方式

# 将脚本保存为 convert_and_verify.py,与 mobilenetv2.onnx 放在同一目录
python convert_and_verify.py

验证方法与判定标准

  • 步骤1判定:控制台输出“ONNX模型验证通过”,说明输入模型结构合法,可进入转换环节。
  • 步骤2判定:控制台输出“转换命令执行成功”,且无错误信息,说明NPU工具正常完成格式转换。
  • 步骤3判定:控制台输出“验证通过: 输出文件已生成 (N 字节)”,其中N为实际文件大小(大于0),说明转换产物已落盘。
  • 最终判定:脚本退出码为0,且当前目录下出现mobilenetv2.kmodel文件,即表示转换成功。

常见问题

  • 找不到转换工具:确认NPU SDK安装路径已加入系统PATH,或修改脚本中tool参数为工具路径。
  • 转换失败且无明确错误:检查ONNX模型是否包含NPU不支持的算子(如动态shape、特定自定义op),可尝试先用onnxsim简化模型。
  • 输出文件生成但后续加载失败:确认目标NPU硬件平台与转换工具版本匹配,不同芯片型号可能需要不同的编译参数。