您的位置:首页 > 编程语言 > Java开发

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

2012-01-31 11:01 337 查看
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)。因此,包含单词
science 或 history 的所有 Wikipedia 类别都将被添加到该类别中(不需要准确匹配)。此外,系统为每个文档添加了标记并删除了标点、Wikipedia 标记以及此任务不需要的其他特征。最终结果将存储在一个特定的文件中(该文件名包含类别名),并采用每行一个文档的格式,这是 Mahout 所需的输入格式。同样,运行
ant prepare-test-docs
代码可以完成相同的文档测试工作。需要确保测试和训练文件没有重合,否则会造成结果不准确。从理论上说,使用训练文档进行测试应该能实现最的结果,但实际情况可能并非如此。

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

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

ant prepare-docs

ant prepare-test-docs

ant train

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 提交流程中运行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐