上一篇博客我們學習了KNN(K最近鄰)分類算法,主要學習KNN算法的原理和超參數,使用KNN實現分類與迴歸以及通過網格交叉驗證調整超參數,還有數據標準化的作用等。
這一篇我們要學習的是樸素貝葉斯。
首先我們會先複習一下有關概率的基礎知識,之後會引入樸素貝葉斯的學習。
樸素貝葉斯很直觀,計算量也不大,在很多領域有廣泛的應用,這裏我們就對樸素貝葉斯簡單瞭解一下:
樸素貝葉斯:
在所有的機器學習分類算法中,樸素貝葉斯和其他絕大多數的分類算法都不同。對於大多數的分類算法,比如決策樹,KNN,邏輯迴歸,支持向量機等,他們都是判別方法,也就是直接學習出特徵輸出Y和特徵X之間的關係,要麼是決策函數Y=f(X),要麼是條件分佈P(Y|X)。但是樸素貝葉斯卻是生成方法,也就是直接找出特徵輸出Y和特徵X的聯合分佈P(X,Y),然後P(Y|X)=P(X,Y)/P(X)得出。
樸素貝葉斯公式的核心思維:
將求解 P(B|A) 的概率轉換成求解 P(A|B) 的概率。
下面讓我們進入正文吧~
目標:
- 熟悉條件概率,聯合概率,獨立性等概率基礎內容。
- 熟悉全概率公式與貝葉斯公式。
- 能夠熟知樸素貝葉斯算法原理。
- 能夠使用樸素貝葉斯算法實現分類任務
1、知識要點
1.1 概率基礎
1.1.1 隨機事件
隨機事件
,指可能發生,也可能不發生的事件。
例如,當我們拋硬幣時,設出現正面爲事件,則事件可能發生,也可能不發生。
1.1.2 樣本空間
樣本空間
,即我們進行隨機試驗時,所有可能結果構成的集合。
習慣使用S
表示。
1.1.3 概率
概率
,用來反映一個隨機事件出現的可能性大小。
習慣使用P(A)
來表示事件的概率。
從面積圖的角度將,也可以這樣表示:
1.1.4 聯合概率
聯合概率
,指多個事件同時發生的概率,例如, P(AB) 表示事件A與事件B的聯合概率。
1.1.5 條件概率
條件概率
,指在事件A發生的前提下,事件B發生的概率,使用 P(B|A)
表示。
關於條件概率,有以下一個重要的定義:
p(B|A) = P(AB) / P(A)
需要注意的是,P(B|A) 與 P(B) 是不同的,二者很可能也不相等。因爲在事件A發生的前提下,會導致樣本空間的收縮,從而會改變概率。
練習:
下表爲水果店的購物清單,每條記錄代表一名顧客購買的商品。
設事件A爲購買蘋果,事件B爲購買桔子,則以下說法正確的是(
ABCD
)。【不定項】
A P(A) = 3/4
B P(B) = 1/2
C P(B|A) = 1/3
D P(A|B) = 1/2解析: A選項,購買蘋果的概率就是4類樣本中有其中3類有蘋果,所以購買蘋果的概率是3/4。
B選項,4類樣本中有2類有桔子,桔子的概率也就是2/4,就是1/2。 C選項,在購買蘋果概率的基礎上購買桔子的概率,就是1(桔子)/
3(蘋果)。 D選項,在購買桔子概率的基礎上購買蘋果的概率,就是1(蘋果)/ 2(桔子)。
1.1.6 獨立性
1.1.6.1 獨立性現象
從剛纔的練習中,我們發現:
故事件或事件的發生,都對另外一個事件造成了影響。不過,有時候,事件之間可能並不存在相互影響,例如,我們考察兩個學生的逃課情況,設事件爲第一個學生逃課,事件爲第二個學生逃課,則樣本空間爲:
第一個學生A | 第二個學生B |
---|---|
逃課 | 逃課 |
逃課 | 不逃課 |
不逃課 | 逃課 |
逃課 | 不逃課 |
我們可以輕鬆計算事件的概率:
由此可知:
P(A) = P( A|B )
P(B) = P( B|A )
可見,事件與沒有相互造成影響,這也是非常容易理解的。如果兩個學生沒有關係,則一個學生是否逃課,對另外一個學生是否逃課是沒有任何影響的。
1.1.6.2 獨立性定義
如果兩事件, 滿足:
P(AB) = P(A)P(B) 則稱與相互獨立。
同時,又存在:
p(AB) = P(A)P(B|A)
因此,當兩事件A,B獨立時:
P(A)P(B) =P(A)P(B|A)
P(B|A) = P(B)
這也表明,當兩個事件獨立時,一個事件發生與否,對另外一個事件完全沒有任何影響。
練習:
1.1.7 全概率公式
設實驗的樣本空間爲S, A爲E的事件,B1 ,B2 ,…,Bn 爲S的一個劃分(任意兩個事件交集爲空,所以事件並集爲整個樣本空間S),且P(Bi) > 0(i=1,2,…,n ),則:
稱爲全概率公式。
有的時候, P(A) 可能不易求出,但是,我們可以在S上尋找一個劃分(i=1,2,……),並且 Bi與P(A|Bi) 的概率容易獲取,這樣,我們就可以使用全概率公式來求解P(A)。
加深理解,做個練習吧:
已知小張逃課的概率是1 / 4,當小張逃課時,小李逃課的概率爲1 / 2,當小張上課時,小李逃課的概率爲1 / 3,請問小李逃課的概率是多少?(
D
)
A 1 / 4
B 1 / 2
C 1 / 3
D 3 / 8
解析:計算方式=1/4 * 1/2 + 3/4 * 1/3 = 3/8
1.1.8 貝葉斯公式
1.1.8.1 公式定義
設實驗的樣本空間爲S, A爲E的事件,B1 ,B2 ,…,Bn 爲S的一個劃分,且P(A) > 0 ,P(Bi) >0 (i=1,2,…,n ),則:
貝葉斯公式:
這也是條件概率的計算公式。
推導過程:
1.1.8.2 核心思維
貝葉斯公式的核心思維就是將求解 P(B|A) 的概率轉換成求解 P(A|B) 的概率。
有時候,求解P(B|A)難度較大,但是求解P(A|B)比較容易,在這樣的情況下,我們就可以考慮應用貝葉斯公式進行轉換,從而解決問題。
1.1.8.3 相關示例
例:對以往數據分析結果表明,當機器調整得良好時,產品的合格率是爲98%,而當機器發生某種故障時,其合格率爲55%。每天早上機器開動時,機器調整良好的概率爲95%。試求已知某日早上第一件產品是合格品時,機器調整良好的概率是多少?
解:設A爲事件“產品合格”,B 爲事件“機器調整良好”,則B爲事件“機器發生故障”。
解析:
這是一個條件概率的題。我們要在第一件產品是合格品的基礎上去計算機器調整良好的概率是多少,也就是算以A爲條件下B發生的概率。
根據提議我們無法計算以A爲條件下B發生的概率,此時,我們就要換種思維,根據貝葉斯公式的核心思維,我們可以計算以B爲條件下A發生的概率。
通過轉換,我們現在只需求解P(A|B)P(B) / P(A)即可。 根據題意,機器良好產品合格的概率爲98%,也就是P(A|B)=98%;
每天早上機器開動時,機器調整良好的概率爲95%,也就是P(B)=95%;
因爲P(A)我們不知道該怎麼求,所以我們這裏可以用全概率公式進行轉換,轉換成樣本空間,即機器調整良好和機器發生故障;
P(A)----》》
= 機器良好時產品合格的概率(0.98) * 機器良好的概率(0.95) + 機器發生故障時產品合格的概率 (55%) * 機器發生故障的概率( 1-95%)
1.1.8.4 先驗概率與後驗概率
由以往的數據分析而得到的概率,稱爲先驗概率。例如在上例中,每天早上機器開動時,機器調整良好的概率爲95%,這個概率(即P(A))就是先驗概率。
當得到某些信息後,在先驗概率的基礎上進行修正,從而得到的概率,稱爲後驗概率。例如在上例中,當已知某日早上第一件產品是合格品時,機器調整良好的概率是97%,這個概率(P(B|A) )就是後驗概率。
1.1.9 樸素貝葉斯分類
貝葉斯原理、貝葉斯分類和樸素貝葉斯這三者之間是有區別的:
貝葉斯原理是最大的概念,它解決了概率論中“逆向概率”的問題,在這個理論基礎上,人們設計出了貝葉斯分類器,樸素貝葉斯分類是貝葉斯分類器中的一種,也是最簡單,最常用的分類器。樸素貝葉斯之所以樸素是因爲它假設屬性是相互獨立的,因此對實際情況有所約束,如果屬性之間存在關聯,分類準確率會降低。 不過好在對於大部分情況下,樸素貝葉斯的分類效果都不錯。
2.1 樸素貝葉斯算法
樸素貝葉斯算法是基於概率的分類算法,之所以稱爲“樸素”,是因爲其假設特徵之間是獨立的,該算法設計比較簡單,實際上使用的就是全概率公式與貝葉斯公式。樸素貝葉斯算法在文本場景中效果非常好,例如垃圾郵件過濾,新聞分類,情感分析等。
2.1.1 實際案例
之前,我們已經介紹了全概率公式與貝葉斯公式,現在,我們將這兩個公式應用於樸素貝葉斯算法中,實現分類任務。假設我們有如下的數據集:
由以上數據集我們可以看出特徵之間是相互獨立的,我們要通過訓練數據集得到一種模式老預測分類上課情況是上課還是逃課。
該數據集展示在不同的條件下,學生的上課與逃課情況。現在問題是,對於第11條記錄,學生會上課還是逃課?
即我們可以使用樸素貝葉斯方式來解決我們的問題。
2.1.2 算法原理
之前我們提過,樸素貝葉斯是基於概率的分類算法,因此,想要預測未知樣本X所屬的類別,只需要計算屬於每個類別( y )的概率是多少,預測結果就是概率最大的那個類別。 以上例來講,就是比較:哪個概率大。
假設X含有n個特徵(上面的示例中含有4個特徵:天氣、上課距離、學生成績、上課類別),即我們要計算:
然而,以上的概率我們並不容易求解,不過,根據貝葉斯公式,我們可以進行如下的轉換:P(y | x1,x2,…,xn) ------>> P(x1,x2,…,xn | y)
因爲樸素貝葉斯算法的前提假設爲,各個特徵之間都是獨立的
(P(xy) = P(x)P(y)),因此有:
因此,將(2)式代入(1)式,可得:
我們發現,無論是計算樣本屬於哪個類別的概率,分母部分都是不變的,因此,比較概率的大小,只需要比較分子部分就可以了。
故算法最終預測的類別,就是能夠使得分子部分最大的那個類別,即:
從公式中,我們容易發現,若要預測樣本的類別,只需要求解P(y)與P(xi | y)即可。而這兩個概率,都可以從訓練集中獲取。
例如:求解上課基礎上是晴天的概率是多少?P(晴天 | 上課) =2/5
2.1.3 案例求解
對於樣本11,我們就可以分別計算下,在上課與逃課的情況下,各自的概率值是多少。
由此,我們可知,學生逃課的概率,大於上課的概率,因此,最終算法對樣本11預測的結果類別爲:逃課。
但是,我們根據求解出來上課和逃課的概率之和不等於1這是怎麼回事呢?
因爲,我們計算的時候只計算了分子,沒有帶上分母一起計算,如果加上分母一起計算的話得出來的概率之和是肯定爲1的。
2.1.4 平滑改進
當我們以同樣的方式,試圖計算樣本12所屬的類別時,會出現一點小問題。那就是P(xi = 遠 | y = 上課)的值爲0。由於在計算時,是各個概率的乘積,因此,一旦有一個概率爲0,即使其他的概率值較大,也一律會得到0值。這會嚴重影響預測的準確性,爲了避免這種情況的發生,我們在計算概率時,採用平滑改進。
其中,k 爲特徵xi可能的取值數, α(α>0 )稱爲平滑係數,當α=1時,稱爲拉普拉斯平滑(Laplace smoothing),當α<1時,稱爲Lidstone smoothing平滑。
2.1.5 算法優點
相對於其他算法,樸素貝葉斯算法具有如下優勢:
- 即使訓練集數據較少,也能夠實現預測,並且效果不錯。
- 算法的訓練速度非常快。
這是因爲,算法假設特徵之間是獨立的,這意味着每個特徵可以單獨當成一維分佈而進行評估,無需考慮與其他特徵之間的關聯性。反之,如果特徵之間不獨立,則爲了獲得較準確的數據分佈,就需要更多的訓練樣本。假設訓練集中的含有N個特徵,每個特徵需要個M樣本來訓練,則總共需要的樣本數爲各自樣本之間的笛卡爾積,即M的N次,這在很大時,訓練會非常緩慢,然而,如果特徵之間獨立,對於每個特徵,就可以單獨進行考慮,總共只需要N*M個樣本就可以正常訓練。
練習:
關於樸素貝葉斯算法,說法正確的是(
ABCD
)【不定項】
A 樸素貝葉斯算法是基於概率的分類算法。
B 樸素貝葉斯算法之所以“樸素”,是因爲該算法前提假設各個特徵是獨立的。
C 樸素貝葉斯算法訓練速度較快。
D 樸素貝葉斯算法在較少的訓練樣本集上,也可能工作的很好。
3.1 常用樸素貝葉斯
在sklearn中,提供了若干種樸素貝葉斯的實現算法,不同的樸素貝葉斯算法,主要是對 P(xi | y) 的分佈假設不同,進而採用不同的參數估計方式。實際上,通過之前的介紹,我們也應該能夠發現,樸素貝葉斯算法,主要就是計算P(xi | y) ,一旦確定P(xi | y) ,最終屬於每個類別的概率,自然也就迎刃而解了。
常用的三種樸素貝葉斯爲:
- 高斯樸素貝葉斯。
- 伯努利樸素貝葉斯。
- 多項式樸素貝葉斯。
3.1.1 高斯樸素貝葉斯(連續變量&正態分佈)
高斯樸素貝葉斯,適用於連續變量。
其假定各個特徵xi在各個類別y下是服從正態分佈。
算法內部使用正態分佈的概率密度函數來計算概率P(xi | y),如下:
import numpy as np
import pandas as pd
from sklearn.naive_bayes import GaussianNB #高斯樸素貝葉斯
np.random.seed(0) # 設計一個隨機種子
X = np.random.randint(0, 10, size=(6, 2)) #生成0-10之間的隨機數,6行2列的形式(6個樣本2個特徵)
y = np.array([0, 0, 0, 1, 1, 1]) # 前3個樣本是0類別,後三個樣本是1類別
data = pd.DataFrame(np.concatenate([X, y.reshape(-1, 1)], axis=1), columns=["x1", "x2", "y"])
display(data)
gnb = GaussianNB()
gnb.fit(X, y)
# 每個類別的先驗概率。P(y)
print("概率:", gnb.class_prior_)
# 每個類別樣本的數量。
print("樣本數量:", gnb.class_count_)
# 每個類別的標籤。
print("標籤", gnb.classes_)
# 每個特徵在每個類別下的均值。
print("均值:", gnb.theta_)
# 每個特徵在每個類別下的方差。
print("標準差:", gnb.sigma_)
# 測試集
X_test = np.array([[6, 3]])
print("預測結果:", gnb.predict(X_test))
print("預測結果概率:",gnb.predict_proba(X_test))
結果:
3.1.2 伯努利樸素貝葉斯(離散變量&二項分佈)
設實驗只有兩個可能的結果:
伯努利樸素貝葉斯,適用於離散變量,其假設各個特徵xi 在各個類別y下是服從n 重伯努利分佈(二項分佈)的,因爲伯努利試驗僅有兩個結果,因此,算法會首先對特徵值進行二值化處理(假設二值化的結果爲1與0)。即,大於0的認爲是1,小於等於0的認爲是0。
P(xi | y)計算方式如下:
在訓練集中,會進行如下的估計:
因爲在數據集中,只有兩種取值(1與0),因此,對於給定的類別與特徵,只需要計算P(xi =1 | y)就可以了,而P(xi = 0 | y)的概率,用1減去P(xi =1 | y)即可得出。
from sklearn.naive_bayes import BernoulliNB # 伯努利樸素貝葉斯
np.random.seed(0)
X = np.random.randint(-5, 5, size=(6, 2))
y = np.array([0, 0, 0, 1, 1, 1])
data = pd.DataFrame(np.concatenate([X, y.reshape(-1, 1)], axis=1), columns=["x1", "x2", "y"])
display(data)
bnb = BernoulliNB()
bnb.fit(X, y)
# 每個特徵在每個類別下發生(出現)的次數。因爲伯努利分佈只有兩個值,
# 我們只需要計算出現的概率P(x=1|y),不出現的概率P(x=0|y)使用1減去P(x=1|y)即可。
print("數值1出現次數:", bnb.feature_count_)
# 每個類別樣本所佔的比重,即P(y)。注意,該值爲概率取對數之後的結果,如果需要查看
# 原有的概率,需要使用指數還原。
print("類別佔比p(y):", np.exp(bnb.class_log_prior_))
# 每個類別下,每個特徵(值爲1)所佔的比例(概率),即P(x|y)。注意,該值爲概率
#取對數之後的結果,如果需要查看原有的概率,需要使用指數還原。
print("特徵概率:", np.exp(bnb.feature_log_prob_))
結果:
數值1出現的次數:當y類別爲0的時候,x1和x2大於0的有兩個,即[1,1];
類別y爲1的時候,x1和x2大於0的也分別只有1個,所以[1,1]。
大於1 代表1發生的概率,沒有大於1 就是0發生的概率。
特徵概率:即P(x=1 | y)
P(x1=1 | y=0)
P(x1=2 | y=0)
P(x1=1 | y=1)
P(x1=2 | y=1)
我們來計算其中一個,y=0時,x1=1的概率。
那結果爲什麼是0.4呢,因爲我們默認情況下有拉普拉斯平滑α,即:
(1+α) / (3+k*α) = (1+1) / (3+2) = 1/4 ,(k在伯努利樸素貝葉斯中固定爲2)。
其他的都是一樣的計算方式。
3.1.3 多項式樸素貝葉斯(離散變量&多項式分佈)
多項式樸素貝葉斯,適用於離散變量,其假設各個特徵在各個類別下是服從多項式分佈的,故每個特徵值不能是負數。
計算數量個數。
P(xi | y)計算如下:
from sklearn.naive_bayes import MultinomialNB # 多項式樸素貝葉斯
np.random.seed(0)
X = np.random.randint(0, 4, size=(6, 2))
y = np.array([0, 0, 0, 1, 1, 1])
data = pd.DataFrame(np.concatenate([X, y.reshape(-1, 1)], axis=1), columns=["x1", "x2", "y"])
display(data)
mnb = MultinomialNB()
mnb.fit(X, y)
# 每個類別的樣本數量。
print("每個類別的樣本數量:",mnb.class_count_)
# 每個特徵在每個類別下發生(出現)的次數。
print("每個特徵在每個類別下發生(出現)的次數:",mnb.feature_count_)
# 每個類別下,每個特徵所佔的比例(概率),即P(x|y)。注意,該值爲概率
# 取對數之後的結果,如果需要查看原有的概率,需要使用指數還原。
print("每個特徵所佔的比例(概率):",np.exp(mnb.feature_log_prob_))
結果:
每個特徵在每個類別下發生(出現)的次數:
當y=0時,x1出現1+3=4次;
當y=0時,x2出現3+3=6次;
當y=1時,x1出現3+1+1=5次;
當y=1時,x2出現3+3+2=8次。
即[4,6],[5,8]
每個類別下,每個特徵所佔的比例(概率),即P(x|y)。
我們舉其中一個例子來說明:
當y=0時,x1=1的概率,即P(x1=1 | y=0):
當y=0時,所有特徵發生了0+1+3+3+0+3=10次,x1出現0+1+3=4次,所以是4/10=0.4,但是結果是0.41666667,因爲還有拉普拉斯平滑,即(4+α)/ (10 + αn) = (4+1)/ (10+12)=5/12=0.41666667。
其他概率計算方式一樣。
練習:
如果對鳶尾花數據集進行分類,哪種樸素貝葉斯算法效果可能會更好?(
A
)
A 高斯樸素貝葉斯
B 伯努利樸素貝葉斯
C 多項式樸素貝葉斯
D 差不多
鳶尾花數據集是連續性數據並且服從正態分佈,所以選擇高斯樸素貝葉斯更合適。
我麼通過代碼來檢驗下對於鳶尾花數據集來說哪一種方式會更好:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=0)
models = [("多項式樸素貝葉斯:", MultinomialNB()),
("高斯樸素貝葉斯:", GaussianNB()), ("伯努利樸素貝葉斯:", BernoulliNB())]
for name, m in models:
m.fit(X_train, y_train)
print(name, m.score(X_test, y_test))
結果:
可以看到,高斯樸素貝葉斯的效果是最好的。
2、總結
- 概率基礎的相關概念。
- 全概率公式與貝葉斯公式。
- 樸素貝葉斯算法原理。
- 拉普拉斯平滑。
參考學習鏈接:
https://www.cnblogs.com/pinard/p/6069267.html
https://blog.csdn.net/qiu_zhi_liao/article/details/90671932