在软件世界中,两年似乎是永恒的。 在过去的两年中,我们看到了社交媒体的迅猛发展,大规模集群计算的商品化(感谢Amazon和RackSpace等玩家)以及数据的大量增长以及我们理解数据的能力。 距 “ Apache Mahout简介 ”在developerWorks上首次发布已经两年了。 从那时起,Mahout社区以及该项目的代码库和功能得到了极大的发展。 Mahout也已被全球大小企业广泛采用。
在上一篇有关Mahout的文章中,我介绍了许多机器学习的概念以及使用Mahout算法套件的基础。 我提出的概念仍然有效,但是算法套件已发生了相当大的变化。 本文不再讨论基础知识,而是关注Mahout的当前状态以及如何使用Amazon EC2服务和包含700万封电子邮件文档的数据集在整个计算集群上扩展Mahout。 有关基础知识复习,检查出的相关信息 ,特别是象夫在行动书。 另外,我还将假设您具有Apache Hadoop和Map-Reduce范例的基础知识。 (请参阅相关主题关于Hadoop的更多信息。)
Mahout的状态
Mahout在短时间内取得了长足的进步。 尽管该项目的重点仍然放在我喜欢称之为的“三个C”(协作过滤(推荐),聚类和分类)上,但该项目还增加了其他功能。 我将重点介绍两个方面的一些关键扩展和改进:机器学习的核心算法(实现),以及支持基础架构,包括输入/输出工具,与其他库的集成点以及更多示例供参考。 但是请注意,此状态不完整。 此外,本文的篇幅有限,这意味着我只能对每项改进提供几句话。 我鼓励读者阅读Mahout网站的“新闻”部分以及Mahout每个发行版本的发行说明,以找到更多信息。
算法,算法,算法
在尝试解决了一段时间的机器学习问题后,人们很快意识到,没有一种算法适合每种情况。 为此,Mahout添加了许多新的实现。 表1包含了我对Mahout中最重要的新算法实现以及一些示例用例的看法。 在本文的稍后部分,我将使用其中的一些算法。
表1. Mahout中的新算法
算法 | 简要描述;简介 | 用例 |
---|---|---|
Logistic回归,通过随机梯度下降(SGD)解决 | 快速,简单,连续的分类器,可以在苛刻的环境中进行在线学习 | 向用户推荐广告,将文字分类 |
隐马尔可夫模型(HMM) | 经典分类算法的顺序和并行实现,旨在当底层生成过程未知时对真实世界的过程进行建模 | 词性标注文本; 语音识别 |
奇异值分解(SVD) | 旨在减少大型矩阵中的噪声,从而使其更小且更易于处理 | 作为聚类的前身,推荐者和分类可以自动进行特征选择 |
Dirichlet聚类 | 基于模型的集群方法,根据数据是否适合基础模型确定成员资格 | 当数据有重叠或层次结构时很有用 |
光谱聚类 | 一系列类似的方法,这些方法使用基于图的方法来确定集群成员资格 | 像所有聚类算法一样,对于探索大型看不见的数据集很有用 |
Minhash聚类 | 使用散列策略将相似项分组在一起,从而产生聚类 | 与其他聚类方法相同 |
大量推荐程序改进 | 分布式共现,SVD,交替最小二乘 | 约会网站,电子商务,电影或书籍推荐 |
搭配 | 启用Map-Reduce的并置实现 | 在文本中查找统计上有趣的短语 |
Mahout还添加了许多用户可能会觉得有用的低级数学算法(请参阅数学包)。 表1中描述的算法使用了许多方法,但是它们被设计为通用的,因此可以满足您的需求。
改善和扩展Mahout的基础架构
随着越来越多的人使用开放源代码项目并致力于使该项目的代码与他们的代码一起使用,基础结构的填充量也就增加了。对于Mahout而言,这种发展带来了许多改进。 最值得注意的是一个大大改进且一致的命令行界面,它使在本地以及在Apache Hadoop上提交和运行任务变得更加容易。 这个新脚本位于Mahout顶级目录内的bin目录中(从此处开始,我将其称为$ MAHOUT_HOME)。 (请参阅Mahout的命令行侧栏。)
任何机器学习库的两个关键组件是可靠的数学库和有效的收藏包。 数学库(位于$ MAHOUT_HOME下的数学模块中)提供多种功能-从表示向量,矩阵的相关数据结构和用于操纵它们的相关运算符,到生成随机数和对数似然性等有用统计信息的工具(请参阅资源 )。 Mahout的集合库由与Java集合( Map
, List
等)提供的数据结构相似的数据结构组成,不同之处在于它们本机支持Java原语(例如int
, float
和double
而不是它们的Integer
, Float
和Double
Object
对应物。 这很重要,因为在处理具有数百万个功能的数据集时,每一点(双关语都是至关重要的)很重要。 此外,在原语及其Object
对应物之间进行装箱的成本在大规模上是令人望而却步的。
Mahout还引入了一个新的Integration模块,该模块包含旨在补充或扩展Mahout核心功能的代码,但并非在所有情况下每个人都需要。 例如,推荐器(协作过滤)代码现在支持将其模型存储在数据库中(通过JDBC),MongoDB或Apache Cassandra(请参阅参考资料 )。 集成模块还包含许多用于将数据转换为Mahout格式以及评估结果的机制。 例如,它包括一些工具,可以将充满文本文件的目录转换为Mahout的矢量格式(请参阅Integration模块中的org.apache.mahout.text
包)。
最后,Mahout有许多新示例,从计算具有Netflix数据集的推荐到将Last.fm音乐聚类等,不一而足。 此外,我为本文开发的示例也已添加到Mahout的代码库中。 我鼓励您花一些时间来更详细地探索示例模块(位于$ MAHOUT_HOME / examples中)。
现在您已经了解了Mahout的状态,现在该深入探讨主要事件:如何扩展Mahout。
在云中扩展Mahout
要使Mahout有效地扩展,并不是简单地向Hadoop集群添加更多节点那样简单。 诸如算法选择,节点数量,功能选择和数据稀疏性之类的因素,以及常见的内存,带宽和处理器速度的可疑因素,都在确定Mahout扩展的效率方面发挥了作用。 为了激发讨论的热情,我将通过一个示例,在适当的情况下,使用Amazon的EC2计算基础架构和Hadoop在Apache软件基金会(ASF)的邮件归档的公开可用数据集上运行Mahout的一些算法(请参阅参考资料 )。 。
安装程序之后的每个小节都将探讨扩展Mahout的一些关键问题,并探讨在EC2上运行示例的语法。
建立
示例的设置包括两个部分:本地设置和EC2(云)设置。 要运行示例,您需要:
- Apache Maven 3.0.2或更高版本。
- Git版本控制系统(您可能还希望拥有一个Github帐户)。
- 基于* NIX的操作系统,例如Linux或Apple OSX。Cygwin可能适用于Windows®,但我尚未对其进行测试。
要在本地进行设置,请在命令行上运行以下命令:
-
mkdir -p scaling_mahout/data/sample
-
git clone git://github.com/lucidimagination/mahout.git mahout-trunk
-
cd mahout-trunk
-
mvn install
(如果要跳过Mahout的测试,mvn install
添加-DskipTests
,这可能需要一段时间才能运行) -
cd bin
-
/mahout
(您应该会看到可以运行的项目列表,例如kmeans
)
这应该获得您需要编译并正确安装的所有代码。 另外, 下载样本数据 ,将其保存在scaling_mahout / data / sample目录中,然后将其解压缩( tar -xf scaling_mahout.tar.gz
)。 出于测试目的,这只是您将在EC2上使用的一小部分数据。
要在Amazon上进行设置,您需要一个Amazon Web Services (AWS)帐户(注意您的秘密密钥,访问密钥和帐户ID),并对Amazon EC2和Elastic Block Store(EBS)服务的工作原理有基本的了解。 请遵循Amazon网站上的文档以获取必要的访问权限。
在不具备先决条件的情况下,该启动集群了。 最好是从单个节点开始,然后根据需要添加节点。 并请注意,当然,在EC2上运行需要花费金钱。 因此,请确保在完成运行后关闭节点。
要引导群集以供本文中的示例使用,请按照下列步骤操作:
- 从ASF镜像下载 Hadoop 0.20.203.0并在本地解压缩。
-
cd hadoop-0.20.203.0/src/contrib/ec2/bin
- 在编辑器中打开hadoop-ec2-env.sh并:
- 填写您的
AWS_ACCOUNT_ID
,AWS_ACCESS_KEY_ID
,AWS_SECRET_ACCESS_KEY
,EC2_KEYDIR
,KEY_NAME
和PRIVATE_KEY_PATH
。 更多信息请参见该亨利马乌维基的“使用现有的Hadoop AMI”页面(请参阅相关主题 )。 - 将
HADOOP_VERSION
设置为0.20.203.0
。 - 将
S3_BUCKET
设置为490429964467
。 - 设置
ENABLE_WEB_PORTS=true
。 - 至少将
INSTANCE_TYPE
设置为m1.xlarge
。
- 填写您的
- 在编辑器中打开hadoop-ec2-init-remote.sh并:
- 在创建hadoop-site.xml的部分中,添加以下属性:
注意 :如果要运行分类,则需要使用更大的实例和更多的内存。 我使用了两个X-Large实例和12GB的堆。<property> <name>mapred.child.java.opts></name> <value>-Xmx8096m></value> </property>
- 将
mapred.output.compress
更改为false
。
- 在创建hadoop-site.xml的部分中,添加以下属性:
- 启动集群:
./hadoop-ec2 launch-cluster mahout-clustering X
X
是您要启动的节点数(例如2
或10
)。 我建议从一个较小的值开始,然后随着舒适度的提高而添加节点。 这将有助于控制您的费用。 - 为ASF公共数据集创建一个EBS卷(快照:snap--17f7f476)并将其附加到/ dev / sdh上的主节点实例(这是mahout-clustering-master安全组中的实例)。 (请参阅相关主题的链接到EC2在线文档中详细说明。)
- 如果使用EC2命令行API(请参阅参考资料 ),则可以执行以下操作:
-
ec2-create-volume --snapshot snap-17f7f476 --z ZONE
-
ec2-attach-volume $VOLUME_NUMBER -i $INSTANCE_ID -d /dev/sdh
,其中$VOLUME_NUMBER
由create-volume步骤输出,而$INSTANCE_ID
是由launch-cluster命令启动的主节点的ID。
-
- 否则,您可以通过AWS Web控制台执行此操作。
- 如果使用EC2命令行API(请参阅参考资料 ),则可以执行以下操作:
- 将setup-asf-ec2.sh脚本(请参阅下载 )上传到主实例:
./hadoop-ec2 push mahout-clustering $PATH/setup-asf-ec2.sh
- 登录到您的集群:
./hadoop-ec2 login mahout-clustering
- 执行shell脚本来更新您的系统,安装Git和Mahout,并清理一些档案以使其易于运行:
./setup-asf-ec2.sh
在不了解设置细节的情况下,下一步就是了解将Mahout最受欢迎的一些算法投入生产并扩大规模的含义。 我将主要关注扩展的实际任务,但在此过程中,我将涵盖一些有关功能选择以及为何做出某些选择的问题。
推荐建议
协作过滤是Mahout最受欢迎和易于使用的功能之一,因此它是讨论如何扩展Mahout的逻辑起点。 回想一下,我们正在使用ASF中的邮件存档。 在推荐任务的情况下,一种有趣的可能性是构建一个系统,该系统根据其他用户已阅读的线程向用户推荐可能有趣的邮件线程。 要将其设置为协作过滤问题,我将定义系统建议作为邮件线程的项目,具体由邮件标题中的Message-ID和References确定。 将通过邮件中的“发件人”地址定义用户。 换句话说,我关心的是谁发起或回复了邮件。 至于首选项本身的值,我只是将与邮件线程的交互视为布尔首选项:如果用户X与线程Y交互,则打开;否则,则关闭。 此选择的一个下游影响是,我们必须使用与布尔首选项配合使用的相似性度量,例如Tanimoto或对数似然相似性。 这通常可以加快计算速度,并且可能会减少系统中的噪音,但是您的行驶里程可能会有所不同,并且您可能希望尝试使用不同的重量。
因为在协作过滤(用户,项目,可选首选项)方面,功能选择非常简单,所以我们可以快速查看将内容从原始邮件存档转移到本地运行再到云运行的步骤。 请注意,在许多情况下,最后一步通常不是必需的,因为可以在一台机器上以足够快的速度获得结果,而无需增加Hadoop的复杂性。 粗略估计,Mahout社区基准测试表明,一个节点可以合理地提供多达1亿用户的推荐。 就电子邮件数据而言,没有多少项目(大约700万条消息),但是无论如何,我将继续前进并在Hadoop上运行它。
为了查看运行中的代码,我将必需的步骤打包到了位于$ MAHOUT_HOME / examples / bin / build-asf-email.sh文件中的Shell脚本中。 执行shell脚本,传递输入数据的位置以及想要输出结果的位置,如下所示:
./build-asf-email.sh ./scaling_mahout/data/sample/content ./scaling_mahout/output/
出现提示时,选择“ recommender
(选项1),然后坐下来享受Mahout和Hadoop的日志记录输出的详细信息。 完成后,您将看到类似于清单1的内容:
清单1.运行推荐程序代码的示例输出
11/09/08 09:57:37 INFO mapred.JobClient: Reduce output records=2072
11/09/08 09:57:37 INFO mapred.JobClient: Spilled Records=48604
11/09/08 09:57:37 INFO mapred.JobClient: Map output bytes=10210854
11/09/08 09:57:37 INFO mapred.JobClient: Combine input records=0
11/09/08 09:57:37 INFO mapred.JobClient: Map output records=24302
11/09/08 09:57:37 INFO mapred.JobClient: SPLIT_RAW_BYTES=165
11/09/08 09:57:37 INFO mapred.JobClient: Reduce input records=24302
11/09/08 09:57:37 INFO driver.MahoutDriver: Program took 74847 ms
这项工作的结果将是输入数据中所有用户的所有建议。 结果存储在名为prefs / recommendations的输出目录的子目录中,并包含一个或多个名称为part-r-的文本文件。 (这就是Hadoop输出文件的方式。)检查其中一个文件,就可以一目了然地发现建议的格式为:
user_id [item_id:score, item_id:score, ...]
例如,用户ID 25对电子邮件ID 26295和35548提出了建议。警告只不过是user_id
和item_id
不是原始ID,而是从原始ID到整数的映射。 为了帮助您理解为什么这样做,现在是时候解释执行Shell脚本时实际发生的情况了。
产生推荐结果涉及三个步骤:
- 使用Mahout的
SequenceFilesFromMailArchives
将原始的mbox文件转换为Hadoop的SequenceFile
格式。 - 从消息中提取消息ID和From签名,并以Mahout可以理解的格式输出结果。
- 运行Mahout的
RecommenderJob
类。
除了简单地建议感兴趣的读者参考代码外,我不会介绍步骤1。
对于第2步,需要进行更多工作以从文件(消息ID,回复引用和发件人地址)提取相关信息,然后将它们存储为三元组( From
ID, Message-ID
,首选项)。 RecommenderJob
消耗。 此过程由MailToPrefsDriver
驱动,它由三个Map-Reduce作业组成:
- 创建一个字典,将基于字符串的Message-ID映射到唯一的
long
。 - 创建一个字典,将基于字符串的From电子邮件地址映射到唯一的
long
。 - 提取消息ID,引用和发件人; 使用步骤1和2的字典将它们映射为
long
; 并将三元组输出到文本文件。
毕竟,是时候提出一些建议了。 为了创建建议, RecommenderJob
执行图1所示的步骤:
图1.推荐工作流程
![推荐工作流程](https://i-blog.csdnimg.cn/blog_migrate/ec1a31b78b0f7f1f364d5d85ef65d94a.png)
在工作流程中进行繁重工作的主要步骤是“计算共现”步骤。 此步骤负责对整个矩阵进行成对比较,以寻找共同点。 RowSimilarityJob
,此步骤(由Mahout的RowSimilarityJob
)通常可用于在矩阵中的任何行之间进行成对计算(而不仅是评级/评论)。
使用以下命令在shell脚本中调用RecommenderJob
:
bin/mahout recommenditembased --input $PREFS_REC_INPUT --output $RECS_OUT --tempDir
$PREFS_TMP --similarityClassname SIMILARITY_LOGLIKELIHOOD
第一个参数告诉Mahout要运行哪个命令( RecommenderJob
); 其他许多( input
/ output
/ tempDir
)是不言自明的。 similarityClassname
告诉Mahout在计算共现时如何计算项目之间的相似度。 我选择使用对数似然法是因为其简单性,速度和质量。
获得结果后,就该对它们进行评估了。 Mahout带有评估包( org.apache.mahout.cf.taste.eval
),其中包含有用的工具,可让您检查结果的质量。 不幸的是,它们不能与基于Hadoop的算法一起使用,但是在其他情况下它们可能会很有用。 这些工具保留一部分数据作为测试数据,然后将其与系统产生的数据进行比较,以判断质量。
生成建议实际上就是所有这些,其中最美好的部分是可以直接在集群上运行。 为此,请登录到您之前设置的EC2群集,并像以前一样运行相同的Shell脚本(位于/ mnt / asf-email / mahout-trunk / examples / bin中)。 在将节点添加到群集中时,应该会看到运行步骤所需的总时间有所减少。 例如,在本地计算机上运行完整数据集需要三天才能完成。 在EC2的10节点群集上运行,大约花了60分钟来完成主要推荐任务以及将电子邮件转换为可用格式的准备工作。
我留给读者作为练习的最后一部分是将建议作为应用程序的一部分使用。 通常,一旦系统中有大量项目和用户,就会根据业务需求定期生成建议-通常在每小时和每天之间。 毕竟,一旦系统达到一定数量的用户和建议,对所生成建议的更改将变得更加微妙。
接下来,让我们看一下对电子邮件消息进行分类的方法,在某些情况下可以将其视为上下文推荐系统 。
分类
Mahout有几种分类算法,其中大多数算法(一个值得注意的例外,随机梯度下降)被编写为在Hadoop上运行。 出于本文的目的,我将使用朴素的贝叶斯分类器,这是许多人开始使用的分类器,在有效扩展时通常会产生合理的结果。 有关其他分类的详细信息,请参阅 Mahout中的wiki的行动或算法部分Mahout中的相应章节(参见相关主题 )。
电子邮件文档由Apache项目(Lucene,Mahout,Tomcat等)分解,并且每个项目通常具有两个或多个邮件列表(用户,开发等)。 假定ASF电子邮件数据集已按项目进行分区,则逻辑分类问题是尝试预测应向其传递新传入消息的项目。 例如,新消息属于Lucene邮件列表还是Tomcat邮件列表?
为了使Mahout的分类算法起作用,必须训练模型以表示要识别的模式,然后对数据的子集进行测试。 在大多数分类问题中,一个或多个人员必须仔细检查并手动注释要在训练中使用的部分数据。 值得庆幸的是,在这种情况下,数据集已经按项目分开了,因此不需要手动注释-尽管我指望人们通常会在发送电子邮件时选择正确的列表,您和我都知道并非总是如此。
就像在推荐程序中一样,必要的步骤已预先打包到build-asf-email.sh脚本中,并在从菜单中选择选项3(对于标准朴素贝叶斯在第二个提示符下选择选项1)时执行。 与建议类似,扩展代码的部分工作是在准备要使用的数据时。 对于文本分类,这主要是指对特征进行编码,然后从特征中创建矢量 ,但是它还包括设置训练和测试集。 采取的完整步骤包括:
- 使用Mahout的
SequenceFilesFromMailArchives
将原始的mbox文件转换为Hadoop的SequenceFile
格式。 (请注意,此处的运行时选项略有不同。)bin/mahout org.apache.mahout.text.SequenceFilesFromMailArchives --charset "UTF-8" --body --subject --input $ASF_ARCHIVES --output $MAIL_OUT
- 将
SequenceFile
条目转换为稀疏向量并修改标签:-
bin/mahout seq2sparse --input $MAIL_OUT --output $SEQ2SP --norm 2 --weight TFIDF --namedVector --maxDFPercent 90 --minSupport 2 --analyzerName org.apache.mahout.text.MailArchivesClusteringAnalyzer
-
bin/mahout org.apache.mahout.classifier.email.PrepEmailDriver --input $SEQ2SP --output $SEQ2SPLABEL --maxItemsPerLabel 1000
-
- 将输入分为训练和测试集:
bin/mahout split --input $SEQ2SPLABEL --trainingOutput $TRAIN --testOutput $TEST --randomSelectionPct 20 --overwrite --sequenceFiles
- 运行朴素的贝叶斯分类器来训练和测试:
-
bin/mahout trainnb -i $TRAIN -o $MODEL -extractLabels --labelIndex $LABEL
-
bin/mahout testnb -i $TEST -m $MODEL --labelIndex $LABEL
-
值得注意的两个主要步骤是步骤2和步骤4。步骤2a是主要的特征选择和编码步骤,许多输入参数控制着如何将输入文本表示为向量中的权重。 表2分解了步骤2中与功能选择相关的选项:
表2.矢量创建的特征选择选项
选项 | 描述 | 实例和注释 |
---|---|---|
--norm | 范数通过计算其长度的函数修改所有矢量(范数) | 1个标准=曼哈顿距离,2个标准=欧几里德距离 |
--weight | 计算任何给定特征的权重,即TF-IDF(术语频率,反文档频率)或术语频率 | TF-IDF是搜索和机器学习中用于将文本表示为矢量的常见加权方案。 |
--maxDFPercent ,-- --minSupport | 这两个选项都会删除在整个文档集合中过于频繁(max)或不够频繁的术语 | 在自动删除常用或非常少用的术语(对计算几乎没有价值)方面很有用 |
--analyzerName | Apache Lucene分析器类,可用于标记,阻止,删除或以其他方式更改文档中的单词 | 请参阅相关主题 ,以了解更多有关Lucene的 |
鉴于步骤2a中的分析过程正在完成特征选择所需的大部分繁重工作,因此值得进一步深入研究。 Lucene Analyzer
由Tokenizer
类和零个或多个TokenFilter
类组成。 的Tokenizer
是负责用于破碎原始输入到零个或多个标记(例如字)。 TokenFilter
实例链接在一起,然后修改Tokenizer
生成的令牌。 例如,示例中使用的Analyzer
:
- 在空白上进行标记化,外加一些标点符号。
- 小写所有令牌。
- 在可能的情况下,通过转换变音符号等,将非ASCII字符转换为ASCII。
- 丢弃超过40个字符的令牌。
- 删除停用词(请参阅列表的代码,该代码太长了,无法在此处显示)。
- 茎用波特词干令牌(见相关主题 。)
此分析的最终结果是每个文档的矢量明显更小,并且该矢量消除了会混淆分类器的常见“杂色”词( the , a , an等)。 通过查看电子邮件中的示例,然后通过Analyzer
对其进行处理并检查输出,从而做出关于如何进行最佳处理的判断,来迭代开发此Analyzer
。 不幸的是,这个过程既是科学的直觉(经验)。 过程和结果远非完美,但它们可能足够好。
步骤2b对数据进行一些较小的转换以进行处理,并丢弃一些内容,以便在训练数据中均匀地表示各种标签。 这一点很重要,因为我的第一次数据实验导致了机器学习中太常见的问题,即通过大量更多的训练示例来过度拟合这些标签。 实际上,在集群上使用完整的数据集运行时,将--maxItemsPerLabel
设置为1000仍然不足以产生出色的结果,因为某些邮件列表的帖子数少于1000。 这可能是由于Mahout中的一个错误,社区仍在对此进行调查。
在第4步中,完成了实际工作以建立模型,然后测试模型是否有效。 在步骤4a中,-- --extractLabels
选项只是告诉Mahout从输入中找出训练标签。 (另一种方法是传递它们。)此步骤的输出是一个文件,可以通过org.apache.mahout.classifier.naivebayes.NaiveBayesModel
类读取。 步骤4b接收模型和测试数据,并检查以查看培训工作的良好程度。 输出是一个混淆矩阵,如“ Apache Mahout简介 ”中所述。 对于样本数据,输出如清单2所示:
清单2.运行分类器代码的示例输出
Correctly Classified Instances : 41523 61.9219%
Incorrectly Classified Instances : 25534 38.0781%
Total Classified Instances : 67057
=======================================================
Confusion Matrix
-------------------------------------------------------
a b c d e f ><--Classified as
190440 12 1069 0 0 | 20125 a= cocoon_apache_org_dev
2066 0 1 477 0 0 | 2544 b= cocoon_apache_org_docs
165480 2370 704 0 0 | 19622 c= cocoon_apache_org_users
58 0 0 201090 0 | 20167 d= commons_apache_org_dev
147 0 1 4451 0 0 | 4599 e= commons_apache_org_user
您应该注意到,对于分类器而言,这实际上是一个相当差的显示(尽管比猜测要好)。 表现不佳的可能原因是,给定Apache项目的用户和开发邮件列表的词汇表是如此紧密相关,以至于很难区分。 16548个cocoon_user消息被错误地分类为cocoon_dev,这一事实得到了支持。 实际上,仅使用项目名称重新运行任务,而无需区分样本数据中的用户列表和开发列表,将产生清单3中的结果:
清单3.仅使用项目名称重新运行分类器代码的示例输出
Correctly Classified Instances : 38944 96.8949%
Incorrectly Classified Instances : 1248 3.1051%
Total Classified Instances : 40192
=======================================================
Confusion Matrix
-------------------------------------------------------
a b c ><--Classified as
18733 1241 0 | 19974 a = cocoon_apache_org
7 20211 0 | 20218 b = commons_apache_org
我想您会同意96%的准确度比61%略高! 实际上,它可能太好了,难以置信。 该分数可能是由于此特定小数据集的性质或可能需要调查的更深层次的问题所致。 实际上,这样的分数应保证可以通过添加数据和检查代码来进行进一步调查。 现在,我很高兴将其作为结果的一个示例。 但是,我们可以尝试其他技术或更好的特征选择,或者也许更多的训练示例,以提高准确性。 对结果进行交叉验证也很常见。 交叉折叠验证涉及反复从训练样本中取出部分数据,然后将其放入测试样本中或放在一边。 然后,根据所有运行的质量(不仅是运行质量)来判断系统。
与推荐者一样,将其带到云端同样简单。 只需通过传递适当的路径,整个脚本就应该在您的集群中运行。 在10节点群集上的EC2上运行此程序只花了几分钟的时间进行培训和测试,以及通常的准备工作。 但是,不幸的是,当您执行此操作时,由于某些邮件列表中的数据点很少,因此针对云中的完整数据集运行的质量会受到影响。 这些可能应该从考虑中删除。
生产的下一步包括将模型作为您的运行时系统的一部分使用,以及建立工作流程以确保在从系统获得反馈时更新模型。 从这里,我将看一下集群。
聚类
与分类一样,Mahout有许多聚类算法,每种都有不同的特征。 例如,K-Means可以很好地扩展,但是需要您指定想要的聚类数量,而Dirchlet聚类则需要选择模型分布以及想要的聚类数量。 聚类与分类也有很多共同之处,并且有可能在某些地方使用聚类作为分类的一部分来使它们协同工作。 此外,用于分类的许多数据准备工作对于聚类都是相同的,例如将原始内容转换为序列文件,然后转换为稀疏向量,因此您可以参考“ 分类”部分以获取该信息。
对于集群,需要回答的主要问题是:无论项目如何,我们是否都可以基于内容相似性对所有消息进行逻辑分组? 例如,也许关于Apache Solr邮件列表中有关将Apache Tomcat用作Web容器的消息比针对原始项目的消息更接近于Tomcat项目的消息。
对于此示例,第一步非常类似于分类,在完成向稀疏向量的转换后会有所不同。 具体步骤是:
- 分类中与步骤1和步骤2相同的步骤。
-
$ bin/mahout kmeans --input "$SEQ2SP/tfidf-vectors" --output $CLUST_OUT -k 50 --maxIter 20 --distanceMeasure org.apache.mahout.common.distance.CosineDistanceMeasure --clustering --method mapreduce --clusters "$CLUST_OUT/clusters"
在这种情况下,将运行K-Means进行集群,但是shell脚本也支持运行Dirichlet集群。 (执行脚本时,系统会提示您选择要运行的算法。)在前面的示例中,值得研究的参数是:
-
-k
:要创建的集群数。 我从帽子里挑了50个,但这肯定是其他值。 -
--maxIter
:K-Means是一种迭代算法,通过该算法,集群的中心会在每次迭代中进行更新。 在某些情况下,它不能保证自己完成,因此此参数可以确保算法完成。 -
--distanceMeasure
:距离度量值确定当前质心与被检查点之间的相似性。 在这种情况下,我选择了余弦距离测度,这通常是文本数据的不错选择。 Mahout还有许多其他实现,您可能会发现值得对数据进行尝试。 -
--clustering
:告诉Mahout输出哪些点属于哪个质心。 默认情况下,Mahout仅计算质心,因为通常仅需要这些质心。
运行完成后,您可以使用Mahout的ClusterDump
程序转储群集质心(和关联的点)。 最终结果将位于kmeans目录下的子目录中,该子目录以名称clusters-开始,以-final结尾。 The exact value will depend on how many iterations it took to run the task; for instance, clusters-2-final
is the output from the third iteration. As an example, this command dumps out the clusters from running the small sample of data:
bin/mahout clusterdump --seqFileDir ../output/ibm/clustering/kmeans/clusters-2-final
--pointsDir ../output/ibm/clustering/kmeans/clusteredPoints/
The --seqFileDir
points at the centroids created, and the -pointsDir
is the directory of clustered points. A small sampling of the results is in Listing 4:
Listing 4. Sample output from running the ClusterDumper
:VL-337881{n=4420 c=[
Top Terms:
user =>0.060885823267350335
mailscann => 0.05059369006868677
cocoon =>0.048781178576134204
virus => 0.04285897589148712
derek => 0.04084340722527813
legal =>0.040052624979813184
scan => 0.03861016730680097
danger => 0.03848600584647758
csir => 0.03712359352614157
transtec => 0.03388019099942435
Weight : [props - optional]: Point:
1.0 : [distance=0.888270593967813]:
/cocoon.apache.org/dev/200004.gz/NBBBIDJGFOCOKIOHGDPBKEPPEEAA.XXXXX =
[ag:0.165, briefli:0.250, chang:0.075, close:0.137, cocoon:0.060,
cocoon1:0.226, cocoon2:0.218, concept:0.277, develop:0.101, differ:0.144,
explain:0.154, greet:0.197, klingenderstrass:0.223, langham:0.223, look:0.105,
mailserv:0.293, matthew:0.277, mlangham:0.240, paderborn:0.215, processor:0.231,
produc:0.202, put:0.170, scan:0.180, tel:0.163, understand:0.127, virus:0.194]
In Listing 4 , notice that the output includes a list of terms the algorithm has determined are most representative of the cluster. This can be useful for generating labels for use in production, as well as for tuning feature selection in the preparatory steps — because it's often the case that stop words show up (in this case, for example, user
likely is one) in the list in the first few experiments with running the data.
As you've likely come to expect, running this on your cluster is as simple as running it locally — and as simple as the other two examples. Besides the time spent converting the content (approximately 150 minutes), the actual clustering job took about 40 minutes on 10 nodes in my tests.
Unfortunately, with clustering, evaluating the results often comes down to the "smell test," although Mahout does have some tools for evaluation (see CDbwEvaluator
and the ClusterDumper
options for outputting top terms). For the smell test, visualizing the clusters is often the most beneficial, but unfortunately many graph-visualization toolkits choke on large datasets, so you may be left to your own devices to visualize.
As with recommendations and classification, the steps to production involve deciding on the workflow for getting data in as well as how often to do the processing and, of course, making use of it in your business environment. You will also likely need to work through the various algorithms to see which ones work best for your data.
What's coming next in Mahout?
Apache Mahout continues to move forward in a number of ways. The community's primary focus at the moment is on pushing toward a 1.0 release by doing performance testing, documentation, API improvement, and the addition of new algorithms. The next release, 0.6, is likely to happen towards the end of 2011, or soon thereafter. At a deeper level, the community is also starting to look at distributed, in-memory approaches to solving machine-learning problems. In many cases, machine-learning problems are too big for a single machine, but Hadoop induces too much overhead that's due to disk I/O. Regardless of the approach, Mahout is well positioned to help solve today's most pressing big-data problems by focusing in on scalability and making it easier to consume complicated machine-learning algorithms.
致谢
Special thank you to Timothy Potter for assistance in AMI packaging and fellow Mahout committers Sebastian Schelter, Jake Mannix, and Sean Owen for technical review. Part of this work was supported by the Amazon Apache Testing Program.
翻译自: https://www.ibm.com/developerworks/java/library/j-mahout-scaling/index.html