贝叶斯分类算法:
贝叶斯分类是统计学的一种分类算法,它是一类利用概率统计知识进行分类的算法。在许多场合,朴素贝叶斯(Naïve Bayes,NB)分类算法可以与决策树和神经网络分类算法相媲美。
缺陷:
与其本身的设定有关,由于贝叶斯假设一个属性值对给定类的影响独立于其它属性的值,但是该假设在实际情况中经常是不成立的,因此其分类准确率可能会下降。升级版:降低独立性假设的贝叶斯分类算法,如TAN(tree augmented Bayes network)算法。
朴素贝叶斯分类的正式定义如下:
1.设 x={a1,a2,…,am}为一个待分类项,而每个 a 为 x 的一个特征属性。
2.有类别集合 C={y1,y2,…,yn}。
3.计算 P( y1|x) ,P( y2|x),…, P( yn|x)。
4.如果 P( yk|x) =max{P( y1|x),P( y2|x),…, P( yn|x)},则 x∈yk。
贝叶斯算法如下:
#贝叶斯算法实现
#建立一个类
import numpy as np
class Bayes:
def _init_(self):
self.length=-1
self.labelcount=dict()
self.vectorcount=dict()
def fit(self,dataSet:list,labels:list):
if(len(dataSet)!=len(labels)):
raise ValueError("您输入的测试数组跟类别数组长度不一致")
self.length=len(dataSet[0])
#测试数据特征值的长度
labelsnum=len(labels)
#类别所有的数量
norlabels=set(labels)
#不重复类别的数量
for item in norlabels:
thislabel=item
labelcount[thislabel]=labels.count(thislabel)/labelsnum
#当前类别占总类别的比例
for vector,label in zip(dataSet,labels):
#将两变量整合到一起
if(label not in vectorcount):
self.vectorcount[label]=[]
self.vectorcount[label].append(vector)
print("训练结束")
def btest(self,TestData,labelsSet):
if(self.length==-1):
raise ValueError("您还没有进行训练,请先训练")
#计算当前testdata分别为各个类别的概率
IbDict=dict()
for thisIb in labelsSet:
p=1
alllabel=self.labelcount[thisIb]
#当前类别占总类别的多少
allvector=self.vectorcount[thisIb]
vnum=len(allvector)
allvector=np.array(allvector).T
for index in range(0,len(TestData)):
vector=list(allvector[index])
p*=vector.count(TestData[index])/vnum
IbDict[thisIb]=p*alllabel
thislabel=sorted(IbDict,key=lambda x: IbDict[x],reverse=True)[0]
return thislabel
用贝叶斯算法进行手写体数字的识别:
#加载数据
#加载数据
def datatoarray(fname):
arr=[]
fh=open(fname)
for i in range(0,32):
thisline=fh.readline()
for j in range(0,32):
arr.append(int(thisline[j]))
return arr
#建立一个函数取文件名前缀
def seplabel(fname):
filestr=fname.split(".")[0]
label=int(filestr.split("_")[0])
return label
#建立训练数据
#建立训练数据
def traindata():
labels=[]
trainfile=listdir("D:/shujufenxi/traindata")
num=len(trainfile)
#长度1024(列),每一行存储一个文件
#用一个数组存储所有训练数据,行:文件总数,列:1024
trainarr=zeros((num,1024))
for i in range(0,num):
thisfname=trainfile[i]
thislabel=seplabel(thisfname)
labels.append(thislabel)
trainarr[i,:]=datatoarray("D:/shujufenxi/traindata/"+thisfname)
return trainarr,labels
bys=Bayes()
#训练数据
train_data,labels=traindata()
bys.fit(train_data,labels)
#测试数据
#识别多个手写体数字(批量测试)
testfileall=listdir("D:/shujufenxi/testdata")
num=len(testfileall)
x=0
for i in range(0,num):
thisfilename=testfileall[i]
'''print(thisfilename)'''
thislabel=seplabel(thisfilename)
#print(thislabel)
thisdataarray=datatoarray("D:/shujufenxi/testdata/"+thisfilename)
label=bys.btest(thisdataarray,labelsall)
print("该数字是:"+str(thislabel)+",识别出来的数字是:"+str(label)) #输出识别结果
if(label!=thislabel):
x+=1
print("此次出错")
print(x)
print("错误率是:"+str(float(x)/float(num)))
输出结果:错误率是:0.1226215644820296
完整代码如下:
#贝叶斯算法的应用(手写体字体的识别)
from numpy import *
import operator
from os import listdir
import numpy as npy
import numpy
class Bayes:
def __init__(self):
self.length=-1
self.labelcount=dict()
self.vectorcount=dict()
def fit(self,dataSet:list,labels:list):
if(len(dataSet)!=len(labels)):
raise ValueError("您输入的测试数组跟类别数组长度不一致")
self.length=len(dataSet[0])#测试数据特征值的长度
labelsnum=len(labels)#类别所有的数量
norlabels=set(labels)#不重复类别的数量
for item in norlabels:
thislabel=item
self.labelcount[thislabel]=labels.count(thislabel)/labelsnum#求的当前类别占类别总数的比例
for vector,label in zip(dataSet,labels):
if(label not in self.vectorcount):
self.vectorcount[label]=[]
self.vectorcount[label].append(vector)
print("训练结束")
return self
def btest(self,TestData,labelsSet):
if(self.length==-1):
raise ValueError("您还没有进行训练,请先训练")
#计算testdata分别为各个类别的概率
lbDict=dict()
for thislb in labelsSet:
p=1
alllabel=self.labelcount[thislb]
allvector=self.vectorcount[thislb]
vnum=len(allvector)
allvector=numpy.array(allvector).T
for index in range(0,len(TestData)):
vector=list(allvector[index])
p*=vector.count(TestData[index])/vnum
lbDict[thislb]=p*alllabel
thislabel=sorted(lbDict,key=lambda x:lbDict[x],reverse=True)[0]
return thislabel
#加载数据
def datatoarray(fname):
arr=[]
fh=open(fname)
for i in range(0,32):
thisline=fh.readline()
for j in range(0,32):
arr.append(int(thisline[j]))
return arr
#建立一个函数取文件名前缀
def seplabel(fname):
filestr=fname.split(".")[0]
label=int(filestr.split("_")[0])
return label
#建立训练数据
def traindata():
labels=[]
trainfile=listdir("D:/shujufenxi/traindata")
num=len(trainfile)
#长度1024(列),每一行存储一个文件
#用一个数组存储所有训练数据,行:文件总数,列:1024
trainarr=zeros((num,1024))
for i in range(0,num):
thisfname=trainfile[i]
thislabel=seplabel(thisfname)
labels.append(thislabel)
trainarr[i,:]=datatoarray("D:/shujufenxi/traindata/"+thisfname)
return trainarr,labels
bys=Bayes()
#训练数据
train_data,labels=traindata()
bys.fit(train_data,labels)
#测试
thisdata=datatoarray("D:/shujufenxi/testdata/8_90.txt")
labelsall=[0,1,2,3,4,5,6,7,8,9]
#识别单个手写体数字
'''
rst=bys.btest(thisdata,labelsall)
print(rst) #输出训练结果为8
'''
#识别多个手写体数字(批量测试)
testfileall=listdir("D:/shujufenxi/testdata")
num=len(testfileall)
x=0
for i in range(0,num):
thisfilename=testfileall[i]
'''print(thisfilename)'''
thislabel=seplabel(thisfilename)
#print(thislabel)
thisdataarray=datatoarray("D:/shujufenxi/testdata/"+thisfilename)
label=bys.btest(thisdataarray,labelsall)
print("该数字是:"+str(thislabel)+",识别出来的数字是:"+str(label)) #输出识别结果
if(label!=thislabel):
x+=1
print("此次出错")
print(x)
print("错误率是:"+str(float(x)/float(num)))