【火炉炼AI】机器学习010-用朴素贝叶斯分类器解决多分类问题

【火炉炼AI】机器学习010-用朴素贝叶斯分类器解决多分类问题

(本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

前面讲到了使用逻辑回归分类器解决多分类问题(【火炉炼AI】机器学习009-用逻辑回归分类器解决多分类问题 ),但是解决多分类问题并不是只有逻辑回归一种方法,此处我们讲解用朴素贝叶斯分类器来解决多分类问题。

朴素贝叶斯的“朴素”,并不是简单的意思,而是指样本的特征之间是相互独立的。在所有的机器学习分类算法中,朴素贝叶斯和其他绝大部分分类算法都不同,其他分类算法基本都是判别方法,即直接学习出特征输出Y和特征向量X之间的关系,要么是决策函数Y=f(X),要么是条件分布P(Y|X),但是朴素贝叶斯却是生成方法,也就是直接找出特征输出Y和特征向量X之间的联合分布P(X,Y),然后用P(Y|X)=P(X,Y)/P(X)得出。

朴素贝叶斯的优点在于:1,有稳定的分类效率,2,对小规模数据表现很好,能处理多分类任务,适合增量式训练,尤其是数据量超出内存时,可以一批一批的去增量训练。3,对缺失数据不太敏感,算法比较简单,常用于文本分类。

但朴素贝叶斯的缺点是:1,朴素贝叶斯算法有一个重要的使用前提:样本的特征属性之间是相互独立的,这使得朴素贝叶斯算法在满足这一条件的数据集上效果非常好,而不满足独立性条件的数据集上,效果欠佳。理论上,朴素贝叶斯模型与其他分类方法相比,有最小的误差率,但是这一结果仅限于满足独立性条件的数据集上。在实际应用中,属性之间不太可能完全独立,特别是在特征属性个数非常多,且属性之间相关性较大时,朴素贝叶斯分类效果不太好。2,需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳。3,由于通过先验和数据来决定后验的概率从而决定分类,所以分类决策存在一定的错误率。4,对输入数据的表达形式很敏感。

关于朴素贝叶斯模型的数学推导,可以参考:https://blog.csdn.net/malele4th/article/details/79348473


1. 准备数据集

本项目所使用的数据集参考《Python机器学习经典实例》中第二章提供的data_multivar数据集,下面是加载并分析该数据集的代码。

# 准备数据集
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]

--------------------------------------------完-------------------------------------

上面从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,此处定义了一个数据集可视化函数,用于将具有两个特征属性的数据集按照不同类别绘制到散点图中。

#################################################################


2. 构建朴素贝叶斯分类器模型

在sklearn模块中,一共有三个朴素贝叶斯分类方法,分别是GaussianNB, MultinomialNB和BernouliNB,其中,GaussianNB是先验为高斯分布的朴素贝叶斯,适用于样本特征的分布大部分是连续值的情况;MultinomialNB是先验为多项式分布的朴素贝叶斯,适用于样本特征的分布大部分是多元离散值的情况;BernouliNB是先验为伯努利分布的朴素贝叶斯,适用于样本特征是二元离散值或者很稀疏的多元离散值的情况。下面我分别用这三个分类方法来解决本项目的分类问题。

2.1 使用GaussianNB分类器构建朴素贝叶斯模型

直接上代码,构建模型后还测试了一下该模型在整个数据集上的表现:

# 使用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%

--------------------------------------------完-------------------------------------

GaussianNB分类器分类结果

2.2 使用MultinomialNB分类器构建朴素贝叶斯模型

很可惜,貌似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

--------------------------------------------完-------------------------------------

2.3 使用BernouliNB分类器构建朴素贝叶斯模型

构建和测试方法与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%

--------------------------------------------完-------------------------------------

使用BernouliNB分类器得到的分类结果

########################小**********结###############################

1,虽然sklearn模块中有三种朴素贝叶斯方法,但在同一个数据集上的表现却大不相同,只有GaussianNB表现最好,能够正确的将四个数据集区分开来。

2,此处定义了一个数据集可视化函数,用于将具有两个特征属性的数据集按照不同类别绘制到散点图中,对于其他项目这个函数也可以直接使用。

3,这三种朴素贝叶斯方法中,MultinomialNB要求数据集中的特征向量数值必须为非负数,否则直接报错。BernoulliNB虽然没有报错,但是从分类结果图中可以看到,结果非常不理想,可以说完全没有起到分类的效果。

#################################################################


注:本部分代码已经全部上传到(我的github)上,欢迎下载。

参考资料:

1, Python机器学习经典实例,Prateek Joshi著,陶俊杰,陈小莉译

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容