朴素贝叶斯分类器python代码(含注释)

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。

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下面是根据Adult数据集构建朴素贝叶斯分类器,并测试分类器性能,输出性能指标并画出ROC曲线的Python代码: ```python import pandas as pd import numpy as np from sklearn.naive_bayes import GaussianNB from sklearn.metrics import accuracy_score, confusion_matrix, roc_curve, auc from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt # 读取数据集 data = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data', header=None, na_values='?') # 给数据集添加列名 data.columns = ['age', 'workclass', 'fnlwgt', 'education', 'education-num', 'marital-status', 'occupation', 'relationship', 'race', 'sex', 'capital-gain', 'capital-loss', 'hours-per-week', 'native-country', 'income'] # 删除有缺失值的行 data = data.dropna() # 将分类变量进行编码 data['income'] = np.where(data['income'] == '>50K', 1, 0) data['sex'] = np.where(data['sex'] == 'Male', 1, 0) # 将连续变量进行标准化 data['age'] = (data['age'] - data['age'].mean()) / data['age'].std() data['fnlwgt'] = (data['fnlwgt'] - data['fnlwgt'].mean()) / data['fnlwgt'].std() data['education-num'] = (data['education-num'] - data['education-num'].mean()) / data['education-num'].std() data['capital-gain'] = (data['capital-gain'] - data['capital-gain'].mean()) / data['capital-gain'].std() data['capital-loss'] = (data['capital-loss'] - data['capital-loss'].mean()) / data['capital-loss'].std() data['hours-per-week'] = (data['hours-per-week'] - data['hours-per-week'].mean()) / data['hours-per-week'].std() # 将分类变量进行one-hot编码 data = pd.get_dummies(data, columns=['workclass', 'education', 'marital-status', 'occupation', 'relationship', 'race', 'native-country']) # 将数据集划分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(data.drop(['income'], axis=1), data['income'], test_size=0.3, random_state=123) # 构建朴素贝叶斯分类器 nb = GaussianNB() nb.fit(X_train, y_train) # 在测试集上进行预测 y_pred = nb.predict(X_test) # 计算分类器的性能指标 accuracy = accuracy_score(y_test, y_pred) confusion = confusion_matrix(y_test, y_pred) fpr, tpr, thresholds = roc_curve(y_test, y_pred) roc_auc = auc(fpr, tpr) # 输出性能指标 print("Accuracy:", accuracy) print("Confusion matrix:\n", confusion) print("AUC of ROC curve:", roc_auc) # 画出ROC曲线 plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc) plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--') plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('Receiver operating characteristic') plt.legend(loc="lower right") plt.show() ``` 代码解释: 1. 首先读取数据集,并对数据集进行预处理,包括删除有缺失值的行、对分类变量进行编码、对连续变量进行标准化、对分类变量进行one-hot编码等。 2. 然后将数据集划分为训练集和测试集。 3. 接着构建朴素贝叶斯分类器,并在测试集上进行预测。 4. 最后计算分类器的性能指标,包括准确率、混淆矩阵、ROC曲线和AUC。 5. 画出ROC曲线,用于评估分类器的性能。 注意:本代码中使用的是高斯朴素贝叶斯分类器,适用于处理连续变量。如果数据集中有离散变量,可以考虑使用多项式朴素贝叶斯分类器

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值