機器學習經典演算法之樸素貝葉斯分類

程式設計師姜小白發表於2019-06-22
很多人都聽說過貝葉斯原理,在哪聽說過?基本上是在學概率統計的時候知道的。有些人可能會說,我記不住這些概率論的公式,沒關係,我儘量用通俗易懂的語言進行講解。

/*請尊重作者勞動成果,轉載請標明原文連結:*/

/* https://www.cnblogs.com/jpcflyer/p/11069659.html  * /

貝葉斯原理是英國數學家托馬斯·貝葉斯提出的。貝葉斯是個很神奇的人,他的經歷類似梵高。生前沒有得到重視,死後,他寫的一篇關於歸納推理的論文被朋友翻了出來,並發表了。這一發表不要緊,結果這篇論文的思想直接影響了接下來兩個多世紀的統計學,是科學史上著名的論文之一。
貝葉斯原理跟我們的生活聯絡非常緊密。舉個例子,如果你看到一個人總是花錢,那麼會推斷這個人多半是個有錢人。當然這也不是絕對,也就是說,當你不能準確預知一個事物本質的時候,你可以依靠和事物本質相關的事件來進行判斷,如果事情發生的頻次多,則證明這個屬性更有可能存在。    
 
一、 貝葉斯原理
貝葉斯原理是怎麼來的呢?貝葉斯為了解決一個叫“逆向概率”問題寫了一篇文章,嘗試解答在沒有太多可靠證據的情況下,怎樣做出更符合數學邏輯的推測。
 
什麼是“逆向概率”呢?
所謂“逆向概率”是相對“正向概率”而言。正向概率的問題很容易理解,比如我們已經知道袋子裡面有 N 個球,不是黑球就是白球,其中 M 個是黑球,那麼把手伸進去摸一個球,就能知道摸出黑球的概率是多少。但這種情況往往是上帝視角,即瞭解了事情的全貌再做判斷。
在現實生活中,我們很難知道事情的全貌。貝葉斯則從實際場景出發,提了一個問題:如果我們事先不知道袋子裡面黑球和白球的比例,而是通過我們摸出來的球的顏色,能判斷出袋子裡面黑白球的比例麼?
正是這樣的一個問題,影響了接下來近 200 年的統計學理論。這是因為,貝葉斯原理與其他統計學推斷方法截然不同,它是建立在主觀判斷的基礎上:在我們不瞭解所有客觀事實的情況下,同樣可以先估計一個值,然後根據實際結果不斷進行修正。
我們用一個題目來體會下:假設有一種病叫做“貝葉死”,它的發病率是萬分之一,即 10000 人中會有 1 個人得病。現有一種測試可以檢驗一個人是否得病的準確率是 99.9%,它的誤報率是 0.1%,那麼現在的問題是,如果一個人被查出來患有“葉貝死”,實際上患有的可能性有多大?
你可能會想說,既然查出患有“貝葉死”的準確率是 99.9%,那是不是實際上患“貝葉死”的概率也是 99.9% 呢?實際上不是的。你自己想想,在 10000 個人中,還存在 0.1% 的誤查的情況,也就是 10 個人沒有患病但是被診斷成陽性。當然 10000 個人中,也確實存在一個患有貝葉死的人,他有 99.9% 的概率被檢查出來。所以你可以粗算下,患病的這個人實際上是這 11 個人裡面的一員,即實際患病比例是 1/11≈9%。
上面這個例子中,實際上涉及到了貝葉斯原理中的幾個概念:
 
先驗概率
通過經驗來判斷事情發生的概率,比如說“貝葉死”的發病率是萬分之一,就是先驗概率。再比如南方的梅雨季是 6-7 月,就是通過往年的氣候總結出來的經驗,這個時候下雨的概率就比其他時間高出很多。
 
後驗概率
後驗概率就是發生結果之後,推測原因的概率。比如說某人查出來了患有“貝葉死”,那麼患病的原因可能是 A、B 或 C。患有“貝葉死”是因為原因 A 的概率就是後驗概率。它是屬於條件概率的一種。
 
條件概率
事件 A 在另外一個事件 B 已經發生條件下的發生概率,表示為 P(A|B),讀作“在 B 發生的條件下 A 發生的概率”。比如原因 A 的條件下,患有“貝葉死”的概率,就是條件概率。
 
似然函式(likelihood function)
你可以把概率模型的訓練過程理解為求引數估計的過程。舉個例子,如果一個硬幣在 10 次拋落中正面均朝上。那麼你肯定在想,這個硬幣是均勻的可能性是多少?這裡硬幣均勻就是個引數,似然函式就是用來衡量這個模型的引數。似然在這裡就是可能性的意思,它是關於統計引數的函式。
介紹完貝葉斯原理中的這幾個概念,我們再來看下貝葉斯原理,實際上貝葉斯原理就是求解後驗概率,我們假設:A 表示事件 “測出為陽性”, 用 B1 表示“患有貝葉死”, B2 表示“沒有患貝葉死”。根據上面那道題,我們可以得到下面的資訊。
患有貝葉死的情況下,測出為陽性的概率為 P(A|B1)=99.9%,沒有患貝葉死,但測出為陽性的概率為 P(A|B2)=0.1%。另外患有貝葉死的概率為 P(B1)=0.01%,沒有患貝葉死的概率 P(B2)=99.99%。
那麼我們檢測出來為陽性,而且是貝葉死的概率 P(B1,A)=P(B1)*P(A|B1)=0.01%*99.9%=0.00999%。
這裡 P(B1,A) 代表的是聯合概率,同樣我們可以求得 P(B2,A)=P(B2)*P(A|B2)=99.99%*0.1%=0.09999%。
然後我們想求得是檢查為陽性的情況下,患有貝葉死的概率,也即是 P(B1|A)。
所以檢查出陽性,且患有貝葉死的概率為:
檢查出是陽性,但沒有患有貝葉死的概率為:
這裡我們能看出來 0.01%+0.1% 均出現在了 P(B1|A) 和 P(B2|A) 的計算中作為分母。我們把它稱之為論據因子,也相當於一個權值因子。
其中 P(B1)、P(B2) 就是先驗概率,我們現在知道了觀測值,就是被檢測出來是陽性,來求患貝葉死的概率,也就是求後驗概率。求後驗概率就是貝葉斯原理要求的,基於剛才求得的 P(B1|A),P(B2|A),我們可以總結出貝葉斯公式為:
由此,我們可以得出通用的貝葉斯公式:
 
 
 
樸素貝葉斯
講完貝葉斯原理之後,我們再來看下今天重點要講的演算法,樸素貝葉斯。 它是一種簡單但極為強大的預測建模演算法 。之所以稱為樸素貝葉斯,是因為它假設每個輸入變數是獨立的。這是一個強硬的假設,實際情況並不一定,但是這項技術對於絕大部分的複雜問題仍然非常有效。
 
樸素貝葉斯模型由兩種型別的概率組成:
每個 類別的概率 P(Cj);
每個屬性的 條件概率 P(Ai|Cj)。
 
我來舉個例子說明下什麼是類別概率和條件概率。假設我有 7 個棋子,其中 3 個是白色的,4 個是黑色的。那麼棋子是白色的概率就是 3/7,黑色的概率就是 4/7,這個就是類別概率。
假設我把這 7 個棋子放到了兩個盒子裡,其中盒子 A 裡面有 2 個白棋,2 個黑棋;盒子 B 裡面有 1 個白棋,2 個黑棋。那麼在盒子 A 中抓到白棋的概率就是 1/2,抓到黑棋的概率也是 1/2,這個就是條件概率,也就是在某個條件(比如在盒子 A 中)下的概率。
在樸素貝葉斯中,我們要統計的是屬性的條件概率,也就是假設取出來的是白色的棋子,那麼它屬於盒子 A 的概率是 2/3。
為了訓練樸素貝葉斯模型,我們需要先給出訓練資料,以及這些資料對應的分類。那麼上面這兩個概率,也就是類別概率和條件概率。他們都可以從給出的訓練資料中計算出來。一旦計算出來,概率模型就可以使用貝葉斯原理對新資料進行預測。
 
另外我想告訴你的是,貝葉斯原理、貝葉斯分類和樸素貝葉斯這三者之間是有區別的。
貝葉斯原理是最大的概念,它解決了概率論中“逆向概率”的問題,在這個理論基礎上,人們設計出了貝葉斯分類器,樸素貝葉斯分類是貝葉斯分類器中的一種,也是最簡單,最常用的分類器。樸素貝葉斯之所以樸素是因為它假設屬性是相互獨立的,因此對實際情況有所約束,如果屬性之間存在關聯,分類準確率會降低。不過好在對於大部分情況下,樸素貝葉斯的分類效果都不錯。
 
 
二、 樸素貝葉斯分類工作原理
樸素貝葉斯分類是常用的貝葉斯分類方法。我們日常生活中看到一個陌生人,要做的第一件事情就是判斷 TA 的性別,判斷性別的過程就是一個分類的過程。根據以往的經驗,我們通常會從身高、體重、鞋碼、頭髮長短、服飾、聲音等角度進行判斷。這裡的“經驗”就是一個訓練好的關於性別判斷的模型,其訓練資料是日常中遇到的各式各樣的人,以及這些人實際的性別資料。
 
離散資料案例
我們遇到的資料可以分為兩種,一種是離散資料,另一種是連續資料。那什麼是離散資料呢?離散就是不連續的意思,有明確的邊界,比如整數 1,2,3 就是離散資料,而 1 到 3 之間的任何數,就是連續資料,它可以取在這個區間裡的任何數值。
我以下面的資料為例,這些是根據你之前的經驗所獲得的資料。然後給你一個新的資料:身高“高”、體重“中”,鞋碼“中”,請問這個人是男還是女?
針對這個問題,我們先確定一共有 3 個屬性,假設我們用 A 代表屬性,用 A1, A2, A3 分別為身高 = 高、體重 = 中、鞋碼 = 中。一共有兩個類別,假設用 C 代表類別,那麼 C1,C2 分別是:男、女,在未知的情況下我們用 Cj 表示。
那麼我們想求在 A1、A2、A3 屬性下,Cj 的概率,用條件概率表示就是 P(Cj|A1A2A3)。根據上面講的貝葉斯的公式,我們可以得出:
因為一共有 2 個類別,所以我們只需要求得 P(C1|A1A2A3) 和 P(C2|A1A2A3) 的概率即可,然後比較下哪個分類的可能性大,就是哪個分類結果。
在這個公式裡,因為 P(A1A2A3) 都是固定的,我們想要尋找使得 P(Cj|A1A2A3) 的最大值,就等價於求 P(A1A2A3|Cj)P(Cj) 最大值。
我們假定 Ai 之間是相互獨立的,那麼: P(A1A2A3|Cj)=P(A1|Cj)P(A2|Cj)P(A3|Cj)
然後我們需要從 Ai 和 Cj 中計算出 P(Ai|Cj) 的概率,帶入到上面的公式得出 P(A1A2A3|Cj),最後找到使得 P(A1A2A3|Cj) 最大的類別 Cj。
我分別求下這些條件下的概率:
P(A1|C1)=1/2, P(A2|C1)=1/2, P(A3|C1)=1/4,P(A1|C2)=0, P(A2|C2)=1/2, P(A3|C2)=1/2,所以 P(A1A2A3|C1)=1/16, P(A1A2A3|C2)=0。
因為 P(A1A2A3|C1)P(C1)>P(A1A2A3|C2)P(C2),所以應該是 C1 類別,即男性。
 
連續資料案例
實際生活中我們得到的是連續的數值,比如下面這組資料:
那麼如果給你一個新的資料,身高 180、體重 120,鞋碼 41,請問該人是男是女呢?
公式還是上面的公式,這裡的困難在於,由於身高、體重、鞋碼都是連續變數,不能採用離散變數的方法計算概率。而且由於樣本太少,所以也無法分成區間計算。怎麼辦呢?
這時,可以假設男性和女性的身高、體重、鞋碼都是正態分佈,通過樣本計算出均值和方差,也就是得到正態分佈的密度函式。有了密度函式,就可以把值代入,算出某一點的密度函式的值。比如,男性的身高是均值 179.5、標準差為 3.697 的正態分佈。所以男性的身高為 180 的概率為 0.1069。怎麼計算得出的呢? 你可以使用 EXCEL 的 NORMDIST(x,mean,standard_dev,cumulative) 函式,一共有 4 個引數:
x:正態分佈中,需要計算的數值;
Mean:正態分佈的平均值;
Standard_dev:正態分佈的標準差;
Cumulative:取值為邏輯值,即 False 或 True。它決定了函式的形式。當為 TRUE 時,函式結果為累積分佈;為 False 時,函式結果為概率密度。
這裡我們使用的是 NORMDIST(180,179.5,3.697,0)=0.1069。
同理我們可以計算得出男性體重為 120 的概率為 0.000382324,男性鞋碼為 41 號的概率為 0.120304111。
所以我們可以計算得出:
P(A1A2A3|C1)=P(A1|C1)P(A2|C1)P(A3|C1)=0.1069*0.000382324* 0.120304111=4.9169e-6
同理我們也可以計算出來該人為女的可能性:
P(A1A2A3|C2)=P(A1|C2)P(A2|C2)P(A3|C2)=0.00000147489* 0.015354144* 0.120306074=2.7244e-9
很明顯這組資料分類為男的概率大於分類為女的概率。
當然在 Python 中,有第三方庫可以直接幫我們進行上面的操作,這個我們會在下文中介紹。這裡主要是給你講解下具體的運算原理。
 
三、樸素貝葉斯分類器工作流程
樸素貝葉斯分類常用於文字分類,尤其是對於英文等語言來說,分類效果很好。它常用於垃圾文字過濾、情感預測、推薦系統等。
樸素貝葉斯分類器需要三個流程,我來給你一一講解下這幾個流程。
第一階段:準備階段
在這個階段我們需要確定特徵屬性,比如上面案例中的“身高”、“體重”、“鞋碼”等,並對每個特徵屬性進行適當劃分,然後由人工對一部分資料進行分類,形成訓練樣本。
這一階段是整個樸素貝葉斯分類中唯一需要人工完成的階段,其質量對整個過程將有重要影響,分類器的質量很大程度上由特徵屬性、特徵屬性劃分及訓練樣本質量決定。
第二階段:訓練階段
這個階段就是生成分類器,主要工作是計算每個類別在訓練樣本中的出現頻率及每個特徵屬性劃分對每個類別的條件概率。
輸入是特徵屬性和訓練樣本,輸出是分類器。
第三階段:應用階段
這個階段是使用分類器對新資料進行分類。輸入是分類器和新資料,輸出是新資料的分類結果。
好了,在這次課中你瞭解了概率論中的貝葉斯原理,樸素貝葉斯的工作原理和工作流程,也對樸素貝葉斯的強大和限制有了認識。下一節中,我將帶你實戰,親自掌握 Python 中關於樸素貝葉斯分類器工具的使用。
 
四、 sklearn 機器學習包
接下來帶你一起使用樸素貝葉斯做下文件分類的專案,最重要的工具就是 sklearn 這個機器學習神器。
sklearn 的全稱叫 Scikit-learn,它給我們提供了 3 個樸素貝葉斯分類演算法,分別是高斯樸素貝葉斯(GaussianNB)、多項式樸素貝葉斯(MultinomialNB)和伯努利樸素貝葉斯(BernoulliNB)。
 
這三種演算法適合應用在不同的場景下,我們應該根據特徵變數的不同選擇不同的演算法:
高斯樸素貝葉斯 :特徵變數是連續變數,符合高斯分佈,比如說人的身高,物體的長度。
多項式樸素貝葉斯 :特徵變數是離散變數,符合多項分佈,在文件分類中特徵變數體現在一個單詞出現的次數,或者是單詞的 TF-IDF 值等。
伯努利樸素貝葉斯 :特徵變數是布林變數,符合 0/1 分佈,在文件分類中特徵是單詞是否出現。
伯努利樸素貝葉斯是以檔案為粒度,如果該單詞在某檔案中出現了即為 1,否則為 0。而多項式樸素貝葉斯是以單詞為粒度,會計算在某個檔案中的具體次數。而高斯樸素貝葉斯適合處理特徵變數是連續變數,且符合正態分佈(高斯分佈)的情況。比如身高、體重這種自然界的現象就比較適合用高斯樸素貝葉斯來處理。而文字分類是使用多項式樸素貝葉斯或者伯努利樸素貝葉斯。
 
什麼是 TF-IDF 值呢?
我在多項式樸素貝葉斯中提到了“詞的 TF-IDF 值”,如何理解這個概念呢?
TF-IDF 是一個統計方法,用來評估某個詞語對於一個檔案集或文件庫中的其中一份檔案的重要程度。
TF-IDF 實際上是兩個片語 Term Frequency 和 Inverse Document Frequency 的總稱,兩者縮寫為 TF 和 IDF,分別代表了詞頻和逆向文件頻率
詞頻 TF 計算了一個單詞在文件中出現的次數,它認為一個單詞的重要性和它在文件中出現的次數呈正比。
逆向文件頻率 IDF ,是指一個單詞在文件中的區分度。它認為一個單詞出現在的文件數越少,就越能通過這個單詞把該文件和其他文件區分開。IDF 越大就代表該單詞的區分度越大。
所以 TF-IDF 實際上是詞頻 TF 和逆向文件頻率 IDF 的乘積 。這樣我們傾向於找到 TF 和 IDF 取值都高的單詞作為區分,即這個單詞在一個文件中出現的次數多,同時又很少出現在其他文件中。這樣的單詞適合用於分類。
TF-IDF 如何計算
首先我們看下詞頻 TF 和逆向文件概率 IDF 的公式。
為什麼 IDF 的分母中,單詞出現的文件數要加 1 呢?因為有些單詞可能不會存在文件中,為了避免分母為 0,統一給單詞出現的文件數都加 1。
TF-IDF=TF*IDF。
你可以看到,TF-IDF 值就是 TF 與 IDF 的乘積, 這樣可以更準確地對文件進行分類。比如“我”這樣的高頻單詞,雖然 TF 詞頻高,但是 IDF 值很低,整體的 TF-IDF 也不高。
我在這裡舉個例子。假設一個資料夾裡一共有 10 篇文件,其中一篇文件有 1000 個單詞,“this”這個單詞出現 20 次,“bayes”出現了 5 次。“this”在所有文件中均出現過,而“bayes”只在 2 篇文件中出現過。我們來計算一下這兩個詞語的 TF-IDF 值。
針對“this”,計算 TF-IDF 值:
所以 TF-IDF=0.02*(-0.0414)=-8.28e-4。
針對“bayes”,計算 TF-IDF 值:
 
很明顯“bayes”的 TF-IDF 值要大於“this”的 TF-IDF 值。這就說明用“bayes”這個單詞做區分比單詞“this”要好。
如何求 TF-IDF
在 sklearn 中我們直接使用 TfidfVectorizer 類,它可以幫我們計算單詞 TF-IDF 向量的值。在這個類中,取 sklearn 計算的對數 log 時,底數是 e,不是 10。
下面我來講下如何建立 TfidfVectorizer 類。
TfidfVectorizer 類的建立:
建立 TfidfVectorizer 的方法是:
1 TfidfVectorizer(stop_words=stop_words, token_pattern=token_pattern)
我們在建立的時候,有兩個構造引數,可以自定義停用詞 stop_words 和規律規則 token_pattern。需要注意的是傳遞的資料結構,停用詞 stop_words 是一個列表 List 型別,而過濾規則 token_pattern 是正規表示式。
什麼是停用詞?停用詞就是在分類中沒有用的詞,這些詞一般詞頻 TF 高,但是 IDF 很低,起不到分類的作用。為了節省空間和計算時間,我們把這些詞作為停用詞 stop words,告訴機器這些詞不需要幫我計算。
當我們建立好 TF-IDF 向量型別時,可以用 fit_transform 幫我們計算,返回給我們文字矩陣,該矩陣表示了每個單詞在每個文件中的 TF-IDF 值。
在我們進行 fit_transform 擬合模型後,我們可以得到更多的 TF-IDF 向量屬性,比如,我們可以得到詞彙的對應關係(字典型別)和向量的 IDF 值,當然也可以獲取設定的停用詞 stop_words。
舉個例子,假設我們有 4 個文件:
文件 1:this is the bayes document;
文件 2:this is the second second document;
文件 3:and the third one;
文件 4:is this the document。
現在想要計算文件裡都有哪些單詞,這些單詞在不同文件中的 TF-IDF 值是多少呢?
首先我們建立 TfidfVectorizer 類:
1 from sklearn.feature_extraction.text import TfidfVectorizer
2 tfidf_vec = TfidfVectorizer()
然後我們建立 4 個文件的列表 documents,並讓建立好的 tfidf_vec 對 documents 進行擬合,得到 TF-IDF 矩陣:
1 documents = [
2     'this is the bayes document',
3     'this is the second second document',
4     'and the third one',
5     'is this the document'
6 ]
7 tfidf_matrix = tfidf_vec.fit_transform(documents)
輸出文件中所有不重複的詞:
1 print('不重複的詞:', tfidf_vec.get_feature_names())

執行結果

1 不重複的詞: ['and', 'bayes', 'document', 'is', 'one', 'second', 'the', 'third', 'this']
輸出每個單詞對應的 id 值:
1 print('每個單詞的 ID:', tfidf_vec.vocabulary_)
執行結果
1 每個單詞的 ID: {'this': 8, 'is': 3, 'the': 6, 'bayes': 1, 'document': 2, 'second': 5, 'and': 0, 'third': 7, 'one': 4}
輸出每個單詞在每個文件中的 TF-IDF 值,向量裡的順序是按照詞語的 id 順序來的:
1 print('每個單詞的 tfidf 值:', tfidf_matrix.toarray())
執行結果:
1 每個單詞的 tfidf 值: [[0.         0.63314609 0.40412895 0.40412895 0.         0.
2   0.33040189 0.         0.40412895]
3 [0.         0.         0.27230147 0.27230147 0.         0.85322574
4   0.22262429 0.         0.27230147]
5 [0.55280532 0.         0.         0.         0.55280532 0.
6   0.28847675 0.55280532 0.        ]
7 [0.         0.         0.52210862 0.52210862 0.         0.
8   0.42685801 0.         0.52210862]]
 
五、 如何對文件進行分類
如果我們要對文件進行分類,有兩個重要的階段:
1.基於分詞的資料準備 ,包括分詞、單詞權重計算、去掉停用詞;
2.應用樸素貝葉斯分類進行分類 ,首先通過訓練集得到樸素貝葉斯分類器,然後將分類器應用於測試集,並與實際結果做對比,最終得到測試集的分類準確率。
下面,我分別對這些模組進行介紹。
 
模組 1:對文件進行分詞
在準備階段裡,最重要的就是分詞。那麼如果給文件進行分詞呢?英文文件和中文文件所使用的分詞工具不同。
在英文文件中,最常用的是 NTLK 包。NTLK 包中包含了英文的停用詞 stop words、分詞和標註方法。
1 import nltk
2 word_list = nltk.word_tokenize(text) # 分詞
3 nltk.pos_tag(word_list) # 標註單詞的詞性
在中文文件中,最常用的是 jieba 包。jieba 包中包含了中文的停用詞 stop words 和分詞方法。
import jieba
word_list = jieba.cut (text) # 中文分詞
 
模組 2:載入停用詞表
我們需要自己讀取停用詞表檔案,從網上可以找到中文常用的停用詞儲存在 stop_words.txt,然後利用 Python 的檔案讀取函式讀取檔案,儲存在 stop_words 陣列中。
1 stop_words = [line.strip().decode('utf-8') for line in io.open('stop_words.txt').readlines()]
 
模組 3:計算單詞的權重
這裡我們用到 sklearn 裡的 TfidfVectorizer 類,上面我們介紹過它使用的方法。
直接建立 TfidfVectorizer 類,然後使用 fit_transform 方法進行擬合,得到 TF-IDF 特徵空間 features,你可以理解為選出來的分詞就是特徵。我們計算這些特徵在文件上的特徵向量,得到特徵空間 features。
1 tf = TfidfVectorizer(stop_words=stop_words, max_df=0.5)
2 features = tf.fit_transform(train_contents)
這裡 max_df 引數用來描述單詞在文件中的最高出現率。假設 max_df=0.5,代表一個單詞在 50% 的文件中都出現過了,那麼它只攜帶了非常少的資訊,因此就不作為分詞統計。
一般很少設定 min_df,因為 min_df 通常都會很小。
 
模組 4:生成樸素貝葉斯分類器
我們將特徵訓練集的特徵空間 train_features,以及訓練集對應的分類 train_labels 傳遞給貝葉斯分類器 clf,它會自動生成一個符合特徵空間和對應分類的分類器。
這裡我們採用的是多項式貝葉斯分類器,其中 alpha 為平滑引數。為什麼要使用平滑呢?因為如果一個單詞在訓練樣本中沒有出現,這個單詞的概率就會被計算為 0。但訓練集樣本只是整體的抽樣情況,我們不能因為一個事件沒有觀察到,就認為整個事件的概率為 0。為了解決這個問題,我們需要做平滑處理。
當 alpha=1 時,使用的是 Laplace 平滑。Laplace 平滑就是採用加 1 的方式,來統計沒有出現過的單詞的概率。這樣當訓練樣本很大的時候,加 1 得到的概率變化可以忽略不計,也同時避免了零概率的問題。
當 0<alpha<1 時,使用的是 Lidstone 平滑。對於 Lidstone 平滑來說,alpha 越小,迭代次數越多,精度越高。我們可以設定 alpha 為 0.001。
# 多項式貝葉斯分類器
1 from sklearn.naive_bayes import MultinomialNB  
2 clf = MultinomialNB(alpha=0.001).fit(train_features, train_labels)
 
模組 5:使用生成的分類器做預測
首先我們需要得到測試集的特徵矩陣。
方法是用訓練集的分詞建立一個 TfidfVectorizer 類,使用同樣的 stop_words 和 max_df,然後用這個 TfidfVectorizer 類對測試集的內容進行 fit_transform 擬合,得到測試集的特徵矩陣 test_features。
1 test_tf = TfidfVectorizer(stop_words=stop_words, max_df=0.5, vocabulary=train_vocabulary)
2 test_features=test_tf.fit_transform(test_contents)
 
然後我們用訓練好的分類器對新資料做預測。
方法是使用 predict 函式,傳入測試集的特徵矩陣 test_features,得到分類結果 predicted_labels。predict 函式做的工作就是求解所有後驗概率並找出最大的那個。
1 predicted_labels=clf.predict(test_features)
 
模組 6:計算準確率
計算準確率實際上是對分類模型的評估。我們可以呼叫 sklearn 中的 metrics 包,在 metrics 中提供了 accuracy_score 函式,方便我們對實際結果和預測的結果做對比,給出模型的準確率。
使用方法如下:
1 from sklearn import metrics
2 print metrics.accuracy_score(test_labels, predicted_labels)
 
搜尋關注微信公眾號“程式設計師姜小白”,獲取更新精彩內容哦。

相關文章