mahout源码分析之贝叶斯算法

整个流程包括数据处理部分和分类算法部分。数据处理部分对语料库进行处理生成算法能执行的标准格式。分类算法部分的实现被分作三个部分:训练器(The Trainer)、数据模型(The Model)、分类器(The Classifier)。

数据预处理

PrepareTwentyNewsgroups

for(dir in categoryDirectorys)

BayesFileFormatter.collapse(dir,分词器,outputdir,charsetoutputfile);

 dir.listFiles(new FileProcessor())

 FileProcessor.accept();

 Analyzer.tokenstream();//分词,得到tokenstream

 BayesFileFormatter.writeFile();//label\ttokens

 

org.apache.mahout.classifier.bayes.PrepareTwentyNewsgroups对数据进行预处理:遍历根目录(categoryDirectorys)下面的所有子目录,并将目录名作为类别名。对于每个子目录(存放着一个类别的数据),使用listFiles遍历所有的文件,并将文件交由FileProcessoraccpet函数处理。FileProcessor使用参数提供的分词器(如,lucence)处理每个文件,得到token序列。最后,调用writeFile函数,将每个文件的数据按照“label\ttoken token ...”的格式作为一行输出到输出文件(outputDir/labelName+".txt")

分类器训练过程

大致的执行路径:

TrainClassifier.trainNaiveBayes()

BayesDriver.runJob()

BayesFeatureDriver.runJob()

FeaturePartation//决定什么样的keyitem映射到同一reducer

FeatureLabelComparator//决定了不同item到达reducer的次序

BayesFeatureMapper

BayesFeatureReducer                       

BayesFeatureOutput//定义了reducer的输出位置

BayesTfIdfDriver.runJob()

  BayesTfIdfMapper

BayesTfIdfReducer

BayesWeightSummerDriver.runJob()

BayesWeightSummerMapper

BayesWeightSummerReducer

BayesThetaNormalizerDriver.runJob() //求贝叶斯的m-估计

BayesThetaNormalizerMapper

BayesThetaNormalizerMapper

 

每个JobMapperReducer执行的工作与输出:

BayesFeatureMapper

一行输入就是一个文档,label为该文档的标签,token为特征即文档中的单词,BayesFeatureMapper的输出为MapReducer的标准形式:keyvalue。输出的每一行在数据模型里都是一个item,如下:

WEIGHT                    key: _WT label token     value:Log[(1.0+dKJ)/∑dKJ21/2] //某文档中某单词的TF

DOCUMENT FREQUENCY        key: _DF label token     value: 1

FEATURE COUNT             key: _FC token           value: 1

FEATURE TERM FREQUENCY    key: _FF token            value: dkj 

LABEL COUNT               key: _LC label            value: 1 

 

BayesFeatureReducer

Mapper将处理相同的keyitem,并执行合并操作,并将合并的结果输出到BayesFeatureOutput类中配置的路径中。Mapper的输出可以预见每一项输出的value的意义:

LABEL_COUNT          key:_LC,label        value:label下的文档数                         

DOCUMENT_FREQUENCY  key:_DF,label,token value:label下出现token的文档数           

FEATURE_COUNT        key:_FC,token        value:出现token的文档数     

WEIGHT                key:_WT,label,token value: ∑(Log[(1.0+dKJ) /SQRT(∑dKJ2)])(即label下token的TF值    

 

BayesTfIdfMapper

根据BayesFeatureReducer输出到文件中的数据计算IDF=某类下的文档数(LABEL_COUNT/某类下出现该token的文档数(DOCUMENT_FREQUENCY)。输出如下:

WEIGHT              key: _WT,label,token  value: logidf 

WEIGHT              key: _WT,label,token  value: tf 

FEATURE_SET_SIZE   key: _FS               value: 1

 

BayesTfIdfReducer

根据Mapper输出的tf值和idf值计算TF-IDF,并统计FEATURE_SET_SIZE的总和为vocabCount并输出:

FEATURE_SET_SIZE  key: _FS               value: vocabCount

WEIGHT              key:_WT,label,token   value: TF-IDF

 

BayesWeightSummerMapper

每个Mapper统计该Mapper下所有label下某token(_SJ)的TF-IDF的值总和,某label(_SK)下所有tokenTF-IDF的值总和,以及所有label下所有tokenTF-IDF的值:

FEATURE_SUM   key: _SJ,token   value: TF-IDF

LABEL_SUM     key: _SK,label   value: TF-IDF 

TOTAL_SUM     key: _SJSK       value: TF-IDF 

 

BayesWeightSummerReducer

Reducert将各个Mapper node下相同token的值合并,求得所有数据下featurelabeltotal值,即:

FEATURE_SUM   key: _SJ,token   value: SUM(TF-IDF)

LABEL_SUM     key: _SK,label   value: SUM(TF-IDF) 

TOTAL_SUM     key: _SJSK       value: SUM(TF-IDF) 

 

BayesThetaNormalizerMapper

Mapper将求贝叶斯的m-估计,至于其必要性,以及为什么公式是这样的,详见 贝叶斯的m-估计

LABEL_THETA_NORMALIZER key: _LTN,label   value: log(( tfidf +1)/(vocabCount+SigmaK))

 

BayesThetaNormalizerReducer

将所有Mapper的数据执行合并操作

LABEL_THETA_NORMALIZER key: _LTN  label   value: SUM(log(( tfidf +1)/(vocabCount+SigmaK)))

 

分类器分类过程

分类过程有串行和并行两种实现,下面只介绍并行实现。

TestClassifier.classifyParallel()

BayesClassifierDriver.runJob()

BayesClassifierMapper.configure()

ClassifierContext.initialize();

InMemoryBayesDatastore.initialize()

//将训练模型装入datastore

BayesAlgorithm.initialize();

BayesClassifierMapper.map()

ClassifierContext.classifyDocument();

BayesAlgorithm.classifyDocument();

BayesClassifierReducer

 

BayesClassifierMapper

Mapper在初始化时运行ClassifierContext.initialize(),然后调用SequenceFileModelReaderloadModel方法将输入装入datastore。其次,运行map函数,最终调用BayesAlgorithm.classifyDocument()。对每个类别循环,调用documentWeight,先计算文档中每个词的次数生成一个Map类型的wordlist,针对wordlisteach pair计算:

∑[frequency×featureweight(datastore,label,word)]

其中featureweight函数返回log[(tfidf+1.0)/(sumLabelWeight+vocabCount)]

documenWeight返回的值是测试文档属于某类的概率的大小,即所有属性的在某类下的frequency×featureweight之和,值得注意的是sumLabelWeight是类别下权重之和与在其他类下的和值进行比较,取出最大值的label文档就属于此类,并输出:

CLASSIFIER_TUPLE  key:_CT correctLabel classifiedLabel  value:1

 

BayesClassifierReducer

合并Mapper的结果,输出:

CLASSIFIER_TUPLE  key:_CT correctLabel classifiedLabel  value:正确分类的文档数

 

 

总结:贝叶斯原理,后验概率=先验概率×条件概率。此处没有乘先验概率,直接输出为最佳label,可能是因为所用的20个新闻的数据每类中的文档数大致一样先验概率几乎一样)。

http://blog.csdn.net/cyningsun/article/details/8679989

 

你可能感兴趣的:(机器学习)