Mahout朴素无华贝叶斯文本分类

Mahout朴素贝叶斯文本分类

Mahout朴素贝叶斯文本分类算法

     Mahout贝叶斯分类器按照官方的说法,是按照《Tackling the PoorAssumptions of Naive Bayes Text Classiers》实现的。分为三个模块:训练、测试和分类。该文档首先简要介绍朴素贝叶斯的基本原理,然后介绍MapReduce实现的思路。

一、MapReduce 朴素贝叶斯算法实现

(一)预处理

     在训练和分类之前都需要将小文档合并,以及分词处理。大量的小文档会让NameNode占用太多的内存空间存储元数据,另一方面在执行MapReduce时会占用太多的Map槽。

(二)训练

      将训练数据组织成下图的结构。子文件夹的名字为类型名,子文件夹下为该类的文档。子文件夹下不能有文件夹。

      训练数据目录结构

                                                                                                       Mahout朴素无华贝叶斯文本分类                   

 

     该过程将训练数据生成model,生成三个目录:trainer-tfidf、trainer-weights和trainer-thetaNormalizer 。有四个Job完成该过程。抽取正则化的特征,计算TFIDF,计算权重和计算正则化因子。

(1)特征抽取

  输入数据格式:

clazzlable

文档内容

 


Map:

对每一篇文档分词后计算该片文档中的词频(wordcount)、、。

输出:

  (1)归一化的词频

key:<_WT,lable,token>

value :

  (2)词的文档频率

Key:  <_DF,lable,token>

Value: 1

  (3)特征数量

Key:<_FC,lable,token>

Value:1

  (4)TF

Key:<"_FF”,lable,token>

Value:wordcount

  (5)类型数

Key:<_LC,lable>

Value:1

Combiner:

    在Map计算完之后value值求和。

Reduce:

在reduce计算主要做特征选择。过滤掉小于最小词频数和最小文档数的词。

最终输出:

trainer-wordFreq,存储归一化的词频。
       trainer-termDocCount,存储文档词的文档频率。

trainer-featureCount,存储特征数量。

trainer-docCount,存储类型数量,每个类型的文档数。

(2)计算TFIDF

输入:

        trainer-termDocCount,trainer-wordFreq和trainer-featureCount文件。

     将trainer-docCount添加到configuration中。

Map:

Configure(JobConf job){

从configuration中加载trainer-docCount数据。

   }

   map(StringTupleDoubleWritable,StringTuple,DoubleWritable){

1.对于TF ,直接输出。

2.对于DF=Log(该词对应的类型的总文档数/df)。输出:Key <_WT,lable, token>   value:DF

3.对于特征总数,特征词的数量

     输出:key <_FS> ,  value 1

Reduce:

       1.对于特征集数量,求和,输出 key: <_FS>  value: 特征数

       2.对于TF和IDF。由于对同一个类型中的同一个词,hadoop会将其值合并在一起,这样reduce传入的同一key的迭代器中只有两个值,一个是TF值,一个是IDF值。计算tfidf =TF*IDF .

    输出:key <_WT,lable,token>  value :tfidf

最终输出:

   trainer-tfidf 文档,key <_WT,lable,token>  value :tfidf

(3)计算权重和

该过程为特征和类表计算权重。

输入:

trainer-tfidf文件。格式为key <_WT,label ,token> ,value <tfidf>

Map:

1.特征和,计算全局词特征权重和

     从key中拿到token 输出其tfidf值。

    输出:key <_SJ,token>   value <tfidf>

2.类型label和,计算全局类型权重和

从key中拿到label,输出其tfidf。

输出: key<_SK,label>  value <tfidf>

3.特征及label和,计算所有特征所有类型的和

 从key中拿到tfidf,输出。

输出: key <_SJSK>  value <tfidf>

Reduce:

对map的结果求和,输出。输出格式和map的一样。

(4)计算正则化因子

输入:

trainer-tfidf文件。格式为key <_WT,label ,token> ,value <tfidf>

将trainer-vocabcount 中的数据写入configuration。

Map:

setup(){

从configuration中读取trainer-vocabcount数据。

}

Map{

   对输入的每一个词

      W=Log(tfidf/(该词的类型的特征和+总特征数))

   输出:key <_LTN,label> , value<W>

}

Reduce:

  对Map结果求和。

  输出:key<_LTN,label>  value <SUM(W)>

输出:

trainer-thetaNormalizer文件.格式Key  <_LTN,label>   value <W>

(三)分类

训练好模型之后,最终会生成如下图的文档结构:

                                                                                        Mahout朴素无华贝叶斯文本分类

首先将模型信息存储到内存中,InMemoryBayesDatastore 负责。

分类时传入分好词的词数组document,InMemoryBayesDatastore 的实例,没有分出来时默认的类型名(默认为unknow)。

  public ClassifierResult classifyDocument(String[] document,

                                           Datastore datastore,

                                           String defaultCategory){

   maxWeight =Double.MAX_VALUE;

   ClassifierResult  clazz =new ClassifierResult ();

For(int i  = 0 ;i <类型总数;i++){

   Label =datastore.get(i);

   Frequency=document中计算词频

   TFIDF: 该词在当前类型中的TFIDF

   Sigma_ k 该类型的tfidf和VocabCount 总特征词个数

    Weight= frequency*log[(TFIDF +1.0) /(Sigma_ k +VocabCount)]

   If(Weight<maxWeight){

      maxWeight=Weight;

      clazz.setLable(Label);

   }

}

clazz.setScore(maxWeight);

  return  clazz;

}

在map中做分类,输出分类结果。

输入:输入文件格式:文档路径\t分词后的文档内容

Map:

setUp(){

加载模型。

}

Map(Text key,Text value){//key为文档路径  ,value为分词后的文档内容

(1)对分词后的文档内容计算N-Gram

(2)计算词频

(3)类型=classifyDocument(String[] document,

                           Datastore datastore,

                          String defaultCategory)

输出分类结果 key: 文档路径,value:类型
}

(四)测试

 测试本身就是分类后统计分类的正确率。

 测试数据的格式为:文档类型 \t 分词后的文档内容

 Map:key 正确的标签,value 分词后的文档内容

    分类后的类型标签=classifyDocument();

    输出:key <_CT,正确的标签,分类后的标签>  value  1

 Reduce:对map的value求和。

二、API

    第一部分叙述了Mahout 朴素贝叶斯分类算法的实现原理。下面叙述API的使用。在说API之前先说说文本预处理,一般来说需要训练或分类的文本都不太可能是TXT格式的,pdf、word ,html网页等等。首先要做的就是从各种格式的文件中抽取出文本。然后要将文本分词。

(一)训练

 对于训练数据,需要组织成如图的目录结构。

                                                                                                      Mahout朴素无华贝叶斯文本分类

art248 ,computer200等都是类型信息,每一类中有若干文本。各类中文本的数量保持基本一致。

每一类中都是大量的小文件,而如果需要用MapReduce做训练,需要合并小文件,组成一个或多个大文件。组合后的文件格式为:

类型名

\t

分词后的一个小文件内容

参数说明

TrainClassfier.main(args [])

--gramSize (-ng)

Ngram 个数,默认为1。5以上运算量大,存储空间多,精度提高小,建议不要使用。

--input (-i)

训练数据路径。(注意:是HDFS路径)

--output (-o)

模型输出路径。(注意:是HDFS路径)

--classifierType (-type)

分类器类型。bayes ,默认。

--dataSource (-source)

模型存储位置,默认是hdfs。实际上Mahout并没有实现其它的存储方式。

--alpha (-a)

平滑因子,默认为1。

--minDf (-mf)

最小df值,默认为1。

--minSupport (-ms)

最小tf值,默认为1。

训练后生成的文件:

(二)分类

文类数据和训练数据一样,需要抽取和分词。处理后的待分类数据存放在HDFS的一个目录下。

                                                                                         Mahout朴素无华贝叶斯文本分类                                                       


同样待分类数据再分之前也需要合并,原理同上。

合并后的文件格式(SequenceFile)为:

文件路径

\t

分词后的一个小文件内容

 

 

参数说明:

ClassifyClassifier.main(args  []);

--defaultCat (-default)

默认的类型,unknown。这种情况出现在模型数据为空。若分类数据出现unknown,需要检查模型。

--testDir (-d)

分类数据存放路径

--encoding (-e)

编码格式 (UTF-8)

--gramSize (-ng)

Ngram大小,默认为1。建议和训练的ngram值一样。

--model (-m)

模型路径

--classifierType (-type)

默认bayes.

--dataSource (-source)

默认hdfs

--method (-method)

默认MapReduce

--verbose (-v)

是否显示文档分类正确或者错误。注意:该参数在分类时作用不大,分类数据不知道原始的类型信息。

--alpha (-a)

平滑因子,默认为1。

--outputDir (-o)

分类后输出路径。

 

 















结果文件是SequenceFile,格式如下:

文件路径(Text)

类型(Text)

 

(三)测试

测试数据和训练数据的组织一样,合并后的文件格式如下:

真实类型

\t

分词后的文档内容

 

 

参数说明

TestClassifier.main(args);

--defaultCat (-default)

默认的类型,unknown。这种情况出现在模型数据为空。若分类数据出现unknown,需要检查模型。

--testDir (-d)

分类数据存放路径

--encoding (-e)

编码格式 (UTF-8)

--gramSize (-ng)

Ngram大小,默认为1。建议和训练的ngram值一样。

--model (-m)

模型路径

--classifierType (-type)

默认bayes.

--dataSource (-source)

默认hdfs

--method (-method)

默认MapReduce

--alpha (-a)

平滑因子

--verbose (-v)

是否显示分类正确或者错误。

 

 













测试结果,模糊矩阵 

                                           

                                                 Mahout朴素无华贝叶斯文本分类

三、参考文档

1.《Tackling the Poor Assumptions of Naive Bayes Text Classiers》