朴素贝叶斯python代码实现(西瓜书)
朴素贝叶斯python代码实现(西瓜书)
摘要:
朴素贝叶斯也是机器学习中一种非常常见的分类方法,对于二分类问题,并且数据集特征为离散型属性的时候,
使用起来非常的方便。原理简单,训练效率高,拟合效果好。
朴素贝叶斯
贝叶斯公式:

朴素贝叶斯之所以称这为朴素,是因为假设了各个特征是相互独立的,因此假定下公式成立:

则朴素贝叶斯算法的计算公式如下:

在实际计算中,上面的公式会做如下略微改动:
- 由于某些特征属性的值P(Xi|Ci)可能很小,多个特征的p值连乘后可能被约等于0。可以公式两边取log然后变乘法为加法,避免类乘问题。
- P(Ci) 和P(Xi|Ci) 一般不直接使用样本的频率计算出来,一般会使用拉普拉斯平滑。

上面公式中,Dc为该类别的频数,N表示所有类别的可能数。

上面公式中,Dc,xi为该特征对应属性的频数,Dc为该类别的频数,Ni表示该特征的可能的属性数。
对应的西瓜书数据集为
色泽 根蒂 敲声 纹理 脐部 触感 好瓜
青绿 蜷缩 浊响 清晰 凹陷 硬滑 是
乌黑 蜷缩 沉闷 清晰 凹陷 硬滑 是
乌黑 蜷缩 浊响 清晰 凹陷 硬滑 是
青绿 蜷缩 沉闷 清晰 凹陷 硬滑 是
浅白 蜷缩 浊响 清晰 凹陷 硬滑 是
青绿 稍蜷 浊响 清晰 稍凹 软粘 是
乌黑 稍蜷 浊响 稍糊 稍凹 软粘 是
乌黑 稍蜷 浊响 清晰 稍凹 硬滑 是
乌黑 稍蜷 沉闷 稍糊 稍凹 硬滑 否
青绿 硬挺 清脆 清晰 平坦 软粘 否
浅白 硬挺 清脆 模糊 平坦 硬滑 否
浅白 蜷缩 浊响 模糊 平坦 软粘 否
青绿 稍蜷 浊响 稍糊 凹陷 硬滑 否
浅白 稍蜷 沉闷 稍糊 凹陷 硬滑 否
乌黑 稍蜷 浊响 清晰 稍凹 软粘 否
浅白 蜷缩 浊响 模糊 平坦 硬滑 否
青绿 蜷缩 沉闷 稍糊 稍凹 硬滑 否
python实现
#encoding:utf-8
import pandas as pd
import numpy as np
class NaiveBayes:
def __init__(self):
self.model = {}#key 为类别名 val 为字典PClass表示该类的该类,PFeature:{}对应对于各个特征的概率
def calEntropy(self, y): # 计算熵
valRate = y.value_counts().apply(lambda x : x / y.size) # 频次汇总 得到各个特征对应的概率
valEntropy = np.inner(valRate, np.log2(valRate)) * -1
return valEntropy
def fit(self, xTrain, yTrain = pd.Series()):
if not yTrain.empty:#如果不传,自动选择最后一列作为分类标签
xTrain = pd.concat([xTrain, yTrain], axis=1)
self.model = self.buildNaiveBayes(xTrain)
return self.model
def buildNaiveBayes(self, xTrain):
yTrain = xTrain.iloc[:,-1]
yTrainCounts = yTrain.value_counts()# 频次汇总 得到各个特征对应的概率
yTrainCounts = yTrainCounts.apply(lambda x : (x + 1) / (yTrain.size + yTrainCounts.size)) #使用了拉普拉斯平滑
retModel = {}
for nameClass, val in yTrainCounts.items():
retModel[nameClass] = {'PClass': val, 'PFeature':{}}
propNamesAll = xTrain.columns[:-1]
allPropByFeature = {}
for nameFeature in propNamesAll:
allPropByFeature[nameFeature] = list(xTrain[nameFeature].value_counts().index)
#print(allPropByFeature)
for nameClass, group in xTrain.groupby(xTrain.columns[-1]):
for nameFeature in propNamesAll:
eachClassPFeature = {}
propDatas = group[nameFeature]
propClassSummary = propDatas.value_counts()# 频次汇总 得到各个特征对应的概率
for propName in allPropByFeature[nameFeature]:
if not propClassSummary.get(propName):
propClassSummary[propName] = 0#如果有属性灭有,那么自动补0
Ni = len(allPropByFeature[nameFeature])
propClassSummary = propClassSummary.apply(lambda x : (x + 1) / (propDatas.size + Ni))#使用了拉普拉斯平滑
for nameFeatureProp, valP in propClassSummary.items():
eachClassPFeature[nameFeatureProp] = valP
retModel[nameClass]['PFeature'][nameFeature] = eachClassPFeature
return retModel
def predictBySeries(self, data):
curMaxRate = None
curClassSelect = None
for nameClass, infoModel in self.model.items():
rate = 0
rate += np.log(infoModel['PClass'])
PFeature = infoModel['PFeature']
for nameFeature, val in data.items():
propsRate = PFeature.get(nameFeature)
if not propsRate:
continue
rate += np.log(propsRate.get(val, 0))#使用log加法避免很小的小数连续乘,接近零
#print(nameFeature, val, propsRate.get(val, 0))
#print(nameClass, rate)
if curMaxRate == None or rate > curMaxRate:
curMaxRate = rate
curClassSelect = nameClass
return curClassSelect
def predict(self, data):
if isinstance(data, pd.Series):
return self.predictBySeries(data)
return data.apply(lambda d: self.predictBySeries(d), axis=1)
dataTrain = pd.read_csv("xiguadata.csv", encoding = "gbk")
naiveBayes = NaiveBayes()
treeData = naiveBayes.fit(dataTrain)
import json
print(json.dumps(treeData, ensure_ascii=False))
pd = pd.DataFrame({'预测值':naiveBayes.predict(dataTrain), '正取值':dataTrain.iloc[:,-1]})
print(pd)
print('正确率:%f%%'%(pd[pd['预测值'] == pd['正取值']].shape[0] * 100.0 / pd.shape[0]))
输出
{"否": {"PClass": 0.5263157894736842, "PFeature": {"色泽": {"浅白": 0.4166666666666667, "青绿": 0.3333333333333333, "乌 黑": 0.25}, "根蒂": {"稍蜷": 0.4166666666666667, "蜷缩": 0.3333333333333333, "硬挺": 0.25}, "敲声": {"浊响": 0.4166666666666667, "沉闷": 0.3333333333333333, "清脆": 0.25}, "纹理": {"稍糊": 0.4166666666666667, "模糊": 0.3333333333333333, "清晰": 0.25}, "脐部": {"平坦": 0.4166666666666667, "稍凹": 0.3333333333333333, "凹陷": 0.25}, "触感": {"硬滑": 0.6363636363636364, "软粘": 0.36363636363636365}}}, "是": {"PClass": 0.47368421052631576, "PFeature": {"色泽": {"乌黑": 0.45454545454545453, "青绿": 0.36363636363636365, "浅白": 0.18181818181818182}, "根蒂": {"蜷缩": 0.5454545454545454, "稍蜷": 0.36363636363636365, "硬挺": 0.09090909090909091}, "敲声": {"浊响": 0.6363636363636364, "沉闷": 0.2727272727272727, "清脆": 0.09090909090909091}, "纹理": {"清晰": 0.7272727272727273, "稍糊": 0.18181818181818182, "模糊": 0.09090909090909091}, "脐 部": {"凹陷": 0.5454545454545454, "稍凹": 0.36363636363636365, "平坦": 0.09090909090909091}, "触感": {"硬滑": 0.7, "软粘": 0.3}}}}
预测值 正取值
0 是 是
1 是 是
2 是 是
3 是 是
4 是 是
5 是 是
6 否 是
7 是 是
8 否 否
9 否 否
10 否 否
11 否 否
12 是 否
13 否 否
14 是 否
15 否 否
16 否 否
正确率:82.352941%
总结:
- 贝叶斯分类器是一种生成式模型,不是直接拟合分类结果,而是拟合出后验概率公式计算对应分类的概率。
- 本文只介绍了二分类,也可以用来处理多分类问题。
- 对于小规模数据集,表现良好。
- 建立在特征相互独立的假设上。
- 这是我的github主页https://github.com/fanchy,有些有意思的分享。
朴素贝叶斯python代码实现(西瓜书)的更多相关文章
- 朴素贝叶斯python实现
概率论是非常多机器学习算法基础,朴素贝叶斯分类器之所以称为朴素,是由于整个形式化过程中仅仅做最原始.简单的如果. (这个如果:问题中有非常多特征,我们简单如果一个个特征是独立的.该如果称做条件独立性, ...
- 统计学习方法(李航)朴素贝叶斯python实现
朴素贝叶斯法 首先训练朴素贝叶斯模型,对应算法4.1(1),分别计算先验概率及条件概率,分别存在字典priorP和condP中(初始化函数中定义).其中,计算一个向量各元素频率的操作反复出现,定义为c ...
- 朴素贝叶斯python小样本实例
朴素贝叶斯优点:在数据较少的情况下仍然有效,可以处理多类别问题缺点:对于输入数据的准备方式较为敏感适用数据类型:标称型数据朴素贝叶斯决策理论的核心思想:选择具有最高概率的决策朴素贝叶斯的一般过程(1) ...
- 机器学习:朴素贝叶斯--python
今天介绍机器学习中一种基于概率的常见的分类方法,朴素贝叶斯,之前介绍的KNN, decision tree 等方法是一种 hard decision,因为这些分类器的输出只有0 或者 1,朴素贝叶斯方 ...
- Python机器学习笔记:朴素贝叶斯算法
朴素贝叶斯是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法.对于大多数的分类算法,在所有的机器学习分类算法中,朴素贝叶斯和其他绝大多数的分类算法都不同.比如决策树,KNN,逻辑回归,支持向 ...
- 朴素贝叶斯方法(Naive Bayes Method)
朴素贝叶斯是一种很简单的分类方法,之所以称之为朴素,是因为它有着非常强的前提条件-其所有特征都是相互独立的,是一种典型的生成学习算法.所谓生成学习算法,是指由训练数据学习联合概率分布P(X,Y ...
- 朴素贝叶斯算法简介及python代码实现分析
概念: 贝叶斯定理:贝叶斯理论是以18世纪的一位神学家托马斯.贝叶斯(Thomas Bayes)命名.通常,事件A在事件B(发生)的条件下的概率,与事件B在事件A(发生)的条件下的概率是不一样的:然而 ...
- 朴素贝叶斯算法源码分析及代码实战【python sklearn/spark ML】
一.简介 贝叶斯定理是关于随机事件A和事件B的条件概率的一个定理.通常在事件A发生的前提下事件B发生的概率,与在事件B发生的前提下事件A发生的概率是不一致的.然而,这两者之间有确定的关系,贝叶斯定理就 ...
- 3.朴素贝叶斯和KNN算法的推导和python实现
前面一个博客我们用Scikit-Learn实现了中文文本分类的全过程,这篇博客,着重分析项目最核心的部分分类算法:朴素贝叶斯算法以及KNN算法的基本原理和简单python实现. 3.1 贝叶斯公式的推 ...
随机推荐
- [原创]Zabbix3.4_API的python示例
说明: 1.python版本为:python2.7 2.zabbix版本为:zabbix3.4 3.通过python脚本调用zabbix的api接口可以实现批量增删改查主机的信息. 示例如下: #-* ...
- Java异常与处理机制
Java的异常层次体系 Java的所有异常对象都派生自Throwable类,下层有两个分支:error和exception. Error分支描述Java运行时系统内部错误或资源耗尽错误,遇到派生自Er ...
- 个人用户永久免费,可自动升级版Excel插件,使用VSTO开发,Excel催化剂安装过程详解及安装失败解决方法
因Excel催化剂用了VSTO的开发技术,并且为了最好的用户体验,用了Clickonce的布署方式(无需人工干预自动更新,让用户使用如浏览器访问网站一般,永远是最新的内容和功能).对安装过程有一定的难 ...
- C语言入门2-程序设计的灵魂—算法及Raptor的应用
一. 什么是算法(5个特性) 算法就是 解决问题的方法和步骤. 算法为解决一个具体问题而采取的确定的 有限的 执行步骤 ,仅指 计算机 能执行的算法. 算法是程序设计的灵魂和核心 ...
- JAVA面试题 请谈谈你对Sychronized关键字的理解?
面试官:sychronized关键字有哪些特性? 应聘者: 可以用来修饰方法; 可以用来修饰代码块; 可以用来修饰静态方法; 可以保证线程安全; 支持锁的重入; sychronized使用不当导致死锁 ...
- UPC Contest RankList – 2019年第二阶段我要变强个人训练赛第十五场
传送门 A: Colorful Subsequence •题意 给一个长为n的小写字母序列,从中选出字母组成子序列 问最多能组成多少种每个字母都不相同的子序列 (不同位置的相同字母也算是不同的一种) ...
- 【TensorFlow 1】操作变量
打印 在tf中直接打印只是输出变量格式,如: #代码 data1 = tf.constant(2,dtype=tf.int32) #浮点数据 data2 = tf.Variable(10,name=' ...
- 给定一个IP地址,转化为二进制32位,再转化为十进制,写出一个方法让其十进制转为IP地址
十进制是已知的数值 第一种方法: <script type="text/javascript"> var num=2148140545; var str=num.toS ...
- Spring MVC中的 权限拦截定义 以及 权限拦截的研发步骤
权限拦截 (拦截器: 对请求进行区分) 1 实现的价值(作用) 用户未登录:访问没用登录的URL,拦截到以后 跳转回登录 用户未登录:访问登录的URL,直接放行到后续流程处理框架,进行后续的操作 用户 ...
- rabbitMQ_routing(四)
路由 本次我们将通过路由将信息发送到指定的队列中,将消息发送给指定的队列需要在转发器和队列之间建立一个routeKey 绑定 在以前的例子中,我们已经创建了绑定.你可能会记得如下代码: channel ...