python实现一个朴素贝叶斯分类方法
1.公式

上式中左边D是需要预测的测试数据属性,h是需要预测的类;右边式子分子是属性的条件概率和类别的先验概率,可以从统计训练数据中得到,分母对于所有实例都一样,可以不考虑,所有只需
,返回最大概率的那个类别。但是如果测试数据中没有那个属性,整个预测概率会是0;此外,此式针对离散型属性进行训练,针对连续的数值型属性可以考虑分段,也可以假设其满足某种分布,比如正态分布,利用概率密度函数求概率。
2.部分改进
(1).针对测试数据中没有那个属性,可以平滑一下,比如下(针对非数值型属性):

上式中n是某个类别下的实例数,nc是此类别下的属性个数,m是此属性的取值个数,p是此属性取值出现的概率。比如一个属性:性别,取值男或女,则 m=2,p=1/2。
(2).针对连续的数值型属性,可以分段比如年龄0-10为A,10-30为B等;还可以假设它服从高斯分布(正态分布),利分布函数计算概率:

其中uij是某列数值型属性的均值,Qij是某列数值型属性样本标准差,Xi是数值属性。训练的时候只需要统计均值,样本标准差就行了,预测的时候利用。
3.python实现
#!/usr/bin/python
# -*- coding: utf-8 -*- import codecs
import math class BayesClassifier: def __init__(self,dataFormat):
self.prior = {}#类别的先验概率
self.conditional = {}#属性的条件概率
# 输入的数据格式,attr表示非数值型属性,num表示数值型属性,class表示类别
self.format=dataFormat.strip().split('\t') #读取数据
def readData(self,dataFile):
total = 0#所有实例数
self.classes = {}#统计类别
self.counts = {}#用来统计
totals={}#统计数值型每列的和
numericValues={}#数值型每列值 with codecs.open(dataFile,'r','utf-8') as f:
for line in f:
fields=line.strip().split('\t')
fieldSize=len(fields)
vector=[]
nums=[]
for i in range(fieldSize):
if self.format[i]=='num':
nums.append(float(fields[i]))
elif self.format[i]=='attr':
vector.append(fields[i])
elif self.format[i]=='class':
category=fields[i]
total+=1
self.classes.setdefault(category,0)
self.counts.setdefault(category,{})
totals.setdefault(category,{})
numericValues.setdefault(category,{})
self.classes[category]+=1
#统计一条非数值型实例的属性
col=0
for columnValue in vector:
col+=1
self.counts[category].setdefault(col,{})
self.counts[category][col].setdefault(columnValue,0)
self.counts[category][col][columnValue]+=1
col=0
for columnValue in nums:
col+=1
totals[category].setdefault(col,0)
totals[category][col]+=columnValue
numericValues[category].setdefault(col,[])
numericValues[category][col].append(columnValue) #以上统计完成,计算类别先验概率和属性条件概率
#计算类的先验概率=此类的实例数/总的实例数
for category,count in self.classes.items():
self.prior[category]=count/total
#计算属性的条件概率=此类中属性数/此类实例数
for category,columns in self.counts.items():
self.conditional.setdefault(category,{})
for col,valueCounts in columns.items():
self.conditional[category].setdefault(col,{})
colSize=len(valueCounts)#这一列属性的取值个数(如性别取值为男和女,则colSize=2)
for attr,count in valueCounts.items():
#平滑一下
self.conditional[category][col][attr]=(count+colSize*1/colSize)/(self.classes[category]+colSize)
#在数值型列中计算均值和样本标准差
#每列的均值
self.means={}
self.totals=totals
for category,columns in totals.items():
self.means.setdefault(category,{})
for col,colSum in columns.items():
self.means[category][col]=colSum/self.classes[category]
#每列的标准差
self.std={}
for category,columns in numericValues.items():
self.std.setdefault(category,{})
for col,values in columns.items():
ssd=0
mean=self.means[category][col]
for value in values:
ssd+=(value-mean)**2
self.std[category][col]=math.sqrt(ssd/(self.classes[category]-1)) #分类,返回分类结果
def classify(self,itemVector):
results=[]
for category,prior in self.prior.items():
prob=prior
col=1
for attrValue in itemVector:
if self.format[col]=='attr':
# 如果预测数据没有这个属性,则平滑一下,不是返回0(返回0会导致整个预测结果为0)
if not attrValue in self.conditional[category][col]:
colSize=len(self.counts[category][col])
prob=prob*(0+colSize*1/colSize)/(self.classes[category]+colSize)
else:
prob=prob*self.conditional[category][col][attrValue]
#针对数值型,我们先得到该列均值与样本标准差,利用正态分布得到概率(假设该列数值满足正态分布)
elif self.format[col]=='num':
mean=self.means[category][col]
std=self.std[category][col]
prob=prob*self.gaussian(mean,std,attrValue)
col+=1
results.append((prob,category))
return max(results)[1] #高斯分布
def gaussian(self,mean,std,x):
sqrt2pi = math.sqrt(2 * math.pi)
ePart=math.pow(math.e,-(x-mean)**2/(2*std**2))
prob=(1.0/sqrt2pi*std)*ePart
return prob # 十折验证读取数据,prefix为文件名前缀,i作为测试集编号
def tenFoldReadData(self,prefix,testNumber):
total = 0 # 所有实例数
self.classes = {} # 统计类别
self.counts = {} # 用来统计
totals = {} # 统计数值型每列的和
numericValues = {} # 数值型每列值 for i in range(1,11):
if i!=testNumber:
filename='%s-%02s' % (prefix,i)
with codecs.open(filename, 'r', 'utf-8') as f:
for line in f:
fields = line.strip().split('\t')
fieldSize = len(fields)
vector = []
nums = []
for i in range(fieldSize):
if self.format[i] == 'num':
nums.append(float(fields[i]))
elif self.format[i] == 'attr':
vector.append(fields[i])
elif self.format[i] == 'class':
category = fields[i]
total += 1
self.classes.setdefault(category, 0)
self.counts.setdefault(category, {})
totals.setdefault(category, {})
numericValues.setdefault(category, {})
self.classes[category] += 1
# 统计一条非数值型实例的属性
col = 0
for columnValue in vector:
col += 1
self.counts[category].setdefault(col, {})
self.counts[category][col].setdefault(columnValue, 0)
self.counts[category][col][columnValue] += 1
col = 0
for columnValue in nums:
col += 1
totals[category].setdefault(col, 0)
totals[category][col] += columnValue
numericValues[category].setdefault(col, [])
numericValues[category][col].append(columnValue) # 以上统计完成,计算类别先验概率和属性条件概率
# 计算类的先验概率=此类的实例数/总的实例数
for category, count in self.classes.items():
self.prior[category] = count / total
# 计算属性的条件概率=此类中属性数/此类实例数
for category, columns in self.counts.items():
self.conditional.setdefault(category, {})
for col, valueCounts in columns.items():
self.conditional[category].setdefault(col, {})
colSize = len(valueCounts) # 这一列属性的取值个数(如性别取值为男和女,则colSize=2)
for attr, count in valueCounts.items():
# 平滑一下
self.conditional[category][col][attr] = (count + colSize * 1 / colSize) / (
self.classes[category] + colSize)
# 在数值型列中计算均值和样本标准差
# 每列的均值
self.means = {}
self.totals = totals
for category, columns in totals.items():
self.means.setdefault(category, {})
for col, colSum in columns.items():
self.means[category][col] = colSum / self.classes[category]
# 每列的标准差
self.std = {}
for category, columns in numericValues.items():
self.std.setdefault(category, {})
for col, values in columns.items():
ssd = 0
mean = self.means[category][col]
for value in values:
ssd += (value - mean) ** 2
self.std[category][col] = math.sqrt(ssd / (self.classes[category] - 1)) #利用十折交叉验证,测试一个桶中的数据,prefix为统计文件名前缀,testNumber为要测试的一个桶中的数据
def testOneBucket(self,prefix,testNumber):
filename='%s-%02i' % (prefix,testNumber)
totals={}
with codecs.open(filename,'r','utf-8') as f:
for line in f:
data=line.strip().split('\t')
itemVector=[]
classInColumn=-1
for i in range(len(self.format)):
if self.format[i]=='num':
itemVector.append(float(data[i]))
elif self.format[i]=='attr':
itemVector.append(data[i])
elif self.format[i]=='class':
classInColumn=i
realClass=data[classInColumn]#真实的类
classifiedClass=self.classify(itemVector)#预测的类
totals.setdefault(realClass,{})
totals[realClass].setdefault(classifiedClass,0)
totals[realClass][classifiedClass]+=1
return totals #十折交叉验证,prefix为十个文件名字的前缀,dataForamt为数据格式
def tenfold(prefix,dataFormat):
results={}
for i in range(1,11):
classify=BayesClassifier(dataFormat)
classify.tenFoldReadData(prefix,i)
totals=classify.testOneBucket(prefix,i)
for key,value in totals.items():
results.setdefault(key,{})
for ckey,cvalue in value.items():
results[key].setdefault(ckey,0)
results[key][ckey]+=cvalue
#结果展示
classes=list(results.keys())
classes.sort()
print( '\n classes as: ')
header=' '
subheader=' +'
for cls in classes:
header+='% 10s '% cls
subheader+='--------+'
print(header)
print(subheader)
total=0.0
correct=0.0
for cls in classes:
row=' %10s |' % cls
for c2 in classes:
if c2 in results[cls]:
count=results[cls][c2]
else:
count=0
row+=' %5i |' % count
total+=count
if c2==cls:
correct+=count
print(row)
print(subheader)
print('\n%5.3f 正确率' % ((correct*100/total)))
print('总共 %i 实例'% total) if __name__=='__main__':
#classify=BayesClassifier('num,num,num,num,num,num,num,num,class')
#classify.readData('dataFile')
#print(classify.classify([2,120,54,0,0,26.8,0.455,27]))
tenfold('dataFilePrefix','num,num,num,num,num,num,num,num,class')#十折交叉验证
python实现一个朴素贝叶斯分类方法的更多相关文章
- python 类属性与方法
Python 类属性与方法 标签(空格分隔): Python Python的访问限制 Python支持面向对象,其对属性的权限控制通过属性名来实现,如果一个属性有双下划线开头(__),该属性就无法被外 ...
- Python执行系统命令的方法 os.system(),os.popen(),commands
os.popen():用python执行shell的命令,并且返回了结果,括号中是写shell命令 Python执行系统命令的方法: https://my.oschina.net/renwofei42 ...
- python 调用 shell 命令方法
python调用shell命令方法 1.os.system(cmd) 缺点:不能获取返回值 2.os.popen(cmd) 要得到命令的输出内容,只需再调用下read()或readlines()等 ...
- python 面向对象、特殊方法与多范式、对象的属性及与其他语言的差异
1.python 面向对象 文章内容摘自:http://www.cnblogs.com/vamei/archive/2012/06/02/2532018.html 1.__init__() 创建对 ...
- python 字典内置方法get应用
python字典内置方法get应用,如果我们需要获取字典值的话,我们有两种方法,一个是通过dict['key'],另外一个就是dict.get()方法. 今天给大家分享的就是字典的get()方法. 这 ...
- [转] python程序的调试方法
qi09 原文 python程序的调试方法 本文讨论在没有方便的IDE工具可用的情况下,使用pdb调试python程序 源码例子 例如,有模拟税收计算的程序: #!/usr/bin/python de ...
- Python prettytable的使用方法
Python prettytable的使用方法 prettytable可以整齐地输出一个表格信息: +-----------+------+------------+----------------- ...
- Python多线程及其使用方法
[Python之旅]第六篇(三):Python多线程及其使用方法 python 多线程 多线程使用方法 GIL 摘要: 1.Python中的多线程 执行一个程序,即在操作系统中开启了一个进 ...
- Python学习笔记4-如何快速的学会一个Python的模块、方法、关键字
想要快速的学会一个Python的模块和方法,两个函数必须要知道,那就是dir()和help() dir():能够快速的以集合的型式列出该模块下的所有内容(类.常量.方法)例: #--encoding: ...
随机推荐
- 跨 PostgreSQL 大版本复制怎么做?| 逻辑复制
当需要升级PostgreSQL时,可以使用多种方法.为了避免应用程序停机,不是所有升级postgres的方法都适合,如果避免停机是必须的,那么可以考虑使用复制作为升级方法,并且根据方案,可以选择使用逻 ...
- P1816忠诚
这是一个区间查询最值的问题,用线段树来做. 建树的时候,这里不是求和,应该是e[k].w=min(e[k*2].w,e[k*2+1].w),所以这里要注意以下,其次是查询的时候,因为本题不用让我们修改 ...
- 【GDOI】2018题目及题解(未写完)
我的游记:https://www.cnblogs.com/huangzihaoal/p/11154228.html DAY1 题目 T1 农场 [题目描述] [输入] 第一行,一个整数n. 第二行,n ...
- Redis学习笔记(一)Windows下redis的安装和启动
在Windows上安装redis 下载地址:https://github.com/microsoftarchive/redis/releases 选择图中红框标出来的下载,解压到磁盘上,文件夹命名为r ...
- 前端-CSS-初探-注释-语法结构-引入方式-选择器-选择器优先级-01(待完善)
目录 CSS(Cascading Style Sheet) CSS注释 CSS语法结构 CSS的三种引入方式 选择器 伪类.伪元素选择器速查 CSS选择器优先级***** 选择器相同的情况下 选择器不 ...
- angular 4+中关于父子组件传值的示例
home.component.ts import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-hom ...
- SpringMVC整体架构
总结: 1. 用户发起请求到前端控制器(DispatchServlet): 2. 前端控制器没有处理业务逻辑的能力,需要找到具体的模型对象处理(Handler),到处理器映射器中查找Handler对象 ...
- 为何 linux 要用 tar.gz,而不用 7z 或 zip?
因为 7z 和 zip 压缩格式都不能保留 unix 风格的文件权限,比如解压出个可执行文件要重新 chmod chown 才能恢复正常.而 tar 格式可以.而 tar 本身不提供压缩,无非就是把包 ...
- java8学习之Stream陷阱剖析
上一次[http://www.cnblogs.com/webor2006/p/8297603.html]在最后用stream.iterate()生成了6个奇数,接着基于它来实现如下需求:找出该流中大于 ...
- win redis安装
一.下载windows版本的Redis 去官网找了很久,发现原来在官网上可以下载的windows版本的,现在官网以及没有下载地址,只能在github上下载,官网只提供linux版本的下载 官网下载地址 ...