阅读学习了《机器学习》第7章的贝叶斯分类器后,为了加深理解和加强python的代码能力,因此尝试使用Python实现朴素贝叶斯分类器,由于初学Python的缘故,代码的一些实现方法可能比较繁琐,可阅读性有待提高。代码如下:
#import numpy as np
import math
def loadDataset () :
#西瓜数据集2.0
postingList=[['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑'],
['乌黑', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑'],
['乌黑', '蜷缩', '浊响', '清晰', '凹陷', '硬滑'],
['青绿', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑'],
['浅白', '蜷缩', '浊响', '清晰', '凹陷', '硬滑'],
['青绿', '稍蜷', '浊响', '清晰', '稍凹', '软粘'],
['乌黑', '稍蜷', '浊响', '稍糊', '稍凹', '软粘'],
['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '硬滑'],
['乌黑', '稍蜷', '沉闷', '稍糊', '稍凹', '硬滑'],
['青绿', '硬挺', '清脆', '清晰', '平坦', '软粘'],
['浅白', '硬挺', '清脆', '稍糊', '平坦', '硬滑'],
['浅白', '蜷缩', '浊响', '模糊', '平坦', '软粘'],
['青绿', '稍蜷', '浊响', '稍糊', '凹陷', '硬滑'],
['浅白', '稍蜷', '沉闷', '稍糊', '凹陷', '硬滑'],
['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '软粘'],
['浅白', '蜷缩', '浊响', '模糊', '平坦', '硬滑'],
['青绿', '蜷缩', '沉闷', '稍糊', '稍凹', '硬滑']]
classVec = [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0] #1表示好瓜, 0表示坏瓜
return postingList, classVec
def extractInfo(dataset):
#提取西瓜数据集2.0的信息
feature_num=[] #记录每项属性的全部属性取值的数目
feature_sort=[] #记录每项属性的全部的属性取值
for i in range(len(dataset[0])):
temp=set(x[i] for x in dataset) #一列代表一项属性,取一项属性
feature_sort.append(list(temp))
feature_num.append(len(temp))
return feature_num, feature_sort
#训练朴素贝叶斯分类器
def trainBYS(dataset, feature_num, feature_sort, classLabel):
T_data=[] #记录好瓜的数据集
F_data=[] #记录坏瓜的数据集
sort_num=len(set(classLabel)) #类别的数目,如好瓜和坏瓜,只有两个类别
for i in range(len(classLabel)): #将总数据集分类成好瓜数据集和坏瓜数据集
if classLabel[i]==1:
T_data.append(dataset[i])
else:
F_data.append(dataset[i])
#计算加入拉普拉斯修正的先验概率和似然概率
Pc=(sum(classLabel) + 1) / (len(classLabel) + sort_num) #样本中好瓜的概率,即先验概率
p1num={} #用于记录好瓜数据集中各属性取值的概率
p0num={} #用于记录坏瓜数据集中各属性取值的概率
for i in range(len(feature_num)): #统计数据,计算概率
temp1=[x[i] for x in T_data]
temp2=[x[i] for x in F_data]
for sort_value in feature_sort[i]: #初始化概率,加入了拉普拉斯修正
if sort_value not in p1num.keys():
p1num[sort_value] = 1 / (len(temp1) + feature_num[i])
if sort_value not in p0num.keys():
p0num[sort_value] = 1 / (len(temp2) + feature_num[i])
for y in temp1: #统计正样本的各属性取值概率
p1num[y]+= 1 / (len(temp1) + feature_num[i])
for y in temp2: #统计负样本的各属性取值概率
p0num[y]+= 1 / (len(temp2) + feature_num[i])
return p0num,p1num,Pc
#对输入的测试样本进行计算比较后验概率
def classifyBYS(inputdata, p0num, p1num, Pc, length):
input_length=len(inputdata)
sample_length=length
if input_length != sample_length:
print('输入数据格式不对')
return -1
Pt=math.log(Pc) #避免连乘造成下溢,使用对数似然
Pf=math.log(1-Pc)
for x in inputdata:
Pt += math.log(p1num.get(x))
Pf += math.log(p0num.get(x))
if Pt >= Pf:
return 1
else:
return 0
#测试代码
dataset, classLabel=loadDataset()
feature_num, feature_sort = extractInfo(dataset)
#print(feature_sort)
p0num, p1num, Pc = trainBYS(dataset, feature_num, feature_sort, classLabel)
#print(p1num)
inputdata = ['浅白', '稍蜷', '沉闷', '稍糊', '凹陷', '硬滑']
result=classifyBYS(inputdata, p0num, p1num, Pc, len(dataset[0]))
if result == 1:
print('好瓜')
elif result == 0:
print('坏瓜')