【问题标题】:ML.NET Merge IDataViews in a genric wayML.NET 以通用方式合并 IDataView
【发布时间】:2021-06-28 08:37:52
【问题描述】:

我正在为 ML.NET 创建一个 CLI 工具,我需要创建一个合并函数来合并两个相同类型的数据集。但它需要尽可能通用,因为该工具包含不同的数据集类型。

我设法创建了一个方法,将 IDataview 转换为具有给定数据集类型的通用 IEnumerable:

private IEnumerable<object> GetDataEnumerable(MLContext mlContext, IDataView dataView, Type dataViewType) {
        var createEnumerableMethod = typeof(DataOperationsCatalog).GetMethod(nameof(MLContext.Data.CreateEnumerable));
        var generic = createEnumerableMethod.MakeGenericMethod(dataViewType);
        return (IEnumerable<object>)generic.Invoke(mlContext.Data, new object[] { dataView, false, null, null });
    }

【问题讨论】:

    标签: c# machine-learning reflection ml.net


    【解决方案1】:

    所以几天后我想通了。首先,我将 2 个 IDataviews 转换为在运行时获取类型的 IEnumerable。之后,我通过将它们转换为列表来将它们合并在一起,并使用反射将它们转换为正确的类型。最后我再次使用反射将最终的可枚举加载回 IDataview。

        var oldDataEnumerable = GetDataEnumerable(mlContext, oldDataView, dataViewType).ToList();
        var newDataEnumerable = GetDataEnumerable(mlContext, newDataView, dataViewType).ToList();
    
        var mergedEnumerable = MergeDataEnumerables(oldDataEnumerable, newDataEnumerable, dataViewType);
    
        return LoadEnumerableFromObject(mlContext, mergedEnumerable, dataViewType);
    
        private IEnumerable<object> GetDataEnumerable(MLContext mlContext, IDataView dataView, Type dataViewType) {
            var createEnumerableMethod = typeof(DataOperationsCatalog).GetMethod(nameof(MLContext.Data.CreateEnumerable));
            var generic = createEnumerableMethod.MakeGenericMethod(dataViewType);
            return (IEnumerable<object>)generic.Invoke(mlContext.Data, new object[] { dataView, false, null, null });
        }
    
        private object MergeDataEnumerables(List<object> firstDataEnumerable, List<object> secondDataEnumerable, Type dataViewType) {
            firstDataEnumerable.AddRange(secondDataEnumerable);
            var castMethod = typeof(Enumerable).GetMethod("Cast");
            var genericCast = castMethod.MakeGenericMethod(dataViewType);
            var toListMethod = typeof(Enumerable).GetMethod("ToList");
            var genericToList = toListMethod.MakeGenericMethod(dataViewType);
            var castedEnumerable = genericCast.Invoke(null, new[] { firstDataEnumerable });
            return genericToList.Invoke(null, new[] { castedEnumerable });
        }
    
        private IDataView LoadEnumerableFromObject(MLContext mlContext, object dataEnumerable, Type dataViewType) {
            var dataType = mlContext.Data.GetType();
            var loadFromEnumerableMethod = dataType.GetMethods().First(m => m.Name == "LoadFromEnumerable" && m.IsGenericMethod);
            var generic = loadFromEnumerableMethod.MakeGenericMethod(dataViewType);
            var schema = SchemaDefinition.Create(dataViewType);
            return (IDataView)generic.Invoke(mlContext.Data, new object[] { dataEnumerable, schema });
        }
    

    【讨论】:

    • 你也可以使用泛型类型,但这不适合我当前的架构,所以我不得不使用类型参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 1970-01-01
    • 2020-03-05
    • 1970-01-01
    • 2022-06-11
    相关资源
    最近更新 更多