【十大算法實現之naive bayes】朴素貝葉斯算法之文本分類算法的理解與實現


關於bayes的基礎知識,請參考:

  基於朴素貝葉斯分類器的文本聚類算法 (上) http://www.cnblogs.com/phinecos/archive/2008/10/21/1315948.html 
  基於朴素貝葉斯分類器的文本聚類算法 (下) http://www.cnblogs.com/phinecos/archive/2008/10/21/1316044.html

  算法雜貨鋪——分類算法之朴素貝葉斯分類  http://www.cnblogs.com/leoo2sk/archive/2010/09/17/naive-bayesian-classifier.html

  網上的數據源: http://archive.ics.uci.edu/ml/

  斯坦福大學公開課 :機器學習課程:朴素貝葉斯算法 http://v.163.com/movie/2008/1/7/H/M6SGF6VB4_M6SGJVV7H.html

 


P(Y|X)稱為Y的后驗概率(posterior probability),與之相對的,P(Y)稱為Y的先驗概率(prior probability)

測試集:  
7月12日電 據外電報道,在離開克里夫蘭騎士,前往邁阿密熱火為追逐冠軍4年之后,小皇帝詹姆斯宣布回家了!詹姆斯在《體育畫報》網站上以第一人稱發表了一份聲明,小皇帝決定帶着妻兒回家直到退役。 
  “我一直都相信我會回到克里夫蘭,並在那里結束自己的職業生涯,”詹姆斯說道,“只是我不知道什么時候會回去。在賽季結束后,我並沒有考慮過自由選擇權。但我現在已經有兩個兒子,我妻子又懷上了一個女孩,我開始想,如果能帶着整個家庭回到家鄉生活會是怎樣。我也看到了其他的球隊,但我從未想過離開邁阿密會去克里夫蘭以外的地方。時間過得越久,我越覺得這個想法是正確的。這個決定讓我很開心。” 
在連續四年闖入NBA總決賽並拿到兩座總冠軍之后,詹姆斯要與韋德和波什分別了。據悉,波什也在籌划離開熱火。消息源稱,就在詹姆斯宣布回歸騎士后,火箭開始籌划交易林書豪,來為波什4年8800萬美元的合同騰出薪金空間。 

 

簡述處理過程: 

1、構造bayes分類器(引用jar包); 

 

2、中文分詞處理ChineseSpliter.split(): 
7月, 12日, 電, 據外電報道, 離開, 克里夫蘭, 騎士, 前往, 邁阿密, 熱火, 追逐, 冠軍, 4年, 之后, 小皇帝, 詹姆斯, 宣布, 回家, 詹姆斯, 體育, 畫報, 網站, 第一人稱, 發表, 一份, 聲明, 小皇帝, 決定, 帶着, 妻兒, 回家, 直到, 退役, , 一直都, 相信, 我會, 回到, 克里夫蘭, 並在, 那里, 結束, 自己, 職業, 生涯, 詹姆斯, 說道, 只是, 我不, 知道, 什么時候, 會, 回去, 賽季, 結束, 我並, 沒有, 考慮, 過, 自由選擇, 權, 但我, 現在, 已經有, 兩個, 兒子, , 妻子, 懷, 上了, 一個, 女孩, , 開始, 想, 如果能, 帶着, 整個, 家庭, 回到, 家鄉, 生活會, 怎樣, 我也, 看到了, 其他, 球隊, 但我, 從未, 想過, 離開, 邁阿密, 會去, 克里夫蘭, 以外, 地方, 時間, 過得, 越久, 我, 越, 覺得, 這個, 想法, 正確, 這個, 決定, 讓我, 開心, 連續, 四年, 闖入, nba, 總決賽, 拿到, 兩座, 總, 冠軍, 之后, 詹姆斯, 要, 韋德, 波什, 分別, 據悉, 波什, 也在, 籌划, 離開, 熱火, 消息, 源, 稱, 就在, 詹姆斯, 宣布, 回歸, 騎士, 火箭, 開始, 籌划, 交易, 林書豪, 波什, 4年, 8800萬, 美元, 合同, 騰出, 薪金, 空間 


3、刪除常用停用詞: 
stopWordsList[] ={"的", "我","我們","要","自己","之","將","“","”",",","(",")","后","應","到","某","后","個","是","位","新","一","兩","在","中","或","有","更","好",""}; 

7月, 12日, 電, 據外電報道, 離開, 克里夫蘭, 騎士, 前往, 邁阿密, 熱火, 追逐, 冠軍, 4年, 之后, 小皇帝, 詹姆斯, 宣布, 回家, 詹姆斯, 體育, 畫報, 網站, 第一人稱, 發表, 一份, 聲明, 小皇帝, 決定, 帶着, 妻兒, 回家, 直到, 退役, 一直都, 相信, 我會, 回到, 克里夫蘭, 並在, 那里, 結束, 職業, 生涯, 詹姆斯, 說道, 只是, 我不, 知道, 什么時候, 會, 回去, 賽季, 結束, 我並, 沒有, 考慮, 過, 自由選擇, 權, 但我, 現在, 已經有, 兩個, 兒子, 妻子, 懷, 上了, 一個, 女孩, 開始, 想, 如果能, 帶着, 整個, 家庭, 回到, 家鄉, 生活會, 怎樣, 我也, 看到了, 其他, 球隊, 但我, 從未, 想過, 離開, 邁阿密, 會去, 克里夫蘭, 以外, 地方, 時間, 過得, 越久, 越, 覺得, 這個, 想法, 正確, 這個, 決定, 讓我, 開心, 連續, 四年, 闖入, nba, 總決賽, 拿到, 兩座, 總, 冠軍, 之后, 詹姆斯, 韋德, 波什, 分別, 據悉, 波什, 也在, 籌划, 離開, 熱火, 消息, 源, 稱, 就在, 詹姆斯, 宣布, 回歸, 騎士, 火箭, 開始, 籌划, 交易, 林書豪, 波什, 4年, 8800萬, 美元, 合同, 騰出, 薪金, 空間

 

4、步驟3執行完畢算式得到了真正的測試樣本x,根據給定的文本屬性向量在給定的分類中計算分類條件概率,先取第一個分類——IT 
根據公式P(x|C=”IT”)= P(x=”7月”|C=”IT”) * P(x=”12月”|C=”IT”)* P(x=”電”|C=”IT”) * P(x=”據外電報道”|C=”IT”) * ……*P(x=”空間”|C=”IT”)==>得到ans(因為文本屬性向量相互獨立) 

 1  /**
 2     * 計算給定的文本屬性向量X在給定的分類Cj中的類條件概率
 3     * <code>ClassConditionalProbability</code>連乘值
 4     * @param X 給定的文本屬性向量
 5     * @param Cj 給定的類別
 6     * @return 分類條件概率連乘值,即<br>
 7     */
 8     float calcProd(String[] X, String Cj) 
 9     {
10         float ret = 1.0F;
11         // 類條件概率連乘
12         for (int i = 0; i <X.length; i++)                   //步驟4
13         {
14             String Xi = X[i];
15             //因為結果過小,因此在連乘之前放大10倍,這對最終結果並無影響,因為我們只是比較概率大小而已
16             ret *=ClassConditionalProbability.calculatePxc(Xi, Cj)*zoomFactor;
17         }
18         // 再乘以先驗概率
19         ret *= PriorProbability.calculatePc(Cj);                   //步驟5
20         return ret;
21     }
P(x=”?”|C=”IT”)的計算=(給定分類中包含關鍵字/詞的訓練文本的數目)/(訓練文本集中在給定分類下的訓練文本數目+訓練文本類別) 

5、根據bayes公式,P(C=”IT”)P(x|C=”IT”)= P(C=”IT”)* ans=P((x)∩(C=”IT”)) 
P(C=”?”)的計算=(訓練文本集中在給定分類下的訓練文本數目)/(訓練文本集中所有的文本數目) 

6、重復4、5,計算出P((x)∩(C=”汽車”))、P((x)∩(C=”健康”))、P((x)∩(C=”軍事”))……最后取最大值,也就是最有可能的。
 

1、2、3屬於准備階段 
4、5、6包含了分類器的訓練階段以及利用已訓練好的分類器的應用階段 
P(C=”?”)的計算就是分類器的訓練過程,即計算先驗概率 
 
 1 /**
 2 * 先驗概率計算
 3 * P(cj)=N(C=cj)/N
 4 * 其中,N(C=cj)表示類別cj中的訓練文本數量;
 5 * N表示訓練文本集總數量。
 6 */
 7 
 8 public class PriorProbability 
 9 {
10     private static TrainingDataManager tdm =new TrainingDataManager();
11     /**
12     * 先驗概率
13     * @param c 給定的分類
14     * @return 給定條件下的先驗概率
15     */
16     public static float calculatePc(String c)
17     {
18         float ret = 0F;
19         float Nc = tdm.getTrainingFileCountOfClassification(c);     //訓練文本集中在給定分類下的訓練文本數目
20         float N = tdm.getTrainingFileCount();                            //訓練文本集中所有的文本數目
21         ret = Nc / N;
22         return ret;
23     }
24 }

訓練樣本為:TrainningSet文件夾,其中包含了各個類別的文本集。 

 


In process. 
IT:4.5137176E-26 
In process. 
體育:4.5942127E-8 
In process. 
健康:8.096193E-22 
In process. 
軍事:2.7799264E-25 
In process. 
招聘:1.828473E-23 
In process. 
教育:6.3704085E-12 
In process. 
文化:1.114498E-25 
In process. 
旅游:2.8563375E-24 
In process. 
汽車:2.0799206E-14 
In process. 
財經:4.2796716E-22 
此項屬於[體育] 

 

 

 

運行文件下載:

鏈接: http://pan.baidu.com/s/1hq88LA8 密碼: 05w3

 

 


 

 后來,又用了naive bayes做了代碼的分類,遇到了很多問題。

  • 訓練集過大,運行時間過慢

    平均800KB的文件中大約含有20000個單詞

過程簡述:
a)    已知test(待測試的文本),對其進行分詞(因為里面有很多的特殊符號和空格,所以自己寫了一個過濾的方法,星期六上午寫完了之后,給學長看了,提到了過濾的方法的不足的地方就是:我不應該把里面的全部數字都刪除,而是應該把單獨的代表量度的數字給刪除,有些單詞中包含數字作為變量名的應該保留下來);
b)    訓練分類器
c)    對test做分詞處理,並去掉停用詞
d)    正式開始進行分類操作:
i.    選取第一個分類A
ii.    獲取A類下所有文件的路徑
iii.    獲取A類下第一個文本,並將其內容全部轉化為String
iv.    從test中的第一個單詞開始判斷,是否存在與A類的第一個文本中
For(從第一個分類開始到最后一個分類)        7類
    For(從當前分類的第一個文本開始到當前分類的最后一個文本)  平均24文本,每個文本15000個單詞
  {
      For(從test的第一個單詞到test最后一個單詞)    平均有15000個單詞
    {
        If(該單詞在這個文本中)    
        {
            Ret++;
         }
    }
    P(test在當前分類的當前文本中的概率)
  }
  P(test|分類Xi)
}
復雜度為:7*24*15000*15000=3.78*(10^10)

已經不能愉快的玩耍了

 

這里,以上naive bayes分類器代碼存在的問題:

  • 需要盡可能保證每一個訓練集大小基本一致:因為后驗概率判斷的是分詞之后的單詞是否存在與訓練集某類的某個文本中,因此,文本較大的話,相對來說,
    • 可能含有單詞的概率也大,這樣,要是訓練集A類中一個文本1kb,B類中一個文本1000kb,那么,顯然是不合理的;
  • 程序耗時的問題,當處理較大訓練集的時候,就會很慢
  • 之前的中文分類需要用到中文分詞組件,而英文分詞只要根據空格和標點就可以了

 

 

解決方案:

  預處理(等於是先打表):

    利用java中的hashmap<String,Double>計算了每一類下每個單詞出現的次數,然后處理每一類的總次數(A類下B單詞出現的次數/A類單詞總數)

  之后直接讀取hashmap中的數值就好。

程序下載:鏈接: http://pan.baidu.com/s/1ntwTI4L 密碼: d9qi

 


 

費舍爾方法與貝葉斯方法的區別:

  • 貝葉斯方法: P(Category|Document)=P(Document|Category)*P(Category)/P(Document)

其中,P(Document|Category i)=P(feature 1|Category i)*P(feature 2|Category i)*......*P(feature N|Category i)

     P(Category):先驗概率

     P(Document):常量(實際計算時不考慮)

  • 費舍爾法方法:
  1. 屬於某分類的概率clf = Pr(feature | category)

     

  2. 屬於所有分類的概率freqsum = Pr(feature | category)之和

  3.  

    cprob = clf / (clf+nclf)

    P(Category i|feature 1)

  費舍爾方法的計算過程是將所有概率相乘起來,然后取自然對數,再將所得結果乘以-2。

  費舍爾方法告訴我們,如果概率彼此獨立且隨機分布,則這一計算結果將滿足對數卡方分布(chi-squared distribution)。也許我們會預料到,不屬於某個分類的內容項中,可能會包含針對該分類的不同特征概率的單詞(可能會隨機出現);或者,一個屬於該分類的內容項中會包含許多概率值很高的特征。通過將費舍爾方法的計算結果傳給倒置對數卡方函數,我們會得到一組隨機概率中的最大值。

  

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM