将 ML.NET 的 CreatePredictionEngine 与发出的类型一起使用

Using ML.NET's CreatePredictionEngine with emitted types

对于我正在处理的项目,我需要使用 ML.NET's CreatePredictionEngine 方法和 TSrcTDst 的发射类型。我用 System.Reflection.Emit.

发出那些

以下是我创建动态预测引擎的方式:

dynamic dynamicPredictionEngine;
var genericPredictionMethod = mlContext.Model.GetType().GetMethod("CreatePredictionEngine", new[] { typeof(ITransformer), typeof(DataViewSchema) });
var predictionMethod = genericPredictionMethod.MakeGenericMethod(inputObject.GetType(), outputObject.GetType());
dynamicPredictionEngine = predictionMethod.Invoke(mlContext.Model, new object[] { TrainedModel, PredictionPipeline });

这里,inputObjectoutputObject 是我发出的 classes 的实例。

那么,我就是这样的 运行 预测引擎 :

var result = dynamicPredictionEngine.Predict(inputObject)

但我得到以下异常:

'The best overloaded method match for 'Microsoft.ML.PredictionEngineBase<Object0f33ea95-c496-4c57-bd2c-728bb65dd0a9,Object5623e4bd-ba82-42cf-876f-5e11a5cb8bb2>.Predict(Object0f33ea95-c496-4c57-bd2c-728bb65dd0a9)' has some invalid arguments'

您在此处看到的 GUID 是我发出的 classes 的名称。

为了调试这个,我尝试手动创建一个 class 与发出的具有相同的属性,并再次 运行 预测引擎,手动创建 class作为 TSrc 并将发出的保持为 TDst。这一次,效果很好。

我查看了调试器,将发出的输入 class 与手动创建的进行比较,它们似乎匹配(TaxiTrip 是我创建的 class 的名称) :

Debugger screenshot

作为参考,我的 TaxiTrip class 是这样定义的

namespace VL.ML
{
    class TaxiTrip
    {
        public string VendorId { get; set; }
        public string RateCode { get; set; }
        public float PassengerCount { get; set; }
        public float TripTime { get; set; }
        public float TripDistance { get; set; }
        public string PaymentType { get; set; }
        public float FareAmount { get; set; }
    }
}

有人知道这里发生了什么吗?

我已经在 SO 上偶然发现了 this question,但我的问题看起来有所不同:正如我所说,如果我手动创建一个没有任何属性的 class(见上文),Predict 可以工作正好。另外,它似乎能够为 TDst 使用我发出的类型,那么为什么 TSrc 会失败?

如有必要,很乐意提供更多详细信息。

提前致谢!

您必须调用 Predict 方法:

var predictMethod = dynamicPredictionEngine.GetType().GetMethod("Predict", new[] { runtimeType });
var predict = predictMethod.Invoke(dynamicPredictionEngine, new[] { inputObject });