ML.NET动态培训/测试课程 [英] dynamic training/test classes with ML.NET

查看:57
本文介绍了ML.NET动态培训/测试课程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是问题的跟进动态类/对象ML.net的PredictionMoadel< TInput,TOutput>火车()

我的系统在编译时无法使用预定义的类,因此我尝试将动态类馈入ML.NET,如下所示

My system cannot use a predefined class at compile time, therefore I tried to feed a dynamic class into ML.NET like below

    // field data type
    public class Field
    {
        public string FieldName { get; set; }
        public Type FieldType { get; set; }
    }

    // dynamic class helper
    public class DynamicClass : DynamicObject
    {
        private readonly Dictionary<string, KeyValuePair<Type, object>> _fields;

        public DynamicClass(List<Field> fields)
        {
            _fields = new Dictionary<string, KeyValuePair<Type, object>>();
            fields.ForEach(x => _fields.Add(x.FieldName,
                new KeyValuePair<Type, object>(x.FieldType, null)));
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            if (_fields.ContainsKey(binder.Name))
            {
                var type = _fields[binder.Name].Key;
                if (value.GetType() == type)
                {
                    _fields[binder.Name] = new KeyValuePair<Type, object>(type, value);
                    return true;
                }
                else throw new Exception("Value " + value + " is not of type " + type.Name);
            }
            return false;
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = _fields[binder.Name].Value;
            return true;
        }
    }

    private static void Main(string[] args)
    {
        var fields = new List<Field>
        {
            new Field {FieldName = "Name", FieldType = typeof(string)},
            new Field {FieldName = "Income", FieldType = typeof(float)}
        };

        dynamic obj1 = new DynamicClass(fields);
        obj1.Name = "John";
        obj1.Income = 100f;

        dynamic obj2 = new DynamicClass(fields);
        obj2.Name = "Alice";
        obj2.Income = 200f;

        var trainingData = new List<dynamic> {obj1, obj2};

        var env = new LocalEnvironment();
        var schemaDef = SchemaDefinition.Create(typeof(DynamicClass));
        schemaDef.Add(new SchemaDefinition.Column(null, "Name", TextType.Instance));
        schemaDef.Add(new SchemaDefinition.Column(null, "Income", NumberType.R4));
        var trainDataView = env.CreateStreamingDataView(trainingData, schemaDef);

        var pipeline = new CategoricalEstimator(env, "Name")
            .Append(new ConcatEstimator(env, "Features", "Name"))
            .Append(new FastTreeRegressionTrainer(env, "Income", "Features"));

        var model = pipeline.Fit(trainDataView);
    }

,并收到错误:在'System.Object'类型中找不到'名称为'Name'的字段或属性".我尝试使用反射生成类,只是遇到了同样的问题.

and got the error: "'No field or property with name 'Name' found in type 'System.Object'". I tried generating the class using Reflection only to run into the same problem.

有解决方法吗?谢谢

推荐答案

动态类实际上并不创建类定义,而是为您提供动态对象.

Dynamic class doesn't actually create a class definition but it rather provides you with dynamic object.

我查看了 SchemaDefinition.Create()的代码,它需要一个实际的类定义来构建模式.因此,您的选择是动态创建和加载类定义.

I looked at the code for SchemaDefinition.Create() it needs an actual class definition to build the schema. So your options are to create and load a class definition dynamically.

您可以将类创建为具有所有动态属性的字符串,并使用Microsoft编译器服务(也称为 Roslyn )对其进行编译.请参见此处.这将使用您的动态类型生成一个程序集(在内存中作为内存流或在文件系统上).

You can create your class as string with all dynamic properties and compile it using Microsoft compiler services aka Roslyn. See here. This will generate an assembly (in memory as memory stream or on file system) with your dynamic type.

现在您只在那儿了一半.要从动态程序集获取动态类型,您需要将其加载到App Domain中.请参阅帖子.加载程序集后,您可以使用' yourDomain.CreateInstanceAndUnwrap()来从动态生成的类中创建对象并使用 Assembly.GetType()获取类型.

Now you are only half way there. To get your dynamic type from dynamic assembly you need to load it in the App Domain. See this post. Once the assembly is loaded you can use 'Activator.CreateInstance()' if it's same domain or if it's your custom domain then you would need yourDomain.CreateInstanceAndUnwrap() to create the object out of dynamically generated Class and to get the type use Assembly.GetType().

这里的样本很少,有些过时了,但是如果您愿意的话,会让您站起来.参见 CompilerEngine

Few sample here, A little out of date but will get you on your feet if you are up for this. See CompilerEngine and CompilerService to compile and load the assembly.

其他选项: Refelection.Emit(),但它需要大量的IL级编码.参见此帖子.

Other options: Refelection.Emit() but it requires a great deal of IL level coding. See this post.

这篇关于ML.NET动态培训/测试课程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆