最为广泛的两种分类模型是决策树模型(Decision Tree Model)和朴素贝叶斯模型(Naive Bayesian Model,NBC)。
贝叶斯定理是在250多年前发明的算法,在信息领域内有着无与伦比的地位。贝叶斯分类是一系列分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。朴素贝叶斯算法(Naive Bayesian) 是其中应用最为广泛的分类算法之一。
贝叶斯定理(朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法)
描述
贝叶斯定理是关于随机事件A和B的条件概率的一则定理。
在贝叶斯定理中,每个名词都有约定俗成的名称:
- P(A)是A的先验概率。之所以称为"先验"是因为它不考虑任何B方面的因素。
- P(A|B) 由于得自B的取值而被称作A的后验概率。
- P(B|A) 由于得自A的取值而被称作B的后验概率。
- P(B)是B的先验概率,也作标准化常量。
按这些术语,Bayes定理可表述为:
后验概率 = (相似度*先验概率) / 标准化常量
P(B|A)称为“可能性函数”,这是个调整因子,使得预估计概率更接近真实概率。
所以,条件概率可以理解为式子:
后验概率 = 先验概率 * 调整因子
这就是贝叶斯推断的含义:我们先预测一个“先验概率”,然后加入实验结果,看这个实验到底是增强还是削弱了“先验概率”,由此得到更加真实的“后验概率”。
在这里,如果“可能性函数”P(B|A)/P(B)>1,意味着“先验概率”被增强,事件A发生的可能性增大;如果“可能性函数”P(B|A)/P(B)=1,意味着事件B无助于判断事件A的可能性;如果“可能性函数”P(B|A)/P(B)<1,意味着“先验概率”被减弱,事件A发生的可能性变小。
推导
根据条件概率的定义。在事件B发生的条件下事件A发生的概率是
同样地,在事件A发生的条件下事件B发生的概率
整理与合并这两个方程式,我们可以找到
这个引理有时称作概率乘法规则。上式两边同除以P(B),若P(B)是非零的,我们可以得到贝叶斯定理:
贝叶斯定理通常可以再写成下面的形式:
其中AC是A的补集。故上式亦可写成:
在更一般化的情况,假设{Ai}是事件集合里的部分集合,对于任意的Ai,贝叶斯定理可用下式表示:
案例
暗箱操作,现在从其中一个箱子中得到一个绿球,问是从黑箱中取得的概率是?
分析:假定“从黑箱中取球”为事件A,“从红箱中取球”为事件B,“取到绿球”为事件M.
则问题为求P(A|M)
由贝叶斯定理得:P(A|M) = P(A) * P(M|A) / P(M)
= P(A) * P(M|A) /[ P(M|A)*P(A) + P(M|B) *P(B)]
其中,P(A)=P(B) = 1/2, P(M|A) = 3/4, P(M|B) = 1/2
结果为0.6,表明,来自黑箱的概率为0.6。也就是得到绿球后,事件A(取自于黑箱)的可能性增强了。
总论
朴素贝叶斯法是典型的生成学习方法。生成方法由训练数据学习联合概率分布P(X,Y),然后得到后验概率P(Y|X)。即:
一)利用训练数据得到P(X|Y)和P(Y)的估计
二)根据公式P(X,Y)=P(Y)P(X|Y)得到P(X,Y)
展开
假设
输入空间χ⊆Rn为n维向量的集合
输出空间为类标记集合У={c1,c2,…cK}
输入为特征向量x∈χ
输出为类标记y∈У
X是定义在输入空间χ上的随机变量
Y是定义在输出空间У上的随机变量
训练数据集为T={(x1,x2),(x2,y2),…(xN,yN)}
特征的总个数为n
每一个特征的可能取值为Sj
训练数据的总个数为N
类标记个数为K
推导
一)通过训练数据得到
1. 先验概率P(Y=ck), k=1,2,…K
2. 条件概率分布P(X=x|Y=ck)=P(X(1)=x(1),…X(n)=x(n)|Y=ck)
朴素贝叶斯法的基本假设为条件独立性,即用于分类的特征在类确定的条件下都是条件独立的。所以
P(X=x|Y=ck)=P(X(1)=x(1),…X(n)=x(n)|Y=ck)
对于参数P(Y=ck)、P(X(j)=x|Y=ck)的估计可以是极大似然估计也可以是贝叶斯估计。
极大似然估计
设第j个特征x(j)可能的取值为{aj1,aj2,…ajsj}个数为Sj个
贝叶斯估计
用几大似然估计可能会出现所要估计的概率值为0的情况,这时候影响到后验概率的计算结果,使分类产生偏差。解决这一问题的方法是采用贝叶斯估计的方法估计。此时条件概率的贝叶斯估计为
等价于在随机变量的各个取值的频数上加上一个正数。当
时为极大似然估计,常去
,此时成为拉普拉斯平滑。显然有
二)根据公式P(X,Y)=P(Y)P(X|Y)得到P(X,Y)
P(Y|X)= =P(Y=ck)
P(X(j)=x(j) |Y=ck) /
可以看出此时分母是一样的,所以,
y=arg P(Y=ck)
P(X(j)=x(j) |Y=ck)
后验概率最大化的含义
y=arg P(Y=ck)
P(X(j)=x(j) |Y=ck)
等价式是取得最大值,原因是:朴素贝叶斯法将实例分到后验概率最大的类中,这等价于期望风险最小化。后验概率最大等价于0-1损失函数的期望风险最小化。
假设选择0-1损失函数:
此时,期望风险函数为
Rexp(f) = E[L(Y,f(X))]
可以看出是取条件期望,设
=argmaxP(y=ck|X=x)
这样一来,风险最小化准则得到后验概率最大化准则:
f(x)=argmaxP(ck|X=x)
4.Python源代码:
(1).NaiveBayes.py 训练朴素贝叶斯模型(仅针对属性值为离散型情况)
#-*- coding:utf-8 -*-
from __future__ import division
class BayesClassifier(): #简单贝叶斯分类器
def __init__(self):
pass
def train(self,features,labels): #训练简单贝叶斯分类器
featuresNum=len(features[1]) #样本特征数目
self.sampleNum=len(features) #样本数目
self.countDic={} #统计各个条件概率的出现次数
self.labelSet=set([]) #集合存放类标,如:Y=1 or Y=-1
for i in range(0,len(labels)): #统计类标不同值出现的次数
tempStr='Y='+str(labels[i])
self.labelSet.add(str(labels[i]))
if tempStr in self.countDic:
self.countDic[tempStr]+=1
else:
self.countDic[tempStr]=1
for i in range(0,len(features)): #统计各个条件概率组合出现的次数
for j in range(0,featuresNum):
tempStr='F'+str(j)+'='+str(features[i][j])+'|'+'Y='+str(labels[i])
if tempStr in self.countDic:
self.countDic[tempStr]+=1
else:
self.countDic[tempStr]=1
for key in self.countDic.keys(): #遍历次数统计字典计算概率
if key.find('|')!=-1: #计算条件概率P(Fi=a|Y=b)
targetStr=key[key.find('|')+1:] #类标字符串: Y=1 or Y=-1
self.countDic[key]/=self.countDic[targetStr] #算出条件概率P(Fi=a|Y=b)=Count(Fi=a,Y=b)/Count(Y=b)
for label in self.labelSet: #计算类标概率P(Y=b)
tempStr="Y="+str(label)
self.countDic[tempStr]/=self.sampleNum
def classify(self,feature): #使用训练后的贝叶斯分类器分类新样本
#计算后验概率P(Y=b|Sample=feature)
probabilityMap={}
for label in self.labelSet:
tempProbability=1.0
for i in range(0,len(feature)):
tempStr='F'+str(i)+'='+str(feature[i])+'|Y='+label
if tempStr not in self.countDic: #遇到新的特征值,导致该概率P(Fi=a|Y=b)为0,将它校正为非0值(1/Count(Y=b))
tempProbability*=(1.0/self.countDic['Y='+label])/self.sampleNum
else:
tempProbability*=self.countDic[tempStr]
tempProbability*=self.countDic['Y='+label]
probabilityMap[label]=tempProbability
maxProbability=0.0
for label in self.labelSet: #选取使后验概率P(Y=b|Sample=feature)最大的类标作为目标类标
if probabilityMap[label]>maxProbability:
maxProbability=probabilityMap[label]
targetLabel=label
probabilityMap.clear()
return targetLabel
def __del__(self):
self.countDic.clear()
(2). TestBayes.py 使用数据集测试前面训练的朴素贝叶斯模型
#-*- coding:utf-8-*-
from NaiveBayes import BayesClassifier
from numpy import *
def main():
file=open("D:\\CF\\Weather.txt",'r')
features=[] #数据集特征集
labels=[] #数据集类标集
for line in file: #一行行读数据文件
line=line.strip()
tempVec=line.split(',')
labels.append(tempVec[len(tempVec)-1])
tempVec2=[tempVec[i] for i in range(0,len(tempVec)-1)]
features.append(tempVec2)
Bay=BayesClassifier()
Bay.train(features,labels)
correct=0
for i in range(0,len(features)):
label=Bay.classify(features[i])
print("Original:"+str(labels[i])+"==>"+"Classified:"+label)
if str(label)==str(labels[i]):
correct+=1
print("Accuracy:",correct/len(features)) #正确率
if __name__=='__main__':
main()
(3).针对Weather.txt 小数据集:
sunny,hot,high,FALSE,no
sunny,hot,high,TRUE,no
overcast,hot,high,FALSE,yes
rainy,mild,high,FALSE,yes
rainy,cool,normal,FALSE,yes
rainy,cool,normal,TRUE,no
overcast,cool,normal,TRUE,yes
sunny,mild,high,FALSE,no
sunny,cool,normal,FALSE,yes
rainy,mild,normal,FALSE,yes
sunny,mild,normal,TRUE,yes
overcast,mild,high,TRUE,yes
overcast,hot,normal,FALSE,yes
rainy,mild,high,TRUE,no
输出结果: