貝葉斯分類器(3)樸素貝葉斯分類器

根據貝葉斯分類器(1)貝葉斯決策論概述、貝葉斯和頻率、概率和似然,我們對貝葉斯分類器所要解決的問題、問題的求解方法做了概述,將貝葉斯分類問題轉化成了求解P(x|c)的問題,在上一篇貝葉斯分類器(2)極大似然估計、MLE與MAP
中,我們分析了第一個求解方法:極大似然估計。在本篇中,我們來介紹一個更加簡單的P(x|c)求解方法,并在此基礎上講講常用的一個貝葉斯分類器的實現:樸素貝葉斯分類器(Naive Bayes classifier)。

1 樸素貝葉斯分類原理

1.1 分類問題回顧

我們的目標是通過對樣本的學習來得到一個分類器,以此來對未知數據進行分類,即求后驗概率P(c|x)。在貝葉斯分類器(1)貝葉斯決策論概述、貝葉斯和頻率、概率和似然中,我們描述了貝葉斯分類器是以生成式模型的思路來處理這個問題的,如下面的公式所示,貝葉斯分類器通過求得聯合概率P(x,c)來計算P(c|x),并將聯合概率P(x,c)轉化成了計算類先驗概率P(c)、類條件概率P(x|c)、證據因子P(x)

h^*(x)=\argmax_{c\in Y} P(c|x)=\argmax_{c\in Y} \frac{P(x,c)}{P(x)}=\argmax_{c\in Y} \frac{P(c)*P(x|c)}{P(x)}

其中的難點是類條件概率P(x|c)的計算,因為樣本x本身就是其所有屬性的聯合概率,各種屬性隨意組合,變幻莫測,要計算其中某一種組合出現的概率真的是太難了,而樸素貝葉斯的出現就是為了解決這個問題的。

要想計算聯合概率P(a,b),我們肯定是希望事件a與事件b是相互獨立的,可以簡單粗暴的P(a,b)=P(a)P(b),多想對著流星許下心愿:讓世界上復雜的聯合概率都變成簡單的連乘!

1.2 樸素貝葉斯

樸素貝葉斯實現了我們的夢想!樸素貝葉斯中的樸素就是對多屬性的聯合分布做了一個大膽的假設,即xn個維度之間相互獨立:

P([x_1,x_2,...,x_n]|c)=P(x_1|c)P(x_2|c)...P(x_1|c)

樸素貝葉斯通過這一假設大大簡化了P(x|c)的計算,當然,使用這個假設是有代價的,一般情況下,大量樣本的特征之間獨立這個條件是弱成立的,畢竟哲學上說聯系是普遍的,所以我們使用樸素貝葉斯會降低一些準確性;如果實際問題中的事件的各個屬性非常不獨立的話,甚至是無法使用樸素貝葉斯的。總的來說,樸素貝葉斯大大簡化了計算,同時犧牲了一些結果的準確性,具體要不要使用、怎么使用就看我們在實際問題中的權衡了。

在樸素貝葉斯的思想下再看回分類問題,事件xm個屬性,可將分類問題按下式轉化:

只需要計算出上式不同類別c下的值,令值最大的類別c_i即為分類結果。

其中,根據大數定律,P(c)=\frac{N_c}{N}P(x_i|c)是類別c下的后驗概率,其計算要取決于先驗x,這里需要分為X是離散或連續兩種情況:

1.2.1 特征/屬性是離散型隨機變量

  • 1)先驗服從多項式分布:假設x的特征取值服從多項式分布,那么同樣根據大數定律,可通過頻率來計算P(x_i|c)

P(x_i=x_{i*}|c)=\frac{N_{ci*}}{N_c}

N_c為樣本中類別為c的頻數,N_{ci*}為類別為c的樣本中,第i個屬性中i*出現的頻數。
不過有些出現的概率比較低的屬性,在我們的樣本中不一定會出現,即頻數為0,如果不作處理的話會導致其P(x_i|c)為0,會導致包含這個屬性的樣本永遠都不會被分類到類別c,而現實不一定是這樣,因此我們需要對沒出現的情況做平滑處理,比如常見的拉普拉斯平滑,給分子i*的頻數加上一個定值\lambda,而分母加上a*\lambda,表示為第i個屬性中的每一種取值的頻數都加定值\lambda

P(x_i=x_{i*}|c)=\frac{N_{ci*}+\lambda}{N_c+a*\lambda}

舉例:垃圾郵件判斷
樸素貝葉斯分類在垃圾郵件的判斷上有不錯的實踐效果,這是一個二分類問題,c\in[垃圾郵件,正常郵件],假設c_0為垃圾郵件,c_1為正常郵件,統計出:

P(c_0)=0.2,P(c_1)=0.8

現在收到一封郵件包含一些關鍵詞:【中獎,筆記本電腦,特朗普,大選,...】,根據大量的數據可以統計出這些詞出現的頻數,除以類別中所有詞的總頻數得到其出現的后驗概率,在垃圾郵件中:

P(中獎|c_0)=0.7,P(筆記本電腦|c_0)=0.5,P(特朗普|c_0)=0.3,P(大選|c_0)=0.4

在正常郵件中:

P(中獎|c_1)=0.1,P(筆記本電腦|c_1)=0.2,P(特朗普|c_1)=0.1,P(大選|c_1)=0.2

可以計算得到:

P(c_0)\cdot\prod_{} P(x_{i}|c_0)=0.2*0.7*0.5*0.3*0.4=0.0084

P(c_1)\cdot\prod_{} P(x_{i}|c_1)=0.8*0.1*0.2*0.1*0.2=0.00032

c=c_0時的值是c=c_1時值的26倍,所以判斷此郵件是垃圾郵件。

我們判斷西瓜好壞的問題也可以轉化成離散型隨機變量的分類問題,過程與上面類似。

  • 2)先驗服從伯努利分布:x的屬性是離散型隨機變量的分類問題中,如果一個屬性只關注其出現或者不出現,而不關注其在一個樣本內出現的次數,也就是其取值只有0和1,那么我們可以假設這個屬性是服從伯努利分布的(注意:不要求屬性為伯努利分布,只要業務需要,我們可以把它變成伯努利分布,比如對于銷量,我們讓小于100的都是0,大于100的為1)。其后驗概率的計算為:

P(x_{i*} \mid c) = P(x_{i*} \mid c) *x_{i*} + (1 - P(x_{i*}\mid c)) *(1 - x_{i*})

比如垃圾郵件的例子,在多項式樸素貝葉斯中:

P(x_{i*}=中獎|c=垃圾郵件)=\frac{垃圾郵件中“中獎”詞頻+\lambda}{垃圾郵件中總詞頻+詞數*\lambda}

如果我們只關心“中獎”出現與否,不管詞頻,則在伯努利樸素貝葉斯中:

P(x_{i*}=中獎|c=垃圾郵件)=\frac{垃圾郵件中含有“中獎”的郵件數 +α }{垃圾郵件數 + α*郵件類別數}

1.2.2 特征/屬性是連續型隨機變量

  • 連續變量離散化,使用多項式分布或伯努利分布:x的屬性是連續型隨機變量時,如果我們對取值的業務理解較好,一些情況下可以選擇將連續變量離散化,比如在一個商品的分類中,我們根據業務理解把低于100塊的映射到“便宜”,100到200塊的映射到“一般”,高于100塊的映射到“好貴”,這樣就可以轉化為離散變量的問題,這是比較簡單的處理方式,不過對業務理解的要求比較高,而且要求樣本的量不能太少,要保證每個區間有一定的樣本量。

  • 假設x的連續型屬性服從某種分布,比如正態分布: 假設P(x_i|c)服從正態分布,其中參數\mu通過類別為c的所有樣本中屬性x_i的各種取值的平均得到,參數\sigma同理,通過樣本的標準差得到,以此概率密度函數來計算P(x_i=x_{i*}|c)

舉例:性別判斷
下面是一組人類身體特征的統計資料。

有人身高6英尺、體重130磅,腳掌8英寸,判斷此人性別:

各屬性為連續變量,假設男性和女性的身高、體重、腳掌都是正態分布,通過樣本計算出均值和方差。男性的身高是均值5.855、方差0.035的正態分布。所以,例如男性的身高為6英尺的概率的相對值等于1.5789(密度函數的值,并不是概率,只用來反映各個值的相對可能性)。

分布確定后,就可以計算性別的分類了:

P(身高=6|男) * P(體重=130|男) * P(腳掌=8|男) * P(男) = 6.1984 * 10^{-9}

P(身高=6|女) * P(體重=130|女) * P(腳掌=8|女) * P(女) = 5.3778 *10^{-4}

女性的概率比男性要高出將近10000倍,所以判斷該人為女性。

1.3 樸素貝葉斯分類的平滑方法

在前文1.2.1小節中我們已經提過平滑處理,主要針對于那些在樣本中沒有出現過的詞,它們的概率是0,導致在分類中完全沒有存在感,所以要對這些進行平滑處理。

平滑處理的方法也有很多種,包括我們上面說過的拉普拉斯平滑,除此之外還有古德圖靈平滑,線性插值法,回退法(K-Z回退)等,不過這些方法在自然語言處理中比較常用,我們暫時先不多介紹了,還是聚焦在樸素貝葉斯上,下面我們看看樸素貝葉斯在sklearn中的實現。

2 樸素貝葉斯的sklearn實現

sklearn中有3種常用的不同類型的樸素貝葉斯:

1)高斯分布型樸素貝葉斯

sklearn.naive_bayes.GaussianNB(*, priors=None, var_smoothing=1e-09)

Parameters
priors:array-like of shape (n_classes,)
類別的先驗概率,如果指定,則不再根據數據計算調整
var_smoothing:float, default=1e-9
Portion of the largest variance of all features that is added to variances for calculation stability.(不是很明白)

Gaussian NB的方法
>> import numpy as np
>> X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
>> Y = np.array([1, 1, 1, 2, 2, 2])
>> from sklearn.naive_bayes import GaussianNB
>> clf = GaussianNB()
>> clf.fit(X, Y)
GaussianNB()
>> print(clf.predict([[-0.8, -1]]))
[1]
>> clf_pf = GaussianNB()
>> clf_pf.partial_fit(X, Y, np.unique(Y))  # 增量訓練
GaussianNB()
>> print(clf_pf.predict([[-0.8, -1]]))
[1]
>> clf.predict_proba(np.array([[2,2]]))   # 輸出概率
array([[2.31952419e-16, 1.00000000e+00]])
>> clf.predict_log_proba(np.array([[2,2]]))    # 輸出對數概率
array([[-35.99999941,   0.        ]])

2)多項式分布型樸素貝葉斯

sklearn.naive_bayes.MultinomialNB(*, alpha=1.0, fit_prior=True, class_prior=None)

Parameters
alpha:float, default=1.0
Additive (Laplace/Lidstone) smoothing parameter (0 for no smoothing).

fit_prior:bool, default=True
Whether to learn class prior probabilities or not. If false, a uniform prior will be used.

class_prior:array-like of shape (n_classes,), default=None
Prior probabilities of the classes. If specified the priors are not adjusted according to the data.

其常用函數與高斯型一樣。

>> import numpy as np
>> rng = np.random.RandomState(1)
>> X = rng.randint(5, size=(6, 100))
>> y = np.array([1, 2, 3, 4, 5, 6])
>> from sklearn.naive_bayes import MultinomialNB
>> clf = MultinomialNB()
>> clf.fit(X, y)
MultinomialNB()
>> print(clf.predict(X[2:3]))
[3]

3)伯努利分布型樸素貝葉斯

sklearn.naive_bayes.BernoulliNB(*, alpha=1.0, binarize=0.0, fit_prior=True, class_prior=None)

Parameters
binarize:float or None, default=0.0
Threshold for binarizing (mapping to booleans) of sample features. If None, input is presumed to already consist of binary vectors.(用于設置二值化的閾值)

官方例子與多項式型的基本一樣,而且也沒有設置binarize,相當于默認使用binarize=0.0,根據源碼 sklearn/preprocessing/_data.py
中的binarize(X, *, threshold=0.0, copy=True)函數可以發現,大于binarize的都賦值為1,其他為0。

>> import numpy as np
>> rng = np.random.RandomState(1)
>> X = rng.randint(5, size=(6, 100))
>> Y = np.array([1, 2, 3, 4, 4, 5])
>> from sklearn.naive_bayes import BernoulliNB
>> clf = BernoulliNB()
>> clf.fit(X, Y)   # X中各個特征的取值為[0,1,2,3,4],二值化后大于0的都為1
BernoulliNB()
>> print(clf.predict(X[2:3]))
[3]

3 樸素貝葉斯總結

優點

  • 樸素貝葉斯算法假設了數據集屬性之間是相互獨立的,因此算法的邏輯性十分簡單,并且算法較為穩定,當數據呈現不同的特點時,樸素貝葉斯的分類性能不會有太大的差異;
  • 當數據集屬性之間的關系相對比較獨立時,樸素貝葉斯分類算法會有較好的效果;
  • 數據量要求不大,適合增量式訓練,能直接處理多分類;
  • 算法簡單直觀,具有很好的可解釋性,可以直接輸出概率。

缺點

  • 屬性獨立性的條件也是樸素貝葉斯的不足之處,數據集屬性的獨立性在很多情況下很難滿足;
  • 需要知道先驗概率,且先驗概率很多時候也是取決于假設,故對假設的合理性較為依賴。

可見,樸素貝葉斯的缺點很大程度來來源于其假設太強,對于其假設符合程度較低的問題會損失較多的準確性,因此,如果我們能把假設弱化一下,是不是就能提高樸素貝葉斯的性能呢?在接下來的篇章中我們來繼續探索。



主要參考資料

《機器學習》周志華
《統計學習方法》 李航
scikit-learn Naive Bayes文檔

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374