【MATLAB】一行代碼實現(xiàn)樸素貝葉斯分類算法

樸素貝葉斯分類法是聚類分析的一種方法,關(guān)于什么是聚類分析,前文提過:

再提一次,聚類分析的目的就是根據(jù)個體的多個參數(shù),對群體進(jìn)行分類。數(shù)學(xué)上看就是輸入一個多維向量,輸出一個標(biāo)簽值。
樸素貝葉斯呢,就是聚類分析的一種,其實也是機器學(xué)習(xí)的一種。選擇一組經(jīng)過標(biāo)記類型的數(shù)據(jù)作為訓(xùn)練集,利用樸素貝葉斯方法計算模型參數(shù),再選擇一組數(shù)據(jù)作為測試集,去看剛才用訓(xùn)練集訓(xùn)練好的模型的分類正確率是多少。

那么,樸素貝葉斯方法如何對數(shù)據(jù)進(jìn)行分類呢?
這就得先介紹一下概率統(tǒng)計中的貝葉斯公式:

我們都知道條件概率公式

它表示在B發(fā)生的情況下A發(fā)生的概率。它的公式是AB同時發(fā)生的概率除以B發(fā)生的概率。

我們從全概空間的角度理解,它限定了全概空間是B,在這一全概空間內(nèi)發(fā)生A的概率就是條件概率。
如圖所示:全概空間是U,即U包含了所有可能發(fā)生的情況,U對應(yīng)的“面積”是1,內(nèi)部的概率大小對應(yīng)面積大小。AB同時發(fā)生的概率就是P(A∩B),對應(yīng)陰影面積;如果B已經(jīng)發(fā)生,那么全概空間就“塌縮”成為了B,總面積也縮小為P(B),因此AB同時發(fā)生的概率就是陰影面積:P(B)*P(A|B)。

反過來,自然也有在A發(fā)生的情況下,B發(fā)生的概率。

我們把P(A)乘到等式另一邊,就得到了下面的式子:

最后一步,我們把P(A∩B)=P(A)P(B|A)代入最開始的式子,我們就得到了貝葉斯公式:

這個公式將A發(fā)生的情況下B發(fā)生的概率與B發(fā)生的情況下A發(fā)生的概率聯(lián)系起來,可以用作預(yù)測。
P(A|B)是在B發(fā)生的條件下的A發(fā)生的概率。這在貝葉斯中被稱為”后驗概率“。即事件B發(fā)生后,重新評估事件A發(fā)生的概率。這也是樸素貝葉斯能做預(yù)測的原理。
P(A),P(B)是先驗概率,即人為經(jīng)驗提供的概率,比如基于大規(guī)模統(tǒng)計得到的概率,或者根據(jù)具體古典概型問題計算的概率。
貝葉斯公式大概是干這個用的:你在盒子里放了若干個黑球和白球,這個時候你一把抓出來幾個球,結(jié)果全是黑的,這個時候你會不會憑直覺認(rèn)為盒子里黑球比白球多一些?你再抓一大把,結(jié)果還全是黑的,你會不會覺得盒子里黑球比白球多很多很多?貝葉斯公式,就是把你的直覺定量化計算。
貝葉斯經(jīng)典例題是假陽性問題,假設(shè)某種疾病的人群發(fā)病率為0.001,現(xiàn)有一種檢測試劑在一個人得病的情況下,有99%的幾率呈現(xiàn)為陽性,而在人沒有得病的情況下,它仍有5%的幾率呈現(xiàn)為陽性。那么這種檢測方法是否能用于人群疾病普查呢?
要解決這個問題,我們計算一下,假如有一個人的結(jié)果為陽性,那么他的得病概率是多少呢?
設(shè)事件A表示為得病的概率,即P(A) = 0.001
,再設(shè)事件B為試劑結(jié)果為陽性的概率,我們瞎想得到條件概率P(A|B)
,即后驗概率。
P(A|B)=P(B|A)P(A)/P(B)=0.99×0.001/(0.99×0.001+0.05×0.999)≈0.02
注意這里的P(B)是利用全概空間計算得到的。B是陽性的概率,所有陽性的可能是:患病且陽性,不患病且陽性,因此P(B)=P(A)×0.99+(1-P(A))×0.05
得到結(jié)果:一個病人的試劑結(jié)果為陽性,他的患病概率也只有約2%。也就是說,這種方法不適用于大規(guī)模疾病普查。
樸素貝葉斯方法就是基于貝葉斯公式。大概是這樣:你給定一組數(shù)據(jù),根據(jù)數(shù)據(jù)分布算出先驗概率和條件分布概率。樸素貝葉斯法通過訓(xùn)練數(shù)據(jù)集學(xué)習(xí)聯(lián)合概率分布,也就是學(xué)習(xí)以下先驗概率分布及條件概率分布:
先驗分布:

條件概率分布:

我們注意到,交叉項概率是隨著參數(shù)的增多以指數(shù)形式增長的,為了避免概率項過多,樸素貝葉斯對條件概率分布做了條件獨立性假設(shè)。
即:

因此聯(lián)合分布就變成了各自的概率相乘。
下面展示一下樸素貝葉斯分類原理:
首先計算每一類的概率,這就是我們訓(xùn)練好的模型參數(shù)

然后對于新的點,我們利用貝葉斯公式計算發(fā)現(xiàn),在鄰域是綠色的情況下其為綠色的概率更大,因此判斷它是綠色的。

如果數(shù)據(jù)不是像上面那樣,而是一個連續(xù)變化的值,這種情況如何算概率呢?這種情況,我們假設(shè)數(shù)據(jù)滿足正態(tài)分布,我們就可以用數(shù)據(jù)計算正態(tài)分布的均值和方差,進(jìn)而得到概率密度函數(shù),我們就可以用這個概率密度函數(shù)去算每一個位置的概率了。

好了,最后還是說一下MATLAB實現(xiàn)方法:
創(chuàng)建貝葉斯模型:fitcnb
測試性能:loss
拿MATLAB說明文檔的例子來說吧:
用樸素貝葉斯分類垃圾郵件:
1.Create Training Data 創(chuàng)建訓(xùn)練集
Suppose you observed 1000 emails and classified them as spam or not spam. Do this by randomly assigning -1 or 1 to y?for each email.
n = 1000; ? ? ? ? ? ? ? ? ? ? ? % Sample size
rng(1); ? ? ? ? ? ? ? ? ? ? ? ? % For reproducibility
Y = randsample([-1 1],n,true); ?% Random labels
2.特征描述
假設(shè)郵件內(nèi)的信息只包含20個字母,且只由5個字母租車給,而垃圾郵件和非垃圾郵件的字母出現(xiàn)概率不同。
tokenProbs = [0.2 0.3 0.1 0.15 0.25;...? ?
0.4 0.1 0.3 0.05 0.15]; ? ? ? ? ? ? % Token relative frequencies ?
tokensPerEmail = 20; ? ? ? ? ? ? ? ? ? ?% Fixed for convenience
X = zeros(n,5);?
X(Y == 1,:) = mnrnd(tokensPerEmail,tokenProbs(1,:),sum(Y == 1));?
X(Y == -1,:) = mnrnd(tokensPerEmail,tokenProbs(2,:),sum(Y == -1));
3.模型訓(xùn)練
Mdl = fitcnb(X,Y,'DistributionNames','mn');
4.性能測試
isGenRate = resubLoss(Mdl,'LossFun','ClassifErr')
5.生成測試集
newN = 500;?
newY = randsample([-1 1],newN,true);?
newX = zeros(newN,5);?
newX(newY == 1,:) = mnrnd(tokensPerEmail,tokenProbs(1,:),... ? ?sum(newY == 1)); newX(newY == -1,:) = mnrnd(tokensPerEmail,tokenProbs(2,:),... ? ?sum(newY == -1));
6.測試對測試集識別率
oosGenRate = loss(Mdl,newX,newY)
模型的計算只需要一行代碼:Model1=fitcnb(X,Y);是不是很簡單!
參考資料:
1.MATLAB說明文檔:https://ww2.mathworks.cn/help/stats/classification-naive-bayes.html
2.維基百科
3.《統(tǒng)計學(xué)習(xí)方法》(李航)