Python機器學習筆記:朴素貝葉斯算法


  朴素貝葉斯是經典的機器學習算法之一,也是為數不多的基於概率論的分類算法。對於大多數的分類算法,在所有的機器學習分類算法中,朴素貝葉斯和其他絕大多數的分類算法都不同。比如決策樹,KNN,邏輯回歸,支持向量機等,他們都是判別方法,也就是直接學習出特征輸出Y和特征X之間的關系,要么是決策函數,要么是條件分布。但是朴素貝葉斯卻是生成方法,該算法原理簡單,也易於實現。

1,基本概念

  朴素貝葉斯:貝葉斯分類是一類分類算法的總稱,這類算法均以貝葉斯定理為基礎,故統稱為貝葉斯分類。而朴素貝葉斯分類時貝葉斯分類中最簡單,也是最常見的一種分類方法。

  貝葉斯公式

(X:特征向量, Y:類別)

  先驗概率P(X):先驗概率是指根據以往經驗和分析得到的概率。

  后驗概率P(Y|X):事情已經發生,要求這件事情發生的原因是由某個因素引起的可能性的大小,后驗分布P(Y|X)表示事件X已經發生的前提下,事件Y發生的概率,叫做事件X發生下事件Y的條件概率。

  后驗概率P(X|Y):在已知Y發生后X的條件概率,也由於知道Y的取值而被稱為X的后驗概率。

  朴素:朴素貝葉斯算法是假設各個特征之間相互獨立,也是朴素這詞的意思,那么貝葉斯公式中的P(X|Y)可寫成:

  朴素貝葉斯公式

 

2,貝葉斯算法簡介

  貝葉斯方法源域它生前為解決一個“逆概”問題寫的一篇文章。其要解決的問題:

  正向概率:假設袋子里面有N個白球,M個黑球,你伸手進去摸一把,摸出黑球的概率是多大

  逆向概率:如果我們事先不知道袋子里面黑白球的比例,而是閉着眼睛摸出一個(或者好幾個)球,觀察這些取出來的球的顏色之后,那么我們可以就此對袋子里面的黑白球的比例做出什么樣的推測。

  那么什么是貝葉斯呢?

  • 1,現實世界本身就是不確定的,人類的觀察能力是有局限性的
  • 2,我們日常觀察到的只是事物表明上的結果,因此我們需要提供一個猜測

  NaiveBayes算法,又稱朴素貝葉斯算法。朴素:特征條件獨立;貝葉斯:基於貝葉斯定理。屬於監督學習的生成模型,實現監督,沒有迭代,並有堅實的數學理論(即貝葉斯定理)作為支撐。在大量樣本下會有較好的表現,不適用於輸入向量的特征條件有關聯的場景。

  朴素貝葉斯會單獨考量每一維獨立特征被分類的條件概率,進而綜合這些概率並對其所在的特征向量做出分類預測。因此,朴素貝葉斯的基本數據假設是:各個維度上的特征被分類的條件概率之間是相互獨立的。它經常被用於文本分類中,包括互聯網新聞的分類,垃圾郵件的篩選。

  朴素貝葉斯分類時一種十分簡單的分類算法,叫他朴素貝葉斯分類時因為這種方法的思想真的很朴素,朴素貝葉斯的思想基礎是這樣的:對於給出的待分類項,求解在此項出現的條件下各個類別出現的概率,哪個最大,即認為此待分類項屬於哪個類別。

3,朴素貝葉斯的推導過程

  貝葉斯學派很古老,但是從誕生到一百年前一直不是主流。主流是頻率學派。頻率學派的權威皮爾遜和費歇爾都對貝葉斯學派不屑一顧,但是貝葉斯學派硬是憑借着在現代特定領域的出色應用表現為自己贏得了半壁江山。

   貝葉斯學派的思想可以概括為先驗概率 + 數據 = 后驗概率。也就是說我們在實際問題中需要得到的后驗概率,可以通過先驗概率和數據一起綜合得到。數據大家好理解,被頻率學派攻擊的是先驗概率,一般來說先驗概率就是我們對於數據所在領域的歷史經驗,但是這個經驗常常難以量化或者模型化,於是貝葉斯學派大膽的假設先驗分布的模型,比如正態分布,beta分布等。這個假設一般沒有特定的依據,因此一直被頻率學派認為很荒謬。雖然難以從嚴密的數學邏輯推出貝葉斯學派的邏輯,但是在很多實際應用中,貝葉斯理論很好用,比如垃圾郵件分類,文本分類。

  條件概率就是事件X在另外一個事件Y已經發生條件下的概率。條件概率表示為P(X|Y)。

  我們先看看條件獨立公式,如果X和Y相互獨立,則由:

  我們接着看條件概率公式:

  或者說:

  接着看看全概公式:

  從上面的公式很容易得出貝葉斯公式:

3.1 完整的推導過程

  這里我們從條件概率的定義推導出貝葉斯定理,其實上面已經推導了,但是這個更簡潔一些,所以使用一個叫聯合概率的概念。

  聯合概率:表示兩件事共同發生(數學概念上的交集)的概念,A和B的聯合概率表示為

 P(AnB)。

  根據條件概率的定義,在事件B發生的條件下事件A發生的概率為:

  同樣地,在事件A發生的條件下事件B發生的概率為:

  結合這兩個方程式,我們可以得到:

  這個引理有時稱為概率乘法規則。上式兩邊同時除以P(A),若P(A)是非零的,我們可以得到貝葉斯定理:

 

   解釋:事件X在事件Y發生的條件下的概率,與事件Y在事件X發生的條件下的概率是不一樣的;然而這兩者是有確定關系的,貝葉斯定理就是這種關系的陳述。

  貝葉斯公式的用途在於通過已知三個概率來推測第四個概率。它的內容是:在 X 出現的前提下, Y 出現的概率等於 Y 出現的前提下 X 出現的概率乘以 Y 出現的概率再除以 X 出現的概率。通過聯系X和Y,計算從一個事件發生的情況下另一事件發生的概率,即從結果上追溯到源頭。

  通俗地講就是當你不能確定某一個事件發生的概率時,你可以依靠與該事件本質屬性相關的時間發生的概率去推測該事件發生的概率。用數學語言表達就是:支持某項屬性的事件發生的愈多,則該事件發生的可能性就愈大。這個推理過程有時候也叫貝葉斯推理。

 

4,朴素貝葉斯的模型

  從統計學知識回到我們的數據分析。假設我們的分類模型樣本是:

  即我們有 m 個樣本,每個樣本有 n 個特征,特征輸出有 K 個類別,定義為

  從樣本我們可以學習到朴素貝葉斯的先驗分布,接着學習到條件概率分布,然后我們就可以用貝葉斯公式得到X 和 Y 的聯合分布 P(X,Y)了。聯合分布P(X,Y)定義為:

  從上面的式子就可以看出比較容易通過最大似然法求出,得到的就是類別在訓練集里面出現的頻數。但是很難求出,這是一個超級復雜的有n個維度的條件分布。朴素貝葉斯模型在這里做一個大膽的假設,即 X 的n個維度之間相互獨立,這樣就可以得出:

  從上式可以看出,這個很難的條件分布大大的簡化了,但是這也可能帶來預測的不准確性。你會說我的特征之間非常不獨立怎么辦?如果真是非常不獨立的話,那就盡量不要使用朴素貝葉斯模型了,考慮使用其他的分類方法比較好。但是一般情況下,樣本的特征之間獨立這個條件的確是弱成立的,尤其是數據量非常大的時候。雖然我們犧牲了准確性,但是得到的好處是模型的條件分布的計算大大簡化了,這就是貝葉斯模型的選擇。

  最后回到我們要解決的問題,我們的問題是給定測試集的一個新樣本特征,我們如何判斷它屬於哪個類型?

  既然是貝葉斯模型,當然是后驗概率最大化來判斷分類了。我們只要計算出所有的K個條件概率,然后找出最大的條件概率對應的類別,這就是朴素貝葉斯的預測了。

 

5,一個簡單的貝葉斯例子

  舉個簡單的例子:

  一個學校的男女比例為6:4,男生總是穿長褲,女生則一半穿長褲一半穿裙子。

  正向概率:隨機選出一個學生,他(她)穿長褲的概率和穿裙子的概率是多大

  逆向概率:迎面走來一個穿長褲的學生,你只看得見他(她)穿的是否長褲,而無法確定他(她)的性別,你能夠推斷出他(她)是女生的概率是多大嗎?

  我們假設學校里面的總人數為 U 個

  穿長褲的男生的概率為: U*P(Boy)*P(Pants|Boy)

    P(Boy) 是男生的概率為:60%

    P(Pants|Boy) 是條件概率,即在Boy這個條件下穿長褲的概率是多大,這里是 100%,因為男孩都穿長褲

  穿長褲的女生的概率為:U*P(Girl)*P(Pants|Girl)

  而我們要求解的是:穿長褲的人里面有多少是女生

  穿長褲的總人數為: U*P(Boy)*P(Pants|Boy) + U*P(Girl)*P(Pants|Girl)

  P(Girl|Pants) = U * P(Girl) * P(Pants|Girl) / 穿長褲總數

  即 P(Girl|Pants)= U * P(Girl) * P(Pants|Girl) / [ U*P(Boy)*P(Pants|Boy) + U*P(Girl)*P(Pants|Girl) ]

  我們發現分母分子都有 U,那么我們可以消去:

  P(Girl|Pants) = P(Girl) * P(Pants|Girl) / [ P(Boy)*P(Pants|Boy) + P(Girl)*P(Pants|Girl) ]

  所以我們可以發現:

    分母其實就是 P(Pants) 

    分子其實就是P(Pants, Girl)

  所以:

    P(Girl|Pants) = P(Girl) * P(Pants|Girl) / P(Pants)

 

6,三種常見的貝葉斯模型

6.1,多項式模型(MultinomialNB)

  多項式朴素貝葉斯常用語文本分類,特征是單詞,值時單詞出現的次數。

  多項式模型在計算先驗概率P(Yk)和和條件概率P(Xi|Yk)時,會做出一些平滑處理,具體公式為:

  • N:樣本數
  • NYk:類別為Yk的樣本數
  • K:總的類別個數
  • α:平滑值

  • NYk,Xi:類別為Yk,且特征為X1的樣本數
  • n:特征X1可以選擇的數量

6.2,高斯模型(GaussianNB)

  當特征是連續變量的時候,假設特征分布為正態分布,根據樣本算出均值和方差,再求得概率。

  其中Ck為的第K類類別。Y的需要求出μk 和σk2 ,μk 在樣本類別Ck中,所有 Xj 的平均值。σk2 為在樣本類別 Ck 中,所有 Xj 的方差。

  GaussianNB類的主要參數僅有一個,即先驗概率priors,對應Y的各個類別的先驗概率 P(Y=Ck)。這個值默認不給出,如果不給出此時P(Y=Ck) = mk/m。其中m為訓練集樣本總數量,mk為輸出為第k類別的訓練集樣本數。如果給出的話就以priors為准。

  在使用GaussianNB 的 fit方法擬合數據后,我們可以進行預測。此時預測有三種方法,包括predict,predict_log_proba 和 predict_proba。

  predict方法就是我們最常用的預測方法,直接給出測試集的預測類別輸出。

  predict_proba則不同,它會給出測試集樣本在各個類別上預測的概率。容易理解,predict_proba預測出的各個類別概率里最大值對應的類別,也就是predict方法得到類別。

  predict_log_proba 和 predict_proba類似,它會給出測試集樣本在各個類別上預測的概率的一個對數轉化。轉化后 predict_log_proba 預測出的各個類別對數概率里的最大值對應的類別,也就是 predict 方法得到類別。

>>> from sklearn import datasets
>>> iris = datasets.load_iris()
>>> from sklearn.naive_bayes import GaussianNB
>>> gnb = GaussianNB()
>>> y_pred = gnb.fit(iris.data, iris.target).predict(iris.data)
>>> print("Number of mislabeled points out of a total %d points : %d"
...       % (iris.data.shape[0],(iris.target != y_pred).sum()))
Number of mislabeled points out of a total 150 points : 6

  

6.3,伯努利模型(BernoulliNB)

  伯努利模型適用於離散特征的情況,伯努利模型中每個特征的取值只能是1和0。

   此時 l 只有兩種取值。Xjl只能取值0或者1。

  BernoulliNB一共有四個參數,其中三個參數的名字和意義和MultinomialNB完全相同。唯一增加的一個參數是binarize。這個參數主要是用來幫BernoulliNB處理二項分布的,可以是數值或者不輸入。如果不輸入,則BernoulliNB認為每個數據特征已經是二元的。否則的話,小於binarize的會歸為一類,大於 binarize的會歸為另外一類。

  在使用BernoulliNB 的fit 或者 partial_fit 方法擬合數據后,我們可以進行預測,此時預測方法有三種。包括predict,predict_log_proba和predict_proba。由於方法和GaussianNB完全一樣,這里就不累述了。

7,算法流程

  我們假設訓練集為m個樣本n個維度,如下:

  共有K個特征輸出類別,分別為C1,C2,...Ck,每個特征輸出類別的樣本個數為m1,m2,...mk,在第k 個類別中,如果是離散特征,則特征Xj各個類別取值為mjl。其中l取值為1,2,...Sj,Sj為特征j不同的取值數。

  輸出為實例X(test)的分類。

7.1,准備工作階段

  此階段是為朴素貝葉斯分類做必要的准備,主要工作是根據具體情況確定特征屬性,並對每個特征屬性進行適當划分,然后由人工對一部分待分類項進行分類,形成訓練樣本集合。這一階段的輸入是所有待分類數據,輸出是特征屬性和訓練樣本。這一階段是整個朴素貝葉斯分類中唯一需要人工完成的階段,其質量對整個過程將有重要影響,分類器的質量很大程度上由特征屬性,特征屬性划分及訓練樣本質量決定。

  1,如果沒有Y的先驗概率,則計算Y的K個先驗概率:,否則為輸入的先驗概率。

  2,分別計算第K個類別的第 j 維特征的第 l 個取值條件概率:

    a) 如果是離散值:

    λ 可以取值為1,或者其他大於0 的數字。

    b)如果是稀疏二項離散值:

    此時 l 只有兩種取值。

    c)如果是連續值不需要計算各個 l 的取值概率,直接求正態分布的參數:

  需要求出μk 和σk2 ,μk 在樣本類別Ck中,所有 Xj 的平均值。σk2 為在樣本類別 Ck 中,所有 Xj 的方差。

  3,對於實例 X(test),分別計算:

  4,確定實例 X(test) 的分類Cresult

  從上面的計算可以看出,沒有復雜的求導和矩陣運算,因此效率很高。

7.2,分類器訓練階段

  這個階段的認為就是生成分類器,主要工作是計算每個類別在訓練樣本中的出現頻率及每個特征屬性划分對每個類別的條件概率估計,並將結果記錄。其輸入時特征屬性和訓練樣本,輸出是分類器。這一階段是機械性階段,根據前面討論的公式可以由程序自動計算完成。

7.3,應用階段

  這一階段的任務是使用分類器對待分類項進行分類,其輸入時分類器和待分類項,輸出是待分類項和類別的映射關系。這一階段也是機械性階段,由程序完成。

 

8,朴素貝葉斯算法優缺點小結

8.1  優點

1,朴素貝葉斯模型發源於古典數學理論,有穩定的分類效率

2,對小規模的數據表現很好,能處理多分類任務,適合增量式訓練,尤其是數據量超出內存時,我們可以一批批的去增量訓練

3,對缺失數據不太敏感,算法也比較簡單,常用於文本分類。

8.2  缺點

 1,理論上,朴素貝葉斯模型與其他分類方法相比具有最小的誤差率。但是實際上並非總是如此,這是因為朴素貝葉斯模型給定輸出類別的情況下,假設屬性之間相互獨立,這個假設在實際應用中往往是不成立的,在屬性個數比較多或者屬性之間相關性較大時,分類效果不好。而在屬性相關性較小的時,朴素貝葉斯性能最為良好。對於這一點,有半朴素貝葉斯之類的算法通過考慮部分關聯性適度改進。

2,需要知道先驗概率,且先驗概率很多時候取決於假設,假設的模型可以有很多種,因此在某些時候會由於假設的先驗模型的原因導致預測效果不佳。

3,由於我們是通過先驗和數據來決定后驗的概率從而決定分類,所以分類決策存在一定的錯誤率。

4,對輸入數據的表達形式很敏感。

 

 

Sklearn朴素貝葉斯類庫使用小結

  官網地址:請點擊我

  朴素貝葉斯是一類比較簡單的算法,scikit-learn中朴素貝葉斯類庫的使用也比較簡單。相對於決策樹,KNN之類的算法,朴素貝葉斯需要關注的參數是比較少的,這樣也比較容易掌握。

  在scikit-learn中,提供了三種朴素貝葉斯分類算法:GaussianNB(高斯分布的朴素貝葉斯),MultinomailNB(先驗為多項式分布的朴素貝葉斯),BernoulliNB(先驗為伯努利分布的朴素貝葉斯)。

  這三個類適用的分類場景各不相同,一般來說,如果樣本特征的分布大部分是連續值,適用GaussianNB會比較好。如果樣本特征的分布大部分是多元離散值,使用MultinomialNB比較合適。而如果樣本特征是二元離散值或者很稀疏的多元離散值,應該使用BernoulliNB。

1,高斯朴素貝葉斯

sklearn.naive_bayes.GaussianNB(priors=None)

1.1 利用GaussianNB建立簡單模型

import numpy as np
from sklearn.naive_bayes import GaussianNB
X = np.array([[-1, -1], [-2, -2], [-3, -3], [-4, -4], [1, 1], [2, 2], [3, 3]])
y = np.array([1, 1, 1, 1, 2, 2, 2])
clf = GaussianNB()
re = clf.fit(X, y)
print(re)
# GaussianNB(priors=None, var_smoothing=1e-09)

  

1.2  經過訓練集訓練后,觀察各個屬性值

re1 = clf.priors
# print(re1)  #None

# 設置priors參數值
re2 = clf.set_params(priors=[0.625, 0.375])
# print(re2)
# GaussianNB(priors=[0.625, 0.375], var_smoothing=1e-09)

# 返回各類標記對應先驗概率組成的列表
re3 = clf.priors
# print(re3)
# [0.625, 0.375]

  

1.3  priors屬性:獲取各個類標記對應的先驗概率

re4 = clf.class_prior_
# print(re4)
# [0.57142857 0.42857143]

re5 = type(clf.class_prior_)
# print(re5)
# <class 'numpy.ndarray'>

  

1.4 class_prior_屬性:同priors一樣,都是獲取各個類標記對應的先驗概率,區別在於priors屬性返回列表,class_prior_返回的是數組

re6 = clf.class_count_
# print(re6)
# [4. 3.]

  

1.5  class_count_屬性:獲取各類標記對應的訓練樣本數

re6 = clf.class_count_
# print(re6)
# [4. 3.]

  

1.6  theta_屬性:獲取各個類標記在各個特征上的均值

re7 = clf.theta_
# print(re7)
# [[-2.5 -2.5]
#  [ 2.   2. ]]

 

1.7  sigma_屬性:獲取各個類標記在各個特征上的方差

re8 = clf.sigma_
# print(re8)
# [[1.25000001 1.25000001]
#  [0.66666667 0.66666667]]

  

1.8 方法

  • get_params(deep=True):返回priors與其參數值組成字典
re9 = clf.get_params(deep=True)
# print(re9)
# {'priors': [0.625, 0.375], 'var_smoothing': 1e-09}

re10 = clf.get_params()
# print(re10)
# {'priors': [0.625, 0.375], 'var_smoothing': 1e-09}
  • set_params(**params):設置估計器priors參數
re11 = clf.set_params(priors=[0.625, 0.375])
# print(re11)
# GaussianNB(priors=[0.625, 0.375], var_smoothing=1e-09)
  • fit(X, sample_weight=None):訓練樣本,X表示特征向量,y類標記,sample_weight表示各樣本權重數組  
In [12]: clf.fit(X,y,np.array([0.05,0.05,0.1,0.1,0.1,0.2,0.2,0.2]))#設置樣本不同的權重
Out[12]: GaussianNB(priors=[0.625, 0.375])
 
In [13]: clf.theta_
Out[13]:
array([[-3.375, -3.375],
       [ 2.   ,  2.   ]])
 
In [14]: clf.sigma_
Out[14]:
array([[ 1.73437501,  1.73437501],
       [ 0.66666667,  0.66666667]])
  • partial_fit(X, y, classes=None, sample_weight=None):增量式訓練,當訓練數據集數據量非常大,不能一次性全部載入內存時,可以將數據集划分若干份,重復調用partial_fit在線學習模型參數,在第一次調用partial_fit函數時,必須指定classes參數,在隨后的的調用可以忽略。
In [18]: import numpy as np
    ...: from sklearn.naive_bayes import GaussianNB
    ...: X = np.array([[-1, -1], [-2, -2], [-3, -3],[-4,-4],[-5,-5], [1, 1], [2
    ...: ,  2], [3, 3]])
    ...: y = np.array([1, 1, 1,1,1, 2, 2, 2])
    ...: clf = GaussianNB()#默認priors=None
    ...: clf.partial_fit(X,y,classes=[1,2],sample_weight=np.array([0.05,0.05,0.
    ...: 1,0.1,0.1,0.2,0.2,0.2]))
    ...:
Out[18]: GaussianNB(priors=None)
 
In [19]: clf.class_prior_
Out[19]: array([ 0.4,  0.6])
  • predict(X):直接輸出測試集預測的類標記
In [20]: clf.predict([[-6,-6],[4,5]])
Out[20]: array([1, 2])
  • predict_proba(X):輸出測試樣本在各個類標記預測概率值
In [21]: clf.predict_proba([[-6,-6],[4,5]])
Out[21]:
array([[  1.00000000e+00,   4.21207358e-40],
       [  1.12585521e-12,   1.00000000e+00]])
  • predict_log_proba(X):輸出測試樣本在各個類標記上預測概率值對應對數值
In [22]: clf.predict_log_proba([[-6,-6],[4,5]])
Out[22]:
array([[  0.00000000e+00,  -9.06654487e+01],
       [ -2.75124782e+01,  -1.12621024e-12]])
  • score(X, y, sample_weight=None):返回測試樣本映射到指定類標記上的得分(准確率)
In [23]: clf.score([[-6,-6],[-4,-2],[-3,-4],[4,5]],[1,1,2,2])
Out[23]: 0.75
 
In [24]: clf.score([[-6,-6],[-4,-2],[-3,-4],[4,5]],[1,1,2,2],sample_weight=[0.3
    ...: ,0.2,0.4,0.1])
Out[24]: 0.59999999999999998

  

2,多項式朴素貝葉斯

  主要用於離散特征分類,例如文本分類單詞統計,以出現的次數作為特征值

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

  參數說明:

alpha:浮點型,可選項,默認1.0,添加拉普拉修/Lidstone平滑參數

fit_prior:布爾型,可選項,默認True,表示是否學習先驗概率,參數為
False表示所有類標記具有相同的先驗概率

class_prior:類似數組,數組大小為(n_classes,),默認None,類先驗概率

  

2.1 利用MultinomialNB建立簡單模型

In [2]: import numpy as np
   ...: from sklearn.naive_bayes import MultinomialNB
   ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5],[2,5,6,5],[3,4,5,6],[3,5,6,
   ...: 6]])
   ...: y = np.array([1,1,4,2,3,3])
   ...: clf = MultinomialNB(alpha=2.0)
   ...: clf.fit(X,y)
   ...:
Out[2]: MultinomialNB(alpha=2.0, class_prior=None, fit_prior=True)

2.2 經過訓練后,觀察各個屬性值

  • class_log_prior_:各類標記的平滑先驗概率對數值,其取值會受fit_prior和class_prior參數的影響

若指定了class_prior參數,不管fit_prior為True或False,class_log_prior_取值是class_prior轉換成log后的結果

In [4]: import numpy as np
   ...: from sklearn.naive_bayes import MultinomialNB
   ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5],[2,5,6,5],[3,4,5,6],[3,5,6,
   ...: 6]])
   ...: y = np.array([1,1,4,2,3,3])
   ...: clf = MultinomialNB(alpha=2.0,fit_prior=True,class_prior=[0.3,0.1,0.3,0
   ...: .2])
   ...: clf.fit(X,y)
   ...: print(clf.class_log_prior_)
   ...: print(np.log(0.3),np.log(0.1),np.log(0.3),np.log(0.2))
   ...: clf1 = MultinomialNB(alpha=2.0,fit_prior=False,class_prior=[0.3,0.1,0.3
   ...: ,0.2])
   ...: clf1.fit(X,y)
   ...: print(clf1.class_log_prior_)
   ...:
[-1.2039728  -2.30258509 -1.2039728  -1.60943791]
-1.20397280433 -2.30258509299 -1.20397280433 -1.60943791243
[-1.2039728  -2.30258509 -1.2039728  -1.60943791]

  

若fit_prior參數為False,class_prior=None,則各類標記的先驗概率相同等於類標記總個數N分之一

In [5]: import numpy as np
   ...: from sklearn.naive_bayes import MultinomialNB
   ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5],[2,5,6,5],[3,4,5,6],[3,5,6,
   ...: 6]])
   ...: y = np.array([1,1,4,2,3,3])
   ...: clf = MultinomialNB(alpha=2.0,fit_prior=False)
   ...: clf.fit(X,y)
   ...: print(clf.class_log_prior_)
   ...: print(np.log(1/4))
   ...:
[-1.38629436 -1.38629436 -1.38629436 -1.38629436]
-1.38629436112

  

若fit_prior參數為True,class_prior=None,則各類標記的先驗概率相同等於各類標記個數處以各類標記個數之和

In [6]: import numpy as np
   ...: from sklearn.naive_bayes import MultinomialNB
   ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5],[2,5,6,5],[3,4,5,6],[3,5,6,
   ...: 6]])
   ...: y = np.array([1,1,4,2,3,3])
   ...: clf = MultinomialNB(alpha=2.0,fit_prior=True)
   ...: clf.fit(X,y)
   ...: print(clf.class_log_prior_)#按類標記1、2、3、4的順序輸出
   ...: print(np.log(2/6),np.log(1/6),np.log(2/6),np.log(1/6))
   ...:
[-1.09861229 -1.79175947 -1.09861229 -1.79175947]
-1.09861228867 -1.79175946923 -1.09861228867 -1.79175946923

  

  • intercept_:將多項式朴素貝葉斯解釋的class_log_prior_映射為線性模型,其值和class_log_propr相同
In [7]: clf.class_log_prior_
Out[7]: array([-1.09861229, -1.79175947, -1.09861229, -1.79175947])
 
In [8]: clf.intercept_
Out[8]: array([-1.09861229, -1.79175947, -1.09861229, -1.79175947])

  

  • feature_log_prob_:指定類的各特征概率(條件概率)對數值,返回形狀為(n_classes, n_features)數組
In [9]: clf.feature_log_prob_
Out[9]:
array([[-2.01490302, -1.45528723, -1.2039728 , -1.09861229],
       [-1.87180218, -1.31218639, -1.178655  , -1.31218639],
       [-1.74919985, -1.43074612, -1.26369204, -1.18958407],
       [-1.79175947, -1.38629436, -1.23214368, -1.23214368]])

  

特征條件概率計算過程,以類為1各個特征對應的條件概率為例

In [9]: clf.feature_log_prob_
Out[9]:
array([[-2.01490302, -1.45528723, -1.2039728 , -1.09861229],
       [-1.87180218, -1.31218639, -1.178655  , -1.31218639],
       [-1.74919985, -1.43074612, -1.26369204, -1.18958407],
       [-1.79175947, -1.38629436, -1.23214368, -1.23214368]])
 
In [10]: print(np.log((1+1+2)/(1+2+3+4+1+3+4+4+4*2)),np.log((2+3+2)/(1+2+3+4+1+
    ...: 3+4+4+4*2)),np.log((3+4+2)/(1+2+3+4+1+3+4+4+4*2)),np.log((4+4+2)/(1+2+
    ...: 3+4+1+3+4+4+4*2)))
-2.01490302054 -1.45528723261 -1.20397280433 -1.09861228867

  

特征的條件概率=(指定類下指定特征出現的次數+alpha)/(指定類下所有特征出現次數之和+類的可能取值個數*alpha)

  • coef_:將多項式朴素貝葉斯解釋feature_log_prob_映射成線性模型,其值和feature_log_prob相同
In [11]: clf.coef_
Out[11]:
array([[-2.01490302, -1.45528723, -1.2039728 , -1.09861229],
       [-1.87180218, -1.31218639, -1.178655  , -1.31218639],
       [-1.74919985, -1.43074612, -1.26369204, -1.18958407],
       [-1.79175947, -1.38629436, -1.23214368, -1.23214368]])
  • class_count_:訓練樣本中各類別對應的樣本數,按類的順序排序輸出
In [12]: clf.class_count_
Out[12]: array([ 2.,  1.,  2.,  1.])
  • feature_count_:各類別各個特征出現的次數,返回形狀為(n_classes, n_features)數組
In [13]: clf.feature_count_
Out[13]:
array([[  2.,   5.,   7.,   8.],
       [  2.,   5.,   6.,   5.],
       [  6.,   9.,  11.,  12.],
       [  2.,   4.,   5.,   5.]])
 
 
In [14]: print([(1+1),(2+3),(3+4),(4+4)])#以類別1為例
[2, 5, 7, 8]

  

2.3 方法

  • fit(X, y, sample_weight=None):根據X、y訓練模型
In [15]: import numpy as np
    ...: from sklearn.naive_bayes import MultinomialNB
    ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5],[2,5,6,5],[3,4,5,6],[3,5,6
    ...: ,6]])
    ...: y = np.array([1,1,4,2,3,3])
    ...: clf = MultinomialNB(alpha=2.0,fit_prior=True)
    ...: clf.fit(X,y)
    ...:
Out[15]: MultinomialNB(alpha=2.0, class_prior=None, fit_prior=True)

  

  • get_params(deep=True):獲取分類器的參數,以各參數字典形式返回
In [16]: clf.get_params(True)
Out[16]: {'alpha': 2.0, 'class_prior': None, 'fit_prior': True}

  

  • partial_fit(X, y, classes=None, sample_weight=None):對於數據量大時,提供增量式訓練,在線學習模型參數,參數X可以是類似數組或稀疏矩陣,在第一次調用函數,必須制定classes參數,隨后調用時可以忽略
In [17]: import numpy as np
    ...: from sklearn.naive_bayes import MultinomialNB
    ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5],[2,5,6,5],[3,4,5,6],[3,5,6
    ...: ,6]])
    ...: y = np.array([1,1,4,2,3,3])
    ...: clf = MultinomialNB(alpha=2.0,fit_prior=True)
    ...: clf.partial_fit(X,y)
    ...: clf.partial_fit(X,y,classes=[1,2])
    ...:
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-17-b512d165c9a0> in <module>()
      4 y = np.array([1,1,4,2,3,3])
      5 clf = MultinomialNB(alpha=2.0,fit_prior=True)
----> 6 clf.partial_fit(X,y)
      7 clf.partial_fit(X,y,classes=[1,2])
 
ValueError: classes must be passed on the first call to partial_fit.
 
In [18]: import numpy as np
    ...: from sklearn.naive_bayes import MultinomialNB
    ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5],[2,5,6,5],[3,4,5,6],[3,5,6
    ...: ,6]])
    ...: y = np.array([1,1,4,2,3,3])
    ...: clf = MultinomialNB(alpha=2.0,fit_prior=True)
    ...: clf.partial_fit(X,y,classes=[1,2])
    ...: clf.partial_fit(X,y)
    ...:
    ...:
Out[18]: MultinomialNB(alpha=2.0, class_prior=None, fit_prior=True)

  

  • predict(X):在測試集X上預測,輸出X對應目標值
In [19]: clf.predict([[1,3,5,6],[3,4,5,4]])
Out[19]: array([1, 1])

  

  • predict_log_proba(X):測試樣本划分到各個類的概率對數值
In [22]: import numpy as np
    ...: from sklearn.naive_bayes import MultinomialNB
    ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5],[2,5,6,5],[3,4,5,6],[3,5,6
    ...: ,6]])
    ...: y = np.array([1,1,4,2,3,3])
    ...: clf = MultinomialNB(alpha=2.0,fit_prior=True)
    ...: clf.fit(X,y)
    ...:
Out[22]: MultinomialNB(alpha=2.0, class_prior=None, fit_prior=True)
 
In [23]: clf.predict_log_proba([[3,4,5,4],[1,3,5,6]])
Out[23]:
array([[-1.27396027, -1.69310891, -1.04116963, -1.69668527],
       [-0.78041614, -2.05601551, -1.28551649, -1.98548389]])

  

  • predict_proba(X):輸出測試樣本划分到各個類別的概率值
In [1]: import numpy as np
   ...: from sklearn.naive_bayes import MultinomialNB
   ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5],[2,5,6,5],[3,4,5,6],[3,5,6,
   ...: 6]])
   ...: y = np.array([1,1,4,2,3,3])
   ...: clf = MultinomialNB(alpha=2.0,fit_prior=True)
   ...: clf.fit(X,y)
   ...:
Out[1]: MultinomialNB(alpha=2.0, class_prior=None, fit_prior=True)
 
In [2]: clf.predict_proba([[3,4,5,4],[1,3,5,6]])
Out[2]:
array([[ 0.27972165,  0.18394676,  0.35304151,  0.18329008],

  

  • score(X, y, sample_weight=None):輸出對測試樣本的預測准確率的平均值
In [3]: clf.score([[3,4,5,4],[1,3,5,6]],[1,1])
Out[3]: 0.5

  

  • set_params(**params):設置估計器的參數
In [4]: clf.set_params(alpha=1.0)
Out[4]: MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)

  

3,伯努利朴素貝葉斯

  類似於多項式朴素貝葉斯,也主要用於離散特征分類,和MultinomialNB的區別是:MultinomialNB以出現的次數為特征值,BernnoulliNB為二進制或者布爾值特征

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

  參數說明:

binarize:將數據特征二值化的閾值

  

3.1  利用BernoulliNB建立簡單模型

In [5]: import numpy as np
   ...: from sklearn.naive_bayes import BernoulliNB
   ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5]])
   ...: y = np.array([1,1,2])
   ...: clf = BernoulliNB(alpha=2.0,binarize = 3.0,fit_prior=True)
   ...: clf.fit(X,y)
   ...:
Out[5]: BernoulliNB(alpha=2.0, binarize=3.0, class_prior=None, fit_prior=True)

  經過binarize=0.3二值化處理,相當於輸入的X數組為:

In [7]: X = np.array([[0,0,0,1],[0,0,1,1],[0,1,1,1]])
 
In [8]: X
Out[8]:
array([[0, 0, 0, 1],
       [0, 0, 1, 1],
       [0, 1, 1, 1]])

  

3.2  訓練后查看個屬性值

  • class_log_prior_:類先驗概率對數值,類先驗概率等於各類的個數/類的總個數
In [9]: clf.class_log_prior_
Out[9]: array([-0.40546511, -1.09861229])

  

  • feature_log_prob_ :指定類的各特征概率(條件概率)對數值,返回形狀為(n_classes, n_features)數組
Out[10]:
array([[-1.09861229, -1.09861229, -0.69314718, -0.40546511],
       [-0.91629073, -0.51082562, -0.51082562, -0.51082562]])

  

上述結果計算過程:
假設X對應的四個特征為A1、A2、A3、A4,類別為y1,y2,類別為y1時,特征A1的概率為:P(A1|y=y1) = P(A1=0|y=y1)*A1+P(A1=1|y=y1)*A1
In [11]: import numpy as np
    ...: from sklearn.naive_bayes import BernoulliNB
    ...: X = np.array([[1,2,3,4],[1,3,4,4],[2,4,5,5]])
    ...: y = np.array([1,1,2])
    ...: clf = BernoulliNB(alpha=2.0,binarize = 3.0,fit_prior=True)
    ...: clf.fit(X,y)
    ...: print(clf.feature_log_prob_)
    ...: print([np.log((2+2)/(2+2*2))*0+np.log((0+2)/(2+2*2))*1,np.log((2+2)/(2
    ...: +2*2))*0+np.log((0+2)/(2+2*2))*1,np.log((1+2)/(2+2*2))*0+np.log((1+2)/
    ...: (2+2*2))*1,np.log((0+2)/(2+2*2))*0+np.log((2+2)/(2+2*2))*1])
    ...:
[[-1.09861229 -1.09861229 -0.69314718 -0.40546511]
 [-0.91629073 -0.51082562 -0.51082562 -0.51082562]]
[-1.0986122886681098, -1.0986122886681098, -0.69314718055994529, -0.405465108108
16444]

  

  • class_count_:按類別順序輸出其對應的個數
In [12]: clf.class_count_
Out[12]: array([ 2.,  1.])

 

  • feature_count_:各類別各特征值之和,按類的順序輸出,返回形狀為[n_classes, n_features] 的數組
In [13]: clf.feature_count_
Out[13]:
array([[ 0.,  0.,  1.,  2.],
       [ 0.,  1.,  1.,  1.]])

  

3.3 方法

  類似於MultinomialNB的方法類似

 

Sklearn實戰一(多項式朴素貝葉斯)

  朴素貝葉斯模型被廣泛應用於海量互聯網文本分類任務。由於其較強的特征條件獨立假設,使得模型預測所需要顧及的參數規模從冪指數數量級向線性量級減少,極大的節約了內存消耗和計算時間。但是,也正是受這種強假設的限制,模型訓練時無法將各個特征之間的聯系考量在內,使得該模型在其他數據特征關聯性較強的分類任務上性能表現不佳。

 代碼:

#_*_coding:utf-8_*_
# 從sklearn.datasets中導入新聞數據抓取器
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
# 從sklearn.feature_extraction.text里導入文本特征向量化模板
from sklearn.feature_extraction.text import CountVectorizer
# 從sklearn.naive_bayes里導入朴素貝葉斯模型
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report

# 數據獲取
news = fetch_20newsgroups(subset='all')
# 輸出數據的條數  18846
print(len(news.data))

# 數據預處理:訓練集和測試集分割,文本特征向量化
# 隨機采樣25%的數據樣本作為測試集
X_train, X_test, y_train, y_test = train_test_split(
    news.data, news.target, test_size=0.25, random_state=33
)
# # 查看訓練樣本
# print(X_train[0])
# # 查看標簽
# print(y_train[0:100])

# 文本特征向量化
vec = CountVectorizer()
X_train = vec.fit_transform(X_train)
X_test = vec.transform(X_test)

# 使用朴素貝葉斯進行訓練
# 使用默認配置初始化朴素貝葉斯
mnb = MultinomialNB()
# 利用訓練數據對模型參數進行估計
mnb.fit(X_train, y_train)
# 對參數進行預測
y_predict = mnb.predict(X_test)

# 獲取結果報告
score = mnb.score(X_test, y_test)
print('The accuracy of Naive bayes Classifier is %s' %score)

res = classification_report(y_test, y_predict, target_names=news.target_names)
print(res)

  結果如下:

 

The accuracy of Naive bayes Classifier is 0.8397707979626485

  

 

 

 Sklearn實戰二(多項式朴素貝葉斯)

代碼:

#_*_coding:utf-8_*_

import pandas as pd
import numpy as np
import cv2
import time

from sklearn.model_selection import train_test_split
from sklearn.metrics  import accuracy_score

# 獲取數據
def load_data():
    # 讀取csv數據
    raw_data = pd.read_csv('train.csv', header=0)
    data = raw_data.values
    features = data[::, 1::]
    labels = data[::, 0]
    # 避免過擬合,采用交叉驗證,隨機選取33%數據作為測試集,剩余為訓練集
    train_X, test_X, train_y, test_y = train_test_split(features, labels, test_size=0.33, random_state=0)
    return train_X, test_X, train_y, test_y

# 二值化處理
def binaryzation(img):
    # 類型轉化成Numpy中的uint8型
    cv_img = img.astype(np.uint8)
    # 大於50的值賦值為0,不然賦值為1
    cv2.threshold(cv_img, 50, 1, cv2.THRESH_BINARY_INV, cv_img)
    return cv_img

# 訓練,計算出先驗概率和條件概率
def Train(trainset, train_labels):
    # 先驗概率
    prior_probability = np.zeros(class_num)
    # 條件概率
    conditional_probability = np.zeros((class_num, feature_len, 2))

    # 計算
    for i in range(len(train_labels)):
        # 圖片二值化,讓每一個特征都只有0, 1 兩種取值
        img = binaryzation(trainset[i])
        label = train_labels[i]

        prior_probability[label] += 1
        for j in range(feature_len):
            conditional_probability[label][j][img[j]] += 1

    # 將條件概率歸到 [1, 10001]
    for i in range(class_num):
        for j in range(feature_len):
            # 經過二值化后圖像只有0, 1 兩種取值
            pix_0 = conditional_probability[i][i][0]
            pix_1 = conditional_probability[i][j][1]
            # 計算0, 1像素點對應的條件概率
            probability_0 = (float(pix_0)/float(pix_0 + pix_1))*10000 + 1
            probability_1 = (float(pix_1)/float(pix_0 + pix_1))*10000 + 1

            conditional_probability[i][j][0] = probability_0
            conditional_probability[i][j][1] = probability_1

    return prior_probability, conditional_probability

# 計算概率
def calculate_probability(img, label):
    probability = int(prior_probability[label])
    for j in range(feature_len):
        probability *= int(conditional_probability[label][j][img[j]])
    return probability

# 預測
def Predict(testset, prior_probability, conditional_probability):
    predict = []
    # 對於每個輸入的X,將后驗概率最大的類作為X的類輸出
    for img in testset:
        # 圖像二值化
        img = binaryzation(img)

        max_label = 0
        max_probability = calculate_probability(img, 0)
        for j in range(1, class_num):
            probability = calculate_probability(img, j)
            if max_probability < probability:
                max_label = j
                max_probability = probability
        predict.append(max_label)
    return np.array(predict)


# MNIST數據集有10種labels,分別為“0,1,2,3,4,5,6,7,8,9
class_num = 10
feature_len = 784

if __name__ == '__main__':
    time_1 = time.time()
    train_X, test_X, train_y, test_y = load_data()
    prior_probability, conditional_probability = Train(train_X, train_y)
    test_predict = Predict(test_X, prior_probability, conditional_probability)
    score = accuracy_score(test_y, test_predict)
    print(score)

  需要數據的去我的GitHub上拿,地址:https://github.com/LeBron-Jian/MachineLearningNote

Sklearn實戰三(高斯朴素貝葉斯)

   代碼:

from sklearn import metrics
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler

# 讀取數據
X = []
Y = []
fr = open("datingTestSet.txt", encoding='utf-8')
print(fr)
index = 0
for line in fr.readlines():
    # print(line)
    line = line.strip()
    line = line.split('\t')
    X.append(line[:3])
    Y.append(line[-1])

# 歸一化
scaler = MinMaxScaler()
# print(X)
X = scaler.fit_transform(X)
# print(X)

# 交叉分類
train_X, test_X, train_y, test_y = train_test_split(X, Y, test_size=0.2)

#高斯貝葉斯模型
model = GaussianNB()
model.fit(train_X, train_y)

# 預測測試集數據
predicted = model.predict(test_X)
# 輸出分類信息
res = metrics.classification_report(test_y, predicted)
# print(res)
# 去重復,得到標簽類別
label = list(set(Y))
# print(label)
# 輸出混淆矩陣信息
matrix_info = metrics.confusion_matrix(test_y, predicted, labels=label)
# print(matrix_info)

  需要數據的去我的GitHub上拿,地址:https://github.com/LeBron-Jian/MachineLearningNote

 

完整代碼及其數據,請移步小編的GitHub

  傳送門:請點擊我

  如果點擊有誤:https://github.com/LeBron-Jian/MachineLearningNote

 

 

參考文獻:https://www.cnblogs.com/pinard/p/6069267.html

 https://www.cnblogs.com/youngsea/p/9327972.html

https://blog.csdn.net/qq_35044025/article/details/79322169

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM