【火爐煉AI】機(jī)器學(xué)習(xí)010-用樸素貝葉斯分類(lèi)器解決多分類(lèi)問(wèn)題
(本文所使用的Python庫(kù)和版本號(hào): Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )
前面講到了使用邏輯回歸分類(lèi)器解決多分類(lèi)問(wèn)題(【火爐煉AI】機(jī)器學(xué)習(xí)009-用邏輯回歸分類(lèi)器解決多分類(lèi)問(wèn)題 ),但是解決多分類(lèi)問(wèn)題并不是只有邏輯回歸一種方法,此處我們講解用樸素貝葉斯分類(lèi)器來(lái)解決多分類(lèi)問(wèn)題。
樸素貝葉斯的“樸素”,并不是簡(jiǎn)單的意思,而是指樣本的特征之間是相互獨(dú)立的。在所有的機(jī)器學(xué)習(xí)分類(lèi)算法中,樸素貝葉斯和其他絕大部分分類(lèi)算法都不同,其他分類(lèi)算法基本都是判別方法,即直接學(xué)習(xí)出特征輸出Y和特征向量X之間的關(guān)系,要么是決策函數(shù)Y=f(X),要么是條件分布P(Y|X),但是樸素貝葉斯卻是生成方法,也就是直接找出特征輸出Y和特征向量X之間的聯(lián)合分布P(X,Y),然后用P(Y|X)=P(X,Y)/P(X)得出。
樸素貝葉斯的優(yōu)點(diǎn)在于:1,有穩(wěn)定的分類(lèi)效率,2,對(duì)小規(guī)模數(shù)據(jù)表現(xiàn)很好,能處理多分類(lèi)任務(wù),適合增量式訓(xùn)練,尤其是數(shù)據(jù)量超出內(nèi)存時(shí),可以一批一批的去增量訓(xùn)練。3,對(duì)缺失數(shù)據(jù)不太敏感,算法比較簡(jiǎn)單,常用于文本分類(lèi)。
但樸素貝葉斯的缺點(diǎn)是:1,樸素貝葉斯算法有一個(gè)重要的使用前提:樣本的特征屬性之間是相互獨(dú)立的,這使得樸素貝葉斯算法在滿(mǎn)足這一條件的數(shù)據(jù)集上效果非常好,而不滿(mǎn)足獨(dú)立性條件的數(shù)據(jù)集上,效果欠佳。理論上,樸素貝葉斯模型與其他分類(lèi)方法相比,有最小的誤差率,但是這一結(jié)果僅限于滿(mǎn)足獨(dú)立性條件的數(shù)據(jù)集上。在實(shí)際應(yīng)用中,屬性之間不太可能完全獨(dú)立,特別是在特征屬性個(gè)數(shù)非常多,且屬性之間相關(guān)性較大時(shí),樸素貝葉斯分類(lèi)效果不太好。2,需要知道先驗(yàn)概率,且先驗(yàn)概率很多時(shí)候取決于假設(shè),假設(shè)的模型可以有很多種,因此在某些時(shí)候會(huì)由于假設(shè)的先驗(yàn)?zāi)P偷脑驅(qū)е骂A(yù)測(cè)效果不佳。3,由于通過(guò)先驗(yàn)和數(shù)據(jù)來(lái)決定后驗(yàn)的概率從而決定分類(lèi),所以分類(lèi)決策存在一定的錯(cuò)誤率。4,對(duì)輸入數(shù)據(jù)的表達(dá)形式很敏感。
關(guān)于樸素貝葉斯模型的數(shù)學(xué)推導(dǎo),可以參考:https://blog.csdn.net/malele4th/article/details/79348473
1. 準(zhǔn)備數(shù)據(jù)集
本項(xiàng)目所使用的數(shù)據(jù)集參考《Python機(jī)器學(xué)習(xí)經(jīng)典實(shí)例》中第二章提供的data_multivar數(shù)據(jù)集,下面是加載并分析該數(shù)據(jù)集的代碼。
# 準(zhǔn)備數(shù)據(jù)集
data_path='D:\PyProjects\DataSet/NaiveBayers/data_multivar.txt'
df=pd.read_csv(data_path,header=None)
# print(df.head())
# print(df.info()) # 查看數(shù)據(jù)信息,確保沒(méi)有錯(cuò)誤
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))
# 上面檢查加載沒(méi)有問(wèn)題,一共有四個(gè)不同類(lèi)別,類(lèi)別名稱(chēng)為:0,1,2,3
-------------------------------------輸---------出--------------------------------
class Num: 4, class: [0, 1, 2, 3]
--------------------------------------------完-------------------------------------
上面從txt文件中加載了數(shù)據(jù)集,可以看出,該數(shù)據(jù)集含有400個(gè)樣本,被平均分成4個(gè)不同類(lèi)別(0,1,2,3)。下面將這不同類(lèi)別的數(shù)據(jù)集繪制到散點(diǎn)圖中,以觀察每個(gè)類(lèi)別的大概聚集位置。
# 數(shù)據(jù)集可視化
def visual_2D_dataset(dataset_X,dataset_y):
'''將二維數(shù)據(jù)集dataset_X和對(duì)應(yīng)的類(lèi)別dataset_y顯示在散點(diǎn)圖中'''
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)
########################小**********結(jié)###############################
1,數(shù)據(jù)集的準(zhǔn)備,分析,可視化等常常是機(jī)器學(xué)習(xí)的第一步,也是非常重要的一個(gè)部分,更是非常耗時(shí)的一個(gè)部分。
2,此處定義了一個(gè)數(shù)據(jù)集可視化函數(shù),用于將具有兩個(gè)特征屬性的數(shù)據(jù)集按照不同類(lèi)別繪制到散點(diǎn)圖中。
#################################################################
2. 構(gòu)建樸素貝葉斯分類(lèi)器模型
在sklearn模塊中,一共有三個(gè)樸素貝葉斯分類(lèi)方法,分別是GaussianNB, MultinomialNB和BernouliNB,其中,GaussianNB是先驗(yàn)為高斯分布的樸素貝葉斯,適用于樣本特征的分布大部分是連續(xù)值的情況;MultinomialNB是先驗(yàn)為多項(xiàng)式分布的樸素貝葉斯,適用于樣本特征的分布大部分是多元離散值的情況;BernouliNB是先驗(yàn)為伯努利分布的樸素貝葉斯,適用于樣本特征是二元離散值或者很稀疏的多元離散值的情況。下面我分別用這三個(gè)分類(lèi)方法來(lái)解決本項(xiàng)目的分類(lèi)問(wèn)題。
2.1 使用GaussianNB分類(lèi)器構(gòu)建樸素貝葉斯模型
直接上代碼,構(gòu)建模型后還測(cè)試了一下該模型在整個(gè)數(shù)據(jù)集上的表現(xiàn):
# 使用GaussianNB分類(lèi)器構(gòu)建樸素貝葉斯模型
from sklearn.naive_bayes import GaussianNB
gaussianNB=GaussianNB()
gaussianNB.fit(dataset_X,dataset_y)
# 評(píng)估本模型在整個(gè)數(shù)據(jù)集上的表現(xiàn)
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%
--------------------------------------------完-------------------------------------
2.2 使用MultinomialNB分類(lèi)器構(gòu)建樸素貝葉斯模型
很可惜,貌似MultinomialNB分類(lèi)器要求數(shù)據(jù)集的所有特征屬性都是非負(fù)數(shù),否則沒(méi)法訓(xùn)練。故而下面的代碼報(bào)錯(cuò)。
# 使用MultinomialNB分類(lèi)器構(gòu)建樸素貝葉斯模型
from sklearn.naive_bayes import MultinomialNB
multinomialNB=MultinomialNB()
multinomialNB.fit(dataset_X,dataset_y)
# 此處報(bào)錯(cuò),multinomialNB的數(shù)據(jù)集的特征屬性必須是非負(fù)數(shù)
# 評(píng)估本模型在整個(gè)數(shù)據(jù)集上的表現(xiàn)
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
--------------------------------------------完-------------------------------------
2.3 使用BernouliNB分類(lèi)器構(gòu)建樸素貝葉斯模型
構(gòu)建和測(cè)試方法與GaussianNB幾乎一樣,代碼為:
# 使用BernouliNB分類(lèi)器構(gòu)建樸素貝葉斯模型
from sklearn.naive_bayes import BernoulliNB
bernoulliNB=BernoulliNB()
bernoulliNB.fit(dataset_X,dataset_y)
# 評(píng)估本模型在整個(gè)數(shù)據(jù)集上的表現(xiàn)
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%
--------------------------------------------完-------------------------------------
########################小**********結(jié)###############################
1,雖然sklearn模塊中有三種樸素貝葉斯方法,但在同一個(gè)數(shù)據(jù)集上的表現(xiàn)卻大不相同,只有GaussianNB表現(xiàn)最好,能夠正確的將四個(gè)數(shù)據(jù)集區(qū)分開(kāi)來(lái)。
2,此處定義了一個(gè)數(shù)據(jù)集可視化函數(shù),用于將具有兩個(gè)特征屬性的數(shù)據(jù)集按照不同類(lèi)別繪制到散點(diǎn)圖中,對(duì)于其他項(xiàng)目這個(gè)函數(shù)也可以直接使用。
3,這三種樸素貝葉斯方法中,MultinomialNB要求數(shù)據(jù)集中的特征向量數(shù)值必須為非負(fù)數(shù),否則直接報(bào)錯(cuò)。BernoulliNB雖然沒(méi)有報(bào)錯(cuò),但是從分類(lèi)結(jié)果圖中可以看到,結(jié)果非常不理想,可以說(shuō)完全沒(méi)有起到分類(lèi)的效果。
#################################################################
注:本部分代碼已經(jīng)全部上傳到(我的github)上,歡迎下載。
參考資料:
1, Python機(jī)器學(xué)習(xí)經(jīng)典實(shí)例,Prateek Joshi著,陶俊杰,陳小莉譯