Onnx简要介绍

🧩 在 C# 中使用 ONNX 调用深度学习模型的完整笔记

本文系统总结了在 C# 环境中调用 ONNX 深度学习模型 的全流程,包括模型导出、模型结构分析、Metadata 信息提取、推理实现与性能优化。


一、ONNX 模型基础概念

1. 什么是 ONNX

  • ONNX(Open Neural Network Exchange) 是一种跨框架的模型中间表示格式。

  • 支持 PyTorch、TensorFlow、Keras、Scikit-Learn、XGBoost 等主流框架的互通。

  • 优点:

    • 平台无关,跨语言部署。
    • 提供推理优化(如算子融合、图剪枝)。
    • 可在 C#、C++、Python、Java 等环境运行。

2. ONNX 模型文件结构

  • 模型文件为 .onnx 二进制格式。

  • 核心组成:

    模块 说明
    Graph 网络计算图
    Node 每个算子(Conv、Relu、MatMul 等)
    Initializer 权重与偏置张量
    Input/Output 模型输入输出定义
    Metadata 模型元信息(版本、框架来源等)

二、ONNX 模型导出(PyTorch 示例)

1. 基本导出方式

import torch

dummy_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(
    model,
    dummy_input,
    "model.onnx",
    input_names=["input"],
    output_names=["output"],
    opset_version=17,
    dynamic_axes={
        "input": {0: "batch_size"},
        "output": {0: "batch_size"}
    }
)

2. 导出时的注意事项

  • 确保模型处于 eval() 模式。
  • 动态维度能避免 batch 固定问题。
  • 使用 onnx.checker.check_model() 验证模型有效性。

三、在 C# 中读取模型 Metadata 信息

在加载 ONNX 模型后,可通过 session.InputMetadatasession.OutputMetadata 获取模型的输入输出结构信息(名称、类型、维度等)。该数据在C#中是一个字典。

1. 获取输入元数据(InputMetadata)

using Microsoft.ML.OnnxRuntime;

// 加载模型
using var session = new InferenceSession("model.onnx");

// 获取输入元数据
var inputMeta = session.InputMetadata;

Console.WriteLine("=== 模型输入信息 ===");
foreach (var item in inputMeta)
{
    string name = item.Key; // 输入名称
    var meta = item.Value;  // Tensor 元信息

    Console.WriteLine($"输入名称: {name}");
    Console.WriteLine($"数据类型: {meta.ElementType}");
    Console.WriteLine($"维度信息: [{string.Join(", ", meta.Dimensions)}]");
    Console.WriteLine();
}

输出示例:

=== 模型输入信息 ===
输入名称: input
数据类型: Single
维度信息: [1, 3, 224, 224]

2. 获取输出元数据(OutputMetadata)

var outputMeta = session.OutputMetadata;

Console.WriteLine("=== 模型输出信息 ===");
foreach (var item in outputMeta)
{
    Console.WriteLine($"输出名称: {item.Key}");
    Console.WriteLine($"输出类型: {item.Value.ElementType}");
    Console.WriteLine($"输出维度: [{string.Join(", ", item.Value.Dimensions)}]");
}

3. 获取模型的全局元信息(MetadataProperties)

Console.WriteLine("=== 模型全局元信息 ===");
foreach (var kvp in session.ModelMetadata.CustomMetadataMap)
{
    Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
Console.WriteLine($"Producer: {session.ModelMetadata.ProducerName}");
Console.WriteLine($"Graph Name: {session.ModelMetadata.GraphName}");
Console.WriteLine($"Domain: {session.ModelMetadata.Domain}");

输出示例:

=== 模型全局元信息 ===
author: torch.onnx
version: 17
Producer: pytorch
Graph Name: model_graph
Domain: ai.onnx

4. 提取输入输出名称列表

若仅需名称列表,可使用:

var inputNames = session.InputMetadata.Keys.ToList();
var outputNames = session.OutputMetadata.Keys.ToList();

Console.WriteLine("输入张量名: " + string.Join(", ", inputNames));
Console.WriteLine("输出张量名: " + string.Join(", ", outputNames));

5. 结合维度信息动态构造输入张量

// 假设模型要求输入 [1, 3, 224, 224]
var inputName = session.InputMetadata.Keys.First();
var inputShape = session.InputMetadata[inputName].Dimensions;

// 构造匹配模型输入的张量
int totalSize = inputShape.Aggregate(1, (a, b) => a * b);
var inputTensor = new DenseTensor<float>(new float[totalSize], inputShape);

✅ 这种方式可确保模型升级或导出变化时,C# 推理端仍能自动适配输入尺寸。


四、ONNX 模型查看与可视化工具

1. 使用 Netron

  • 打开 https://netron.app

  • 拖入 .onnx 文件即可查看:

    • 输入/输出名称与 shape
    • 每层算子结构与连接关系
    • 参数数量与数据流

2. Python 端快速查看

import onnx
model = onnx.load("model.onnx")
for i in model.graph.input:
    print(i.name, [d.dim_value for d in i.type.tensor_type.shape.dim])

五、C# 模型推理与性能优化(简要)

1. 基础推理

var inputName = session.InputMetadata.Keys.First();
var tensor = new DenseTensor<float>(inputData, new[] { 1, 3, 224, 224 });
var inputs = new List<NamedOnnxValue>
{
    NamedOnnxValue.CreateFromTensor(inputName, tensor)
};
using var results = session.Run(inputs);
var output = results.First().AsTensor<float>().ToArray();

2. 优化建议

优化方向 方法
Session 重用 复用同一 InferenceSession 实例
图优化 GraphOptimizationLevel.ORT_ENABLE_ALL
GPU 加速 AppendExecutionProvider_CUDA(0)
异步推理 使用 RunAsync()

六、总结

  1. 导出时务必设置动态轴与合适的 opset。
  2. 在 C# 端可通过 InputMetadata / OutputMetadata 动态解析模型输入输出信息。
  3. 可利用 ModelMetadata 提取模型作者、框架、域等信息,便于版本管理。
  4. 建议结合 NetronMetadata 双重方式了解模型结构,确保推理正确性。

📚 推荐资源:

posted @ 2025-10-21 16:43  Ytytyty  阅读(4)  评论(0)    收藏  举报