mahout源碼分析之貝葉斯算法

整個流程包括數據處理部分和分類算法部分。數據處理部分對語料庫進行處理生成算法能執行的標準格式。分類算法部分的實現被分作三個部分:訓練器(The Trainer)、數據模型(The Model)、分類器(The Classifier)。

數據預處理

PrepareTwentyNewsgroups

for(dir in categoryDirectorys)

BayesFileFormatter.collapse(dir,分詞器,outputdircharsetoutputfile);

 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個新聞的數據每類中的文檔數大致一樣先驗概率幾乎一樣)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章