import xlrd
import random
import math
#将表格文件进行导入
def loaddata(fname):
file=open(fname)
data=xlrd.open_workbook(fname) #将表格的内容进行读取
dataname=data.sheet_names() #生成的是一个列表
#shxrange=range(data.nsheets)
#print(shxrange)
try:
sh=data.sheet_by_name(dataname[0])
except:
print("no sheet %s named Sheet1".format(fname))
nrows=sh.nrows
ncols=sh.ncols
print("nrows {0},ncols {1}".format(nrows,ncols))
datasets=[]
for i in range(nrows):
datasets.append(sh.row_values(i))
del datasets[0]
return datasets
#测试程序,用的是自己建立的表格数据
#dataset=loaddata("E:\\pima_data\\test_data.xlsx")
#print("dataset",dataset)
#print(len(dataset))
#训练集和测试集进行分割
def splitDataset(dataset,splitRatio):
trainSet=[]
dataSet_copy=dataset
trainSize=(len(dataset))*splitRatio
n=0
while trainSize>n:
index=random.randrange(len(dataSet_copy))
#表示在数据集中任意选择样本,保证样本的随机性
trainSet.append(dataSet_copy[index])
dataSet_copy.pop(index)
n+=1
testSet=dataSet_copy
return trainSet,testSet #返回的是包含每一个样本的列表
#进行程序的测试
#(trainSet,testSet)=splitDataset(dataset,0.6)
#print("trainSet",trainSet)
#print("testSet",testSet)
#对属性和标签进行分别存放
def splitAttrLabel(dataSet):
#对于训练集和测试集是一样的处理,所以使用一个函数就可以进行处理
Attr=[]
Label=[]
num=len(dataSet) #表示数据集中样本的数量
n_attr=len(dataSet[0])-1 #为了代码的重复利用,不用修改参数
for i in range(num):
Attr.append(list(dataSet[i][0:n_attr])) #生成包含每个样本属性的列表属性列表
Label.append(dataSet[i][n_attr]) #生成包含每个标签的标签列表
return Attr,Label
#属性应该分为有糖尿病的属性是什么,没有糖尿病的属性是什么
#但是可以不定义函数,直接在程序中写出来
#测试
#(Attr,Label)=splitAttrLabel(trainSet)
#print("trainSet Attr",Attr)
#print("trainSet Label",Label)
#将不同分类的属性进行分别存放,为了可以分别计算均值和标准差
def classfiAttr(Attr,Label):
Attr_have=[]
Attr_no=[]
for i in range(len(Label)):
if Label[i]==1:
Attr_have.append(Attr[i])
else:
Attr_no.append(Attr[i])
return Attr_have,Attr_no
#测试
#(Attr_have,Attr_no)=classfiAttr(Attr,Label)
#print("糖尿病患者属性列表",Attr_have)
#print("非糖尿病患者属性列表",Attr_no)
#因为是连续的数值,
# 所以使用贝叶斯公式对数值进行处理得到各个属性的类条件概率
#由最大似然法得到正太分布的均值就是样本均值
def stmean(Attr):
attr_mean=[] #将8个属性的平均值都放到这个列表中作为向量使用
for each_attr in range(len(Attr[0])):
#print("属性的长度是多少",len(Attr[0]))
#print(each_attr)
sum=0
for each_example in range(len(Attr)):
#print(Attr[each_example][each_attr])
sum+=Attr[each_example][each_attr]
attr_mean.append(sum/len(Attr))
#each_attr_mean=(sum(Attr[:][each_attr]))/(len(Attr))
#print(Attr[:])
#attr_mean.append(each_attr_mean)
return attr_mean
#进行测试
#stmean_no=stmean(Attr_no)
#print("trainSet stmean_no",stmean_no)
#标准差
#标准差就是样本的平均标准差
def stdev(Attr,stmean):
attr_dev=[] #将8个属性的平均值都放到这个列表中作为向量使用
for each_attr in range(len(Attr[0])):
sum=0
for each_example in range(len(Attr)):
#print("函数内",stmean[each_attr])
sum+=pow((Attr[each_example][each_attr]-stmean[each_attr]),2)
attr_dev.append(math.sqrt(sum/len(Attr)))
return attr_dev
#测试
#stdev_no=stdev(Attr_no,stmean_no)
#print("标准差",stdev(Attr_no,stmean_no))
#定义类概率密度函数
def calculateProbability(x, mean, stdev):
exponent = math.exp(-(math.pow(x-mean,2)/(2*math.pow(stdev,2))))
return (1 / (math.sqrt(2*math.pi) * stdev)) * exponent
#测试
#Probability=calculateProbability(4, stmean_no[0], stdev_no[0])
#print("单个值单属性的类条件概率",Probability)
#计算类别的先验概率
def calculatepriorprobability(Attr,Attr_have,Attr_no):
probability_have=(len(Attr_have)+1)/(len(Attr)+2)
probability_no=(len(Attr_no)+1)/(len(Attr)+2)
return probability_have,probability_no
#测试
#(probability_have,probability_no)=calculatepriorprobability(Attr_have,Attr_no)
#print("有糖尿病的先验概率是:",probability_have)
#print("没有糖尿病的先验概率是:",probability_no)
#进行测试集的预测
def predict(priorprobability,Attr_test,mean,stdev):
lateprobability_list=[]
for each_example in range(len(Attr_test)):
lateprobability = priorprobability
for each_attr in range(len(Attr_test[0])):
lateprobability*=calculateProbability(Attr_test[each_example][each_attr], mean[each_attr], stdev[each_attr])
#print("测试集的属性值",Attr_test[each_example][each_attr])
#print(lateprobability)
lateprobability_list.append(lateprobability) #生成测试集相同数量的后延概率的列表
return lateprobability_list
#将有糖尿病和没有糖尿病的预测概率进行比较,谁大就是谁
def compare(lateprobability_list_have,lateprobability_list_no):
compare_list=[]
for i in range(len(lateprobability_list_have)):
if lateprobability_list_have[i]>=lateprobability_list_no[i]:
compare_list.append(1)
else:
compare_list.append(0)
return compare_list
#精度函数
def predict_precision(test_label,compare_list):
n=0 #表示这个时候没有一个数据正确
for i in range(len(test_label)):
if test_label[i]==compare_list[i]:
n+=1
print(n)
precision=n/(len(test_label))
return precision
#定义主函数
def main():
fname="E:\\datasets\\pima_data\\pima.xlsx"
dataset=loaddata(fname) #将数据集导入
(trainSet,testSet)=splitDataset(dataset, 0.67) #将数据集进行分割,分割成训练集和测试集
print("训练集为:",trainSet,"\n训练集数目为:",len(trainSet))
print("测试集为:", testSet,"\n测试集数目为:",len(testSet))
(train_attr,train_label)=splitAttrLabel(trainSet) #将训练集的属性和标签进行分割
(test_attr, test_label) = splitAttrLabel(testSet) #测试集的属性和标签进行单独分割
print("测试集的标签:",test_label,"\n测试集标签数目为:",len(test_label))
(train_Attr_have,train_Attr_no)=classfiAttr(train_attr,train_label) #对训练集的属性值进行分别存放
train_mean_have=stmean(train_Attr_have) #糖尿病人的属性均值
print("训练集中有糖尿病的均值为",train_mean_have)
train_mean_no=stmean(train_Attr_no) #非糖尿病人的属性均值
print("训练集中没有糖尿病的均值为", train_mean_no)
train_dev_have=stdev(train_Attr_have, train_mean_have)
print("训练集中有糖尿病的方差为", train_dev_have)
train_dev_no=stdev(train_Attr_no, train_mean_no)
print("训练集中没有糖尿病的方差为", train_dev_no)
(prior_probability_have, prior_probability_no)=calculatepriorprobability(train_attr,train_Attr_have,train_Attr_no)
print("训练集中有和没有糖尿病的先验概率为:",prior_probability_have, prior_probability_no)
lateprobability_list_have=predict(prior_probability_have, test_attr, train_mean_have, train_dev_have)
print("有糖尿病的后验概率表",lateprobability_list_have)
lateprobability_list_no=predict(prior_probability_no, test_attr, train_mean_no, train_dev_no)
print("没有糖尿病的后验概率表", lateprobability_list_no)
compare_list=compare(lateprobability_list_have, lateprobability_list_no)
print("通过比较得出的比较值0,1值",compare_list)
precision=predict_precision(test_label, compare_list)
return precision
precision=main()
print("精度为:",precision)
使用pima数据集作为训练集和测试集,准确率可以达到74.7。