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

本文关键字:添加 准确性 存储 用于 net Numl 数据 | 更新日期: 2023-09-27 18:16:31

我对Numl.net库非常感兴趣,它可以扫描传入的电子邮件并提取数据位。举个例子,假设我想从一封电子邮件中提取一个客户参考号码,它可以在主题行或正文内容中。

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. 如果我添加到训练数据,在什么时候训练数据变得"超过需要"?

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

我不认为这是一个用机器学习来解决的好问题(尽管我对你的发现很感兴趣)。我担心的是客户数量会随时间变化,每次都需要重新生成模型。二进制分类算法,如Naïve贝叶斯,决策树,逻辑回归和支持向量机要求你提前知道每个类(即客户参考号)。

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

  1. IsWordStartsWithC (bool)
  2. 数字数/字长
  3. 字数/字长

然后使用决策树或逻辑回归分类器来预测单词是否为CRN。要从电子邮件中提取CRN,只需遍历电子邮件中的每个单词,如果Model.Predict(word)输出1,则有望捕获该电子邮件的CRN。

这个方法不需要再训练。

  1. 在一个受监督的网络中,我是否需要每次运行应用程序时都重新构建决策树,或者我是否可以以某种方式存储它并然后在需要的时候重新加载它?我想节省处理时间

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

  • 此外,当数据得到人类验证时,网络能否不断添加自己的训练数据?也就是说,我们有一个初步的培训设置,网络决定一个结果,如果一个人说"做得好"新的例子被添加到训练集中是为了改进它。当网络出错时,反之亦然。我想我可以一旦人类验证了这一预测,就将其添加到训练集中是正确的?我的repo.Add(email)看起来是一个合乎逻辑的方法吗这个吗?
  • 这是一个很好的强化学习例子。目前numl没有实现这个,但希望在不久的将来会实现:)

  • 如果我添加到训练数据,在什么时候训练数据变得"超过需要"?
  • 检查这一点的最好方法是通过验证训练集和测试集的准确性度量。当测试集的准确性提高时,您可以继续添加更多的训练数据。如果你发现测试集的准确度下降,而训练集的准确度继续上升,那么现在是过拟合,可以安全地停止添加更多的数据了。

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

    1. 在一个受监督的网络中,我是否需要每次运行应用程序时都重新构建决策树,或者我是否可以以某种方式存储它并然后在需要的时候重新加载它?我想节省处理时间

    目前有一个IModel.Save方法,应该在每个类中实现。然而,据我所知,它还没有实现。然而,有一些序列化测试适用于大多数模型,包括DecisionTree,如decisiontreesserializationtests:

    所示
    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序列化,我认为这可以使用,直到模型。实现保存。你基本上只是使用numl.Utils.JsonHelpers来序列化/反序列化模型到/从json(你可以坚持你想要的)。而且,我认为这也是他们目前正在做的一件事。

  • 此外,当数据得到人类验证时,网络能否不断添加自己的训练数据?也就是说,我们有一个初步的培训设置,网络决定一个结果,如果一个人说"做得好"新的例子被添加到训练集中是为了改进它。当网络出错时,反之亦然。我想我可以一旦人类验证了这一预测,就将其添加到训练集中是正确的?我的repo.Add(email)看起来是一个合乎逻辑的方法吗这个吗?
  • 你可以随时添加数据点来训练你的模型。但是,我认为您必须从头开始重新训练模型。有一种在线机器学习可以单独训练数据点,但我不认为numl目前实现了这一点。因此,要做到这一点,您可能会根据您的需求运行每日/每周的工作,以使用扩展的训练数据重新训练模型。

  • 如果我添加到训练数据,在什么时候训练数据变得"超过需要"?
  • 一般的规则是"更多的数据意味着更好的预测。"您可以随时查看您的收益,并自行决定是否没有从增加训练数据样本量中获益。也就是说,这不是一个硬性规定(想想看)。如果你在谷歌上搜索"机器学习更多的数据,更好的准确性",你会发现大量关于这个主题的信息,我把所有这些信息都归结为"更多的数据意味着更好的预测"answers"看看什么最适合你"。在您针对电子邮件文本进行训练的特定示例中,我的理解是更多的数据只会对您有所帮助。

    说了这么多,我还想说一些其他的事情:

    1. 听起来,如果你只是想从电子邮件中获得客户/订单号,一个好的正则表达式会比用ML分析更好。至少,我会让正则表达式成为你训练数据特征集的一部分,所以也许你可以训练它来学习拼写错误或输入结构的变化。
    2. 我不是ML专家,也不是numl专家。我只是碰巧也在学习数字。到目前为止,他们在gitter上对我的回应非常积极,你和任何对这个非常棒的开源、成熟、麻省理工学院许可的库感兴趣的人都应该去看看。