C# ONNX使用入门教程

背景

有新入坑的老哥不太了解C# onnx 运行的机理,我这边详细介绍一下,之前直接放官方的样例有点草率了。

准备python环境

1、要使用onnx,首先我们就自己生成一个onnx文件,请大家准备一下以下需要的python环境

cpp 复制代码
python 版本>=3.8 我的机子比较老,只能装3.8
安装torch,可以使用命令行pip install torch
安装netron,可以使用命令行pip install netron
安装onnx,可以使用命令行pip install onnx

2、做好以上准备工作,我们就可以编写一个py文件,命名为create_onnx.py,内容如下:

python 复制代码
#======================================================================#

# 导入依赖库
import torch

#======================================================================#

# 打印pytorch基本信息
print("pytorch版本:",torch.__version__)
print("已安装pytorch版本是否支持英伟达显卡",torch.cuda.is_available())

# 自定义网络必须直接或间接继承自torch.nn.Module
class Net(torch.nn.Module):
    def __init__(self):
        super(self.__class__,self).__init__()
        self.linear=torch.nn.Linear(1,1)

    def forward(self,x):
        return self.linear(x)

#======================================================================#

# 训练自定义网络

# 实例化一个自定义网络对象,用于以下训练
net=Net()

# 选择平方差为标准损失函数
critision=torch.nn.MSELoss()
# 选择随机梯度下降的优化器,学习率设为0.01
optimizer=torch.optim.Adam(net.parameters(),lr=0.01)

# 训练的输入
x=torch.FloatTensor([[0],[1],[2],[3]])
# 训练的输出
y=torch.FloatTensor([[5],[7],[9],[11]])

# 训练3000轮
for epoch in range(1,3001):
    Y=net(x)
    loss=critision(Y,y)
    # 每训练100轮打印一次损失值以便于观察是否收敛
    if epoch%100==0:
        print(f"epoch:{epoch},loss:{loss.item()}")
    # 自动求导
    optimizer.zero_grad()
    # 反向传播
    loss.backward()
    # 更新参数
    optimizer.step()

#======================================================================#

# 保存模型为onnx格式,方便c#调用

# 输入参数格式为1行1列的数组
input_parameter=torch.randn(1,1)
# 导出onnx格式前务必先调用eval函数
net.eval()
with torch.no_grad():
    torch.onnx.export(net,# 自定义的网络对象
                      input_parameter, # 输入参数格式
                      "linear.onnx", # 导出onnx格式文件名称
                      opset_version=11, # 导出onnx指定算子版本
                      input_names=["input"], # 输入参数名称
                      output_names=["output"]) # 输出参数名称
#======================================================================#

命令行直接运行它,过一会它训练完毕,就会给我们生成onnx文件,名称为linear.onnx

3、编写另一个py文件,命名为watch_onnx.py,内容如下:

python 复制代码
import netron
netron.start("linear.onnx")

命令行直接运行它,过一会浏览器会直接显示出此onnx文件的推理图全过程参数

4、观察此onnx文件的输入输出,其输入为1x1的数组,输出也是1x1的数组。同时注意到它的意义,输入是\[x],输出是\[y],于是我们可以开始编写C#程序了。

正题C#调用onnx

1、新建一个DotNet控制台项目,千万别选成了DotNetFramework,命名为UseOnnx

2、NuGet中安装onnxruntime,由于只是简单入门介绍 ,这里我们选择cpu版本的onnx运行时安装即可,图中就是cpu的onnx运行时库

3、项目和依赖都准备好了,开始着手C#程序的编写,把Program.cs内容改为:

cs 复制代码
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using System;
using System.Collections.Generic;

namespace UseOnnx
{
    class Program
    {
        static void Main(string[] args)
        {
            //onnx文件路径,注意把onnx文件放到我们生成程序同级目录下
            string onnx_path = @"linear.onnx";
            //根据onnx文件路径实例化一个推理对象
            using InferenceSession session = new InferenceSession(onnx_path);

            //稠密张量,其维度与模型的输入参数格式一致,1x1==>>new int[]{1,1}
            DenseTensor<float> tensor = new DenseTensor<float>(new int[] { 1, 1 });

            //测试的输入为101
            float x = 101f;

            //把输入赋值到张量中
            tensor[0, 0] = x;

            //构建输入
            List<NamedOnnxValue> inputs = new List<NamedOnnxValue>()
            {
                //onnx推理图的输入名称为input,参数格式为1x1,因此这样构建输入
                NamedOnnxValue.CreateFromTensor("input",tensor)
            };

            //进行推理,得到结果
            using IDisposableReadOnlyCollection<DisposableNamedOnnxValue> outputs = session.Run(inputs);

            //输出是二维数组
            float[,] results = (float[,])outputs[0].Value;

            //输出只有一个,它就是onnx推理结果
            float y = results[0, 0];

            Console.WriteLine($"when x is {x} , onnx calculate y is {y:0.0}");
        }
    }
}

开始运行,如果没报错的话,应该可以看到近似结果

207.0

由于我的系统是win7,跑程序的时候报错没找到onnxruntime.dll,就算把这个动态链接库拷贝到同级目录下也报同样错误,所以没法最后一步截图演示了。希望win10、win11的小伙伴知悉。

相关推荐
小鹿学程序14 小时前
市赛python学习
python
高洁0114 小时前
知识图谱:结构化表达实体与关系的知识组织技术
人工智能·python·深度学习·机器学习·迁移学习
骊山道童14 小时前
第 1 周 LLM 原理与高效微调知识精讲手册
python
tellmewhoisi14 小时前
深度学习24:PyTorch:Sequential构建模型
人工智能·pytorch·深度学习
蘑菇小白14 小时前
Linux多线程开发
linux·开发语言·线程
Metaphor69214 小时前
轻松使用 Python 将 RTF 转换为 Word(含批量转换与格式互转)
python·word·rtf
zh路西法14 小时前
【深入理解 LSTM】从时间反向传播(BPTT)到长时记忆:门控机制与实验验证
pytorch·python·rnn·gru·lstm·bptt
青少儿编程课堂14 小时前
蓝桥杯青少组 + 全国青少年信息素养大赛 + 电子学会图形化考级|校园推箱子大挑战解析
c++·python·算法·bfs·信息学竞赛
2601_9669496515 小时前
Python 实战:如何统计五档盘口买卖盘总挂单量?附计算公式与代码
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
全栈陈序员15 小时前
【Python】基础语法入门(二十九)—— 正则表达式实战:文本处理利器
开发语言·人工智能·python·正则表达式