贝叶斯分类器_Sklearn 中的朴素贝叶斯分类器

(给Python开发者加星标,提升Python技能)

作者:Martin Müller,翻译:github-sisibeloved

https://github.com/xitu/gold-miner/blob/master/TODO1/naive-bayes-classifier-sklearn-python-example-tips.md

d2edf766b585fcdae6d78727b25f0cd5.png

用豆机实现的高斯分布

这篇教程详述了朴素贝叶斯分类器的算法、它的原理及优缺点,并提供了一个使用 Sklearn 库的示例。

背景

以著名的泰坦尼克号遇难者数据集为例。它收集了泰坦尼克号的乘客的个人信息以及是否从那场海难中生还。让我们试着用乘客的船票费用来预测一下他能否生还。

b16ee5c0c8312776fa9f5d7acccfe79b.png

泰坦尼克号上的 500 名乘客

假设你随机取了 500 名乘客。在这些样本中,30% 的人幸存下来。幸存乘客的平均票价为 100 美元,而遇难乘客的平均票价为 50 美元。现在,假设你有了一个新的乘客。你不知道他是否幸存,但你知道他买了一张 30 美元的票穿越大西洋。请你预测一下这个乘客是否幸存。

原理

好吧,你可能回答说这个乘客没能幸存。为什么?因为根据上文所取的乘客的随机子集中所包含的信息,本来的生还几率就很低(30%),而穷人的生还几率则更低。你会把这个乘客放在最可能的组别(低票价组)。这就是朴素贝叶斯分类器所要实现的。

分析

朴素贝叶斯分类器利用条件概率来聚集信息,并假设特征之间相对独立。这是什么意思呢?举个例子,这意味着我们必须假定泰坦尼克号的房间舒适度与票价无关。显然这个假设是错误的,这就是为什么我们将这个假设称为朴素(Naive)的原因。朴素假设使得计算得以简化,即使在非常大的数据集上也是如此。让我们来一探究竟。

朴素贝叶斯分类器本质上是寻找能描述给定特征条件下属于某个类别的概率的函数,这个函数写作 P(Survival | f1,…, fn)。我们使用贝叶斯定理来简化计算:

ed70d33a1dd8513890dda985862055b7.png

式 1:贝叶斯定理

P(Survival) 很容易计算,而我们构建分类器也不需要用到 P(f1,…, fn),因此问题回到计算 P(f1,…, fn | Survival) 上来。我们应用条件概率公式来再一次简化计算:

04146ef7615756eab2e04d3b01ddfaf6.png

式 2:初步拓展

上式最后一行的每一项的计算都需要一个包含所有条件的数据集。为了计算 {Survival, f_1, …, f_n-1} 条件下 fn 的概率(即 P(fn | Survival, f_1, …, f_n-1)),我们需要有足够多不同的满足条件 {Survival, f_1, …, f_n-1} 的 fn 值。这会需要大量的数据,并导致维度灾难。这时朴素假设(Naive Assumption)的好处就凸显出来了。假设特征是独立的,我们可以认为条件 {Survival, f_1, …, f_n-1} 的概率等于 {Survival} 的概率,以此来简化计算:

3df1298a209014ebfd3c4cd508d8b0e8.png

式 3:应用朴素假设

最后,为了分类,新建一个特征向量,我们只需要选择是否生还的值(1 或 0),令 P(f1, …, fn|Survival) 最高,即为最终的分类结果:

a7ef70db1ae300423279aaabd4630057.png

式 4:argmax 分类器

注意:常见的错误是认为分类器输出的概率是对的。事实上,朴素贝叶斯被称为差估计器,所以不要太认真地看待这些输出概率。

找出合适的分布函数

最后一步就是实现分类器。怎样为概率函数 P(f_i| Survival) 建立模型呢?在 Sklearn 库中有三种模型:

  • 高斯分布:假设特征连续,且符合正态分布.

cc21ddb44dc1e5e9b409ee843677954d.png

正态分布

  • 多项式分布:适合离散特征。

  • 贝努利分布:适合二元特征。

fff7086409830fc0df0585cad31d5322.png

二项式分布

Python 代码

接下来,基于泰坦尼克遇难者数据集,我们实现了一个经典的高斯朴素贝叶斯。我们将使用船舱等级、性别、年龄、兄弟姐妹数目、父母/子女数量、票价和登船口岸这些信息。

import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport timefrom sklearn.model_selection import train_test_splitfrom sklearn.naive_bayes import GaussianNB, BernoulliNB, MultinomialNB# 导入数据集data = pd.read_csv("data/train.csv")# 将分类变量转换为数字data["Sex_cleaned"]=np.where(data["Sex"]=="male",0,1)data["Embarked_cleaned"]=np.where(data["Embarked"]=="S",0,np.where(data["Embarked"]=="C",1,np.where(data["Embarked"]=="Q",2,3)))# 清除数据集中的非数字值(NaN)data=data[["Survived","Pclass","Sex_cleaned","Age","SibSp","Parch","Fare","Embarked_cleaned"]].dropna(axis=0, how='any')# 将数据集拆分成训练集和测试集X_train, X_test = train_test_split(data, test_size=0.5, random_state=int(time.time()))# 实例化分类器gnb = GaussianNB()used_features =["Pclass","Sex_cleaned","Age","SibSp","Parch","Fare","Embarked_cleaned"]# 训练分类器gnb.fit(X_train[used_features].values,X_train["Survived"])y_pred = gnb.predict(X_test[used_features])# 打印结果print("Number of mislabeled points out of a total {} points : {}, performance {:05.2f}%".format(X_test.shape[0],(X_test["Survived"] != y_pred).sum(),100*(1-(X_test["Survived"] != y_pred).sum()/X_test.shape[0])))
Number of mislabeled points out of a total 357 points: 68, performance 80.95%

这个分类器的正确率为 80.95%

使用单个特征说明

让我们试着只使用票价信息来约束分类器。下面我们计算 P(Survival = 1) 和 P(Survival = 0) 的概率:

mean_survival=np.mean(X_train["Survived"])mean_not_survival=1-mean_survivalprint("Survival prob = {:03.2f}%, Not survival prob = {:03.2f}%".format(100*mean_survival,100*mean_not_survival))
Survival prob = 39.50%, Not survival prob = 60.50%

然后,根据式 3,我们只需要得出概率分布函数 P(fare| Survival = 0) 和 P(fare| Survival = 1)。我们选用高斯朴素贝叶斯分类器,因此,必须假设数据按高斯分布。

160df2d9394725e3600a2a04a222c0cd.png

式 5:高斯公式(σ:标准差 / μ:均值)

然后,我们需要算出是否生还值不同的情况下,票价数据集的均值和标准差。我们得到以下结果:

mean_fare_survived = np.mean(X_train[X_train["Survived"]==1]["Fare"])std_fare_survived = np.std(X_train[X_train["Survived"]==1]["Fare"])mean_fare_not_survived = np.mean(X_train[X_train["Survived"]==0]["Fare"])std_fare_not_survived = np.std(X_train[X_train["Survived"]==0]["Fare"])print("mean_fare_survived = {:03.2f}".format(mean_fare_survived))print("std_fare_survived = {:03.2f}".format(std_fare_survived))print("mean_fare_not_survived = {:03.2f}".format(mean_fare_not_survived))print("std_fare_not_survived = {:03.2f}".format(std_fare_not_survived))
# 下面是结果mean_fare_survived = 54.75std_fare_survived = 66.91mean_fare_not_survived = 24.61std_fare_not_survived = 36.29

让我们看看关于生还和未生还的直方图的结果分布:

8660e2354927a05d62f062f2dcbad3f1.png

图 1:各个是否生还值的票价直方图和高斯分布(缩放等级并不对应)

可以发现,分布与数据集并没有很好地拟合。在实现模型之前,最好验证特征分布是否遵循上述三种模型中的一种。如果连续特征不具有正态分布,则应使用变换或不同的方法将其转换成正态分布。为了便于说明,这我们将分布看作是正态的。应用式 1 贝叶斯定理,可得以下这个分类器:

f0fd322dc26229511bb08da2ae56b777.png

图 2:高斯分类器

如果票价分类器的值超过 78(classifier(Fare) ≥ ~78),则 P(fare| Survival = 1) ≥ P(fare| Survival = 0),我们将这个人归类为生还。否则我们就将他归为未生还。我们得到了一个正确率为 64.15% 的分类器。

如果我们在同一数据集上训练 Sklearn 高斯朴素贝叶斯分类器,将会得到完全相同的结果:

from sklearn.naive_bayes import GaussianNBgnb = GaussianNB()used_features =["Fare"]y_pred = gnb.fit(X_train[used_features].values, X_train["Survived"]).predict(X_test[used_features])print("Number of mislabeled points out of a total {} points : {}, performance {:05.2f}%".format(X_test.shape[0],(X_test["Survived"] != y_pred).sum(),100*(1-(X_test["Survived"] != y_pred).sum()/X_test.shape[0])))print("Std Fare not_survived {:05.2f}".format(np.sqrt(gnb.sigma_)[0][0]))print("Std Fare survived: {:05.2f}".format(np.sqrt(gnb.sigma_)[1][0]))print("Mean Fare not_survived {:05.2f}".format(gnb.theta_[0][0]))print("Mean Fare survived: {:05.2f}".format(gnb.theta_[1][0]))
# 下面是结果Number of mislabeled points out of a total 357 points: 128, performance 64.15%Std Fare not_survived 36.29Std Fare survived: 66.91Mean Fare not_survived 24.61Mean Fare survived: 54.75

朴素贝叶斯分类器的优缺点

优点:

  • 计算迅速

  • 实现简单

  • 在小数据集上表现良好

  • 在高维度数据上表现良好

  • 即使朴素假设没有完全满足,也能表现良好。在许多情况下,建立一个好的分类器只需要近似的数据就够了。

缺点:

  • 需要移除相关特征,因为它们会在模型中被计算两次,这将导致该特征的重要性被高估。

  • 如果测试集中,某分类变量的一个类别没有在训练集中出现过,那么模型会把这种情况设为零概率。它将无法做出预测。这通常被称为『零位频率』。我们可以使用平滑技术来解决这个问题。最简单的平滑技术之一称为拉普拉斯平滑。当你训练一个朴素贝叶斯分类器时,Sklearn 会默认使用拉普拉斯平滑算法。

结语

非常感谢你阅读这篇文章。我希望它能帮助你理解朴素贝叶斯分类器的概念以及它的优点。

致谢 Antoine Toubhans、Flavian Hautbois、Adil Baaj 和 Raphaël Meudec。

原文链接:

https://www.sicara.ai/blog/2018-02-28-naive-bayes-classification-sklearn

- EOF -

推荐阅读  点击标题可跳转

1、贝叶斯新闻分类实战项目详解

2、30 年前的热门研究,今获经典论文奖,贝叶斯网络之父旧论文「考古」

3、平凡而又神奇的贝叶斯方法

觉得本文对你有帮助?请分享给更多人

推荐关注「Python开发者」,提升Python技能

629cc985aaf3701e6e41a58f5556af65.png

点赞和在看就是最大的支持❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/292097.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux之tr命令使用和总结

1、tr命令介绍 用来从标准输入中通过替换或删除操作进行字符转换。tr主要用于删除文件中控制字符或进行字符转换。使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。tr刚执行时,字符串1中的字符被映射到字符串2中的字符,然后转换操作开始。 带有最常用…

美少女什么味??竟然还有美少女风味泡面......

1 毕业后第一次参加聚餐(via:刘燕铭)▼2 建议使用摩斯密码,谢谢▼3 隆马戏(素材来源网络,侵删)▼4 真的很谢谢▼5 啊,哪里买呢(via:Zero 浅忆)…

ABP vNext微服务架构详细教程——身份管理服务

1框架搭建ABP vNext创建包含app和module两种模板,其中app方式所创建的模板包含用户、角色、权限管理,ABP基础配置IdentityServer的基础配置数据等功能。module模式是一个比较干净的服务,里面不包含默认业务功能。ABP vNext创建包含app和modul…

双网卡上网冲突解决_【技术文章】局域网IP地址冲突罪魁祸首是什么?这几点要注意!(附高手处理方法)...

现如今,人们的生活处处离不开网络。单位办公信息化对网络的依赖则更大。为了提升安全管理和信息化水平,很多单位不仅建设了完善的办公信息系统,还部署了视频监控。但由于缺乏整体规划,或选择网络产品时考虑欠周,导致网…

异常分析

一、请阅读并运行AboutException.java示例,然后通过后面的几页PPT了解Java中实现异常处理的基础知识。 (1)源代码;import javax.swing.*; class AboutException { public static void main(String[] a) { int i1, j0, k; ki/j; try { k i/j…

linux c之wait和waitpid函数的用法和总结

1、wait和waitpid函数的介绍 1) wait()函数用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接收到了一个指定的信号为止。如果该父进程没有子进程或者它的子进程已经结束,则wait()函数就会立即返回。 2) waitpid()的作用和wait()一样,但它并不一…

微软开发者的年度回顾

2021 年 .NET 和 Microsoft 开发人员的技术都发生了什么?很难从 2021 年只选择一个主题。安静的进化?开源的争议?一个让开发人员疑惑的操作系统更新?当我回头看时, 发现一年发生了很多事情, 2021 年的发展是稳步向前的&#xff0c…

我是永远不可能出轨的,除非......

1 当爸妈学会了抠图(素材来源豆瓣,侵删)▼2 帮我带瓶我平时常喝的水(素材来源网络,侵删)▼3 我们是被资本凑在一起的联姻(素材来源网络,侵删)▼4 我是不会出轨的&…

linux之学习linux系统相关的书籍

1.《鸟哥的Linux私房菜-基础学习篇》 2.《Linux Shell 脚本攻略》 3.《Unix环境高级编程》 4.《Linux系统编程》

16岁上大学,25岁博士毕业,她还是南大医学院最年轻的博导!

全世界只有3.14 % 的人关注了爆炸吧知识本文转自:募格学术魏嘉,16岁考上南大,25岁博士毕业,是南大医学院最年轻的博导,已在J Natl Cancer Inst等国际著名杂志上发表64篇SCI论文。在第24届“中国青年五四奖章”入围名单…

十年整理CAD精髓

为什么80%的码农都做不了架构师?>>> AUTOCAD使用心得之一 使用的三个基本方面:清晰、准确、高效 目前,公司的设计文件,特别是图纸,都是用AUTOCAD软件绘制的。但是,现在还有很多人对CAD并不是…

使用这个库,让你的服务操作 Redis 速度飞起

点击上方蓝字关注 👆👆没领红包封面的可以在文末领取大多数人使用 Redis 作为远程缓存存储,因为它速度快。Redis6 通过消除不必要的网络往返,可以使其更快。服务器辅助的客户端缓存这个方法很简单。Redis6 会记录客户端请求的键值…

mysql bigint转string_无语了,直到今天,我才揪出MySQL磁盘消耗迅猛的“真凶”!...

作者:dbapower链接:https://blog.51cto.com/suifu/2135599背景Part1:写在最前当一张单表10亿数据量的表放在你面前,你将面临着什么?Part2:背景介绍为了提升数据库资源利用率,一个实例中,在不互相影响&#…

mysql导入sql脚本命令

2019独角兽企业重金招聘Python工程师标准>>> 使用mysql自带的命令行工具导入sql脚本如下&#xff1a; mysql -h localhost -u root -proot -v -Ddbname < dbname.sql 转载于:https://my.oschina.net/u/2450094/blog/795488

媒体层图形技术之AssetsLibrary 学习笔记

choudang的专栏转载自 http://m.blog.csdn.net/blog/choudang/28274519 1.ALAsset ALAsset类代表相册中的每个资源文件&#xff0c;可以通过它获取资源文件的相关信息还能修改和新建资源文件 Asset Properties – valueForProperty: (1.ALAssetPropertyType 资源的类型&…

jenkins构建触发器定时任务

接上篇Jenkins发布.Net项目到IIS前面说到了把项目部署到iis,那么这边有个问题就是这个部署的触发条件是手工还是需要自动的呢。我觉得这个的看具体的场景&#xff0c;假设团队人员比较多&#xff0c;不断的在提交代码到指定分支&#xff0c;如果是自动化的话&#xff0c; 那么基…

JavaScript基于对象编程

2019独角兽企业重金招聘Python工程师标准>>> JavaScript基于对象编程 1、JavaScript变量/函数声明在代码执行之前被解析&#xff0c;并且变量声明优先级高于函数声明。 代码片段&#xff1a; 1234567var flag test in window;if (!flag){ var te…

idae 安装的插件怎么删掉_X7 IE阻止我安装插件怎么办

为了在网页上表现多彩的多媒体内容&#xff0c;很多网站会要求我们装上相应的网页插件来实现。但IE的默认安全设置会阻止我们进行安装某些网页插件。可是如果不装的话&#xff0c;网页很多媒体的内容就会显示不出来。怎么办呢&#xff1f;其实我们可以调整IE的安全设定来解决。…