根據貝葉斯分類器(1)貝葉斯決策論概述、貝葉斯和頻率、概率和似然,我們對貝葉斯分類器所要解決的問題、問題的求解方法做了概述,將貝葉斯分類問題轉化成了求解的問題,在上一篇貝葉斯分類器(2)極大似然估計、MLE與MAP
中,我們分析了第一個求解方法:極大似然估計。在本篇中,我們來介紹一個更加簡單的求解方法,并在此基礎上講講常用的一個貝葉斯分類器的實現:樸素貝葉斯分類器(Naive Bayes classifier)。
1 樸素貝葉斯分類原理
1.1 分類問題回顧
我們的目標是通過對樣本的學習來得到一個分類器,以此來對未知數據進行分類,即求后驗概率。在貝葉斯分類器(1)貝葉斯決策論概述、貝葉斯和頻率、概率和似然中,我們描述了貝葉斯分類器是以生成式模型的思路來處理這個問題的,如下面的公式所示,貝葉斯分類器通過求得聯合概率
來計算
,并將聯合概率
轉化成了計算類先驗概率
、類條件概率
、證據因子
。
其中的難點是類條件概率的計算,因為樣本
本身就是其所有屬性的聯合概率,各種屬性隨意組合,變幻莫測,要計算其中某一種組合出現的概率真的是太難了,而樸素貝葉斯的出現就是為了解決這個問題的。
要想計算聯合概率,我們肯定是希望事件
與事件
是相互獨立的,可以簡單粗暴的
,多想對著流星許下心愿:讓世界上復雜的聯合概率都變成簡單的連乘!
1.2 樸素貝葉斯
樸素貝葉斯實現了我們的夢想!樸素貝葉斯中的樸素就是對多屬性的聯合分布做了一個大膽的假設,即的
個維度之間相互獨立:
樸素貝葉斯通過這一假設大大簡化了的計算,當然,使用這個假設是有代價的,一般情況下,大量樣本的特征之間獨立這個條件是弱成立的,畢竟哲學上說聯系是普遍的,所以我們使用樸素貝葉斯會降低一些準確性;如果實際問題中的事件的各個屬性非常不獨立的話,甚至是無法使用樸素貝葉斯的。總的來說,樸素貝葉斯大大簡化了計算,同時犧牲了一些結果的準確性,具體要不要使用、怎么使用就看我們在實際問題中的權衡了。
在樸素貝葉斯的思想下再看回分類問題,事件有
個屬性,可將分類問題按下式轉化:
只需要計算出上式不同類別下的值,令值最大的類別
即為分類結果。
其中,根據大數定律,,
是類別
下的后驗概率,其計算要取決于先驗
,這里需要分為
是離散或連續兩種情況:
1.2.1 特征/屬性是離散型隨機變量
-
1)先驗服從多項式分布:假設
的特征取值服從多項式分布,那么同樣根據大數定律,可通過頻率來計算
:
為樣本中類別為
的頻數,
為類別為
的樣本中,第
個屬性中
出現的頻數。
不過有些出現的概率比較低的屬性,在我們的樣本中不一定會出現,即頻數為0,如果不作處理的話會導致其為0,會導致包含這個屬性的樣本永遠都不會被分類到類別
,而現實不一定是這樣,因此我們需要對沒出現的情況做平滑處理,比如常見的拉普拉斯平滑,給分子
的頻數加上一個定值
,而分母加上
,表示為第
個屬性中的每一種取值的頻數都加定值
:
舉例:垃圾郵件判斷
樸素貝葉斯分類在垃圾郵件的判斷上有不錯的實踐效果,這是一個二分類問題,,假設
為垃圾郵件,
為正常郵件,統計出:
現在收到一封郵件包含一些關鍵詞:【中獎,筆記本電腦,特朗普,大選,...】,根據大量的數據可以統計出這些詞出現的頻數,除以類別中所有詞的總頻數得到其出現的后驗概率,在垃圾郵件中:
在正常郵件中:
可以計算得到:
時的值是
時值的26倍,所以判斷此郵件是垃圾郵件。
我們判斷西瓜好壞的問題也可以轉化成離散型隨機變量的分類問題,過程與上面類似。
-
2)先驗服從伯努利分布:在
的屬性是離散型隨機變量的分類問題中,如果一個屬性只關注其出現或者不出現,而不關注其在一個樣本內出現的次數,也就是其取值只有0和1,那么我們可以假設這個屬性是服從伯努利分布的(注意:不要求屬性為伯努利分布,只要業務需要,我們可以把它變成伯努利分布,比如對于銷量,我們讓小于100的都是0,大于100的為1)。其后驗概率的計算為:
比如垃圾郵件的例子,在多項式樸素貝葉斯中:
如果我們只關心“中獎”出現與否,不管詞頻,則在伯努利樸素貝葉斯中:
1.2.2 特征/屬性是連續型隨機變量
連續變量離散化,使用多項式分布或伯努利分布:當
的屬性是連續型隨機變量時,如果我們對取值的業務理解較好,一些情況下可以選擇將連續變量離散化,比如在一個商品的分類中,我們根據業務理解把低于100塊的映射到“便宜”,100到200塊的映射到“一般”,高于100塊的映射到“好貴”,這樣就可以轉化為離散變量的問題,這是比較簡單的處理方式,不過對業務理解的要求比較高,而且要求樣本的量不能太少,要保證每個區間有一定的樣本量。
假設
的連續型屬性服從某種分布,比如正態分布: 假設
服從正態分布,其中參數
通過類別為
的所有樣本中屬性
的各種取值的平均得到,參數
同理,通過樣本的標準差得到,以此概率密度函數來計算
。
舉例:性別判斷
下面是一組人類身體特征的統計資料。
有人身高6英尺、體重130磅,腳掌8英寸,判斷此人性別:
各屬性為連續變量,假設男性和女性的身高、體重、腳掌都是正態分布,通過樣本計算出均值和方差。男性的身高是均值5.855、方差0.035的正態分布。所以,例如男性的身高為6英尺的概率的相對值等于1.5789(密度函數的值,并不是概率,只用來反映各個值的相對可能性)。
分布確定后,就可以計算性別的分類了:
女性的概率比男性要高出將近10000倍,所以判斷該人為女性。
1.3 樸素貝葉斯分類的平滑方法
在前文1.2.1小節中我們已經提過平滑處理,主要針對于那些在樣本中沒有出現過的詞,它們的概率是0,導致在分類中完全沒有存在感,所以要對這些進行平滑處理。
平滑處理的方法也有很多種,包括我們上面說過的拉普拉斯平滑,除此之外還有古德圖靈平滑,線性插值法,回退法(K-Z回退)等,不過這些方法在自然語言處理中比較常用,我們暫時先不多介紹了,還是聚焦在樸素貝葉斯上,下面我們看看樸素貝葉斯在sklearn中的實現。
2 樸素貝葉斯的sklearn實現
sklearn中有3種常用的不同類型的樸素貝葉斯:
- 高斯分布型 (Gaussian NB):用于上面所說的連續型變量的分類問題,假定屬性/特征服從正態分布;
- 多項式型 (Multinomial NB):用于離散值模型里。比如我們在1.2.1中的例子;
- 伯努利型 (Bernoulli NB):用于離散值模型里,最后得到的特征只有0(沒出現)和1(出現過)。
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.(不是很明白)
>> 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文檔