机器学习---用python实现朴素贝叶斯算法(Machine Learning Naive Bayes Algorithm Application)...
在《机器学习---朴素贝叶斯分类器(Machine Learning Naive Bayes Classifier)》一文中,我们介绍了朴素贝叶斯分类器的原理。现在,让我们来实践一下。
在这里,我们使用一份皮马印第安女性的医学数据,用来预测其是否会得糖尿病。文件一共有768个样本,我们先剔除缺失值,然后选出20%的样本作为测试样本。
文件下载地址:https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv
特征分别是:
怀孕次数
口服葡萄糖耐量试验中血浆葡萄糖浓度
舒张压(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文件,然后去除缺失值:
import pandas as pd import numpy as npdata=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 in data_train.index.values] data_test=data.loc[test_idx,:]
由于我们一共有8个特征,2个类别,因此,我们一共需要计算16个条件概率以及2个先验概率,然后根据这些数据计算出2个极大后验概率。该如何计算这些数据,又该如何合并,如果不事先想清楚怎么做,很容易被搞晕。此外,考虑到数据是连续值,我们假设其符合正态分布,因此在训练时需要计算出每个特征的平均值和方差。
让我们先来理清一下思路:
1,按类别分隔数据
2,获取类别总数和类别名称
3,训练数据:计算每个类别的先验概率,计算每个类别每个特征的平均值和方差
4,预测:计算每个类别每个特征的条件概率,计算每个类别的极大后验概率并合并,得出最大可能的类别名称
按照这个步骤,我们发现以下几项都是需要复用的:按类别分隔数据,计算每个类别的先验概率,计算每个类别每个特征的平均值和方差,计算每个类别每个特征的条件概率。因此,我们把这几项分别做成function。
按类别分隔数据:
def SepByClass(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
计算每个类别的先验概率:
def CalPriorProb(y_byclass):###计算y的先验概率(使用拉普拉斯平滑)######输入当前类别下的目标,输出该目标的先验概率####计算公式:(当前类别下的样本数+1)/(总样本数+类别总数)return (len(y_byclass)+1)/(num_of_samples+num_of_class)
计算每个类别每个特征的平均值和方差:
def CalXMean(X_byclass):###计算各类别特征各维度的平均值######输入当前类别下的特征,输出该特征各个维度的平均值###X_mean=[]for i in range(X_byclass.shape[1]):X_mean.append(np.mean(X_byclass[:,i]))return X_meandef CalXVar(X_byclass):###计算各类别特征各维度的方差######输入当前类别下的特征,输出该特征各个维度的方差###X_var=[]for i in range(X_byclass.shape[1]):X_var.append(np.var(X_byclass[:,i]))return X_var
计算每个类别每个特征的条件概率:
def CalGaussianProb(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 in zip(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
接下来,我们开始训练数据。首先按类别分隔数据,然后遍历每一个类别,分别计算每个类别的先验概率和每个类别每个特征的平均值和方差,并储存在列表中。
def fit(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 in data_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
最后,输入一个新样本的特征,预测其所属的类别。首先,遍历之前在训练数据时计算出的每个类别的先验概率和每个类别每个特征的平均值和方差,再以此计算条件概率和极大后验概率。选出最大的极大后验概率所对应的索引,最后提取其对应的类别名称。
def predict(X_new):###预测数据######输入新样本的特征,输出新样本最有可能的目标####将输入的x_new转换为numpy数组X_new=np.asarray(X_new, np.float32)posteriori_prob=[] #初始化极大后验概率for i,j,o in zip(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]
整理一下以上代码,我们把这个高斯朴素贝叶斯分类器做成一个类,完整代码如下:
import pandas as pd import numpy as npdata=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 in data_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]class Gaussian_NB:def __init__(self):self.num_of_samples = Noneself.num_of_class = Noneself.class_name = []self.prior_prob = []self.X_mean = []self.X_var = []def SepByClass(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()) #类别总数return data_byclassdef CalPriorProb(self, y_byclass):###计算y的先验概率(使用拉普拉斯平滑)######输入当前类别下的目标,输出该目标的先验概率####计算公式:(当前类别下的样本数+1)/(总样本数+类别总数)return (len(y_byclass)+1)/(self.num_of_samples+self.num_of_class)def CalXMean(self, X_byclass):###计算各类别特征各维度的平均值######输入当前类别下的特征,输出该特征各个维度的平均值###X_mean=[]for i in range(X_byclass.shape[1]):X_mean.append(np.mean(X_byclass[:,i]))return X_meandef CalXVar(self, X_byclass):###计算各类别特征各维度的方差######输入当前类别下的特征,输出该特征各个维度的方差###X_var=[]for i in range(X_byclass.shape[1]):X_var.append(np.var(X_byclass[:,i]))return X_vardef CalGaussianProb(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 in zip(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_probdef fit(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 in data_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))return self.prior_prob, self.X_mean, self.X_vardef predict(self,X_new):###预测数据######输入新样本的特征,输出新样本最有可能的目标####将输入的x_new转换为numpy数组X_new=np.asarray(X_new, np.float32)posteriori_prob=[] #初始化极大后验概率for i,j,o in zip(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)return self.class_name[idx]if __name__=="__main__":Gaussian_NB=Gaussian_NB() #实例化Gaussian_NBGaussian_NB.fit(X_train,y_train) #使用Gaussian_NB模型训练数据acc=0TP=0FP=0FN=0for i in range(len(X_test)):predict=Gaussian_NB.predict(X_test.iloc[i,:])target=np.array(y_test)[i]if predict==1 and target==1:TP+=1if predict==0 and target==1:FP+=1if predict==target:acc+=1if predict==1 and target==0:FN+=1print("准确率:",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.6296296296296297 F1: 0.68
由于样本不均衡,因此光看准确率是不够的,在这里一并计算了查准率和查全率以及F1值。可以看出这个分类器的效果不是很好,一方面是因为样本数量较少,另一方面朴素贝叶斯的预测能力确实比不上复杂模型,只能提供一个粗略的判断。
转载于:https://www.cnblogs.com/HuZihu/p/10896677.html
机器学习---用python实现朴素贝叶斯算法(Machine Learning Naive Bayes Algorithm Application)...相关推荐
- python实现朴素贝叶斯算法_机器学习---用python实现朴素贝叶斯算法(Machine Learning Naive Bayes Algorithm Application)...
在这里,我们使用一份皮马印第安女性的医学数据,用来预测其是否会得糖尿病.文件一共有768个样本,我们先剔除缺失值,然后选出20%的样本作为测试样本. 特征分别是: 怀孕次数 口服葡萄糖耐量试验中血浆葡 ...
- Python实现朴素贝叶斯算法
Python实现朴素贝叶斯算法 1.算法介绍 朴素贝叶斯假设特征相互独立,于是有下面的公式: x表示特征向量,c表示类别. 原理: 通过数据集计算出公式中右边分子中的各个概率.预测时根据公式计算出该样 ...
- 【机器学习入门】(2) 朴素贝叶斯算法:原理、实例应用(文档分类预测)附python完整代码及数据集
各位同学好,今天我向大家介绍python机器学习中的朴素贝叶斯算法.内容有:算法的基本原理:案例实战--新闻文档的分类预测. 案例简介:新闻数据有20个主题,有10万多篇文章,每篇文章对应不同的主题, ...
- 【机器学习入门】(3) 朴素贝叶斯算法:多项式、高斯、伯努利,实例应用(心脏病预测)附python完整代码及数据集
各位同学好,今天我和大家分享一下朴素贝叶斯算法中的三大模型.在上一篇文章中,我介绍了朴素贝叶斯算法的原理,并利用多项式模型进行了文本分类预测. 朴素贝叶斯算法 -- 原理,多项式模型文档分类预测,附p ...
- 【人工智能】机器学习及与智能数据处理Python使用朴素贝叶斯算法对垃圾短信数据集进行分类
朴素贝叶斯算法 输入:样本集合D={(x_1,y_1),(x_2,y_2) (x_m,y_m); 待预测样本x; 样本标记的所有可能取值{c_1,c_2,c_3 c_k}; 样本输入变量X的每个属性变 ...
- 用python实现朴素贝叶斯算法_朴素贝叶斯算法 python 实现
应用贝叶斯准则: 使用上面这些定义,可以定义贝叶斯分类准则为: 如果 P(c1|x, y) > P(c2|x, y), 那么属于类别 c1; 如果 P(c2|x, y) > P(c1|x, ...
- 机器学习(8)朴素贝叶斯算法(20条新闻分类)
目录 一.基础理论 二.实战:20条新闻分类 1.读取数据 2.训练集划分 3.特征工程(文本特征提取) 4.朴素贝叶斯算法训练 5.模型评估 方法一:预测值与真实值比对 方法二:计算准确率 总代码 ...
- Python高斯朴素贝叶斯算法问题总结
1.什么是高斯朴素贝叶斯 高斯朴素贝叶斯是一种可以根据样本文件进行预测,其算法本质是对某一事件或某组事件及其结果为样本数据进行学习(其学习过程类似于一种概率计算的过程,具体的过程可以百度贝叶斯算法.) ...
- Andrew Ng机器学习公开课笔记 -- 朴素贝叶斯算法
网易公开课,第5,6课 notes,http://cs229.stanford.edu/notes/cs229-notes2.pdf 前面讨论了高斯判别分析,是一种生成学习算法,其中x是连续值 这 ...
最新文章
- 30年间,软件开发行业为何Bug纷飞?
- 第1章 Java语言概述
- 剑指offer 刷题 01
- python 栈排序
- 【Hadoop Summit Tokyo 2016】Spark上可扩展的深度学习
- mysql lock_MySQL-锁总结
- 运用多种设计模式的综合案例_SpreadJS 纯前端表格控件应用案例:表格数据管理平台...
- Bluetooth---如何使用Android蓝牙开发
- 基于python实现细胞自动机
- 河海大学2021年硕士研究生招考公告
- w ndows系统启动日志ID,WIN7日志总能看到 特殊登陆 事件ID 4672,是怎么回事?
- Codeforces Round #101 (Div. 2)
- N-Tiers开发方式(ASP/ASP.NET、VB6/VB.NET呼叫使用COM+组件)
- 因数据迁移导致跨库连接失效的解决办法
- docker导入镜像报错:open /var/lib/docker/tmp/docker-import-970689518/bin/json: no such file or
- Java数组转集合之Arrays.asList()用法
- 推荐系统(3)—基于标签的推荐系统(Python)
- 如何构建一个大脑---为工程师们介绍神经生理学.
- 51Nod_1534 棋子游戏【博弈论】
- PHPMailer邮箱发送
热门文章
- Git与华为云(上传代码到华为云)
- 征稿 | 第22届国际语义网大会​(ISWC 2023)征稿通知
- 结合企业微信/钉钉/飞书/AAD/Google等账号实现内网802.1X准入
- java检查版本_如何检查Java版本
- ubuntu16 编译安装boost1.69与cuda8的opencv3.2.0
- 【微信开发】玩转PHP 数组用法!
- 华为交换机Vlan间访问控制ACL配置
- linux升级到指定内核版本,如何在CentOS/RHEL上安装或升级新的内核版本
- ChinaUnicom 中国联通wifi连接上输入联通手机号和密码后提示ip非法的解决办法
- 车牌识别系统开发记录(一) 系统概述