使用mahout实现内容分类(转)

来源:互联网 发布:mpp文件用什么打开mac 编辑:程序博客网 时间:2024/06/14 13:55
Mahout 目前支持两种根据贝氏统计来实现内容分类的方法。第一种方法是使用简单的支持 Map-Reduce 的 Naive Bayes 分类器。Naive Bayes 分类器为速度快和准确性高而著称,但其关于数据的简单(通常也是不正确的)假设是完全独立的。当各类的训练示例的大小不平衡,或者数据的独立性不符合要求 时,Naive Bayes 分类器会出现故障。第二种方法是 Complementary Naive Bayes,它会尝试纠正 Naive Bayes 方法中的一些问题,同时仍然能够维持简单性和速度。但在本文中,我只会演示 Naive Bayes 方法,因为这能让您看到总体问题和 Mahout 中的输入。

      简单来讲,Naive Bayes 分类器包括两个流程:跟踪特定文档及类别相关的特征(词汇),然后使用此信息预测新的、未见过的内容的类别。第一个步骤称作训练(training),它将通过查看已分类内容的示例来创建一个模型,然后跟踪与特定内容相关的各个词汇的概率。第二个步骤称作分类, 它将使用在训练阶段中创建的模型以及新文档的内容,并结合 Bayes Theorem 来预测传入文档的类别。因此,要运行 Mahout 的分类器,您首先需要训练模式,然后再使用该模式对新内容进行分类。下一节将演示如何使用 Wikipedia 数据集来实现此目的。

      运行 Naive Bayes 分类器

      在运行训练程序和分类器之前,您需要准备一些用于训练和测试的文档。您可以通过运行 ant prepare-docs 来准备一些 Wikipedia 文件(通过install 目标下载的文件)。这将使用 Mahout 示例中的 WikipediaDatasetCreatorDriver 类来分开 Wikipedia 输入文件。分开文档的标准是它们的类似是否与某个感兴趣的类别相匹配。感兴趣的类别可以是任何有效的 Wikipedia 类别(或者甚至某个 Wikipedia 类别的任何子字符串)。举例来说,在本例中,我使用了两个类别:科学(science)和历史(history)。因此,包含单词sciencehistory 的所有 Wikipedia 类别都将被添加到该类别中(不需要准确匹配)。此外,系统为每个文档添加了标记并删除了标点、Wikipedia 标记以及此任务不需要的其他特征。最终结果将存储在一个特定的文件中(该文件名包含类别名),并采用每行一个文档的格式,这是 Mahout 所需的输入格式。同样,运行ant prepare-test-docs 代码可以完成相同的文档测试工作。需要确保测试和训练文件没有重合,否则会造成结果不准确。从理论上说,使用训练文档进行测试应该能实现最的结果,但实际情况可能并非如此。

      设置好训练和测试集之后,接下来需要通过 ant train 目标来运行 TrainClassifier 类。这应该会通过 Mahout 和 Hadoop 生成大量日志。完成后,ant test 将尝试使用在训练时建立的模型对示例测试文档进行分类。这种测试在 Mahout 中输出的数据结构是混合矩阵。混合矩阵可以描述各类别有多少正确分类的结果和错误分类的结果。

     总的来说,生成分类结果的步骤如下:

  1. ant prepare-docs
  2. ant prepare-test-docs
  3. ant train
  4. ant test

      运行所有这些命令(Ant 目标 classifier-example 将在一次调用中捕获所有它们),这将生成如清单 6 所示的汇总和混合矩阵:


清单 6. 运行 Bayes 分类器对历史和科学主题进行分类的结果
    [java] 09/07/22 18:10:45 INFO bayes.TestClassifier: history                                  95.458984375    3910/4096.0[java] 09/07/22 18:10:46 INFO bayes.TestClassifier: science                                  15.554072096128172      233/1498.0[java] 09/07/22 18:10:46 INFO bayes.TestClassifier: =================[java] Summary[java] -------------------------------------------------------[java] Correctly Classified Instances          :       4143                                                    74.0615%[java] Incorrectly Classified Instances        :       1451                                                    25.9385%[java] Total Classified Instances              :       5594[java][java] =======================================================[java] Confusion Matrix[java] -------------------------------------------------------[java] a           b       <--Classified as[java] 3910        186      |  4096        a     = history[java] 1265        233      |  1498        b     = science[java] Default Category: unknown: 2

      中间过程的结果存储在 base 目录下的 wikipedia 目录中。

      获取了结果之后,显然还有一个问题:“我应该如何做?”汇总结果表明,正确率和错误率大概分别为 75% 和 25%。这种结果看上去非常合理,特别是它比随机猜测要好很多。但在仔细分析之后,我发现对历史信息的预测(正确率大约为 95%)相当出色,而对科学信息的预测则相当糟糕(大约 15%)。为了查找其原因,我查看了训练的输入文件,并发现与历史相关的示例要比科学多很多(文件大小几乎差了一倍),这可能是一个潜在的问题。

      对于测试,您可以向 ant test 添加 -Dverbose=true 选项,这会显示关于各测试输入的信息,以及它的标签是否正确。仔细研究此输出,您可以查找文档并分析它分类错误的原因。我还可以尝试不同的输入参数,或者使用更加科学数据来重新训练模型,以确定是否能够改善此结果。

      在训练模型时考虑使用特征选择也是很重要的。对于这些示例,我使用 Apache Lucene 中的 WikipediaTokenizer 来标记初始文档,但是我没有尽力删除可能标记错误的常用术语或垃圾术语。如果要将此分类器投入生产,那么我会更加深入地研究输入和其他设置,以弥补性能的每个方面。

      为 了确定 Science 结果是否是个意外,我尝试了一组不同的类别:共和(Republican)与民主(Democrat)。在本例中,我希望预测新文档是否与 Republicans 或者 Democrats 相关。为了帮助您独立实现此功能,我在 src/test/resources 中创建了 repubs-dems.txt 文件。然后,通过以下操作完成分类步骤:

ant classifier-example -Dcategories.file=./src/test/resources/repubs-dems.txt -Dcat.dir=rd

      两个 -D 值仅仅指向类别文件以及 wikipedia 目录中存储中间结果的目录。此结果概要和混合矩阵如清单 7 所示:


清单 7. 运行 Bayes 分别器查找 Republicans 和 Democrats 的结果
     [java] 09/07/23 17:06:38 INFO bayes.TestClassifier: -------------- [java] 09/07/23 17:06:38 INFO bayes.TestClassifier: Testing:                                wikipedia/rd/prepared-test/democrats.txt [java] 09/07/23 17:06:38 INFO bayes.TestClassifier: democrats      70.0                                                                    21/30.0 [java] 09/07/23 17:06:38 INFO bayes.TestClassifier: -------------- [java] 09/07/23 17:06:38 INFO bayes.TestClassifier: Testing:                              wikipedia/rd/prepared-test/republicans.txt [java] 09/07/23 17:06:38 INFO bayes.TestClassifier: republicans    81.3953488372093                                                                    35/43.0 [java] 09/07/23 17:06:38 INFO bayes.TestClassifier: [java] Summary [java] ------------------------------------------------------- [java] Correctly Classified Instances          :         56           76.7123% [java] Incorrectly Classified Instances        :         17           23.2877% [java] Total Classified Instances              :         73 [java] [java] ======================================================= [java] Confusion Matrix [java] ------------------------------------------------------- [java] a           b       <--Classified as [java] 21          9        |  30          a     = democrats [java] 8           35       |  43          b     = republicans [java] Default Category: unknown: 2

      虽然最终结果在正确性方面差不多是相同的,但您可以看到我在 这两个类别中进行选择时采取更好的方式。查看包含输入文档的 wikipedia/rd/prepared 目录,我们发现两个训练文件在训练示例方面更加平衡了。 此外,与 “历史/科学” 结果相比,得到了示例也少了很多,因为每个文件都比历史或科学训练集小很多。总的来说,结果至少表明平衡性得到了显著改善。更大的训练集可能会抵消 Republicans 和 Democrats 之间的差异,即便不行也可以暗示某个分组坚持其在 Wikipedia 上的消息是较好的选择 — 但是,我选择将这留给政治学者来决定。

      现在,我已经展示了如何在独立模式中执行分类,接下来需要将代码添加到云中,并在 Hadoop 集群上运行。与集群代码相同,您需要 Mahout Job JAR。除此之外,我之前提到的所有算法都是支持 Map-Reduce 的,并且能够在 Hadoop 教程所述的 Job 提交流程中运行。

原创粉丝点击