scikit-learn 樸素貝葉斯類庫
樸素貝葉斯方法是基於貝葉斯定理的一組有監督學習算法,即“簡單”地假設每對特徵之間相互獨立。 給定一個類別 和一個從$ x_1$ 到 的相關的特徵向量, 貝葉斯定理闡述了以下關係:
使用簡單(navie)的假設-每對特徵之間都是相互獨立的:
可以對關係式進行化簡爲:
由於在給定的輸入中是常量,使用下面的分類規則:
我們可以使用最大後驗概率(Maximum A Posteriori, MAP) 來估計 和,前者是訓練集中類別 的相對頻率。各種各樣的的樸素貝葉斯分類器的差異大部分來自於處理分佈時的所做的假設不同。
儘管其假設過於簡單,在很多實際情況下,樸素貝葉斯工作得很好,特別是文檔分類和垃圾郵件過濾。這些工作都要求 一個小的訓練集來估計必需參數。相比於其他更復雜的方法,樸素貝葉斯學習器和分類器非常快。 分類條件分佈的解耦意味着可以獨立單獨地把每個特徵視爲一維分佈來估計。這樣反過來有助於緩解維度災難帶來的問題。
另一方面,儘管樸素貝葉斯被認爲是一種相當不錯的分類器,但卻不是好的估計器(estimator),所以不能太過於重視從predict_proba
輸出的概率。
1.高斯樸素貝葉斯
GaussianNB實現了運用於分類的高斯樸素貝葉斯算法。特徵的可能性(即概率)假設爲高斯分佈:
參數和使用極大似然然估計。
2. 多項分佈樸素貝葉斯
MultinomialNB實現了服從多項分佈數據的樸素貝葉斯算法,也是用於文本分類(這個領域中數據往往以詞向量表示,儘管在實踐中 tf-idf 向量在預測時表現良好)的兩大經典樸素貝葉斯算法之一。布參數由每類 的 向量決定, 式中 是特徵的數量(對於文本分類,是詞彙量的大小) 是樣本中屬於類 中特徵 概率。
參數 使用平滑過的最大似然估計法來估計,即相對頻率計數:
式中 是 訓練集 中 特徵 在類 中出現的次數, 是類 中出現所有特徵的計數總和。
先驗平滑因子 應用於在學習樣本中沒有出現的特徵,以防在將來的計算中出現0概率輸出。 把 被稱爲拉普拉斯平滑(Lapalce smoothing),而 被稱爲利德斯通平滑(Lidstone smoothing)。
3. 伯努利樸素貝葉斯
BernoulliNB實現了用於多重伯努利分佈數據的樸素貝葉斯訓練和分類算法,即有多個特徵,但每個特徵 都假設是一個二元 (Bernoulli, boolean) 變量。 因此,這類算法要求樣本以二元值特徵向量表示;如果樣本含有其他類型的數據, 一個BernoulliNB
實例會將其二值化(取決於binarize
參數)。
伯努利樸素貝葉斯的決策規則基於
與多項分佈樸素貝葉斯的規則不同 伯努利樸素貝葉斯明確地懲罰類中沒有出現作爲預測因子的特徵 ,而多項分佈分佈樸素貝葉斯只是簡單地忽略沒出現的特徵。
BernoulliNB
一共有4個參數,其中3個參數的名字和意義和MultinomialNB
完全相同。唯一增加的一個參數是binarize
。這個參數主要是用來幫BernoulliNB
處理二項分佈的,可以是數值或者不輸入。如果不輸入,則BernoulliNB
認爲每個數據特徵都已經是二元的。否則的話,小於binarize
的會歸爲一類,大於binarize
的會歸爲另外一類。
在文本分類的例子中,詞頻向量(word occurrence vectors)(而非詞數向量(word count vectors))可能用於訓練和用於這個分類器。 BernoulliNB
可能在一些數據集上可能表現得更好,特別是那些更短的文檔。實際使用時,最好對兩個模型都進行評估。
4. 在鶯尾花數據集上的測試代碼及結果
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn.preprocessing import StandardScaler
from sklearn.naive_bayes import GaussianNB, MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.neighbors import KNeighborsClassifier
#解決中文顯示亂碼的問題
from matplotlib.font_manager import FontProperties
myfont = FontProperties(fname='/home/liyuanshuo/Downloads/simheittf/simhei.ttf')
def iris_type(s):
it = {b'Iris-setosa': 0, b'Iris-versicolor': 1, b'Iris-virginica': 2}
return it[s]
def GasssianNB_test():
data = np.loadtxt('iris.data', dtype=float, delimiter=',', converters={4: iris_type})
print(data)
x, y = np.split(data, (4, ), axis=1)
x = x[:, :2]
print(x)
print(y)
gnb = Pipeline([('sc', StandardScaler()), ('clf', GaussianNB())])
gnb.fit(x, y.ravel())
#下面使用多項式分佈貝葉斯和K緊鄰分類作爲對比
# gnb = MultinomialNB().fit(x, y.ravel())
# gnb = KNeighborsClassifier(n_neighbors=5).fit(x, y.ravel())
#下面畫圖展示結果
N, M = 500, 500 #橫縱各採樣多少個值
x1_min, x1_max = x[:, 0].min(), x[:, 0].max() #第0列的範圍
x2_min, x2_max = x[:, 1].min(), x[:, 1].max() #第一列的範圍
t1 = np.linspace(x1_min, x1_max, N)
t2 = np.linspace(x2_min, x2_max, N)
x1, x2 = np.meshgrid(t1, t2) #生成網格採樣點
x_test = np.stack((x1.flat, x2.flat), axis=1) #測試點
# mpl.rcParams['font.sans-serif'] = ['simhei']
mpl.rcParams['axes.unicode_minus'] = False
# plt.rcParams['font.sans-serif'] = ['simhei']
plt.rcParams['axes.unicode_minus'] = False
cm_light = mpl.colors.ListedColormap(['#77E0A0', '#FF8080', '#A0A0FF'])
cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])
y_hat = gnb.predict(x_test) #預測值
y_hat = y_hat.reshape(x1.shape) #保證輸入和輸出的形狀相同
plt.figure(facecolor='w')
plt.pcolormesh(x1, x2, y_hat, cmap=cm_light) #顯示預測值
plt.scatter(x[:, 0], x[:, 1], c='y', edgecolors='k', s=50, cmap=cm_dark) #顯示樣本
plt.xlabel(u'花萼長度', fontsize=14, fontproperties=myfont)
plt.ylabel(u'花萼寬度', fontsize=14, fontproperties=myfont)
plt.xlim(x1_min, x1_max)
plt.ylim(x2_min, x2_max)
plt.title('GaussianNB對鶯尾花數據分類結果', fontsize=18, fontproperties=myfont)
plt.grid(True)
plt.show()
plt.savefig('GaussianNB對鶯尾花數據分類結果.png')
#訓練集上的預測結果
y_hat = gnb.predict(x)
y = y.reshape(-1)
result = y_hat==y
print(y_hat)
print(result)
acc = np.mean(result)
print('訓練集分類準確率: %.2f%%'%(100*acc))
if __name__ == '__main__':
GasssianNB_test()
結果圖片如下:
5使用隨機數據實現的代碼
import numpy as np
from sklearn.naive_bayes import GaussianNB, MultinomialNB
from sklearn import metrics
def MultinomialNB_test():
np.random.seed(0)
M = 20
N = 5
x = np.random.randint(2, size=(M, N))
x = np.array(list(set([tuple(t) for t in x])))
M = len(x)
y = np.arange(M)
print('樣本個數: %d,特徵數目: %d'%x.shape)
print('樣本爲:\n', x)
mnb = MultinomialNB(alpha=1)
mnb.fit(x, y)
y_hat = mnb.predict(x)
print('預測類別: ', y_hat)
print('預測準確率: %.2f%%'%(100*np.mean(y_hat==y)))
print('系統得分: ', mnb.score(x, y))
print('系統得分: ', metrics.accuracy_score(y, y_hat))
err = y_hat != y
for i, e in enumerate(err):
if e:
print(y[i], ': \t', x[i], '被認爲與', x[y_hat[i]], '一個類別')
if __name__ == '__main__':
MultinomialNB_test()s