(本文所使用的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著,陶俊杰,陈小莉译