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

在F#中运行ONNX模型遇类型错误,求正确类型定义方案

问题描述

我尝试在.NET中运行用Python训练并转换为ONNX格式的Keras模型,使用ML.NET实现。该ONNX模型输入为两个float32张量:input_5(维度[unk_298,50])、input_6(维度[unk_297,50]),输出为float32张量out(维度[unk_299,1])。我参考微软官方文档将C#代码转换为F#代码,定义了OnnxInput和OnnxOutput类型,代码如下:

#r "nuget: Microsoft.ML"
#r "nuget: Microsoft.ML.OnnxRuntime, 1.10.0"
#r "nuget: Microsoft.ML.OnnxTransformer"


open Microsoft.ML
open Microsoft.ML.Data
open Microsoft.ML.Transforms.Onnx
open Microsoft.ML.OnnxRuntime.Tensors
open System
open System.IO

[<CLIMutable>]
type OnnxInput = {
    [<ColumnName("input_5");>]
    input1: DenseTensor<float32>
    [<ColumnName("input_6")>]
    input2: DenseTensor<float32>
}


[<CLIMutable>]
type OnnxOutput = {
    [<ColumnName("out")>]
    output: DenseTensor<float32>
}

let onnxModelPath = @""
let mlContext = new MLContext()
let createFloat32DenseTensor (data: float32 array) (dimensions: int array) =
    let memory = Memory<float32>(data)
    let tensor = new DenseTensor<float32>(memory, dimensions)
    tensor
let data = Array.create 50 0f
let dimensions = [| 1; 50 |]

let init = createFloat32DenseTensor data dimensions
let initialOnnxInput = {
    input1 = init
    input2 = init
}
let getPredictionPipeline (mlContext: MLContext) =
    let inputColumns = [|"input_5"; "input_6"|]
    let outputColumns = [|"out"|]
    let onnxPredictionPipeline =
        mlContext.Transforms.ApplyOnnxModel(
                outputColumnNames = outputColumns,
                inputColumnNames = inputColumns,
                modelFile = onnxModelPath
                )
    let emptyDataView = mlContext.Data.LoadFromEnumerable<OnnxInput>([||])
    onnxPredictionPipeline.Fit(emptyDataView)

let onnxPredictionPipeline = getPredictionPipeline mlContext
let onnxPredictionEngine = mlContext.Model.CreatePredictionEngine<OnnxInput, OnnxOutput>(onnxPredictionPipeline)
let testinputName = createFloat32DenseTensor outputResult dimensions

let testInput = {
    input1 = createFloat32DenseTensor outputResult dimensions 
    input2 = createFloat32DenseTensor outputResult dimensions
    }

let prediction = onnxPredictionEngine.Predict testInput

运行let onnxPredictionPipeline = getPredictionPipeline mlContext时,出现错误:

System.ArgumentOutOfRangeException: Could not determine an IDataView type and registered custom types for member input1@ (Parameter 'rawType')

请问如何创建正确的类型来运行该预训练ONNX模型?

解决方案

ML.NET无法直接识别DenseTensor<float32>作为IDataView的兼容类型,需要改用ML.NET原生支持的向量/数组类型来定义输入输出,具体修改如下:

  • 修改输入输出类型定义
    将DenseTensor<float32>替换为float32[],并通过VectorType属性指定张量的维度,让ML.NET正确映射到ONNX模型的张量输入:

    [<CLIMutable>]
    type OnnxInput = {
        [<ColumnName("input_5"); VectorType(1, 50)>]
        input1: float32[]
        [<ColumnName("input_6"); VectorType(1, 50)>]
        input2: float32[]
    }
    
    [<CLIMutable>]
    type OnnxOutput = {
        [<ColumnName("out"); VectorType(1, 1)>]
        output: float32[]
    }
    

    注意:VectorType的参数要和ONNX模型输入维度对应,这里用[1,50]匹配测试数据维度,实际使用时可根据模型动态维度调整。

  • 调整张量创建逻辑
    无需再创建DenseTensor,直接使用float32数组作为输入数据:

    // 直接生成对应长度的数组,无需封装为DenseTensor
    let data = Array.create (1*50) 0f
    let initialOnnxInput = {
        input1 = data
        input2 = data
    }
    
    // 测试输入直接用数组
    let testInput = {
        input1 = outputResult // 确保outputResult是长度为50的float32数组
        input2 = outputResult
    }
    
  • 预测结果转换(可选)
    如果需要将输出数组转为DenseTensor做后续处理,可在得到预测结果后手动转换:

    let prediction = onnxPredictionEngine.Predict testInput
    let outputTensor = DenseTensor<float32>(prediction.output, [|1;1|])
    

修改后重新运行代码,即可解决类型识别错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 08:09:57