一、算法說明
- 為了便於計算類條件概率\(P(x|c)\),朴素貝葉斯算法作了一個關鍵的假設:對已知類別,假設所有屬性相互獨立。
- 當使用訓練完的特征向量對新樣本進行測試時,由於概率是多個很小的相乘所得,可能會出現下溢出,故對乘積取自然對數解決這個問題。
- 在大多數朴素貝葉斯分類器中計算特征向量時采用的都是詞集模型,即將每個詞的出現與否作為一個特征。而在該分類器中采用的是詞袋模型,即文檔中每個詞匯的出現次數作為一個特征。
- 當新樣本中有某個詞在原訓練詞中沒有出現過,會使得概率為0,故使用拉普拉斯平滑處理技術解決這一問題。對應公式如下:
二、數據源
在該模型中,所用到的訓練數據和測試數據均來自於搜狗分類語料庫,並選擇了體育類、財經類和教育類這三種新聞的各40個樣本,以作為該多分類器的輸入數據。
三、中文分詞
為了對文本完成分詞,對於英文文本而言,只需要簡單得利用str.split(" ")
,用空格對整個英文文本進行切割即可。而對於中文文本而言就相對復雜了點,因為在中文文本中,往往包含了中文、英文、數字、標點符號等多種字符,此外中文中常常是多個詞組連接起來組成一個句子,所以也無法類似英文那樣簡單利用某個符號進行分割。為了完成中文文本的分詞,使用了如下的文本過濾算法:
stopWords = open("stop_words.txt", encoding='UTF-8').read().split("\n")
def textParse(inputData):
import re
global stopWords
inputData = "".join(re.findall(u'[\u4e00-\u9fa5]+', inputData))
wordList = "/".join(jieba.cut(inputData))
listOfTokens = wordList.split("/")
return [tok for tok in listOfTokens if (tok not in stopWords and len(tok) >= 2)]
- 利用正則表達式
u'[\u4e00-\u9fa5]+'
過濾掉輸入數據中的所有非中文字符; - 在Python下,有個中文分詞組件叫做jieba,可以很好得完成對中文文本的分詞。在這里便是利用jieba中的cut函數
"/".join(jieba.cut(inputData))
完成對中文的分詞,並且以“/”作為分隔符。 - 在中文文本中,存在在大量的停用詞,這些停用詞對於表示一個類別的特征沒有多少貢獻,因此必需過濾掉輸入數據中的停用詞。這里所用到的stop_words.txt ,包含了1598個停用詞,利用
tok not in stopWords
過濾掉輸入數據中的停用詞。 - 在利用jieba完成分詞后,往往會存在大量長度為1的詞(不在停用詞表里),這些詞對特征表示同樣貢獻不大,利用
len(tok) >= 2
將其過濾掉。
通過以上過程,便完成了中文文本的分詞。分詞結果如下:
四、分類結果
為了對分類器的泛化誤差進行評估,遂使用留存交叉驗證法,即從輸入的40 * 3共120個樣本中,隨機選中20個樣本作為測試數據,其他100個樣本作為訓練數據,以此來測定泛化誤差。
經過10次測試,得到分類器的泛化誤差為:(0.1 + 0.0 + 0.1 + 0.1 = 0.0 + 0.05 + 0.1 + 0.15 + 0.1 + 0.25)/ 10 = 0.095
,可見該中分多分類器在新樣本上的表現還是很好的。其中部分分類結果如下所示: