用mahout运行bayes算法进行测试新闻分类的例子

执行步骤:

  1. 数据准备

    • 将新闻文件解压后整个放到hdfs中去:

      1
      hadoop fs -put mini_newsgroups ./newsgroups
    • 将文本文件转换为序列化文件:

      1
      mahout seqdirectory -i ./newsgroups -o ./newsgroups_seq
    • 将序列化文件转换为向量化文件:

      1
      mahout seq2sparse -i ./newsgroups_seq -o ./newsgroups_vector -lnorm -nv -wt tfidf
    • 将向量数据集分为训练数据和检测数据,以随机40-60拆分

      1
      2
      3
      4
      5
      mahout split -i ./newsgroups_vector/tfidf-vectors \
      --trainingOutput ./newsgroups_train \
      --testOutput ./newsgroups_test \
      --randomSelectionPct 40 --overwrite \
      --sequenceFiles -xm sequential
  2. 训练

    • 训练朴素贝叶斯模型:
      1
      2
      mahout trainnb -i  ./newsgroups_train -el -o ./model \
      -li ./labelindex -ow -c
  3. 检验

    • 检验朴素贝叶斯模型:

      1
      2
      mahout testnb -i ./newsgroups_train -m ./model  \
      -l ./labelindex -ow -o newsgroups_result1
    • 检验模型分类效果:

      1
      2
      mahout testnb -i ./newsgroups_test -m ./model 
      -l ./labelindex -ow -o ./newsgroups_result2
  4. 打印结果

    • 将检验结果的序列化文件转换为文本文件
      1
      mahout seqdumper -i ./newsgroups_result2/part-m-00000 -o ./newsgroups.res

其中:

第1步所需的数据集从http://www.cs.cmu.edu/afs/cs/project/theo-11/www/naive-bayes.html下载

第1步生成的向量化文件的目录结构是这样的:
df-count 目录:保存着文本的频率信息
tf-vectors 目录:保存着以 TF 作为权值的文本向量
tfidf-vectors 目录:保存着以 TFIDF 作为权值的文本向量
tokenized-documents 目录:保存着分词过后的文本信息
wordcount 目录:保存着全局的词汇出现的次数
dictionary.file-0 目录:保存着这些文本的词汇表
frequcency-file-0 目录 : 保存着词汇表对应的频率信息。
来源: http://blog.csdn.net/aidayei/article/details/6674135

第3步正常运行的结果应该会看到一个矩阵,叫confision matrix,即混合矩阵,包含了分类的结果。

此外,每一个命令,可以通过加上“-h”来查看所需参数及含义,如
mahout seqdirectory -h

在此过程中我遇到的错误如下:

  1. Caused by: java.io.IOException: Task process exit with nonzero status of 1
    解决:情况不明,换了一个集群就没有这个错误了,网上有说或是hadoop的日志文件需要清除,或是日志文件夹的权限不够需要赋权限777,或是hdfs下的temp目录已满需要清除,或是内存不足需要设置hadoop参数的值或者运行命令改变java的内存限制,或是程序本身有问题。

  2. Caused by: java.io.IOException: Task process exit with nonzero status of 126
    解决:情况不明,貌似是内存不足的问题。在出现第一个问题之后换了一个集群才出现这个错误,但有时又不出现,而出现的时候我用free命令看了下,貌似内存确实在变小,但我上网一查,发现linux有个机制——内存不用白不用,因此它尽可能的cache和buffer一些数据,以方便下次使用。但实际上这些内存也是可以立刻拿来使用的。

至于为什么会出现以上提示,经上网查询得到如下结果:

通过分析hadoop 1.0.1代码,发现map/reduce task在执行的时候,hadoop系统会先把要执行的java 命令已经一些环境变量写到一个本地的sh文件taskjvm.sh中,然后使用bash -c file的方式执行这个sh脚本,如果出错当然后抛出异常,进而导致看到
Caused by: java.io.IOException: Task process exit with nonzero status of 126.
at org.apache.hadoop.mapred.TaskRunner.run(TaskRunner.java:258)
这样的错误
所以,这个exitcode实际就是bash执行时的推出代码,bash的exitcode是有特殊含义的,通过google可以知道126表明是permission的问题,具体为啥是这样的,不是很清楚了~~

上面的那个文件在创建的是权限是700(rwx——), 而这个文件在执行的过程中又被以setsid的方式exec,会不会这中间有些permission上的问题那~~~ 源码里说了,这样做是为了防止special character attacks

好吧水平有限,看不出来这里有什么竞争条件导致出现那样的错误

bash的退出码含义可以在下面的地方查到
http://tldp.org/LDP/abs/html/exitcodes.html

这个问题可以修改hadoop源码DefaultTaskControl加入重试机制,或者对task启用reuse=-1得到缓解(reuse和非reuse执行逻辑不一样),因为涉及到文件系统,不太容易根治。
来源: http://hi.baidu.com/liusc/item/e54bcd1778ded225f7625c4e

小鹏 wechat
公众号:数据Man
0%