貝葉斯文本分類實驗

這個其實是我數據挖掘 的大作業 :

實驗原理

主要是利用樸素貝葉斯對文本進行分類,用TF-IDF 權重進行優化。

實驗流程:

1 首先下載搜狗語料庫

採用其中的五個類別,分別是,1 – 汽車2 –財經3 — 教育 IT4 — 健康5 — 體育 。其中每個分類的訓練文檔爲1000篇,測試文檔爲131篇。

2中文分詞

利用中科院的分詞軟件,對所有的文檔進行分詞。比如 第一個類別下的 10.txt 分詞後的結果存儲在1_re_10.txt 中 。 分詞結果(只列出部分):

/x /x 本報/rz 記者/n 陳雪/nr 頻/ag 實習/v 記者/n 唐翔/nr 發自/v 上海/ns

/x /x 一家/n 剛剛/d 成立/vi 兩年/m 的/ude1 網絡/n 支付/vn 公司/n ,/wd 它/rr 的/ude1 目標/n 是/vshi 成爲/v 市值/n 100億/m 美元/q 的/ude1 上市/vn 公司/n 。/wj

他的結果 後面還可以跟着詞性,後面我們我們建立詞典的時候,只用名詞。

 
  clip_image002

然後所有的訓練文檔和 測試 的文檔放在同一個目錄下,我的程序是 讀一個ls .txt的文件來決定處理哪些文件。 我採用每個分類1000-1999 作爲訓練文檔,10-140 作爲測試文檔。

對於第一個分類來說,1_re_10 到1_re_140 都是測試文檔 , 1_re_1000 到1_re_1999是訓練文檔。

3 建立詞典

對所有的文檔進行詞頻統計,並只記錄下高於某個times 的詞,然後再利用stopword.txt ,去掉一些停用詞。這樣最後得到一個 dict.txt的文件。dict.txt 的格式是 :詞 空格 詞頻,詞典一共有33845 個名詞。

 
  clip_image004

其中可以通過生成dict.txt ,可以手工判斷一些詞作爲新的停用詞放到到 stopword中去,再次運行程序 ,下次生成新的dict.txt 就可以去掉了 。

4 利用樸素貝葉斯算法對文本進行分類

bayes 算法 : 假設 d 爲任意文檔,文檔 d 用其含有的特徵詞來表示,即 d=(t

1,t2,……,tk),k 爲文檔的特徵詞數,tj表示文檔 d 中的第 j 個特徵詞,由此得到下式:

clip_image006; 其中, clip_image008 表示分類器預測特徵值在類別 cj的文檔中發生的概率。

根據貝葉斯定理:

clip_image010

由於 P ( d )對所有類來說都是常數 , 同時有C++ 浮點運算的原因,對於clip_image012 就不用乘法了clip_image014 正比於 clip_image008[1]的和 。

clip_image008[2] 表示分類cj特徵詞ti 出現的概率 ,那麼就是等於 特徵詞ti出現的頻率除以cj分類的總的詞數 。

詳見tf-idf-nb.cpp :bayes()用來訓練訓練文本,int getType(string filename ) 返回文件的類別。 下面主要介紹下主代碼區。

/*計算 P(ti| cj) count(ti) / count(cj), 該分類下的某個詞的

出現的概率 除以 該分類的總的詞的數目

因爲我各自分類取的文檔數是一定的所以 我的p(cj) = 1/N */

for(type = 0 ; type < N ; type ++ )

{

long sizeInt = bMap[type].size();

map<string ,double >::iterator iter ;

for(iter =bMap[type].begin() ; iter != bMap[type].end() ; iter ++ )

{

iter->second = (iter->second + 1.0)/( count_classify[type]) ; //這裏就是計算 clip_image008[3]

}

}

while(input >> word)

{

string rc = word.substr(0,word.find("/")) ;

//cout << rc << endl;

for(i = 0 ; i < N ; i ++) /*這個就是對測試文檔 累加在每個分類下的概率*/

{

iter = bMap[i].find(rc);

if( iter != bMap[i].end())

result[i] += iter->second;

}

}

但是 使用詞頻的方法正確率只有73%

5 利用TF-IDF 進行優化

之前使用的樸素貝葉斯,使用的是詞頻權重,這個對文本預處理的依賴性很強。然後我在網上搜索改進方法,使用TF-IDF 作爲新的權重計算方法。

clip_image017 ,就是在計算 clip_image008[4] 的時候 ,再乘上這個權重。這個IDF權重。

N 表示文檔總數,N(tk)表示包含詞 tk的文檔數。IDF 的值越大,說明包含該特徵詞的文檔越少,那麼這個特徵詞分佈得就相對集中,則這個特徵詞有可能包含更多的類別信息;相反,如果 IDF 的值比較小,則說明這個特徵詞在文檔集中分佈得相對均勻,對文檔的分類沒有多大貢獻,該詞不適合作爲分類的特徵。

相應在代碼中的修改如下表:

while(input >> word)

{

string rc = word.substr(0,word.find("/")) ;

//cout << rc << endl;

for(int i = 0 ; i < N ; i ++)

{

iter = bMap[i].find(rc);

if( iter != bMap[i].end() && dictMap.find(rc) != dictMap.end() )

{

if( weightMap.find(rc) != weightMap.end() )

result[i] += (iter->second * (log( documentN / (weightMap.find(rc)->second) ) ) ) ;

else

cout << "can not find " << rc << "in weightMap" << endl;

}

}

}

實驗結果爲:

clip_image020

這裏我用數字代表分類,一共五個類別,5 5 表示第5個類別的文檔,然後用改進後的算法計算之後的的類別。下面簡單的統計了每個分類的正確率,和整體的正確率。


原始博客地址

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