【发布时间】:2019-06-04 17:58:03
【问题描述】:
我想制作一个用于 Web 应用程序的机器学习 api,字段名称将与其数据类型一起传递给 api。
目前我正在使用此答案中提供的代码在运行时创建一个类:https://stackoverflow.com/a/3862241
当我需要调用 ML.NET PredictionFunction 时出现问题,我无法传入泛型函数的类型,因为它们是在运行时生成的。 我试过使用反射来调用它,但是它似乎无法找到该函数。
注意:目前 ML.NET 的文档正在更新为 0.9.0,因此不可用。
我尝试过的是这个(最小):
Type[] typeArgs = { generatedType, typeof(ClusterPrediction) };
object[] parametersArray = { mlContext }; // value
MethodInfo method = typeof(TransformerChain).GetMethod("MakePredictionFunction");
if (method == null) { // Using PredictionFunctionExtensions helps here
Console.WriteLine("Method not found!");
}
MethodInfo generic = method.MakeGenericMethod(typeArgs);
var temp = generic.Invoke(model, parametersArray);
完整(修订和修剪)来源(更多上下文): 程序.cs
namespace Generic {
class Program {
public class GenericData {
public float SepalLength;
public float SepalWidth;
public float PetalLength;
public float PetalWidth;
}
public class ClusterPrediction {
public uint PredictedLabel;
public float[] Score;
}
static void Main(string[] args) {
List<Field> fields = new List<Field>() {
new Field(){ name="SepalLength", type=typeof(float)},
new Field(){ name="SepalWidth", type=typeof(float)},
new Field(){ name="PetalLength", type=typeof(float)},
new Field(){ name="PetalWidth", type=typeof(float)},
};
var generatedType = GenTypeBuilder.CompileResultType(fields);
var mlContext = new MLContext(seed: 0);
TextLoader textLoader = mlContext.Data.TextReader(new TextLoader.Arguments() {
Separator = ",",
Column = new[]
{
new TextLoader.Column("SepalLength", DataKind.R4, 0),
new TextLoader.Column("SepalWidth", DataKind.R4, 1),
new TextLoader.Column("PetalLength", DataKind.R4, 2),
new TextLoader.Column("PetalWidth", DataKind.R4, 3)
}
});
IDataView dataView = textLoader.Read(Path.Combine(Environment.CurrentDirectory, "Data", "flowers.txt"););
var pipeline = mlContext.Transforms
.Concatenate("Features", "SepalLength", "SepalWidth", "PetalLength", "PetalWidth")
.Append(mlContext.Clustering.Trainers.KMeans("Features", clustersCount: 3));
var model = pipeline.Fit(dataView);
Type[] typeArgs = { generatedType, typeof(ClusterPrediction) };
object[] parametersArray = { mlContext }; // value
MethodInfo method = typeof(TransformerChain).GetMethod("MakePredictionFunction");
if (method == null) { // Using PredictionFunctionExtensions helps here
Console.WriteLine("Method not found!");
}
MethodInfo generic = method.MakeGenericMethod(typeArgs);
var temp = generic.Invoke(model, parametersArray);
var prediction = temp.Predict(new GenericData {SepalLength = 5.6f, SepalWidth = 2.5f,
PetalLength = 3.9f, PetalWidth = 1.1f});
}
}
}
【问题讨论】:
-
我不确定问题到底是什么。是
method == null的问题,即在TransformerChain上找不到方法? -
请提供minimal reproducible example - 显然
TransformerChain(无论它是什么)没有您正在寻找的方法......但是没有真实样本就无法知道为什么。跨度> -
@Paprika 您现在已经展示了大量的无关代码。您应该展示一个 minimal 可重现的示例。显示重现问题所需的内容,仅此而已。
-
但是,正如 Kevin Grosse 所指出的,
MakePredictionFunction是一种可以应用于ITransformer实例的扩展方法,而TransformerChain<T>正在实现ITransformer。请注意,此扩展方法不是TransformerChain<T>类型定义的一部分,因此您在查询TransformerChain<T>类型时也会得到null。如果需要扩展方法的MethodInfo,需要查询声明扩展方法的类型。如果是MakePredictionFunction,您需要查询PredictionFunctionExtensions类型... -
@elgonzo 您可能应该将您的评论转换为答案......或者我们应该将其关闭为“通过反射的呼叫扩展”(如stackoverflow.com/questions/1452261/…)
标签: c# class generics dynamic ml.net