一、数据准备
版本说明
使用的Mahout版本为apache-mahout-distribution-0.10.1
使用的Hadoop版本为hadoop-2.3.0-cdh5.0.0
分词
使用爬虫对每个URL的标题、关键词、描述进行爬取,再用中文分词工具进行分词;
(中文分词工具:http://lxw1234.com/archives/2015/07/422.htm)
最后,每个URL的分词结果生成一个文本文件,以空格分隔,如:
- url1.txt
- 四驱 旗舰版 多媒体 配置 参数 明细
- url2.txt
- 代表 四宝 厨艺 视频 烹饪 四宝 如意 金砖 富贵 骑士 视频
- url3.txt
- 体验 泰国 之旅 曼谷 高尔夫球场 球场 腾讯网 体验 泰国 之旅 曼谷 高尔夫球场 球场
- ……
将文本文件转换成SequenceFile
将前面分词后的*.txt压缩上传至Hadoop网关机,解压到一个本地目录,如/tmp/txt/
使用Mahout命令将文本文件转换成SequenceFile,同时会将这么多小文本文件合并成一个Sequence:
- cd $MAHOUT_HOME/bin
- export MAHOUT_LOCAL=true
- ./mahout seqdirectory -i file:///tmp/txt/ -o file:///home/lxw1234/txt-seq/ -c UTF-8 -chunk 64 -xm sequential
参数说明:
MAHOUT_LOCAL:指定Mahout是否以本地模式运行;如果该变量值为空,则表示在Hadoop上运行;
seqdirectory:Mahout自带的将文本文件转换成SequenceFile的命令;
-i:输入的文本文件目录;
-o:输出的SequenceFile目录;
-xm sequential:表示在本地执行,而不是用MapReduce执行;
-c UTF8:使用UTF8编码格式;
-chunk 64:64M一个chunk,也就是文件块block,应该和HDFS的块大小一致或成倍数关系;
执行成功后,在本地的/home/lxw1234/txt-seq/目录下生成了chunk-0文件,该文件格式为SequenceFile,可以用hadoop fs –text命令查看文件内容:
- hadoop fs -text file:///home/lxw1234/txt-seq/chunk-0 | more
- /url809.txt 哈弗 精英 网易 精英 图片 哈弗 精英 哈弗 精英 车厢 内饰 哈弗 精英 细节 图片 哈弗 精英 经销商 图片
-
- /url1369.txt 内饰 基本 不变 凤凰网 内饰 基本 不变
-
- /url2625.txt 浪琴 按钮 致敬 历史 传统
-
- /url2267.txt 一汽 马自达 阿特 少量
-
- /url1831.txt 广州 的哥 收入 减半 租车公司 广州 的哥 收入 广州 的哥 离职 广州
-
将文本文件转换成SequenceFile也可以自己写程序来完成,Mahout也提供了相应的API。
将转换好的SequenceFile上传至HDFS
hadoop fs -mkdir /tmp/mahout/txt-seq/
hadoop fs -put /home/lxw1234/txt-seq/chunk-0 /tmp/mahout/txt-seq/
将SequenceFile上传至HDFS的/tmp/mahout/txt-seq/目录
二、解析SequenceFile,转换成向量表示
Mahout聚类算法使用向量空间(Vectors)作为数据数据。
接下来在Hadoop上,使用之前生成的SequenceFile,转换成向量表示:
使用命令:
- cd $MAHOUT_HOME/bin
- export MAHOUT_LOCAL=
- export HADOOP_CLASSPATH=/home/lxw1234/apache-mahout-distribution-0.10.1/lib/lucene-analyzers-common-4.6.1.jar:
- /home/lxw1234/apache-mahout-distribution-0.10.1/lib/lucene-core-4.6.1.jar:$HADOOP_CLASSPATH
- ./mahout seq2sparse -i /tmp/mahout/txt-seq/ -o /tmp/mahout/txt-sparse -ow \
- --weight tfidf --maxDFPercent 90 --namedVector \
- -a org.apache.lucene.analysis.core.WhitespaceAnalyzer
参数说明:
MAHOUT_LOCAL:由于要在Hadoop上完成转换,因此,设该变量值为空;
HADOOP_CLASSPATH:加入需要的jar包到Hadoop的classpath,这两个jar包主要是mahout用来分词的;
seq2sparse:Mahout自带的解析向量的命令;
-i:输入的SequenceFile目录;
-o:输出目录;
-ow:当输出目录存在时,覆盖;
–weight tfidf:权重公式,可选的有tfidf和tf;
–maxDFPercent:过滤高频词,当DF值大于90%时候,将会被过滤掉;
–namedVector:生成的向量同时输出附加信息;
-a:指定分词器;由于Mahout本身对中文支持不好,前面已经将中文做好了分词,以空格分隔,这里指定的WhitespaceAnalyzer是以空格为分隔符的分词器;
其他可能有用的选项:
–minDF:最小DF阈值;
–minSupport:最小的支持度阈值,默认为2;
–maxNGramSize:是否创建ngram,默认为1。建议一般设定到2就够了;
–minLLR:The minimum Log Likelihood Ratio。默认为1.0。当设定了-ng > 1后,建议设置为较大的值,只过滤有意义的N-Gram。
–logNormalize:是否对输出向量做Log变换;
其他可输入命令./mahout seq2sparse –help 来查看。
在HDFS上查看解析后的结果:
- hadoop fs -ls /tmp/mahout/txt-sparse
- Found 7 items
- /tmp/mahout/txt-sparse/df-count
- /tmp/mahout/txt-sparse/dictionary.file-0
- /tmp/mahout/txt-sparse/frequency.file-0
- /tmp/mahout/txt-sparse/tf-vectors
- /tmp/mahout/txt-sparse/tfidf-vectors
- /tmp/mahout/txt-sparse/tokenized-documents
- /tmp/mahout/txt-sparse/wordcount
-
各个文件的用途:
- file-0:文件。词文本 -> 词id(int)的映射。词转化为id,这是常见做法。
- hadoop fs -text /tmp/mahout/txt-sparse/dictionary.file-0 | more
- 一发不可收拾 0
- 万元 1
- 两种 2
- 书店 3
- 书画 4
- 以上 5
- 低于 6
- 偷窥 7
- 全部 8
- 写真 9
- 前排 10
-
- df-count:目录。词id->文档频率(df);
- hadoop fs -text /tmp/mahout/txt-sparse/df-count/* | more
- 0 1
- 15 2
- 30 4
- 45 7
- 60 2
- 75 1
- 90 6
- 105 1
- 120 5
- 135 1
- 150 2
- 165 2
- 180 2
-
- hadoop fs -text /tmp/mahout/txt-sparse/frequency.file-0 | more
- 0 1
- 15 2
- 30 4
- 45 7
- 60 2
- 75 1
- 90 6
- 105 1
- 120 5
- 135 1
- 150 2
- 165 2
- 180 2
- 195 470
-
- wordcount:目录。词文本 -> 文档集词频(cf),这个应该是各种过滤处理之前的信息。
- hadoop fs -text /tmp/mahout/txt-sparse/wordcount/* | more
- 一发不可收拾 2
- 万元 220
- 两种 2
- 书店 2
- 书画 2
- 以上 2
- 低于 2
- 偷窥 3
- 全部 2
- 写真 3
- 前排 11
-
- tf-vectors、tfidf-vectors:目录。词向量,每篇文档一行,格式为{词id:特征值},其中特征值为tf或tfidf。采用了内置类型VectorWritable,需要用命令”mahout vectordump -i ”查看。
- ./mahout vectordump -i /tmp/mahout/txt-sparse/tf-vectors/ | more
- {346:1.0,208:1.0,1532:1.0,668:1.0,238:1.0}
- {390:2.0,367:1.0,844:2.0,692:2.0,952:1.0}
- {1070:1.0}
- {896:1.0,1341:1.0,434:1.0,153:6.0,195:1.0,838:1.0,1005:1.0,739:3.0,1025:1.0,1480:6.0,707:6.0}
- {896:1.0,1341:1.0,838:1.0,153:6.0,195:1.0,1480:6.0,739:3.0,707:6.0}
- {896:1.0,1341:1.0,838:1.0,153:6.0,195:1.0,1480:6.0,1005:1.0,739:3.0,707:6.0}
-
- ./mahout vectordump -i /tmp/mahout/txt-sparse/tfidf-vectors/ | more
- {346:5.210176467895508,208:4.858778476715088,1532:7.749150276184082,668:6.545177459716797,238:6.075173854827881}
- {390:7.129191875457764,367:7.749150276184082,844:11.532367706298828,692:11.532367706298828,952:7.749150276184082}
- {1070:7.749150276184082}
- {896:3.622015953063965,1341:2.697159767150879,434:7.2383246421813965,153:16.578933715820312,195:2.692904472351074,838:2.680246114730835,1005:3.03
- 6621570587158,739:4.602833271026611,1025:7.2383246421813965,1480:16.578933715820312,707:10.790275573730469}
- {896:3.622015953063965,1341:2.697159767150879,838:2.680246114730835,153:16.578933715820312,195:2.692904472351074,1480:16.578933715820312,739:4.60
- 2833271026611,707:10.790275573730469}
-
- tokenized-documents:分词后的文档。
三、运行K-Means
- cd $MAHOUT_HOME/bin
- export MAHOUT_LOCAL=
- ./mahout kmeans -i /tmp/mahout/txt-sparse/tfidf-vectors -c /tmp/mahout/txt-kmeans-clusters \
- -o /tmp/mahout/txt-kmeans -k 30 \
- -dm org.apache.mahout.common.distance.CosineDistanceMeasure -x 300 -ow --clustering
-
参数说明:
-i:输入为上面产出的tfidf向量。
-o:每一轮迭代的结果将输出在这里。
-k:几个簇,即最终聚为几个类别。
-c:若不设定k,则用这个目录里面的点,作为聚类中心点。否则,随机选择k个点,作为中心点。
-dm:距离公式,文本类型推荐用cosine距离。
-x:最大迭代次数。
–clustering:在mapreduce模式运行。
–convergenceDelta:迭代收敛阈值,默认0.5,对于Cosine来说略大。
输出1,初始随机选择的中心点;
hadoop fs -ls /tmp/mahout/txt-kmeans-clusters
Found 1 items
/tmp/mahout/txt-kmeans-clusters/part-randomSeed
输出2,聚类过程、结果:
hadoop fs -ls /tmp/mahout/txt-kmeans
Found 5 items
/tmp/mahout/txt-kmeans/_policy
/tmp/mahout/txt-kmeans/clusteredPoints
/tmp/mahout/txt-kmeans/clusters-0
/tmp/mahout/txt-kmeans/clusters-1
/tmp/mahout/txt-kmeans/clusters-2-final
其中,clusters-k(-final)为每次迭代后,簇的30个中心点的信息。
四、查看聚类结果
由于Mahout的clusterdump命令只能在本地运行,因此需要将聚类结果从HDFS下载到本地:
hadoop fs -get /tmp/mahout/txt-kmeans/ /home/lxw1234/
hadoop fs -get /tmp/mahout/txt-sparse/ /home/lxw1234/
运行命令:
- cd $MAHOUT_HOME/bin
- export MAHOUT_LOCAL=true
- ./mahout clusterdump -i /home/lxw1234/txt-kmeans/clusters-2-final \
- -d /home/lxw1234/txt-sparse/dictionary.file-0 -dt sequencefile \
- -o /home/lxw1234/txt-kmeans-cluster-dump -n 50
-
参数说明:
-i:输入最终迭代生成的簇结果。
-d:使用 词 -> 词id 映射,使得我们输出结果中,可以直接显示每个簇,权重最高的词文本,而不是词id。
-dt:上面映射类型。
-o:最终产出目录。
-n:每个簇,只输出50个权重最高的词。
看看dump出来的结果:
出来的聚类结果有些还可以,有些看上去有点不靠谱。
对Mahout的很多参数理解不够,还有待调整。