如何将动态 类 传递给通用函数?
How to pass dynamic classes to a generic function?
我想制作一个机器学习 api 用于 Web 应用程序,字段名称将连同它们的数据类型一起传递给 api。
目前我正在使用此答案中提供的代码在运行时制作 class:
当我需要调用 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);
完整(修订和修剪)来源(更多上下文):
Program.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});
}
}
}
尝试在 IDataView 中读取测试数据,而不是将 IDataView 传递给 model.Transform();
这应该将 Score 和 PredictedLabel 作为单独的列插入到您的测试数据中。
看来,在尝试反映 MakePredictionFunction
时,您混淆了 TransformerChain<TLastTransformer>
类型(这是一个可实例化的通用类型)与静态 class TransformerChain
.
但是即使反思TransformerChain<TLastTransformer>
也不会成功,因为MakePredictionFunction
不是这个类型声明的方法。相反,MakePredictionFunction
是在静态 class PredictionFunctionExtensions
⁽¹⁾.
中声明的扩展方法
因此,要获取 MakePredictionFunction
的 MethodInfo,试试这个:
MethodInfo method = typeof(PredictionFunctionExtensions).GetMethod("MakePredictionFunction");
⁽¹⁾
我不是 100% 确定 PredictionFunctionExtensions 位于哪个命名空间。搜索 ML.NET 0.9.0 API 文档,它似乎位于 Microsoft.ML.Runtime.Data 命名空间。但是尝试访问 MakePredictionFunction 的实际文档页面目前只会导致 404 错误,因此此信息可能不准确(我不是 ML.NET用户,所以我无法验证):-(
我想制作一个机器学习 api 用于 Web 应用程序,字段名称将连同它们的数据类型一起传递给 api。
目前我正在使用此答案中提供的代码在运行时制作 class:
当我需要调用 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);
完整(修订和修剪)来源(更多上下文): Program.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});
}
}
}
尝试在 IDataView 中读取测试数据,而不是将 IDataView 传递给 model.Transform();
这应该将 Score 和 PredictedLabel 作为单独的列插入到您的测试数据中。
看来,在尝试反映 MakePredictionFunction
时,您混淆了 TransformerChain<TLastTransformer>
类型(这是一个可实例化的通用类型)与静态 class TransformerChain
.
但是即使反思TransformerChain<TLastTransformer>
也不会成功,因为MakePredictionFunction
不是这个类型声明的方法。相反,MakePredictionFunction
是在静态 class PredictionFunctionExtensions
⁽¹⁾.
因此,要获取 MakePredictionFunction
的 MethodInfo,试试这个:
MethodInfo method = typeof(PredictionFunctionExtensions).GetMethod("MakePredictionFunction");
⁽¹⁾ 我不是 100% 确定 PredictionFunctionExtensions 位于哪个命名空间。搜索 ML.NET 0.9.0 API 文档,它似乎位于 Microsoft.ML.Runtime.Data 命名空间。但是尝试访问 MakePredictionFunction 的实际文档页面目前只会导致 404 错误,因此此信息可能不准确(我不是 ML.NET用户,所以我无法验证):-(