Mahout 中文分类 (1)

来源:互联网 发布:二维字符串数组 编辑:程序博客网 时间:2024/06/05 02:25

更好的排版请转到我的博客,原文链接:http://zaumreit.me/blog/2013/12/15/mahout-chinese-classification/

==================================

之前汇聚了 10w 条左右的食品安全相关的新闻网页,但是这里有一部分数据是跟视食品安全不相关的,所以需要用一个分类器训练出一个二分类模型,然后对所有数据进行二分类。

刚开始用了 fudannlp 提供的分类接口直接对训练集进行训练,然后利用模型测试,测试结果惨不忍睹,怀疑是分类器用错了。然后就打算用 mahout 试一试。

Mahout 的中文文档分类的资料比较少,看了几篇网上的博客,差点被坑到死,真是不能多说!接下来把这两天摸索的过程以及出错的环节总结一下,以免以后再用的时候再被坑到死。

部署环境

1.安装 Hadoop

Mahout 很多算法都是 map-reduce 模型,所以要在 Hadoop 上跑。

我用的版本是 Hadoop-1.2.1,hadoop 安装过程不要看别的博客,只要参考官方文档就可以Hadoop Single Node Setup。

2.安装 Maven

Maven 用于编译源代码并构建可执行的程序,对 Maven 没有做深入了解。

我用的版本是 maven-3.1.1,从官网下载 Maven,解压之后,在 PATH 环境变量里添加 maven 目录下的 /bin/ 目录就安装完成了。

3.安装 Mahout

我用的版本是 mahout-0.8,根据 Building Mahout 安装。我是在 mahout 根目录下执行的 mvn install,跑了很长时间,中间没有出错,不知道出错了会是什么样的情况。

可以把 mahout 的 /bin/ 目录也添加到 PATH 环境变量里,这样省很多事儿,不用每次都敲路径来执行 mahout。

用 Mahout 中文分类

使用 Mahout

mahout 根目录下有个 examples/bin 目录,这里有很多例子。看看这些 shell 脚本 大概就知道如何简单地使用 mahout 了。

如果在使用 mahout 的过程中需要用到外部的 jar包,可以把 jar包 放到 mahout 根目录下的/mahout-0.8/examples/target/dependency/ 目录里,运行 mahout 的时候自动会把这个目录下的所有 jar包 添加到 CLASSPATH 里。打开 mahout 的执行文件,在 158 行,会有一段代码:

123
for f in $MAHOUT_HOME/examples/target/dependency/*.jar; do  CLASSPATH=${CLASSPATH}:$f;done

中文分类

分词

mahout 默认的分词器不支持中文分词,所以要用其他的方法先对中文文档进行分词。网上有人用庖丁解牛 作为分词器,但是我尝试各种方法,在执行 mahout 时总是会有 ClassNotFound 异常,后来就先用 fudannlp 的分词工具对文档进行分词并输出到文件,然后用这些分词后的作为 mahout 最开始的输入。

mahout 最初的样例文件的组织方式是将每一个类别样例文件放到同一个文件夹里,然后多个类别文件夹放在同一个目录下作为输入。

运行 mahout 的步骤

首先,要确保 Hadoop 已经运行起来。我在 hdfs 上建了一个目录 /home/jfb/mahout-dirs,用来存放分类过程中生成的文件。

对具体的参数我还不太清楚,所以就不介绍了。

第一步
mahout seqdirectory:这是把输入的文本文件转换成 sequenceFile文件,sequenceFile 是二进制存储的 key-value形式的文件。

完整的执行命令:

1
mahout seqdirectory -i ~/mahout-dirs/training-data -o ~/mahout-dirs/seq -ow -xm sequential

~/mahout-dirs/training-data 可以是本地目录,也可以是 hdfs 上的目录,为了不出错,我直接上传到了 hdfs 上,而 ~/mahout-dirs/seq 就是 hdfs 上的目录了。以后的命令用到的输入输出目录都是 hdfs 上的目录。

在 hdfs 上 ~/mahout-dirs/seq 目录下会生成一个 chunk-0 的文件,如果没有,就是没执行成功。

第二步
mahout seq2sparse:对 sequenceFile 进行向量化。

完整的执行命令:

1
mahout seq2sparse -i ~/mahout-dirs/seq -o ~/mahout-dirs/vectors -lnorm -nv -wt tfidf -a org.apache.lucene.analysis.core.WhitespaceAnalyzer

最后一个参数是修改了默认的分词器,因为之前已经对文档进行过分词,词与词之间是用空格分开的(就像英文是用空格分开的一样),在向量化的时候就用 WhitespaceAnalyzer,当然也可以用自定义的 Analyzer,但必须是从 lucene 继承过来的。比如:庖丁解牛

第三部
mahout split:把向量化的文件随机分成两部分,一部分用来训练模型,另一部分用来测试。

完整的执行命令:

1
mahout split -i ~/mahout-dirs/vectors/tfidf-vectors --trainingOutput ~/mahout-dirs/train-vectors --testOutput ~/mahout-dirs/test-vectors --randomSelectionPct 40 --overwrite --sequenceFiles -xm sequential

第四步
mahout trainnb:用第三步随机分割的训练数据作为 Naive Bayesian 的输入进行训练并生成模型。我在这一步被坑了好长时间,运行时抛一个 java.lang.IllegalArgumentException: Wrong numLabels: 0. Must be > 0! 异常,找了好长时间才发现,生成的 labelindex 文件是错的!

完整的执行命令:

1
mahout trainnb -i ~/mahout-dirs/train-vectors/ -el -o ~/mahout-dirs/model -li ~/mahout-dirs/labelindex -ow -c

如果这一步出现错误了,去看一下 labelindex 的内容,用 mahout seqdumper -i ~/mahout-dirs/labelindex -o ~/tmp.txt 我是二分类(nev类和pos类),所以是下面这个样子:

12345
Input Path: /home/jfb/mahout-dirs/labelindexKey class: class org.apache.hadoop.io.Text Value Class: class org.apache.hadoop.io.IntWritableKey: nev: Value: 0Key: pos: Value: 1Count: 2

如果不是这个样子,可能就是出错的原因了。

第五步
mahout testnb:用第三步的测试数据作为输入进行测试。

完整的执行命令:

1
mahout testnb -i ~/mahout-dirs/test-vectors/ -m ~/mahout-dirs/model -l ~/mahout-dirs/labelindex -ow -o ~/mahout-dirs/result -c

运行成功后会是这个样子:

测试结果测试结果

总结

试错了整整两天,才运行起来,期间出现了 hadoop 错误,由于经验不足,很难定位是 hadoop 错误。希望这篇文章能帮助刚开始用 mahout 做中文分类的人吧。

0 0