朴素贝叶斯分类器和一般朴素的贝叶斯分类器器有什么区别

贝叶斯分类算法_百度百科
声明:百科词条人人可编辑,词条创建和修改均免费,绝不存在官方及代理商付费代编,请勿上当受骗。
贝叶斯分类算法
贝叶斯分类算法是统计学的一种,它是一类利用概率统计知识进行分类的算法。在许多场合,(Na?ve Bayes,NB)分类算法可以与和神经网络分类算法相媲美,该算法能运用到大型中,而且方法简单、分类准确率高、速度快。由于假设一个对给定类的影响独立于其它属性的值,而此假设在实际情况中经常是不成立的,因此其分类准确率可能会下降。为此,就衍生出许多降低独立性假设的贝叶斯分类算法,如TAN(tree augmented Bayes network)算法。
贝叶斯分类算法分类
贝叶斯分类算法朴素贝叶斯算法
设每个数据样本用一个n维特征向量来描述n个属性的值,即:X={x1,x2,…,xn},假定有m个类,分别用C1, C2,…,Cm表示。给定一个未知的数据样本X(即没有类标号),若分类法将未知的样本X分配给类Ci,则一定是
P(Ci|X)&P(Cj|X) 1≤j≤m,j≠i
根据贝叶斯定理
由于P(X)对于所有类为常数,最大化P(Ci|X)可转化为最大化先验概率P(X|Ci)P(Ci)。如果训练有许多属性和元组,计算P(X|Ci)的开销可能非常大,为此,通常假设各属性的取值互相独立,这样
先验概率P(x1|Ci),P(x2|Ci),…,P(xn|Ci)可以从训练数据集求得。
根据此方法,对一个未知类别的样本X,可以先分别计算出X属于每一个类别Ci的P(X|Ci)P(Ci),然后选择其中概率最大的类别作为其类别。
算法成立的前提是各属性之间互相独立。当数据集满足这种独立性假设时,分类的准确度较高,否则可能较低。另外,该算法没有分类规则输出。[1]
贝叶斯分类算法TAN算法(树增强型朴素贝叶斯算法)
TAN算法通过发现属性对之间的依赖关系来降低NB中任意属性之间独立的假设。它是在NB网络结构的基础上增加属性对之间的关联(边)来实现的。
实现方法是:用结点表示属性,用有向边表示属性之间的依赖关系,把类别属性作为根结点,其余所有属性都作为它的子节点。通常,用虚线代表NB所需的边,用实线代表新增的边。属性Ai与Aj之间的边意味着属性Ai对类别变量C的影响还取决于属性Aj的取值。
这些增加的边需满足下列条件:类别变量没有双亲结点,每个属性有一个类别变量双亲结点和最多另外一个属性作为其双亲结点。
找到这组关联边之后,就可以计算一组随机变量的分布如下:
其中ΠAi代表的是Ai的双亲结点。由于在TAN算法中考虑了n个属性中(n-1)个两两属性之间的关联性,该算法对属性之间独立性的假设有了一定程度的降低,但是属性之间可能存
在更多其它的关联性仍没有考虑,因此其适用范围仍然受到限制。
贝叶斯分类算法分类算法
挖掘是研究的一个重要的、高度活跃的领域。近年来,己将关联规则挖掘用于分类问题,取得了很好的效果。
贝叶斯分类算法ARCS
ARCS(Association Rule Clustering System)基于[2]
,然后使用规则进行分类。将关联规则画在2-D上,算法扫描栅格,搜索规则的矩形。实践发现,当数据中存在孤立点时,ARCS比C4.5稍微精确一点。ARCS的准确性与程度有关。从可伸缩性来说,不论数据库多大,ARCS需要的存储容量为常数。
贝叶斯分类算法CBA
CBA(classification based on association)是基于发现方法的分类算法。该算法分两个步骤构造。第一步:发现所有形如xi1∧x =& Ci 的关联规则,即右部为类别属性值的类别关联规则(classification association rules,CAR)。第二步:从已发现的CAR中选择高优先度的规则来覆盖训练集,也就是说,如果有多条关联规则的左部相同,而右部为不同的类,则选择具有最高的规则作为可能规则。文献[4]对该过程进行了较深入的研究,使得算法在此步骤不需要对训练进行过多的扫描。
CBA算法的优点是其分类准确度较高,在许多数据集上比C4.5更精确。此外,上述两步都具有线性可伸缩性。
贝叶斯分类算法CBA
CBA(Classification Based on Association)是关联分类。此算法把分类规则挖掘和挖掘整合到一起。与CART和C4.5只产生部分规则不同的是,CBA产生所有的类关联规则CARs(Class Association Rules),然后选择最好的规则去覆盖训练集。另外,在此算法的框架中,数据库可以驻留在磁盘中
CAEP使用项集支持度挖掘HV露模式(Emerging Pattern), 而EP用于构造分类。CAEP找出满足给定支持度和增长率阈值的EP。已经发现,在许多数据集上,CAEP比C4.5和基于关联的分类更精确。一种替代的、基于跳跃的HV露模式JEP(Jnmping Emerging Pattern)是一种特殊类型的EP,项集的支持度由在一个数据集中的0陡峭地增长到另一个数据集中的非0。在一此大的多维数据库中,JEP性能优于CAEP, 但在一些小型数据库中,CAEP比JEP优,这二种分类法被认为是互补的。
贝叶斯分类算法ADT
ADT(Association Decision Trec)分二步实现以驱动为基础的过度适合规则的剪枝。第一步,运用规则建立。主要是采用某种置信度的单调性建立基于置信度的剪枝策略。第二步,为实现精确性,用建立一种平衡于DT(Dccision Tree)归纳的精确度驱动剪枝。这样的结果就是ADT(Association Based Decision Trec)。它联合了大量的关联规则和DT归纳精确性驱动剪枝技术。
贝叶斯分类算法CMAR
基于多维[3]
的分类算法CMAR(Classification Based on Multiple Class-Association Rules)是利用FP-Growth算法挖掘关联规则,建立类关联分布树FP-树。采用CR-树(Classification Rulc Trcc)结构有效地存储关联规则。基于、相关性和数据库覆盖来剪枝。分类的具体执行采用加权厂来分析。与CBA和C 4.5相比,CMAR性能优异且伸缩性较好。但CMAR优先生成的是长规则,对数据库的覆盖效果较差;利用x进行分类,会造成x统计量的,致使分类值的准确程度降低。
贝叶斯分类算法CPAR
CPAR(Classification Based on Predictive Association Rules)整合了分类和传统的基于规则分类的优点。为避免过度适合,在规则生成时采用,这比产生所有候选项集的效率高;采用一种动态方法避免在规则生成时的重复计算;采用顶期精确性评价规则,并在预测时应用最优的规则,避免产生冗余的规则。另外,MSR(Minimnm Set Rule)针对基于关联规则分类算法中产生的关联规则集可能太大的问题,在分类中运用最小关联规则集。在此算法中,CARS并不是通过首先排序,因为高置信度规则对是很敏感的。采用早期剪枝力方法可减少的数量,并保证在最小集中没有不相关的规则。实验证实,MSR比C45和CBA的错误率要低得多。
贝叶斯分类算法基本步骤
主要有以下7个步骤:
1. 收集大量的和非垃圾邮件,建立垃圾邮件集和非垃圾邮件集。
2. 提取邮件主题和邮件体中的独立字符串,例如 ABC32,¥234等作为TOKEN串并统计提取出的TOKEN串出现的次数即字频。按照上述的方法分别处理垃圾邮件集和非垃圾邮件集中的所有邮件。
3. 每一个邮件集对应一个哈希表,hashtable_good对应非垃圾邮件集而hashtable_bad对应垃圾邮件集。表中存储TOKEN串到字频的映射关系。
4. 计算每个哈希表中TOKEN串出现的概率P=(某TOKEN串的字频)/(对应哈希表的长度)。
5. 综合考虑hashtable_good和hashtable_bad,推断出当新来的邮件中出现某个TOKEN串时,该新邮件为垃圾邮件的。数学表达式为:
A 事件 ---- 邮件为;
t1,t2 …….tn 代表 TOKEN 串
则 P ( A|ti )表示在邮件中出现 TOKEN 串 ti 时,该邮件为垃圾邮件的概率。
P1 ( ti ) = ( ti 在 hashtable_good 中的值)
P2 ( ti ) = ( ti 在 hashtable_ bad 中的值)
则 P ( A|ti ) =P2 ( ti ) /[ ( P1 ( ti ) +P2 ( ti ) ] ;
6. 建立新的哈希表hashtable_probability存储TOKEN串ti到P(A|ti)的映射。
7. 至此,集和非垃圾邮件集的学习过程结束。根据建立的哈希表 hashtable_probability可以估计一封新到的邮件为垃圾邮件的可能性。
当新到一封邮件时,按照步骤2,生成TOKEN串。查询hashtable_probability得到该TOKEN 串的键值。
假设由该邮件共得到N个TOKEN 串,t1,t2…….tn,hashtable_probability中对应的值为 P1 , P2 , ……PN, P(A|t1 ,t2, t3……tn) 表示在邮件中同时出现多个TOKEN串t1,t2……tn时,该邮件为垃圾邮件的概率。
由复合概率公式可得P(A|t1 ,t2, t3……tn)=(P1*P2*……PN)/[P1*P2*……PN+(1-P1)*(1-P2)*……(1-PN)],当 P(A|t1 ,t2, t3……tn) 超过预定阈值时,就可以判断邮件为。
.知网[引用日期]
.知网[引用日期]
.知网[引用日期]
本词条内容贡献者为
副教授审核
西南大学电子信息工程学院机器学习之用Python从零实现贝叶斯分类器 - Python - 伯乐在线
& 机器学习之用Python从零实现贝叶斯分类器
机器学习之用Python从零实现贝叶斯分类器
朴素贝叶斯算法简单高效,在处理分类问题上,是应该首先考虑的方法之一。
通过本教程,你将学到朴素贝叶斯算法的原理和Python版本的逐步实现。
更新:查看后续的关于朴素贝叶斯使用技巧的文章“”
朴素贝叶斯分类器,保留部分版权
关于朴素贝叶斯
朴素贝叶斯算法是一个直观的方法,使用每个属性归属于某个类的概率来做预测。你可以使用这种监督性学习方法,对一个预测性建模问题进行概率建模。
给定一个类,朴素贝叶斯假设每个属性归属于此类的概率独立于其余所有属性,从而简化了概率的计算。这种强假定产生了一个快速、有效的方法。
给定一个属性值,其属于某个类的概率叫做条件概率。对于一个给定的类值,将每个属性的条件概率相乘,便得到一个数据样本属于某个类的概率。
我们可以通过计算样本归属于每个类的概率,然后选择具有最高概率的类来做预测。
通常,我们使用分类数据来描述朴素贝叶斯,因为这样容易通过比率来描述、计算。一个符合我们目的、比较有用的算法需要支持数值属性,同时假设每一个数值属性服从正态分布(分布在一个钟形曲线上),这又是一个强假设,但是依然能够给出一个健壮的结果。
预测糖尿病的发生
本文使用的测试问题是“皮马印第安人糖尿病问题”。
这个问题包括768个对于皮马印第安患者的医疗观测细节,记录所描述的瞬时测量取自诸如患者的年纪,怀孕和血液检查的次数。所有患者都是21岁以上(含21岁)的女性,所有属性都是数值型,而且属性的单位各不相同。
每一个记录归属于一个类,这个类指明以测量时间为止,患者是否是在5年之内感染的糖尿病。如果是,则为1,否则为0。
机器学习文献中已经多次研究了这个标准数据集,好的预测精度为70%-76%。
下面是文件中的一个样本,了解一下我们将要使用的数据。
注意:下载,然后以.csv扩展名保存(如:pima-indians-diabetes.data.csv)。查看中所有属性的描述。
6,148,72,35,0,33.6,0.627,50,1
1,85,66,29,0,26.6,0.351,31,0
8,183,64,0,0,23.3,0.672,32,1
1,89,66,23,94,28.1,0.167,21,0
0,137,40,35,168,43.1,2.288,33,1
6,148,72,35,0,33.6,0.627,50,11,85,66,29,0,26.6,0.351,31,08,183,64,0,0,23.3,0.672,32,11,89,66,23,94,28.1,0.167,21,00,137,40,35,168,43.1,2.288,33,1
朴素贝叶斯算法教程
教程分为如下几步:
1.处理数据:从CSV文件中载入数据,然后划分为训练集和测试集。
2.提取数据特征:提取训练数据集的属性特征,以便我们计算概率并做出预测。
3.单一预测:使用数据集的特征生成单个预测。
4.多重预测:基于给定测试数据集和一个已提取特征的训练数据集生成预测。
5.评估精度:评估对于测试数据集的预测精度作为预测正确率。
6.合并代码:使用所有代码呈现一个完整的、独立的朴素贝叶斯算法的实现。
1.处理数据
首先加载数据文件。CSV格式的数据没有标题行和任何引号。我们可以使用csv模块中的open函数打开文件,使用reader函数读取行数据。
我们也需要将以字符串类型加载进来属性转换为我们可以使用的数字。下面是用来加载匹马印第安人数据集(Pima indians dataset)的loadCsv()函数。
import csv
def loadCsv(filename):
lines = csv.reader(open(filename, "rb"))
dataset = list(lines)
for i in range(len(dataset)):
dataset[i] = [float(x) for x in dataset[i]]
return dataset
import csvdef loadCsv(filename): lines = csv.reader(open(filename, "rb")) dataset = list(lines) for i in range(len(dataset)):
dataset[i] = [float(x) for x in dataset[i]] return dataset
我们可以通过加载皮马印第安人数据集,然后打印出数据样本的个数,以此测试这个函数。
filename = 'pima-indians-diabetes.data.csv'
dataset = loadCsv(filename)
print('Loaded data file {0} with {1} rows').format(filename, len(dataset))
filename = 'pima-indians-diabetes.data.csv'dataset = loadCsv(filename)print('Loaded data file {0} with {1} rows').format(filename, len(dataset))
运行测试,你会看到如下结果:
Loaded data file iris.data.csv with 150 rows
Loaded data file iris.data.csv with 150 rows
下一步,我们将数据分为用于朴素贝叶斯预测的训练数据集,以及用来评估模型精度的测试数据集。我们需要将数据集随机分为包含67%的训练集合和包含33%的测试集(这是在此数据集上测试算法的通常比率)。
下面是splitDataset()函数,它以给定的划分比例将数据集进行划分。
import random
def splitDataset(dataset, splitRatio):
trainSize = int(len(dataset) * splitRatio)
trainSet = []
copy = list(dataset)
while len(trainSet) & trainSize:
index = random.randrange(len(copy))
trainSet.append(copy.pop(index))
return [trainSet, copy]
import randomdef splitDataset(dataset, splitRatio): trainSize = int(len(dataset) * splitRatio) trainSet = [] copy = list(dataset) while len(trainSet) & trainSize:
index = random.randrange(len(copy))
trainSet.append(copy.pop(index)) return [trainSet, copy]
我们可以定义一个具有5个样例的数据集来进行测试,首先它分为训练数据集和测试数据集,然后打印出来,看看每个数据样本最终落在哪个数据集。
dataset = [[1], [2], [3], [4], [5]]
splitRatio = 0.67
train, test = splitDataset(dataset, splitRatio)
print('Split {0} rows into train with {1} and test with {2}').format(len(dataset), train, test)
dataset = [[1], [2], [3], [4], [5]]splitRatio = 0.67train, test = splitDataset(dataset, splitRatio)print('Split {0} rows into train with {1} and test with {2}').format(len(dataset), train, test)
运行测试,你会看到如下结果:
Split 5 rows into train with [[4], [3], [5]] and test with [[1], [2]]
Split 5 rows into train with [[4], [3], [5]] and test with [[1], [2]]
提取数据特征
朴素贝叶斯模型包含训练数据集中数据的特征,然后使用这个数据特征来做预测。
所收集的训练数据的特征,包含相对于每个类的每个属性的均值和标准差。举例来说,如果如果有2个类和7个数值属性,然后我们需要每一个属性(7)和类(2)的组合的均值和标准差,也就是14个属性特征。
在对特定的属性归属于每个类的概率做计算、预测时,将用到这些特征。
我们将数据特征的获取划分为以下的子任务:
按类别划分数据
计算标准差
提取数据集特征
按类别提取属性特征
按类别划分数据
首先将训练数据集中的样本按照类别进行划分,然后计算出每个类的统计数据。我们可以创建一个类别到属于此类别的样本列表的的映射,并将整个数据集中的样本分类到相应的列表。
下面的SeparateByClass()函数可以完成这个任务:
def separateByClass(dataset):
separated = {}
for i in range(len(dataset)):
vector = dataset[i]
if (vector[-1] not in separated):
separated[vector[-1]] = []
separated[vector[-1]].append(vector)
return separated
def separateByClass(dataset): separated = {} for i in range(len(dataset)):
vector = dataset[i]
if (vector[-1] not in separated):
separated[vector[-1]] = []
separated[vector[-1]].append(vector) return separated
可以看出,函数假设样本中最后一个属性(-1)为类别值,返回一个类别值到数据样本列表的映射。
我们可以用一些样本数据测试如下:
dataset = [[1,20,1], [2,21,0], [3,22,1]]
separated = separateByClass(dataset)
print('Separated instances: {0}').format(separated)
dataset = [[1,20,1], [2,21,0], [3,22,1]]separated = separateByClass(dataset)print('Separated instances: {0}').format(separated)
运行测试,你会看到如下结果:
Separated instances: {0: [[2, 21, 0]], 1: [[1, 20, 1], [3, 22, 1]]}
Separated instances: {0: [[2, 21, 0]], 1: [[1, 20, 1], [3, 22, 1]]}
我们需要计算在每个类中每个属性的均值。均值是数据的中点或者集中趋势,在计算概率时,我们用它作为高斯分布的中值。
我们也需要计算每个类中每个属性的标准差。标准差描述了数据散布的偏差,在计算概率时,我们用它来刻画高斯分布中,每个属性所期望的散布。
标准差是方差的平方根。方差是每个属性值与均值的离差平方的平均数。注意我们使用N-1的方法(译者注:参见无偏估计),也就是在在计算方差时,属性值的个数减1。
import math
def mean(numbers):
return sum(numbers)/float(len(numbers))
def stdev(numbers):
avg = mean(numbers)
variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1)
return math.sqrt(variance)
import mathdef mean(numbers): return sum(numbers)/float(len(numbers))&def stdev(numbers): avg = mean(numbers) variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1) return math.sqrt(variance)
通过计算从1到5这5个数的均值来测试函数。
numbers = [1,2,3,4,5]
print('Summary of {0}: mean={1}, stdev={2}').format(numbers, mean(numbers), stdev(numbers))
numbers = [1,2,3,4,5]print('Summary of {0}: mean={1}, stdev={2}').format(numbers, mean(numbers), stdev(numbers))
运行测试,你会看到如下结果:
Summary of [1, 2, 3, 4, 5]: mean=3.0, stdev=1.
Summary of [1, 2, 3, 4, 5]: mean=3.0, stdev=1.
提取数据集的特征
现在我们可以提取数据集特征。对于一个给定的样本列表(对应于某个类),我们可以计算每个属性的均值和标准差。
zip函数将数据样本按照属性分组为一个个列表,然后可以对每个属性计算均值和标准差。
def summarize(dataset):
summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)]
del summaries[-1]
return summaries
def summarize(dataset): summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)] del summaries[-1] return summaries
我们可以使用一些测试数据来测试这个summarize()函数,测试数据对于第一个和第二个数据属性的均值和标准差显示出显著的不同。
dataset = [[1,20,0], [2,21,1], [3,22,0]]
summary = summarize(dataset)
print('Attribute summaries: {0}').format(summary)
dataset = [[1,20,0], [2,21,1], [3,22,0]]summary = summarize(dataset)print('Attribute summaries: {0}').format(summary)
运行测试,你会看到如下结果:
Attribute summaries: [(2.0, 1.0), (21.0, 1.0)]
Attribute summaries: [(2.0, 1.0), (21.0, 1.0)]
按类别提取属性特征
合并代码,我们首先将训练数据集按照类别进行划分,然后计算每个属性的摘要。
def summarizeByClass(dataset):
separated = separateByClass(dataset)
summaries = {}
for classValue, instances in separated.iteritems():
summaries[classValue] = summarize(instances)
return summaries
def summarizeByClass(dataset): separated = separateByClass(dataset) summaries = {} for classValue, instances in separated.iteritems():
summaries[classValue] = summarize(instances) return summaries
使用小的测试数据集来测试summarizeByClass()函数。
dataset = [[1,20,1], [2,21,0], [3,22,1], [4,22,0]]
summary = summarizeByClass(dataset)
print('Summary by class value: {0}').format(summary)
dataset = [[1,20,1], [2,21,0], [3,22,1], [4,22,0]]summary = summarizeByClass(dataset)print('Summary by class value: {0}').format(summary)
运行测试,你会看到如下结果:
Summary by class value:
{0: [(3.0, 1.0951), (21.5, 0.5476)],
1: [(2.0, 1.0951), (21.0, 1.0951)]}
Summary by class value: {0: [(3.0, 1.0951), (21.5, 0.5476)], 1: [(2.0, 1.0951), (21.0, 1.0951)]}
我们现在可以使用从训练数据中得到的摘要来做预测。做预测涉及到对于给定的数据样本,计算其归属于每个类的概率,然后选择具有最大概率的类作为预测结果。
我们可以将这部分划分成以下任务:
计算高斯概率密度函数
计算对应类的概率
计算高斯概率密度函数
给定来自训练数据中已知属性的均值和标准差,我们可以使用高斯函数来评估一个给定的属性值的概率。
已知每个属性和类值的属性特征,在给定类值的条件下,可以得到给定属性值的条件概率。
关于高斯概率密度函数,可以查看参考文献。总之,我们要把已知的细节融入到高斯函数(属性值,均值,标准差),并得到属性值归属于某个类的似然(译者注:即可能性)。
在calculateProbability()函数中,我们首先计算指数部分,然后计算等式的主干。这样可以将其很好地组织成2行。
import math
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
import mathdef 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
使用一些简单的数据测试如下:
stdev = 6.2
probability = calculateProbability(x, mean, stdev)
print('Probability of belonging to this class: {0}').format(probability)
x = 71.5mean = 73stdev = 6.2probability = calculateProbability(x, mean, stdev)print('Probability of belonging to this class: {0}').format(probability)
运行测试,你会看到如下结果:
Probability of belonging to this class: 0.7
Probability of belonging to this class: 0.7
计算所属类的概率
既然我们可以计算一个属性属于某个类的概率,那么合并一个数据样本中所有属性的概率,最后便得到整个数据样本属于某个类的概率。
使用乘法合并概率,在下面的calculClassProbilities()函数中,给定一个数据样本,它所属每个类别的概率,可以通过将其属性概率相乘得到。结果是一个类值到概率的映射。
def calculateClassProbabilities(summaries, inputVector):
probabilities = {}
for classValue, classSummaries in summaries.iteritems():
probabilities[classValue] = 1
for i in range(len(classSummaries)):
mean, stdev = classSummaries[i]
x = inputVector[i]
probabilities[classValue] *= calculateProbability(x, mean, stdev)
return probabilities
def calculateClassProbabilities(summaries, inputVector): probabilities = {} for classValue, classSummaries in summaries.iteritems():
probabilities[classValue] = 1
for i in range(len(classSummaries)):
mean, stdev = classSummaries[i]
x = inputVector[i]
probabilities[classValue] *= calculateProbability(x, mean, stdev) return probabilities
测试calculateClassProbabilities()函数。
summaries = {0:[(1, 0.5)], 1:[(20, 5.0)]}
inputVector = [1.1, '?']
probabilities = calculateClassProbabilities(summaries, inputVector)
print('Probabilities for each class: {0}').format(probabilities)
summaries = {0:[(1, 0.5)], 1:[(20, 5.0)]}inputVector = [1.1, '?']probabilities = calculateClassProbabilities(summaries, inputVector)print('Probabilities for each class: {0}').format(probabilities)
运行测试,你会看到如下结果:
Probabilities for each class: {0: 0..442e-05}
Probabilities for each class: {0: 0.9118, 1: 6.442e-05}
既然可以计算一个数据样本属于每个类的概率,那么我们可以找到最大的概率值,并返回关联的类。
下面的predict()函数可以完成以上任务。
def predict(summaries, inputVector):
probabilities = calculateClassProbabilities(summaries, inputVector)
bestLabel, bestProb = None, -1
for classValue, probability in probabilities.iteritems():
if bestLabel is None or probability & bestProb:
bestProb = probability
bestLabel = classValue
return bestLabel
def predict(summaries, inputVector): probabilities = calculateClassProbabilities(summaries, inputVector) bestLabel, bestProb = None, -1 for classValue, probability in probabilities.iteritems():
if bestLabel is None or probability & bestProb:
bestProb = probability
bestLabel = classValue return bestLabel
测试predict()函数如下:
summaries = {'A':[(1, 0.5)], 'B':[(20, 5.0)]}
inputVector = [1.1, '?']
result = predict(summaries, inputVector)
print('Prediction: {0}').format(result)
summaries = {'A':[(1, 0.5)], 'B':[(20, 5.0)]}inputVector = [1.1, '?']result = predict(summaries, inputVector)print('Prediction: {0}').format(result)
运行测试,你会得到如下结果:
Prediction: A
Prediction: A
最后,通过对测试数据集中每个数据样本的预测,我们可以评估模型精度。getPredictions()函数可以实现这个功能,并返回每个测试样本的预测列表。
def getPredictions(summaries, testSet):
predictions = []
for i in range(len(testSet)):
result = predict(summaries, testSet[i])
predictions.append(result)
return predictions
def getPredictions(summaries, testSet): predictions = [] for i in range(len(testSet)):
result = predict(summaries, testSet[i])
predictions.append(result) return predictions
测试getPredictions()函数如下。
summaries = {'A':[(1, 0.5)], 'B':[(20, 5.0)]}
testSet = [[1.1, '?'], [19.1, '?']]
predictions = getPredictions(summaries, testSet)
print('Predictions: {0}').format(predictions)
summaries = {'A':[(1, 0.5)], 'B':[(20, 5.0)]}testSet = [[1.1, '?'], [19.1, '?']]predictions = getPredictions(summaries, testSet)print('Predictions: {0}').format(predictions)
运行测试,你会看到如下结果:
Predictions: ['A', 'B']
Predictions: ['A', 'B']
预测值和测试数据集中的类别值进行比较,可以计算得到一个介于0%~100%精确率作为分类的精确度。getAccuracy()函数可以计算出这个精确率。
def getAccuracy(testSet, predictions):
correct = 0
for x in range(len(testSet)):
if testSet[x][-1] == predictions[x]:
correct += 1
return (correct/float(len(testSet))) * 100.0
def getAccuracy(testSet, predictions): correct = 0 for x in range(len(testSet)):
if testSet[x][-1] == predictions[x]:
correct += 1 return (correct/float(len(testSet))) * 100.0
我们可以使用如下简单的代码来测试getAccuracy()函数。
testSet = [[1,1,1,'a'], [2,2,2,'a'], [3,3,3,'b']]
predictions = ['a', 'a', 'a']
accuracy = getAccuracy(testSet, predictions)
print('Accuracy: {0}').format(accuracy)
testSet = [[1,1,1,'a'], [2,2,2,'a'], [3,3,3,'b']]predictions = ['a', 'a', 'a']accuracy = getAccuracy(testSet, predictions)print('Accuracy: {0}').format(accuracy)
运行测试,你会得到如下结果:
Accuracy: 66.
Accuracy: 66.
最后,我们需要将代码连贯起来。
下面是朴素贝叶斯Python版的逐步实现的全部代码。
# Example of Naive Bayes implemented from Scratch in Python
import csv
import random
import math
def loadCsv(filename):
lines = csv.reader(open(filename, "rb"))
dataset = list(lines)
for i in range(len(dataset)):
dataset[i] = [float(x) for x in dataset[i]]
return dataset
def splitDataset(dataset, splitRatio):
trainSize = int(len(dataset) * splitRatio)
trainSet = []
copy = list(dataset)
while len(trainSet) & trainSize:
index = random.randrange(len(copy))
trainSet.append(copy.pop(index))
return [trainSet, copy]
def separateByClass(dataset):
separated = {}
for i in range(len(dataset)):
vector = dataset[i]
if (vector[-1] not in separated):
separated[vector[-1]] = []
separated[vector[-1]].append(vector)
return separated
def mean(numbers):
return sum(numbers)/float(len(numbers))
def stdev(numbers):
avg = mean(numbers)
variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1)
return math.sqrt(variance)
def summarize(dataset):
summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)]
del summaries[-1]
return summaries
def summarizeByClass(dataset):
separated = separateByClass(dataset)
summaries = {}
for classValue, instances in separated.iteritems():
summaries[classValue] = summarize(instances)
return summaries
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
def calculateClassProbabilities(summaries, inputVector):
probabilities = {}
for classValue, classSummaries in summaries.iteritems():
probabilities[classValue] = 1
for i in range(len(classSummaries)):
mean, stdev = classSummaries[i]
x = inputVector[i]
probabilities[classValue] *= calculateProbability(x, mean, stdev)
return probabilities
def predict(summaries, inputVector):
probabilities = calculateClassProbabilities(summaries, inputVector)
bestLabel, bestProb = None, -1
for classValue, probability in probabilities.iteritems():
if bestLabel is None or probability & bestProb:
bestProb = probability
bestLabel = classValue
return bestLabel
def getPredictions(summaries, testSet):
predictions = []
for i in range(len(testSet)):
result = predict(summaries, testSet[i])
predictions.append(result)
return predictions
def getAccuracy(testSet, predictions):
correct = 0
for i in range(len(testSet)):
if testSet[i][-1] == predictions[i]:
correct += 1
return (correct/float(len(testSet))) * 100.0
def main():
filename = 'pima-indians-diabetes.data.csv'
splitRatio = 0.67
dataset = loadCsv(filename)
trainingSet, testSet = splitDataset(dataset, splitRatio)
print('Split {0} rows into train={1} and test={2} rows').format(len(dataset), len(trainingSet), len(testSet))
# prepare model
summaries = summarizeByClass(trainingSet)
# test model
predictions = getPredictions(summaries, testSet)
accuracy = getAccuracy(testSet, predictions)
print('Accuracy: {0}%').format(accuracy)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
# Example of Naive Bayes implemented from Scratch in Pythonimport csvimport randomimport math&def loadCsv(filename): lines = csv.reader(open(filename, "rb")) dataset = list(lines) for i in range(len(dataset)):
dataset[i] = [float(x) for x in dataset[i]] return dataset&def splitDataset(dataset, splitRatio): trainSize = int(len(dataset) * splitRatio) trainSet = [] copy = list(dataset) while len(trainSet) & trainSize:
index = random.randrange(len(copy))
trainSet.append(copy.pop(index)) return [trainSet, copy]&def separateByClass(dataset): separated = {} for i in range(len(dataset)):
vector = dataset[i]
if (vector[-1] not in separated):
separated[vector[-1]] = []
separated[vector[-1]].append(vector) return separated&def mean(numbers): return sum(numbers)/float(len(numbers))&def stdev(numbers): avg = mean(numbers) variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1) return math.sqrt(variance)&def summarize(dataset): summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)] del summaries[-1] return summaries&def summarizeByClass(dataset): separated = separateByClass(dataset) summaries = {} for classValue, instances in separated.iteritems():
summaries[classValue] = summarize(instances) return summaries&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&def calculateClassProbabilities(summaries, inputVector): probabilities = {} for classValue, classSummaries in summaries.iteritems():
probabilities[classValue] = 1
for i in range(len(classSummaries)):
mean, stdev = classSummaries[i]
x = inputVector[i]
probabilities[classValue] *= calculateProbability(x, mean, stdev) return probabilities&def predict(summaries, inputVector): probabilities = calculateClassProbabilities(summaries, inputVector) bestLabel, bestProb = None, -1 for classValue, probability in probabilities.iteritems():
if bestLabel is None or probability & bestProb:
bestProb = probability
bestLabel = classValue return bestLabel&def getPredictions(summaries, testSet): predictions = [] for i in range(len(testSet)):
result = predict(summaries, testSet[i])
predictions.append(result) return predictions&def getAccuracy(testSet, predictions): correct = 0 for i in range(len(testSet)):
if testSet[i][-1] == predictions[i]:
correct += 1 return (correct/float(len(testSet))) * 100.0&def main(): filename = 'pima-indians-diabetes.data.csv' splitRatio = 0.67 dataset = loadCsv(filename) trainingSet, testSet = splitDataset(dataset, splitRatio) print('Split {0} rows into train={1} and test={2} rows').format(len(dataset), len(trainingSet), len(testSet)) # prepare model summaries = summarizeByClass(trainingSet) # test model predictions = getPredictions(summaries, testSet) accuracy = getAccuracy(testSet, predictions) print('Accuracy: {0}%').format(accuracy)&main()
运行示例,得到如下输出:
Split 768 rows into train=514 and test=254 rows
Accuracy: 76.%
Split 768 rows into train=514 and test=254 rowsAccuracy: 76.%
这一部分为你提供了扩展思路,你可以将其作为教程的一部分,使用你已经实现的Python代码,进行应用研究。
到此,你已经使用Python一步步完成了高斯版本的朴素贝叶斯。
你可以进一步扩展算法实现:
计算所属类的概率:将一个数据样本归属于每个类的概率更新为一个比率。计算上就是将一个样本数据归属于某个类的概率,比上其归属于每一个类的概率的和。举例来说,一个样本属于类A的概率时0.02,属于类B的概率时0.001,那么样本属于类A的可能性是(0.02/(0.02+0.001))*100 大约为95.23%。
对数概率:对于一个给定的属性值,每个类的条件概率很小。当将其相乘时结果会更小,那么存在浮点溢出的可能(数值太小,以至于在Python中不能表示)。一个常用的修复方案是,合并其概率的对数值。可以研究实现下这个改进。
名词属性:改进算法实现,使其支持名词属性。这是十分相似的,你所收集的每个属性的摘要信息是对于每个类的类别值的比率。潜心学习参考文献来获取更多信息。
不同的密度函数(伯努利或者多项式):我们已经尝试了高斯朴素贝叶斯,你也可以尝试下其他分布。实现一个不同的分布诸如多项分布、伯努利分布或者内核朴素贝叶斯,他们对于属性值的分布 和/或 与类值之间的关系有不同的假设。
学习资源及深入阅读
这一部分提供了一些用于学习更多朴素贝叶斯算法的资源,包括算法理论和工作原理,以及代码实现中的实际问题。
更多学习预测糖尿病发作问题的资源
:这个页面提供数据集文件,同时描述了各个属性,也列出了使用该数据集的论文列表
:数据集文件
:数据集属性的描述
:许多标准算法在该数据集上的精度
这一部分包含流行的机器学习库中的朴素贝叶斯的开源实现。如果你在考虑实现自己的用于实际使用的版本,可以查阅这些
:scikit-learn库中朴素贝叶斯的实现
:scikit-learn库中关于朴素贝叶斯的文档和样例代码
:朴素贝叶斯的Weka实现
你应该有几本机器学习应用的书籍。这一部分高亮出了常用机器学习书籍中关于朴素贝叶斯的章节。
, page 353
, page 138
, page 171
, page 61 (Chapter 4)
, page 177 (chapter 6)
行动起来。
跟着教程,从头开始实现朴素贝叶斯。将这个例子适用到其他问题。按照扩展改进实现。
评论分享你的经验。
更新:查看后续的关于朴素贝叶斯使用技巧的文章“Better Naive Bayes: 12 Tips To Get The Most From The Naive Bayes Algorithm”
关于作者:
可能感兴趣的话题
注意:下载文件,然后以.scv扩展名保存(如:pima-indians-diabetes.data.csv)。查看文件中所有属性的描述。
其中 .scv 可能是手抖打错了
o 256 回复
关于 Python 频道
Python频道分享 Python 开发技术、相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线}

我要回帖

更多关于 朴素贝叶斯分类器详解 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信