(本文所使用的Python庫和版本號: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )git
前面講到了使用邏輯迴歸分類器解決多分類問題(【火爐煉AI】機器學習009-用邏輯迴歸分類器解決多分類問題 ),可是解決多分類問題並非只有邏輯迴歸一種方法,此處咱們講解用樸素貝葉斯分類器來解決多分類問題。github
樸素貝葉斯的「樸素」,並非簡單的意思,而是指樣本的特徵之間是相互獨立的。在全部的機器學習分類算法中,樸素貝葉斯和其餘絕大部分分類算法都不一樣,其餘分類算法基本都是判別方法,即直接學習出特徵輸出Y和特徵向量X之間的關係,要麼是決策函數Y=f(X),要麼是條件分佈P(Y|X),可是樸素貝葉斯倒是生成方法,也就是直接找出特徵輸出Y和特徵向量X之間的聯合分佈P(X,Y),而後用P(Y|X)=P(X,Y)/P(X)得出。算法
樸素貝葉斯的優勢在於:1,有穩定的分類效率,2,對小規模數據表現很好,能處理多分類任務,適合增量式訓練,尤爲是數據量超出內存時,能夠一批一批的去增量訓練。3,對缺失數據不太敏感,算法比較簡單,經常使用於文本分類。dom
但樸素貝葉斯的缺點是:1,樸素貝葉斯算法有一個重要的使用前提:樣本的特徵屬性之間是相互獨立的,這使得樸素貝葉斯算法在知足這一條件的數據集上效果很是好,而不知足獨立性條件的數據集上,效果欠佳。理論上,樸素貝葉斯模型與其餘分類方法相比,有最小的偏差率,可是這一結果僅限於知足獨立性條件的數據集上。在實際應用中,屬性之間不太可能徹底獨立,特別是在特徵屬性個數很是多,且屬性之間相關性較大時,樸素貝葉斯分類效果不太好。2,須要知道先驗機率,且先驗機率不少時候取決於假設,假設的模型能夠有不少種,所以在某些時候會因爲假設的先驗模型的緣由致使預測效果不佳。3,因爲經過先驗和數據來決定後驗的機率從而決定分類,因此分類決策存在必定的錯誤率。4,對輸入數據的表達形式很敏感。機器學習
關於樸素貝葉斯模型的數學推導,能夠參考:https://blog.csdn.net/malele4th/article/details/79348473函數
本項目所使用的數據集參考《Python機器學習經典實例》中第二章提供的data_multivar數據集,下面是加載並分析該數據集的代碼。post
# 準備數據集
data_path='D:\PyProjects\DataSet/NaiveBayers/data_multivar.txt'
df=pd.read_csv(data_path,header=None)
# print(df.head())
# print(df.info()) # 查看數據信息,確保沒有錯誤
dataset_X,dataset_y=df.iloc[:,:-1],df.iloc[:,-1] # 拆分爲X和Y
# print(dataset_X.head())
# print(dataset_X.info())
# print('-'*100)
# print(dataset_y.head())
dataset_X=dataset_X.values
dataset_y=dataset_y.values
# print(dataset_X.shape) # (400, 2)
# print(dataset_y.shape) # (400,)
classes=list(set(dataset_y))
print('class Num: {}, class: {}'.format(len(classes), classes))
# 上面檢查加載沒有問題,一共有四個不一樣類別,類別名稱爲:0,1,2,3
複製代碼
-------------------------------------輸---------出--------------------------------學習
class Num: 4, class: [0, 1, 2, 3]測試
--------------------------------------------完-------------------------------------spa
上面從txt文件中加載了數據集,能夠看出,該數據集含有400個樣本,被平均分紅4個不一樣類別(0,1,2,3)。下面將這不一樣類別的數據集繪製到散點圖中,以觀察每一個類別的大概彙集位置。
# 數據集可視化
def visual_2D_dataset(dataset_X,dataset_y):
'''將二維數據集dataset_X和對應的類別dataset_y顯示在散點圖中'''
assert dataset_X.shape[1]==2,'only support dataset with 2 features'
plt.figure()
classes=list(set(dataset_y))
markers=['.',',','o','v','^','<','>','1','2','3','4','8'
,'s','p','*','h','H','+','x','D','d','|']
colors=['b','c','g','k','m','w','r','y']
for class_id in classes:
one_class=np.array([feature for (feature,label) in
zip(dataset_X,dataset_y) if label==class_id])
plt.scatter(one_class[:,0],one_class[:,1],marker=np.random.choice(markers,1)[0],
c=np.random.choice(colors,1)[0],label='class_'+str(class_id))
plt.legend()
visual_2D_dataset(dataset_X,dataset_y)
複製代碼
########################小**********結###############################
1,數據集的準備,分析,可視化等經常是機器學習的第一步,也是很是重要的一個部分,更是很是耗時的一個部分。
2,此處定義了一個數據集可視化函數,用於將具備兩個特徵屬性的數據集按照不一樣類別繪製到散點圖中。
#################################################################
在sklearn模塊中,一共有三個樸素貝葉斯分類方法,分別是GaussianNB, MultinomialNB和BernouliNB,其中,GaussianNB是先驗爲高斯分佈的樸素貝葉斯,適用於樣本特徵的分佈大部分是連續值的狀況;MultinomialNB是先驗爲多項式分佈的樸素貝葉斯,適用於樣本特徵的分佈大部分是多元離散值的狀況;BernouliNB是先驗爲伯努利分佈的樸素貝葉斯,適用於樣本特徵是二元離散值或者很稀疏的多元離散值的狀況。下面我分別用這三個分類方法來解決本項目的分類問題。
直接上代碼,構建模型後還測試了一下該模型在整個數據集上的表現:
# 使用GaussianNB分類器構建樸素貝葉斯模型
from sklearn.naive_bayes import GaussianNB
gaussianNB=GaussianNB()
gaussianNB.fit(dataset_X,dataset_y)
# 評估本模型在整個數據集上的表現
dataset_predict_y=gaussianNB.predict(dataset_X)
correct_predicts=(dataset_predict_y==dataset_y).sum()
accuracy=100*correct_predicts/dataset_y.shape[0]
print('GaussianNB, correct prediction num: {}, accuracy: {:.2f}%'
.format(correct_predicts,accuracy))
plot_classifier(gaussianNB,dataset_X,dataset_y)
複製代碼
-------------------------------------輸---------出--------------------------------
GaussianNB, correct prediction num: 398, accuracy: 99.50%
--------------------------------------------完-------------------------------------
很惋惜,貌似MultinomialNB分類器要求數據集的全部特徵屬性都是非負數,不然無法訓練。故而下面的代碼報錯。
# 使用MultinomialNB分類器構建樸素貝葉斯模型
from sklearn.naive_bayes import MultinomialNB
multinomialNB=MultinomialNB()
multinomialNB.fit(dataset_X,dataset_y)
# 此處報錯,multinomialNB的數據集的特徵屬性必須是非負數
# 評估本模型在整個數據集上的表現
dataset_predict_y_multi=multinomialNB.predict(dataset_X)
correct_predicts_multi=(dataset_predict_y_multi==dataset_y).sum()
accuracy=100*correct_predicts_multi/dataset_y.shape[0]
print('MultinomialNB, correct prediction num: {}, accuracy: {:.2f}%'
.format(correct_predicts,accuracy))
複製代碼
-------------------------------------輸---------出--------------------------------
ValueError: Input X must be non-negative
--------------------------------------------完-------------------------------------
構建和測試方法與GaussianNB幾乎同樣,代碼爲:
# 使用BernouliNB分類器構建樸素貝葉斯模型
from sklearn.naive_bayes import BernoulliNB
bernoulliNB=BernoulliNB()
bernoulliNB.fit(dataset_X,dataset_y)
# 評估本模型在整個數據集上的表現
dataset_predict_y_bern=bernoulliNB.predict(dataset_X)
correct_predicts_bern=(dataset_predict_y_bern==dataset_y).sum()
accuracy=100*correct_predicts_bern/dataset_y.shape[0]
print('BernoulliNB, correct prediction num: {}, accuracy: {:.2f}%'
.format(correct_predicts_bern,accuracy))
plot_classifier(bernoulliNB,dataset_X,dataset_y)
複製代碼
-------------------------------------輸---------出--------------------------------
BernoulliNB, correct prediction num: 195, accuracy: 48.75%
--------------------------------------------完-------------------------------------
########################小**********結###############################
1,雖然sklearn模塊中有三種樸素貝葉斯方法,但在同一個數據集上的表現卻大不相同,只有GaussianNB表現最好,可以正確的將四個數據集區分開來。
2,此處定義了一個數據集可視化函數,用於將具備兩個特徵屬性的數據集按照不一樣類別繪製到散點圖中,對於其餘項目這個函數也能夠直接使用。
3,這三種樸素貝葉斯方法中,MultinomialNB要求數據集中的特徵向量數值必須爲非負數,不然直接報錯。BernoulliNB雖然沒有報錯,可是從分類結果圖中能夠看到,結果很是不理想,能夠說徹底沒有起到分類的效果。
#################################################################
注:本部分代碼已經所有上傳到(個人github)上,歡迎下載。
參考資料:
1, Python機器學習經典實例,Prateek Joshi著,陶俊傑,陳小莉譯