13.5.5 算法应用实例
下面我们将对如何使用Mahout进行聚类和分类进行具体介绍,其中聚类算法以K-Means为例,分类算法以贝叶斯(Bayes)为例。
1.K-Means聚类
在Mahout中运行K-Means聚类算法非常简单。对于不同的数据主要有以下三个步骤。
使用seqdirectory命令将待处理的文件转化成序列文件。
使用seq2sparse命令将序列文件转化成向量文件。
使用kmeans命令对数据运行K-Means聚类算法。
将文本文件转化成向量需要两个重要的工具。一个是SequenceFilesFromDirectory类,它能将一个目录结构下的文本文件转化成序列文件,这种序列文件为一种中间文本表示形式。另一个是SparseVectorsFromSequenceFiles类,它使用词频(TF)或TF-IDF(TF-IDF weighting with n-gram generation)将序列文件转化成向量文件。序列文件以文件编号为键、文件内容为值。下面讨论如何将文本转换成向量。
使用路透社14578新闻集作为示例数据。这组数据被广泛应用于机器学习的研究中,它起初是由卡内基集团有限公司和路透社共同搜集整理的,目的是发展文本分类系统。路透社14578新闻集分布于22个文档中,除最后的reut2-0.14.sgm包含578份文件外,其余的每个文件包含1 000份文件。
路透社14578新闻集中的所有文件都为标准通用标记语言SGML(Standard Generalized Markup Language)格式,这种格式的文件与XML文件格式相似。可以为SGML文件创建一个分析器(parser),并将文件编号(document ID)和文件内容(document text)写到序列文件(SequenceFiles)中去。然后用前文提到的向量化工具将序列文件转化成向量。但是,更快捷的方式是使用Lucene Benchmark JAR文件提供的路透社分析器(the Reuters Parser)。Lucene Benchmark JAR是捆绑在Mahout上的,剩下的工作只是到Mahout目录下的examples文件夹运行org.apache.lucene.benchmark.utils.ExtractReuters类。在这之前,需要从http://www.daviddlewis.com/resources/testcollections/reuters14578/reuters14578.tar.gz下载路透社新闻集,并将它解压到Examples/Reuters文件夹下。相关命令如下所示:
mvn-e-q exec:java
-Dexec.mainClass="org.apache.lucene.benchmark.utils.ExtractReuters"
-Dexec.args="reuters/reuters-extracted/"
使用解压得到的文件夹运行SequenceFileFromDirectory类。使用下面的脚本命令(Launch script)可以实现该功能:
bin/mahout seqdirectory-c UTF-8
-i examples/reuters-extracted/
-o reuters-seqfiles
这条命令的作用是将路透社文章转化成序列文件格式,如表13-7所示。
现在剩下的工作是将序列文件转化成向量文件。运行SparseVectorsFromSequenceFiles类即可实现该功能。命令如下:
bin/mahout seq2sparse-i reuters-seqfiles/-o reuters-vectors-w
注意,在seq2sparse命令中,参数-w用来表示是否覆盖输出文件夹。Mahout用来处理海量的数据,任何一个算法的输出都会花费很多时间。有了参数-w, Mahout就可以防止新产生的数据对未完全输出的数据进行破坏。除此之外,seq2sparse命令还有以下参数,如表13-8所示。
Mahout的seq2sparse命令的功能是从序列文件中读取数据,使用上面提到的默认参数,按照基于向量化(vectorizer)的字典生成向量文件。大家可以使用以下命令检查生成文件夹:
ls reuters-vectors/
执行上述命令后,结果如下所示:
dictionary.file-0
tfidf/
tokenized-documents/
vectors/
wordcount/
输出文件夹包含一个目录文件和四个文件夹。目录文件保存着术语(term)和整数编号之间的映射。当读取算法的输出时,这个文件是非常有用的,因此,需要保留它。其他四个文件夹是向量化过程中生成的文件夹。向量化过程主要有以下几步:
第一步,标记文本文档。具体过程是使用Lucene StandardAnalyzer将文本文档分成个体化的单词,将结果存储在tokenized-documents文件夹下。
第二步,对tonkenized文档进行迭代生成一个重要单词的集合。这个过程可能会使用单词统计、n-gram生成,这里使用的是unigrams生成。
第三步,使用TF将标记的文档转化成向量,从而创建TF向量。在默认情况下,向量化是使用TF-IDF,因此需要分两步来进行,一是文档频率(document-frequency)的统计工作;二是创建TF-IDF向量。TF-IDF向量在tfidf/vectors文件夹下。对于大多数的应用来说,需要的仅仅是目录文件和tfidf/vectors文件夹。
使用kmeans命令可以对数据运行K-Means聚类算法。命令如下:
bin/mahout kmeans
-i./examples/bin/work/reuters-out-seqdir-sparse/tfidf/vectors/
-c./examples/bin/work/clusters
-o./examples/bin/work/reuters-kmeans
-k 20-w
表13-9列出了K-Means命令参数的具体意义。
2.贝叶斯分类
在已经安装好Hadoop和Mahout的前提下,运行Bayes分类算法也比较简单。这里简要介绍Mahout的示例程序20NewsGroup的分类。实际上,除了20NewsGroup示例之外,还有Wikimapia数据,但由于其数据量达到了将近7GB,对大多数初学者而言并不合适。这里我们选择数据量较小且非常经典的20NewsGroup示例的分类。
什么是20NewsGroup?20新闻组包含20 000个新闻组文档,这些文档可以被分类成20个新闻组。20新闻组最初来源于Ken Lang的论文《Newsweeder:learning to filter netnews》。从那以后,20新闻组数据集合在机器学习领域越来越多地被用作实验数据。在文本聚类和分类方面的研究中使用尤为突出。20新闻组按照20个不同的类型进行组织,不同的类对应不同的主题。本书用到的20新闻组数据可以从http://people.csail.mit.edu/jrennie/20Newsgroups/下载。在下载页面中,一共有三种版本的20新闻组数据,分别是20news-19997.tar.gz、20news-bydate.tar.gz和20news-18828.tar.gz。
20news-19997. tar.gz是最原始的版本数据;20news-bydate.tar.gz是按照日期进行排序的,其中的60%用来进行训练Bayes分类算法,40%用来测试Bayes分类算法,不包含重复新闻和标识新闻组的标题;20news-18828.tar.gz不包含重复的新闻,但是包含带有新闻来源和新闻主题的标题。这三种20新闻组数据都是以tar.gz形式存在的。读者使用tar命令对它们进行解压即可得到相应的数据。具体选择哪种数据对结果影响不大,这里我们选择20news-bydate.tar.gz。
介绍完20NewsGroup后,下面开始介绍如何运行Mahout自带的Naïve Bayes Classifier算法示例。
数据下载完成后并不可以直接使用,可以看到,数据在目录中均是以文件夹进行区分,即数据已经被分好类别。因此我们首先需要获取所需格式的数据。该操作可以通过如下两个命令完成:
获取训练集:
mahout org.apache.mahout.classifier.bayes.PrepareTwentyNewsgroups\
-p$DATA_HOME/20news-bydate-train\
-o$DATA_HOME/bayes-train-input\
-a org.apache.mahout.vectorizer.DefaultAnalyzer\
-c UTF-8
获取测试集:
mahout org.apache.mahout.classifier.bayes.PrepareTwentyNewsgroups\
-p$DATA_HOME/20news-bydate-test\
-o$DATA_HOME/bayes-test-input\
-a org.apache.mahout.vectorizer.DefaultAnalyzer\
-c UTF-8
在数据获取完成之后,通过“hadoop fs-put”命令将数据上传到HDFS,然后使用下列命令训练Bayes分类器:
mahout trainclassifier\
-i/user/hadoop/20news/bayes-train-input\
-o/user/hadoop/20news/newsmodel\
-type cbayes\
-ng 2\
-source hdfs
该命令将会在Hadoop上运行四个MapReduce作业。在命令执行的过程中,可以打开浏览器,在http://localhost:50030/jobtracker.jsp上监视这些作业的运行状态。
运行下面的命令测试Bayes分类器:
mahout testclassifier\
-m/user/hadoop/20news/newsmodel\
-d/user/hadoop/20news/bayes-test-input\
-type cbayes\
-ng 2\
-source hdfs\
-method mapreduce
关于trainclassifier和testclassifier命令参数,这里不再详细介绍,大家可以通过“mahout[command]-h”命令来查看。
这就是Mahout自带的Bayes分类算法的示例程序。如果大家想要深入了解Mahout的分类算法,可以自行阅读Mahout Core API 0.7来了解已经实现的功能。