You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#.NET从零训练神经网络并通过ONNX在ML.NET中运行?

解决方案

方案1:借助PyTorch Python脚本完成ONNX导出(最直接可行)

TorchSharp保存的模型格式与PyTorch完全兼容,可通过以下步骤完成格式转换:

  1. TorchSharp端保存完整模型
    训练完成后,使用model.Save("your_model.pt")保存完整模型(不要仅保存state_dict,避免后续加载权重时结构不匹配)。

  2. Python脚本加载模型并导出ONNX
    安装PyTorch后,编写与TorchSharp端结构完全一致的模型代码,加载权重并导出:

import torch

# 必须与TorchSharp中的模型结构完全匹配(层数量、参数、激活顺序都要一致)
class CustomModel(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = torch.nn.Linear(784, 256)
        self.relu = torch.nn.ReLU()
        self.fc2 = torch.nn.Linear(256, 10)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# 加载TorchSharp保存的模型权重
model = CustomModel()
model.load_state_dict(torch.load("your_model.pt"))
model.eval()

# 构造与模型输入维度一致的示例张量(需匹配实际输入尺寸)
dummy_input = torch.randn(1, 784)

# 导出ONNX模型
torch.onnx.export(model, dummy_input, "your_model.onnx", opset_version=12)
  1. ML.NET导入ONNX模型并统一接口
    使用OnnxTransformer加载导出的模型,与现有ML.NET代码整合:
var mlContext = new MLContext();

// 定义输入输出数据类
public class ModelInput
{
    [ColumnName("input")]
    [VectorType(784)]
    public float[] Features { get; set; }
}

public class ModelOutput
{
    [ColumnName("output")]
    public float[] PredictedLabels { get; set; }
}

// 构建ML.NET管道,添加ONNX转换节点
var pipeline = mlContext.Transforms.ApplyOnnxModel(
    outputColumnNames: new[] { "output" },
    inputColumnNames: new[] { "input" },
    modelFile: "your_model.onnx");

// 拟合空数据完成管道初始化(模型已训练完成,仅需构建推理管道)
var emptyData = mlContext.Data.LoadFromEnumerable(new List<ModelInput>());
var inferenceModel = pipeline.Fit(emptyData);

// 创建预测引擎,与现有ML.NET接口统一
var predictionEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(inferenceModel);
var input = new ModelInput { Features = new float[784] }; // 替换为实际输入数据
var prediction = predictionEngine.Predict(input);

方案2:纯.NET环境下的替代方案(无需Python)

如果不想依赖Python,可尝试以下两种方式:

  • 使用TorchSharp底层ONNX导出API(实验性)
    部分最新版TorchSharp提供了未公开的底层导出接口,可尝试调用:
using TorchSharp;
using static TorchSharp.torch;

// 模型切换为评估模式
model.eval();

// 构造与实际输入维度一致的示例张量
var dummyInput = torch.randn(1, 784);

// 调用底层导出方法
model.ToONNX("your_model.onnx", dummyInput, opset_version: 12);

注意:该方法仅在部分TorchSharp预览版中可用,稳定性需自行验证。

  • 封装TorchSharp模型为ML.NET自定义Transformer
    直接将TorchSharp模型封装为ML.NET的ITransformer实现,无需转换格式即可统一接口:
public class TorchSharpTransformer : ITransformer
{
    private readonly Module _model;
    private readonly MLContext _mlContext;

    public TorchSharpTransformer(Module model, MLContext mlContext)
    {
        _model = model.eval();
        _mlContext = mlContext;
    }

    public DataViewSchema InputSchema { get; }
    public DataViewSchema OutputSchema { get; }

    public IDataView Transform(IDataView input)
    {
        // 将ML.NET数据转换为TorchSharp张量
        var inputData = _mlContext.Data.CreateEnumerable<ModelInput>(input, reuseRowObject: false).ToList();
        var featureArray = inputData.SelectMany(x => x.Features).ToArray();
        var inputTensor = torch.tensor(featureArray, dtype: torch.float32).view(inputData.Count, 784);

        // 执行模型推理
        using var outputTensor = _model.forward(inputTensor);
        var outputArray = outputTensor.data<float>().ToArray();

        // 将推理结果转换为ML.NET数据格式
        var outputData = inputData.Select((item, index) => new ModelOutput
        {
            PredictedLabels = outputArray.Skip(index * 10).Take(10).ToArray()
        });
        return _mlContext.Data.LoadFromEnumerable(outputData);
    }

    // 按需实现ITransformer接口的其他方法(如Fit、GetRowToRowMapper等)
}

使用时直接将该Transformer加入现有ML.NET管道即可实现接口统一。


内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 09:46:04