F#中ML.NET AutoML传入内存数据时编译错误排查
需要实现的ML.NET命令功能
mlnet classification --dataset output.csv --label-col 0 --has-header true --name test --train-time 300
当前F#代码(编译报错)
let data = ctx.Data.LoadFromEnumerable(input) let preprocessingPipeline = EstimatorChain() .Append(ctx.Transforms.Concatenate("Features", h)) let autoMLEstimator = ctx.Auto().Regression(labelColumnName = labelName) let toIEstimator (est: 'a) = est :> obj :?> IEstimator<ITransformer> let pipeline = (preprocessingPipeline |> toIEstimator) .Append(autoMLEstimator) let experiment = ctx.Auto().CreateExperiment() let x = experiment .SetPipeline(pipeline) .SetRegressionMetric(RegressionMetric.RSquared, labelName) .SetTrainingTimeInSeconds(60u) .SetDataset(data) ctx.Log.Add (fun e -> if e.Source.Equals("AutoMLExperiment") then info(e.RawMessage) ) let! r = experiment.RunAsync()
数据结构
[<CLIMutable>] type ModelInput = { Outcome : bool Side : float32 Open0 : float32; High0 : float32; Low0 : float32; Close0 : float32; Volume0 : float32 Open1 : float32; High1 : float32; Low1 : float32; Close1 : float32; Volume1 : float32 Open2 : float32; High2 : float32; Low2 : float32; Close2 : float32; Volume2 : float32 Open3 : float32; High3 : float32; Low3 : float32; Close3 : float32; Volume3 : float32 Open4 : float32; High4 : float32; Low4 : float32; Close4 : float32; Volume4 : float32 Open5 : float32; High5 : float32; Low5 : float32; Close5 : float32; Volume5 : float32 Open6 : float32; High6 : float32; Low6 : float32; Close6 : float32; Volume6 : float32 Open7 : float32; High7 : float32; Low7 : float32; Close7 : float32; Volume7 : float32 Open8 : float32; High8 : float32; Low8 : float32; Close8 : float32; Volume8 : float32 Open9 : float32; High9 : float32; Low9 : float32; Close9 : float32; Volume9 : float32 Open10 : float32; High10 : float32; Low10 : float32; Close10 : float32; Volume10 : float32 Open11 : float32; High11 : float32; Low11 : float32; Close11 : float32; Volume11 : float32 Open12 : float32; High12 : float32; Low12 : float32; Close12 : float32; Volume12 : float32 Open13 : float32; High13 : float32; Low13 : float32; Close13 : float32; Volume13 : float32 Open14 : float32; High14 : float32; Low14 : float32; Close14 : float32; Volume14 : float32 Open15 : float32; High15 : float32; Low15 : float32; Close15 : float32; Volume15 : float32 Open16 : float32; High16 : float32; Low16 : float32; Close16 : float32; Volume16 : float32 Open17 : float32; High17 : float32; Low17 : float32; Close17 : float32; Volume17 : float32 Open18 : float32; High18 : float32; Low18 : float32; Close18 : float32; Volume18 : float32 Open19 : float32; High19 : float32; Low19 : float32; Close19 : float32; Volume19 : float32 FairPrice : float32 LgH0 : float32; LgL0 : float32; LgH1 : float32; LgL1 : float32 ObH0 : float32; ObL0 : float32; ObH1 : float32; ObL1 : float32 Hh0 : float32; Lh0 : float32; Hl0 : float32; Ll0 : float32 Hh1 : float32; Lh1 : float32; Hl1 : float32; Ll1 : float32 Bosi0 : float32; Bose0 : float32; Coc0 : float32; Mss0 : float32 Bosi1 : float32; Bose1 : float32; Coc1 : float32; Mss1 : float32 }
编译错误
The type 'ML.Data.EstimatorChain<ML.Data.ColumnConcatenatingTransformer>' does not match the type 'ModelInput'
核心需求
- 使用内存中的
ModelInput列表作为数据源 - 以
Outcome字段为标签(布尔类型分类任务) - 其余所有
float32类型字段作为特征 - 通过AutoML自动尝试不同算法,生成最优分类模型
错误原因
- 任务类型不匹配:原代码使用了
Regression回归任务,但实际是分类任务,应该用Classification - 特征列未正确定义:原代码中
h变量未定义,缺少所有非标签特征列的指定 - 冗余类型转换引发错误:手动的
toIEstimator类型转换破坏了类型推断,导致管道拼接时类型不匹配
修正后的完整代码
open Microsoft.ML open Microsoft.ML.AutoML open System open System.Collections.Generic // 初始化MLContext实例 let ctx = MLContext(seed = 1) // 替换为实际获取内存数据的逻辑 let input : List<ModelInput> = List<ModelInput>() // 标签列名称 let labelName = nameof(ModelInput.Outcome) // 自动获取所有非标签的float32字段作为特征列 let featureColumns = typeof<ModelInput>.GetProperties() |> Array.filter (fun prop -> prop.Name <> labelName && prop.PropertyType = typeof<float32>) |> Array.map (fun prop -> prop.Name) // 预处理管道:拼接特征列到统一的"Features"列 let preprocessingPipeline = EstimatorChain() .Append(ctx.Transforms.Concatenate("Features", featureColumns)) // 创建AutoML分类估算器 let autoMLEstimator = ctx.Auto().Classification(labelColumnName = labelName) // 拼接完整管道(依赖F#类型推断自动处理泛型) let pipeline = preprocessingPipeline.Append(autoMLEstimator) // 创建并配置AutoML实验 let experiment = ctx.Auto().CreateExperiment() .SetPipeline(pipeline) .SetClassificationMetric(ClassificationMetric.Accuracy, labelName) .SetTrainingTimeInSeconds(300u) // 匹配命令行的300秒训练时长 .SetDataset(ctx.Data.LoadFromEnumerable(input)) // 监听AutoML日志输出 ctx.Log.Add (fun e -> if e.Source.Equals("AutoMLExperiment") then printfn "%s" e.RawMessage ) // 异步运行实验并获取结果 let! result = experiment.RunAsync() // 提取最优模型 let bestModel = result.BestRun.Model
关键改动说明
- 切换分类任务:将回归估算器替换为分类估算器,匹配原命令行的分类任务类型
- 自动生成特征列:通过反射自动获取所有符合要求的特征字段,无需手动列举,减少维护成本
- 移除冗余类型转换:依靠F#的类型推断直接拼接管道,解决类型不匹配问题
- 对齐训练参数:将训练时间设置为300秒,和原命令行参数保持一致
- 使用分类指标:替换为分类任务对应的
Accuracy指标,也可根据需求切换为F1Score等其他分类指标
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

