用于在Numl.net中训练数据并添加到其中以提高准确性的后备存储

时间:2015-10-08 08:40:06

标签: c# machine-learning neural-network

我真的对Numl.net library感兴趣扫描收到的电子邮件并提取数据。例如,让我们想象一下,我想从电子邮件中提取客户参考号,该电子邮件可能位于主题行或正文内容中。

void Main()
{
    // get the descriptor that describes the features and label from the training objects
    var descriptor = Descriptor.Create<Email>();

    // create a decision tree generator and teach it about the Email descriptor
    var decisionTreeGenerator = new DecisionTreeGenerator(descriptor);

    // load the training data
    var repo = new EmailTrainingRepository(); // inject this
    var trainingData = repo.LoadTrainingData(); // returns List<Email>

    // create a model based on our training data using the decision tree generator
    var decisionTreeModel = decisionTreeGenerator.Generate(trainingData);

    // create an email that should find C4567890
    var example1 = new Email
    {
        Subject = "Regarding my order C4567890",
        Body = "I am very unhappy with your level of service. My order has still not arrived."
    };

    // create an email that should find C89779237
    var example2 = new Email
    {
        Subject = "I want to return my goods",
        Body = "My customer number is C89779237 and I want to return my order."
    };

    // create an email that should find C3239544-1
    var example3 = new Email
    {
        Subject = "Customer needs an electronic invoice",
        Body = "Please reissue the invoice as a PDF for customer C3239544-1."
    };

    var email1 = decisionTreeModel.Predict<Email>(example1);
    var email2 = decisionTreeModel.Predict<Email>(example2);
    var email3 = decisionTreeModel.Predict<Email>(example3);

    Console.WriteLine("The example1 was predicted as {0}", email1.CustomerNumber);


    if (ReadBool("Was this answer correct? Y/N"))
    {
        repo.Add(email1);
    }

    Console.WriteLine("The example2 was predicted as {0}", email2.CustomerNumber);
    if (ReadBool("Was this answer correct? Y/N"))
    {
        repo.Add(email2);
    }

    Console.WriteLine("The example3 was predicted as {0}", email3.CustomerNumber);
    if (ReadBool("Was this answer correct? Y/N"))
    {
        repo.Add(email3);
    }
}

// Define other methods and classes here
public class Email
{
   // Subject
   [Feature]
   public string Subject { get; set; }

   // Body
   [Feature]
   public string Body { get; set; }

   [Label]
   public string CustomerNumber { get; set; } // This is the label or value that we wish to predict based on the supplied features
}

static bool ReadBool(string question)
{
    while (true)
    {
        Console.WriteLine(question);
        String r = (Console.ReadLine() ?? "").ToLower();
        if (r == "y")
            return true;
        if (r == "n")
            return false;
        Console.WriteLine("!!Please Select a Valid Option!!");
    }
}

虽然有一些我无法掌握的东西。

  1. 在受监管的网络中,每次运行应用程序时是否需要重新构建决策树,还是可以以某种方式将其存储起来,然后在需要时重新加载?我试图节省处理时间,以便每次都重建该决策树。

  2. 此外,当数据得到人类验证时,网络能否不断添加自己的训练数据?即我们有一个初步的训练集,网络决定一个结果,如果一个人说“做得好”。新示例将添加到训练集中以改进它。当网络出错时,反之亦然。我假设一旦人类验证了预测是正确的,我可以添加到训练集中吗?我的repo.Add(email)似乎是合乎逻辑的做法吗?

  3. 如果我确实添加了培训数据,那么培训数据在什么时候变得超过了要求&#34;

2 个答案:

答案 0 :(得分:2)

我认为使用机器学习解决这个问题并不是一个好问题(虽然我对你的发现很感兴趣)。我担心的是客户数量会随着时间而变化,需要您每次都重新生成模型。二元分类算法,如NaïveBayes,Decision Trees,Logistic Regression和SVM,要求您提前了解每个类(即Customer Ref No)。

您可以尝试使用特征工程并预测给定的单词是否是客户参考编号(即1或0)。要做到这一点,您只需设计如下功能:

  1. IsWordStartsWithC(bool)
  2. 字长
  3. 数字/字长
  4. 字母数/字长
  5. 然后使用决策树或Logistic回归分类器来预测该单词是否为CRN。要从电子邮件中提取CRN,只需遍历电子邮件中的每个单词,如果Model.Predict(word)输出1,您希望已捕获该电子邮件的CRN。

    此方法不需要重新训练。

      
        
    1. 在受监管的网络中,每次运行应用程序时是否需要重新构建决策树,或者我可以以某种方式将其存储起来   然后在需要时重新加载?我正在尝试保存处理   时间,以便每次都重建该决策树。
    2.   

    您可以通过Model.Save()方法使用任何流对象存储生成的模型。 numl中的所有受监督模型当前都实现了这个基类。除了神经网络模型,他们应该保存好。

      
        
    1. 此外,当数据得到人类验证时,网络是否可以不断添加自己的训练数据?即我们有初步培训   设置,网络决定一个结果,如果一个人说“做得好”   新示例将添加到训练集中以改进它。   当网络出错时,反之亦然。我想我可以   一旦人类验证了预测,就添加到训练集   是正确的?我的repo.Add(电子邮件)是否合乎逻辑?   此?
    2.   

    这是一个很好的强化学习示例。目前,numl没有实现这一点,但希望它能在不久的将来实现:)

      
        
    1. 如果我确实添加了训练数据,那么训练数据在什么时候变得“超过要求”?
    2.   

    检查这一点的最佳方法是通过验证培训和测试集准确度测量。您可以在测试集的准确性提高的同时不断添加更多训练数据。如果您发现测试集的准确度下降并继续上升到训练集上,那么它现在过度拟合,可以安全地停止添加更多数据。

答案 1 :(得分:1)

有点晚了,但我也在学习numl库,我想我可以对你的一些问题有所了解。

  
      
  1. 在受监管的网络中,每次运行应用程序时是否需要重新构建决策树,或者我可以以某种方式将其存储起来   然后在需要时重新加载?我正在尝试保存处理   时间,以便每次都重建该决策树。
  2.   

目前有一个IModel.Save方法应该在每个类中实现。但是,我最好能说它还没有实现。但是,序列化测试适用于大多数模型,包括DecisionTree,如DecisionTreeSerializationTests中所示:

Serialize(model);

简称:

internal void Serialize(object o)
{
    var caller = new StackFrame(1, true).GetMethod().Name;
    string file = string.Format(_basePath, caller);
    if (File.Exists(file))  File.Delete(file);
    JsonHelpers.Save(file, o);
}

他们有一堆自定义创建的转换器用于使用json序列化,我认为这可以在实现model.Save之前使用。您基本上只需使用numl.Utils.JsonHelpers将模型序列化/反序列化为json(您可以根据需要保留)。此外,我认为这是他们目前正在努力的一件事。

  
      
  1. 此外,当数据得到人类验证时,网络是否可以不断添加自己的训练数据?即我们有初步培训   设置,网络决定一个结果,如果一个人说“做得好”   新示例将添加到训练集中以改进它。   当网络出错时,反之亦然。我想我可以   一旦人类验证了预测,就添加到训练集   是正确的?我的repo.Add(电子邮件)是否合乎逻辑?   此?
  2.   

您始终可以添加数据点以在任何时间点训练模型。但是,我认为你必须从头开始重新训练模型。随着数据点单独进行训练有Online Machine Learning,但我认为numl目前没有实现这一点。因此,为此,您可能会根据您的要求运行每日/每周工作,以使用扩展的培训数据重新训练模型。

  
      
  1. 如果我确实添加了训练数据,那么训练数据在什么时候变得“超过要求”?
  2.   

一般规则是“更多数据意味着更好的预测”。如果您没有从增加训练数据样本量中获益,您可以随时查看自己的收益并自行决定。也就是说,这不是一个严格的规则(如图)。如果你只是谷歌“机器学习更多数据更好的准确性”你会发现有关该主题的大量信息,所有这些我剔除“更多的数据意味着更好的预测”和“看看什么最适合你”。在您针对电子邮件文本进行培训的特定示例中,我了解更多数据只会对您有所帮助。

所有这一切,我还会说几件事:

  1. 听起来好像你只是想从电子邮件中获取客户/订单号,一个好的正则表达式比用ML分析更好。至少,我会将训练数据的功能集的一部分用于正则表达式,所以也许你可以训练它来学习拼写错误或输入结构的变化。
  2. 我不是ML的专家,也不是numl的专家。我恰好也正在学习numl。到目前为止,他们对我gitter的回应非常敏感,您和其他任何对这个非常棒的开源,成熟,麻省理工学院许可的图书馆感兴趣的人都应该检查一下。