Python实现朴素贝叶斯分类器的方法详解
本文详细解析了朴素贝叶斯分类器的数学原理及Python实现方法。从贝叶斯定理出发,推导先验概率、后验概率与似然度的关系,并介绍算法流程。通过具体示例演示如何计算条件概率,最后提供完整的Python类封装代码及Matlab实现对比,帮助开发者掌握该算法的核心逻辑与应用。
本文详细介绍利用Python构建朴素贝叶斯分类器的具体实现方案,供读者参考学习。
贝叶斯定理
贝叶斯定理是一种基于主观判断的先验概率分布来修正观测值概率分布的数学定理,在概率论领域占据重要地位。
先验概率分布(即边缘概率)反映的是基于主观判断而非样本数据的概率分布;后验概率(条件概率)则是依据样本分布及未知参数的先验概率分布推导出的条件概率分布。
贝叶斯公式表达如下:
P(A∩B) = P(A)*P(B|A) = P(B)*P(A|B)
对该公式进行变形,可得:
P(A|B)=P(B|A)*P(A)/P(B)
公式中各符号含义如下:
P(A)表示A的先验概率或边缘概率,称为“先验”,因为其推导不依赖于B因素。P(A|B)表示在已知B发生的情况下A的条件概率,也称为A的后验概率。P(B|A)表示在已知A发生的情况下B的条件概率,也称为B的后验概率,此处称为似然度。P(B)表示B的先验概率或边缘概率,此处称为标准化常量。P(B|A)/P(B)称为标准似然度。
朴素贝叶斯分类(Naive Bayes)
朴素贝叶斯分类器在估算类条件概率时,假设各个属性之间是条件独立的。
首先定义以下符号:
x = {a1,a2,...}代表一个样本向量,其中a为单个特征属性。div = {d1 = [l1,u1],...}代表特征属性的一个划分集合。class = {y1,y2,...}代表样本所属的类别集合。
算法执行流程如下:
(1) 根据样本集中各类别的分布情况,计算每个类别的先验概率p(y[i])。
(2) 计算每个类别下,各个特征属性划分的频率p(a[j] in d[k] | y[i])。
(3) 计算每个样本的p(x|y[i])值。
p(x|y[i]) = p(a[1] in d | y[i]) * p(a[2] in d | y[i]) * ...
由于样本的所有特征属性已知,因此特征属性所属的区间d也是已知的。
可以通过步骤(2)确定p(a[k] in d | y[i])的值,进而求得p(x|y[i])。
(4) 根据贝叶斯定理计算:
p(y[i]|x) = ( p(x|y[i]) * p(y[i]) ) / p(x)
由于分母p(x)对所有类别相同,只需计算分子部分即可。
p(y[i]|x)表示观测样本属于分类y[i]的概率,选取概率最大值对应的分类作为最终分类结果。
示例演示:
导入数据集进行预处理。
{a1 = 0, a2 = 0, C = 0} {a1 = 0, a2 = 0, C = 1}
{a1 = 0, a2 = 0, C = 0} {a1 = 0, a2 = 0, C = 1}
{a1 = 0, a2 = 0, C = 0} {a1 = 0, a2 = 0, C = 1}
{a1 = 1, a2 = 0, C = 0} {a1 = 0, a2 = 0, C = 1}
{a1 = 1, a2 = 0, C = 0} {a1 = 0, a2 = 0, C = 1}
{a1 = 1, a2 = 0, C = 0} {a1 = 1, a2 = 0, C = 1}
{a1 = 1, a2 = 1, C = 0} {a1 = 1, a2 = 0, C = 1}
{a1 = 1, a2 = 1, C = 0} {a1 = 1, a2 = 1, C = 1}
{a1 = 1, a2 = 1, C = 0} {a1 = 1, a2 = 1, C = 1}
{a1 = 1, a2 = 1, C = 0} {a1 = 1, a2 = 1, C = 1}
计算各个类别的先验概率。
P(C = 0) = 0.5 P(C = 1) = 0.5
计算每个特征属性的条件概率:
P(a1 = 0 | C = 0) = 0.3 P(a1 = 1 | C = 0) = 0.7 P(a2 = 0 | C = 0) = 0.4 P(a2 = 1 | C = 0) = 0.6 P(a1 = 0 | C = 1) = 0.5 P(a1 = 1 | C = 1) = 0.5 P(a2 = 0 | C = 1) = 0.7 P(a2 = 1 | C = 1) = 0.3
使用测试样本进行验证:
x = { a1 = 1, a2 = 2}
p(x | C = 0) = p(a1 = 1 | C = 0) * p( 2 = 2 | C = 0) = 0.3 * 0.6 = 0.18
p(x | C = 1) = p(a1 = 1 | C = 1) * p (a2 = 2 | C = 1) = 0.5 * 0.3 = 0.15
计算P(C | x) * p(x)的值:
P(C = 0) * p(x | C = 1) = 0.5 * 0.18 = 0.09 P(C = 1) * p(x | C = 2) = 0.5 * 0.15 = 0.075
因此判定测试样本属于类型C1。
Python实现
朴素贝叶斯分类器的训练阶段主要计算步骤(1)和(2)中的概率表,而应用阶段则执行步骤(3)和(4)并寻找最大值。
此处沿用原有的接口进行类的封装:
from numpy import *
class NaiveBayesClassifier(object):
def __init__(self):
self.dataMat = list()
self.labelMat = list()
self.pLabel1 = 0
self.p0Vec = list()
self.p1Vec = list()
def loadDataSet(self,filename):
fr = open(filename)
for line in fr.readlines():
lineArr = line.strip().split()
dataLine = list()
for i in lineArr:
dataLine.append(float(i))
label = dataLine.pop() # pop the last column referring to label
self.dataMat.append(dataLine)
self.labelMat.append(int(label))
def train(self):
dataNum = len(self.dataMat)
featureNum = len(self.dataMat[0])
self.pLabel1 = sum(self.labelMat)/float(dataNum)
p0Num = zeros(featureNum)
p1Num = zeros(featureNum)
p0Denom = 1.0
p1Denom = 1.0
for i in range(dataNum):
if self.labelMat[i] == 1:
p1Num += self.dataMat[i]
p1Denom += sum(self.dataMat[i])
else:
p0Num += self.dataMat[i]
p0Denom += sum(self.dataMat[i])
self.p0Vec = p0Num/p0Denom
self.p1Vec = p1Num/p1Denom
def classify(self, data):
p1 = reduce(lambda x, y: x * y, data * self.p1Vec) * self.pLabel1
p0 = reduce(lambda x, y: x * y, data * self.p0Vec) * (1.0 - self.pLabel1)
if p1 > p0:
return 1
else:
return 0
def test(self):
self.loadDataSet('testNB.txt')
self.train()
print(self.classify([1, 2]))
if __name__ == '__main__':
NB = NaiveBayesClassifier()
NB.test()
Matlab
Matlab的标准工具箱提供了对朴素贝叶斯分类器的支持功能:
trainData = [0 1; -1 0; 2 2; 3 3; -2 -1;-4.5 -4; 2 -1; -1 -3]; group = [1 1 -1 -1 1 1 -1 -1]'; model = fitcnb(trainData, group) testData = [5 2;3 1;-4 -3]; predict(model, testData)
使用fitcnb函数来训练模型,利用predict函数进行预测。
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python数学运算技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》
希望本文所述对大家Python程序设计有所帮助。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













