mahout文本聚类实验

2014/05/13 - BJ

最近用mahout做了一些聚类实验,由于处理的数据比较大(大概有2.4G),因此数据是放在hdfs上在hadoop上实现。这篇博文记录用mahout聚类的命令、以及出现的一些问题和解决方法等。

mahout文本聚类命令

从文本文档中生成向量

首先,需要把文本文档转换成mahout读取是SequenceFile格式。SequenceFile是Hadoop库中的一种文件格式,它由一系列键-值对序列组成。其中,键实现为Hadoop中的WritableComparable,值实现为Writable。实现命令是:

mahout seqdirectory -i hdfsdir/input -o hdfsdir/output -ow

常用的参数及其默认值:

  • -ow 输出目录是否被覆盖,默认是不被覆盖
  • -chunk 为MB为单位的块大小。处理大文档时,将词典分块存入内存,建议设置为jvm堆的80%(《Mahout实战》书中P121)。
  • -xm 执行方法,sequence或者mapreduce,默认是mapreduce
  • -prefix 追加到键上的前缀,默认空
  • -c 字符集,默认utf-8

需要注意的是,-i是指输入文件的目录,在该目录下,每个文档代表一个文本(已分词,空格隔开),用seqdirectory读取之后,key就是文档名,value就是文档的内容。

接下来,就要用sequenceFile文件生成聚类需要的mahout文件了。mahout的seq2sparse命令从SequenceFile文件中读取文本数据,并将基于词典的向量化程序锁生成的向量写入输出目录中。实现命令:

mahout seq2sparse -i hdfsdir/input -o hdfsdir/output -a org.apache.lucene.analysis.WhitespaceAnalyzer -wt tfidf -x 90 -seq

常用的参数及其默认值:

  • -ow 输出目录是否被覆盖,默认是不被覆盖
  • -a 所用分析器的雷鸣,默认StandardAnalyzer
  • -chunk 同上,默认为100MB
  • -wt 加权机制,tf或者tfidf,默认为tfidf
  • -s 最小支持度,可以放入词典文件中的词的最小频率,低于该值的被扔掉,默认为2
  • -md 最小文档频,默认为1
  • -x 最大文档频,默认99
  • -ng 文档集合中选出的n-gram最大长度,默认为1
  • -ml 当ng>1时生效,最小对数似然比,低于值的词去掉,默认为1.0
  • -n 是否归一化,默认是0,不做归一化
  • -nr 并行执行的reduce任务的个数
  • -seq 生成顺序访问的稀疏向量,如果被设置,输出向量就被创建为SequentialAccessSparseVector,而默认情况下,基于目录的向量化程序创建的是RandomAccessSparseVector。前者在某些算法(如kmeans和SVD)上可获得更高的性能。

Mahout中向量被实现为三个不同的类,每个类都是针对不同场景优化的,分别是:

  • DenseVector:一个double类型的数组,大小等于特征数。
  • RandomAccessSparseVector:被实现为一个integer型和double型的HashMap,只有非零元素才被分配空间,适合需要对向量值做很多随机插入和更新的算法。
  • SequentialAccessSparseVector:实现为两个并列数组,一个是integer型,一个是double型,只保留非零元素,为顺序读取而优化的,适合像kmeans这样需要反复计算向量大小的算法。

kmeans聚类

kmeans的输入数据需要是一系列数值化的系特征向量,即上面所说的SequentialAccessSparseVector。kmeans聚类算法可以通过KMeansClusterer或者KMeansDriver类来执行,前者以in-memory方式对数据点聚类,后者则可以启动一个MapReduce作业来执行,两种当时都可以在hadoop集群上执行,在hdfs上读写数据。

kmeans聚类需要指定k(类簇数)和初始点。初始点可以使用kmeans的随机生成方式,也可以自定义(例如用canopy粗略估计初始点)。

kmeans聚类命令为:

mahout kmeans -i -c -o -k -dm -x -cd -ow -cl -xm

常用的参数及其默认值:

  • -c 存储聚类初始点的路径,如果指定了-k,这个路径内容会被重写。
  • -k 类簇数,如果自定义-c,该值可以省略。
  • -dm 距离度量函数,默认是SquaredEuclideanDistanceMeasure
  • -x 最大迭代次数
  • -cd optional convergence delta. Default is 0.5
  • -ow overwrite output directory if present
  • -cl run input vector clustering after computing Canopies
  • -xm execution method: sequential or mapreduce

使用MapReduce架构,可以将聚类算法分配到不同的机器上运行,每个mapper处理一个子集,Mapper作业将以流的形式读物输入数据点,并计算出距离这部分点最近的簇。没有Hadoop集群时,也可以直接在java中运行,模拟hadoop单台机器的情形。

聚类结束后,如何查看簇呢?mahout提供了一个clusterdump的命令:

mahout clusterdump -df sequencefile -d vectors/dictionary.file -s clusters-n -b 0 -n 10

常用的参数及其默认值:

  • -df 指定输入文件的格式
  • -d vectors中的字典文件
  • -s 指定要查看的聚类结果
  • -b 指定输出结果的前多少个字节,0表示全部输出。
  • -n 输出与该类簇最近的前n个词

在mahout的kmeans聚类过程中,遇到这样几个典型的问题:

Q1:mahout命令设置mapred.map.tasks和mapred.reduce.tasks参数,只有后者起作用,前者不起作用。

A1:这是因为mapper的数量是由mapred.min.split.size决定的,一个文件根据split size分成多少份,就会有多少个mapper。

Q2:怎么设置map数量

A2:map tasks的个数主要是看splitSize,splitSize是这样计算的:
splitSize = Math.max(minSize,Math.min(maxSize, blockSize)),分别都是啥意思呢,继续。
minSize就是hadoop配置中的mapred.min.split.size参数,可能配置文件中没有,用-Dmapred.min.split.size就可以,取值0或者1,没有单位。
maxSize就是mapred.max.split.size,mapred-site.xml中也没有,默认值为long类型的最大值,使用时也用-D,单位是B,但是取值时不用写B。
blockSize是hdfs-site.xml中dfs.block.size的值,这个值必须是512的倍数。需要注意的是,如果这个值改变了,那么要重新部署文件才能生效。
参考:http://blog.csdn.net/wf1982/article/details/6672607

Q3:之前运行是不是出现Java Heap Space错误,而我们的机器足够大,怎么回事?

A3:之前把70w条记录的大文件分成了300来个小文件作为mahout的输入文件,在生成vector时,就会把每个小文件当做一条记录,这样的记录太大了,所以造成jvm溢出。解决办法就是把70w条记录的每条当做一个小文本输入。

总之,遇到问题不用怕。如果是设置问题,就去查看mahout脚本文件(一般位于安装目录的bin/mahout)或者hadoop的配置文件(/etc/hadoop/conf),例如开始遇到的JVM OOM错误就是这样解决的。如果找不到根源,可以根据错误栈,查看源代码,找到出错问题的根源来解决。

转载于:https://www.cnblogs.com/pirage/p/4043570.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值