在这里,我们使用一份皮马印第安女性的医学数据,用来预测其是否会得糖尿病。文件一共有768个样本,我们先剔除缺失值,然后选出20%的样本作为测试样本。

特征分别是:

怀孕次数

口服葡萄糖耐量试验中血浆葡萄糖浓度

舒张压(mm Hg)

三头肌组织褶厚度(mm)

2小时血清胰岛素(μU/ ml)

体重指数(kg/(身高(m))^ 2)

糖尿病系统功能

年龄(岁)

(注:特征值为0表示缺失值)

标签是:

是否患有糖尿病,0代表没有糖尿病,1代表患有糖尿病

在开始之前,先回顾一下朴素贝叶斯算法:

假设训练集特征数为i,记作xi,目标为k个类别,记为Ck,样本数为n,新样本特征记作xnew_sample。

1,计算出先验概率P(Ck),即每个类别在训练集中的概率;

2,分别计算出训练集中每个特征在每个类别下的条件概率P(xi|Ck),具体分为以下三种情况;

a)如果特征数据是离散值,那么我们假设其符合多项式分布,代入公式

b)如果特征数据是布尔类型的离散值,那么我们假设其符合伯努利分布,代入公式

c)如果特征数据是连续值,那么我们假设其符合高斯分布。只需要求出这个特征在每个类别下的平均值μk和方差σk2,然后代入公式

3,对于需要预测类别的新样本,分别计算每个类别下的极大后验概率:

(我们在实际计算中为防止数据下溢,将连乘运算取对数变成相加运算);

4,对上述极大后验概率进行比较,最大的那个对应的类别即为结果;

首先导入pandas和numpy库,读取csv文件,然后去除缺失值:

importpandas as pdimportnumpy as np

data=pd.read_csv(r"C:\Users\ccav\pima-indians-diabetes.data.csv",header=None,\

names=["怀孕次数","口服葡萄糖耐量试验中血浆葡萄糖浓度",\"舒张压(mm Hg)","三头肌组织褶厚度(mm)",\"2小时血清胰岛素(μU/ ml)","体重指数(kg/(身高(m))^ 2)",\"糖尿病系统功能","年龄(岁)","是否患有糖尿病"])

data.iloc[:,0:8]=data.iloc[:,0:8].applymap(lambda x:np.NaN if x==0 else x) #把属性值为0的地方转换成NaN

data=data.dropna(how="any",axis=0) #去除有缺失值的行

经过处理还只剩336个有效样本:

print(len(data))336

通过查看,我们发现在这336个有效样本中,225个是没有糖尿病人的样本,111个是患有糖尿病人的样本,显然原数据里两个类别的样本是不均衡的。这个问题可以通过不同的采样方法解决,但是鉴于简便起见,我们随机选取大约20%的样本用于测试:

#随机选取80%的样本作为训练样本

data_train=data.sample(frac=0.8,random_state=4,axis=0)#剩下的作为测试样本

test_idx=[i for i in data.index.values if i not indata_train.index.values]

data_test=data.loc[test_idx,:]

由于我们一共有8个特征,2个类别,因此,我们一共需要计算16个条件概率以及2个先验概率,然后根据这些数据计算出2个极大后验概率。该如何计算这些数据,又该如何合并,如果不事先想清楚怎么做,很容易被搞晕。此外,考虑到数据是连续值,我们假设其符合正态分布,因此在训练时需要计算出每个特征的平均值和方差。

让我们先来理清一下思路:

1,按类别分隔数据

2,获取类别总数和类别名称

3,训练数据:计算每个类别的先验概率,计算每个类别每个特征的平均值和方差

4,预测:计算每个类别每个特征的条件概率,计算每个类别的极大后验概率并合并,得出最大可能的类别名称

按照这个步骤,我们发现以下几项都是需要复用的:按类别分隔数据,计算每个类别的先验概率,计算每个类别每个特征的平均值和方差,计算每个类别每个特征的条件概率。因此,我们把这几项分别做成function。

按类别分隔数据:

defSepByClass(X, y):###按类别分隔数据###

###输入未分类的特征和目标,输出分类完成的数据(字典形式)###

num_of_samples=len(y) #总样本数

y=y.reshape(X.shape[0],1)

data=np.hstack((X,y)) #把特征和目标合并成完整数据

data_byclass={} #初始化分类数据,为一个空字典

#提取各类别数据,字典的键为类别名,值为对应的分类数据

for i in range(len(data[:,-1])):if i in data[:,-1]:

data_byclass[i]=data[data[:,-1]==i]

class_name=list(data_byclass.keys()) #类别名

num_of_class=len(data_byclass.keys()) #类别总数

return data_byclass

计算每个类别的先验概率:

defCalPriorProb(y_byclass):###计算y的先验概率(使用拉普拉斯平滑)###

###输入当前类别下的目标,输出该目标的先验概率###

#计算公式:(当前类别下的样本数+1)/(总样本数+类别总数)

return (len(y_byclass)+1)/(num_of_samples+num_of_class)

计算每个类别每个特征的平均值和方差:

defCalXMean(X_byclass):###计算各类别特征各维度的平均值###

###输入当前类别下的特征,输出该特征各个维度的平均值###

X_mean=[]for i in range(X_byclass.shape[1]):

X_mean.append(np.mean(X_byclass[:,i]))returnX_meandefCalXVar(X_byclass):###计算各类别特征各维度的方差###

###输入当前类别下的特征,输出该特征各个维度的方差###

X_var=[]for i in range(X_byclass.shape[1]):

X_var.append(np.var(X_byclass[:,i]))return X_var

计算每个类别每个特征的条件概率:

defCalGaussianProb(X_new, mean, var):###计算训练集特征(符合正态分布)在各类别下的条件概率###

###输入新样本的特征,训练集特征的平均值和方差,输出新样本的特征在相应训练集中的分布概率###

#计算公式:(np.exp(-(X_new-mean)**2/(2*var)))*(1/np.sqrt(2*np.pi*var))

gaussian_prob=[]for a,b,c inzip(X_new, mean, var):

formula1=np.exp(-(a-b)**2/(2*c))

formula2=1/np.sqrt(2*np.pi*c)

gaussian_prob.append(formula2*formula1)return gaussian_prob

接下来,我们开始训练数据。首先按类别分隔数据,然后遍历每一个类别,分别计算每个类别的先验概率和每个类别每个特征的平均值和方差,并储存在列表中。

deffit(X, y):###训练数据###

###输入训练集特征和目标,输出目标的先验概率,特征的平均值和方差###

#将输入的X,y转换为numpy数组

X, y =np.asarray(X, np.float32), np.asarray(y, np.float32)

data_byclass=Gaussian_NB.SepByClass(X,y) #将数据分类

#计算各类别数据的目标先验概率,特征平均值和方差

for data indata_byclass.values():

X_byclass=data[:,:-1]

y_byclass=data[:,-1]

prior_prob.append(Gaussian_NB.CalPriorProb(y_byclass))

X_mean.append(Gaussian_NB.CalXMean(X_byclass))

X_var.append(Gaussian_NB.CalXVar(X_byclass))return prior_prob, X_mean, X_var

最后,输入一个新样本的特征,预测其所属的类别。首先,遍历之前在训练数据时计算出的每个类别的先验概率和每个类别每个特征的平均值和方差,再以此计算条件概率和极大后验概率。选出最大的极大后验概率所对应的索引,最后提取其对应的类别名称。

defpredict(X_new):###预测数据###

###输入新样本的特征,输出新样本最有可能的目标###

#将输入的x_new转换为numpy数组

X_new=np.asarray(X_new, np.float32)

posteriori_prob=[] #初始化极大后验概率

for i,j,o inzip(prior_prob, X_mean, X_var):

gaussian=Gaussian_NB.CalGaussianProb(X_new,j,o)

posteriori_prob.append(np.log(i)+sum(np.log(gaussian)))

idx=np.argmax(posteriori_prob)return class_name[idx]

整理一下以上代码,我们把这个高斯朴素贝叶斯分类器做成一个类,完整代码如下:

importpandas as pdimportnumpy as np

data=pd.read_csv(r"C:\Users\ccav\pima-indians-diabetes.data.csv",header=None,\

names=["怀孕次数","口服葡萄糖耐量试验中血浆葡萄糖浓度",\"舒张压(mm Hg)","三头肌组织褶厚度(mm)",\"2小时血清胰岛素(μU/ ml)","体重指数(kg/(身高(m))^ 2)",\"糖尿病系统功能","年龄(岁)","是否患有糖尿病"])

data.iloc[:,0:8]=data.iloc[:,0:8].applymap(lambda x:np.NaN if x==0 else x) #把属性值为0的地方转换成NaN

data=data.dropna(how="any",axis=0) #去除有缺失值的行

#随机选取80%的样本作为训练样本

data_train=data.sample(frac=0.8,random_state=4,axis=0)#剩下的作为测试样本

test_idx=[i for i in data.index.values if i not indata_train.index.values]

data_test=data.loc[test_idx,:]#提取训练集和测试集的特征和目标

X_train=data_train.iloc[:,:-1]

y_train=data_train.iloc[:,-1]

X_test=data_test.iloc[:,:-1]

y_test=data_test.iloc[:,-1]classGaussian_NB:def __init__(self):

self.num_of_samples=None

self.num_of_class=None

self.class_name=[]

self.prior_prob=[]

self.X_mean=[]

self.X_var=[]defSepByClass(self, X, y):###按类别分隔数据###

###输入未分类的特征和目标,输出分类完成的数据(字典形式)###

self.num_of_samples=len(y) #总样本数

y=y.reshape(X.shape[0],1)

data=np.hstack((X,y)) #把特征和目标合并成完整数据

data_byclass={} #初始化分类数据,为一个空字典

#提取各类别数据,字典的键为类别名,值为对应的分类数据

for i in range(len(data[:,-1])):if i in data[:,-1]:

data_byclass[i]=data[data[:,-1]==i]

self.class_name=list(data_byclass.keys()) #类别名

self.num_of_class=len(data_byclass.keys()) #类别总数

returndata_byclassdefCalPriorProb(self, y_byclass):###计算y的先验概率(使用拉普拉斯平滑)###

###输入当前类别下的目标,输出该目标的先验概率###

#计算公式:(当前类别下的样本数+1)/(总样本数+类别总数)

return (len(y_byclass)+1)/(self.num_of_samples+self.num_of_class)defCalXMean(self, X_byclass):###计算各类别特征各维度的平均值###

###输入当前类别下的特征,输出该特征各个维度的平均值###

X_mean=[]for i in range(X_byclass.shape[1]):

X_mean.append(np.mean(X_byclass[:,i]))returnX_meandefCalXVar(self, X_byclass):###计算各类别特征各维度的方差###

###输入当前类别下的特征,输出该特征各个维度的方差###

X_var=[]for i in range(X_byclass.shape[1]):

X_var.append(np.var(X_byclass[:,i]))returnX_vardefCalGaussianProb(self, X_new, mean, var):###计算训练集特征(符合正态分布)在各类别下的条件概率###

###输入新样本的特征,训练集特征的平均值和方差,输出新样本的特征在相应训练集中的分布概率###

#计算公式:(np.exp(-(X_new-mean)**2/(2*var)))*(1/np.sqrt(2*np.pi*var))

gaussian_prob=[]for a,b,c inzip(X_new, mean, var):

formula1=np.exp(-(a-b)**2/(2*c))

formula2=1/np.sqrt(2*np.pi*c)

gaussian_prob.append(formula2*formula1)returngaussian_probdeffit(self, X, y):###训练数据###

###输入训练集特征和目标,输出目标的先验概率,特征的平均值和方差###

#将输入的X,y转换为numpy数组

X, y =np.asarray(X, np.float32), np.asarray(y, np.float32)

data_byclass=Gaussian_NB.SepByClass(X,y) #将数据分类

#计算各类别数据的目标先验概率,特征平均值和方差

for data indata_byclass.values():

X_byclass=data[:,:-1]

y_byclass=data[:,-1]

self.prior_prob.append(Gaussian_NB.CalPriorProb(y_byclass))

self.X_mean.append(Gaussian_NB.CalXMean(X_byclass))

self.X_var.append(Gaussian_NB.CalXVar(X_byclass))returnself.prior_prob, self.X_mean, self.X_vardefpredict(self,X_new):###预测数据###

###输入新样本的特征,输出新样本最有可能的目标###

#将输入的x_new转换为numpy数组

X_new=np.asarray(X_new, np.float32)

posteriori_prob=[] #初始化极大后验概率

for i,j,o inzip(self.prior_prob, self.X_mean, self.X_var):

gaussian=Gaussian_NB.CalGaussianProb(X_new,j,o)

posteriori_prob.append(np.log(i)+sum(np.log(gaussian)))

idx=np.argmax(posteriori_prob)returnself.class_name[idx]if __name__=="__main__":

Gaussian_NB=Gaussian_NB() #实例化Gaussian_NB

Gaussian_NB.fit(X_train,y_train) #使用Gaussian_NB模型训练数据

acc=0

TP=0

FP=0

FN=0for i inrange(len(X_test)):

predict=Gaussian_NB.predict(X_test.iloc[i,:])

target=np.array(y_test)[i]if predict==1 and target==1:

TP+=1

if predict==0 and target==1:

FP+=1

if predict==target:

acc+=1

if predict==1 and target==0:

FN+=1

print("准确率:",acc/len(X_test))print("查准率:",TP/(TP+FP))print("查全率:",TP/(TP+FN))print("F1:",2*TP/(2*TP+FP+FN))

结果如下:

准确率: 0.7611940298507462查准率:0.7391304347826086查全率:0.6296296296296297F1:0.68

由于样本不均衡,因此光看准确率是不够的,在这里一并计算了查准率和查全率以及F1值。可以看出这个分类器的效果不是很好,一方面是因为样本数量较少,另一方面朴素贝叶斯的预测能力确实比不上复杂模型,只能提供一个粗略的判断。

python实现朴素贝叶斯算法_机器学习---用python实现朴素贝叶斯算法(Machine Learning Naive Bayes Algorithm Application)...相关推荐

  1. 机器学习---用python实现朴素贝叶斯算法(Machine Learning Naive Bayes Algorithm Application)...

    在<机器学习---朴素贝叶斯分类器(Machine Learning Naive Bayes Classifier)>一文中,我们介绍了朴素贝叶斯分类器的原理.现在,让我们来实践一下. 在 ...

  2. 机器学习 贝叶斯方法_机器学习中的常客与贝叶斯方法

    机器学习 贝叶斯方法 There has always been a debate between Bayesian and frequentist statistical inference. Fr ...

  3. 推荐系统算法_机器学习和推荐系统(二)推荐算法简介

    推荐算法简介 一. 基于人口统计学的推荐算法 二.基于内容的推荐算法 三. 基于协同过滤的推荐算法 协同过滤(Collaborative Filtering , CF) 基于近邻的系统过滤 基于用户( ...

  4. 如何检查python的库是否安装成功_机器学习之Python编程库的安装

    Python机器学习的优势: 1.方便调试的解释型语言 2.跨屏台执行作业 3.广泛的应用编程接口 4.完备的开源工具包 接下来笔者就来数一数如何安装Python的编程库(扩展包),为搭建机器学习的系 ...

  5. 机器学习朴素贝叶斯算法_机器学习中的朴素贝叶斯算法

    机器学习朴素贝叶斯算法 朴素贝叶斯算法 (Naive Bayes Algorithm) Naive Bayes is basically used for text learning. Using t ...

  6. 判别两棵树是否相等 设计算法_机器学习算法-朴素贝叶斯

    一.概述 概率分类器 在许多分类算法应用中,特征和标签之间的关系并非是决定性的.比如说,我们想预测一个人究竟是否会在泰坦尼克号海难中生存下来,那我们可以建一棵决策树来学习我们的训练集.在训练中,其中一 ...

  7. python 隐马尔科夫_机器学习算法之——隐马尔可夫(Hidden Markov ModelsHMM)原理及Python实现...

    前言 上星期写了Kaggle竞赛的详细介绍及入门指导,但对于真正想要玩这个竞赛的伙伴,机器学习中的相关算法是必不可少的,即使是你不想获得名次和奖牌.那么,从本周开始,我将介绍在Kaggle比赛中的最基 ...

  8. 使用opencv和python实现图像的智能处理_机器学习:使用opencv和python进行智能图像处理...

    译者序 序 前言 审校者简介 章 品味机器学习 1 1.1 初步了解机器学习 1 1.2 机器学习可以解决的事情 3 1.3 初步了解 Python 4 1.4 初步了解 OpenCV 4 1.5 安 ...

  9. kmeans聚类算法_机器学习/算法校招面试考点汇总(附面试题和答案)【持续更新】_笔经面经...

    以下不作为机器学习/算法工程师的学习路径,只是汇总的校招机器学习/算法工程师面试考点(因为还有笔试考点,后面结合在一起给大家学习路径),后续会为大家更新10w+字数的机器学习/算法工程师校招面试题库, ...

最新文章

  1. SPOJ220 Relevant Phrases of Annihilation(后缀数组)
  2. 利用非递归方法实现二叉树的先序遍历
  3. ABAP中P类型介绍
  4. Android获取网络状态
  5. [C++STL]list容器用法介绍
  6. 计算机一级试题论述,计算机一级考试理论题及答案要点
  7. Java—接口(工厂模式代理模式)
  8. IOS UI 第三篇:基本UI
  9. Android 系统性能优化(80)---Android性能优化:这是一份详细的布局优化 指南(含lt;includegt;、lt;Viewstubgt;、lt;mergegt;)
  10. IT报表开发者必看:别加班了,快用这个神器提高报表开发效率
  11. oracle java vm,我可以使用Oracle Java 7 HotSpot VM安装DCEVM吗?
  12. js 获取当天时间,实现展示包含今天的一周时间的方法
  13. 余弦距离和欧氏距离,知道原理和公式后真的很简单
  14. 测量法的三种测量方法计算机,圆度的测量方法有哪几种
  15. IPC的标准是什么?
  16. 基于FFMPEG的H264视频解码库(流式解码)
  17. Nessus部署及简单使用
  18. 【树莓派】使用VNC远程桌面
  19. ASR6505基于STM 8位MCU与SX1262 的SiP全频段LoRa芯片
  20. Cys(Npys)-(Arg)₉,H2N-C(Npys)-RRRRRRRRR-OH

热门文章

  1. 如何选择安全可靠质量好的移动电源
  2. cmd 查看java版本
  3. 拆分bam统计clean reads长度
  4. linux代码对齐快捷键和man帮助文档的使用总结
  5. 少林寺与时俱进用电影网络推广少林文化(组图)
  6. 为OkGo网络请求增加自定义log功能
  7. 从游民星空爬取每周壁纸
  8. php 签名 bom,PHP教程:Unicode 签名(BOM)问题_php
  9. 下载Linux 远程工具 Xshell和Xftp最新版本
  10. 临床医学专业计算机必须过几级,临床、金融、计算机电子信息,这些专业过去现在未来都是大热门...