ML.NET加载List<Dictionary<string,dynamic>>动态数据遇问题求助
解决ML.NET动态列数据加载问题
直接使用List<Dictionary<string,dynamic>>调用LoadFromEnumerable加载数据时,ML.NET无法自动推断出正确的列架构,导致DataView列数为0,后续转换会抛出“未找到列”的异常。以下是两种可行的解决方案:
方案一:手动构建DataViewSchema加载数据
通过提取数据中的列名和类型,手动生成Schema,再将数据转换为IRow集合加载:
var mlContext = new MLContext(); // 提取首行数据的列信息(确保inputData非空) var firstRow = inputData.First(); var schemaBuilder = new DataViewSchema.Builder(); // 遍历列,添加Schema定义 foreach (var kvp in firstRow) { var mlDataType = kvp.Value switch { int => DataViewType.Int32, float => DataViewType.Single, double => DataViewType.Double, string => DataViewType.String, bool => DataViewType.Boolean, _ => throw new NotSupportedException($"不支持的数据类型:{kvp.Value.GetType()}") }; schemaBuilder.AddColumn(kvp.Key, mlDataType); } var schema = schemaBuilder.Build(); // 将字典数据转换为IRow枚举 var rowEnumerable = inputData.Select(row => { var columnValues = schema.Select(col => row[col.Name]).ToArray(); return mlContext.Data.CreateRow(schema, columnValues); }); // 加载数据到DataView var dataView = mlContext.Data.LoadFromEnumerable(rowEnumerable, schema);
加载完成后即可正常执行列转换,例如对数值列做标准化:
// 获取所有数值列名 var numericColumnNames = schema.Where(col => col.Type.IsNumeric()) .Select(col => col.Name) .ToArray(); // 构建转换管道并执行 var pipeline = mlContext.Transforms.NormalizeMinMax(numericColumnNames); var transformedData = pipeline.Fit(dataView).Transform(dataView);
方案二:使用ExpandoObject自动推断架构
将Dictionary<string,dynamic>转换为ExpandoObject,ML.NET可通过反射自动推断列架构:
var mlContext = new MLContext(); // 转换字典为ExpandoObject集合 var expandoList = inputData.Select(dict => { var expando = new ExpandoObject(); var expandoDict = (IDictionary<string, object>)expando; foreach (var kvp in dict) { expandoDict[kvp.Key] = kvp.Value; } return expando; }).ToList(); // 自动推断架构并加载数据 var dataView = mlContext.Data.LoadFromEnumerable(expandoList);
注意事项
- 确保所有数据行的列名、数据类型完全一致,否则会出现架构不匹配错误
- 避免使用ML.NET不支持的数据类型(如
decimal),需提前转换为double等兼容类型 - 处理好缺失值,避免类型推断失效
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

