一切为了数据挖掘的准备
4.朴素贝叶斯法(naive Bayes)
朴素贝叶斯是基于贝叶斯定理与特征条件独立假设的分类方法
4.1朴素贝叶斯的学习与分类
4.1.1 基本方法
-
表达:输入空间
X⊆Rn,输出空间
Y=c1,c2,⋯,cK。P(X,Y)是X和Y的联合分布。对条件概率分布作条件独立性假设,即
P(X∣Y)=P(x0∣Y)P(x1∣Y)⋯P(xn∣Y),在分类确定的条件下,用于分类的特征都是条件独立的。
-
通过训练集T歇息联合概率分布P(X,Y)。
- 学习先验概率分布:
P(Y=ck),k=1,2,⋯,K
- 条件概率分布:
P(X=x∣Y=ck)=P(X(1)=x(1),X(2)=x(2),⋯,X(n)=x(n)∣Y=ck)=∏j=1nP(X(j)=x(j)∣Y=ck)
- 联合概率分布:
P(X,Y)=P(X∣Y)P(Y)
-
通过学习到的模型计算后验概率分布
P(Y=ck∣X=x)=P(X=x)P(X=x∣Y=ck)P(Y=ck)
-
朴素贝叶斯的分类器模型
y=f(x)=argmaxckP(Y=ck)j=1∏nP(X(j)=x(j)∣Y=ck)
4.1.2 分类器模型证明
-
选择损失函数:对于分类模型,一般选择0-1损失函数:
L(Y,f(X))={1,0,Y̸=f(X)Y=f(X)
-
期望风险:
对于离散值期望为
∑xP(x)
Rexp(f)=E[L(Y,f(X))]=X∑Y∑L(Y,f(X))P(X,Y)=
X∑Y∑L(Y,f(X))P(Y∣X)P(X)=X∑(Y∑L(Y,f(X))P(Y∣X))P(X)
-
对想要期望风险最小化,对
∑YL(Y,f(X))P(Y∣X)逐个极小化
minY∑L(Y,f(X))P(Y∣X)=mink∑L(Y=ck,f(X))P(Y=ck∣X)
当
Y̸=f(x)即
f(x)̸=ck时,
L(Y=ck,f(X))为1,所以上面公式等效于
mink∑I(f(X)̸=ck)P(Y=ck∣X)=mink∑(1−I(f(X)=ck))P(Y=ck∣X)=
min{k∑P(Y=ck∣X)−k∑I(f(X)=ck)P(Y=ck∣X)}=maxk∑I(f(X)=ck)P(Y=ck∣X)
4.2参数估计
4.2.1 极大似然估计
-
P(Y=ck)=N∑i=1I(yi=ck)
输出空间
Y=c1,c2,⋯,cK,假设参数为
θ假设每个值对应概率为
θ1,θ2,⋯,θK,即
P(Y=ci∣θ)=θi,且满足
st:∑i=1Kθi=1
证:
maxP(y1y2⋯yN∣θ)=P(y1∣θ)P(y2∣θ)⋯P(yN∣θ)=θ1m1θ2m2⋯θNmN
maxln(P(y1y2⋯yN∣θ))=m1lnθ1+m2lnθ2+⋯+mKlnθK
L=ln(P(y1y2⋯yN∣θ))+λ(θ1+θ2+⋯+θK−1)=
m1lnθ1+m2lnθ2+⋯+mKlnθK+λ(θ1+θ2+⋯+θK−1)
∂θi∂L=θimi+λ=0,θi=−λmi,
K∑−λmi=1,λ=−K∑mi=−N,θi=Nmi
-
P(X(j)=a∣Y=ck)=∑i=1NI(yi=ck)∑i=1NI(x(j)=a,yi=ck)
4.2.2贝叶斯估计
假设样本较少,有可能某些条件下计数为0,则计算出该条件下的先验概率为0,会影响到以后后验概率的结果。因此采用贝叶斯估计。
P(Y=ck)=N+Kλ∑i=1I(yi=ck)+λ
P(X(j)=a∣Y=ck)=∑i=1NI(yi=ck)+Sλ∑i=1NI(x(j)=a,yi=ck)+λ
其中K是分类结果的个数,S是第j维输入特征的取值个数。
证:
对于多项分布
Y=c1,c2,⋯,cK,先验概率分布为
π(θ)=γ(α1)γ(α2)⋯γ(αK)γ(α1+α2+⋯+αK)θ1α1−1θ2α2−1⋯θKαK−1
倾向于认为
α1=α2=⋯=αK=α
P(θ∣y1⋯yN)=P(y1⋯yN)P(θ,y1⋯yN)∝π(θ)P(y1⋯yN∣θ)∝
θ1α−1θ2α−1⋯θKα−1θ1m1θ2m2⋯θNmN
L=θ1m1+α−1θ2m2+α−1⋯θKmk+α−1
L1=lnL+λ(θ1+⋯+θK−1)={K∑(mi+α−1)lnθi+λθi}−1
∂θi∂L=θimi+α−1+λ=0,θi=−λmi+α−1,
K∑−λmi+α−1=1,λ=−K∑(mi+α−1)=−N−K(α−1),
θi=N+K(α−1)mi+α−1
4.3 我的实现
import numpy as np
import pandas as pd
from functools import reduce
from pandas import Series,DataFrame
class naive_bayes:
def __init__(self,X,Y):
"""
xclass是个二维数组每行数据对应输入空间X的对应维度的所有取值,
yclass是输出空间所有取值
"""
self.X = X
self.Y = Y
self.model = self.training()
def training(self):
data = DataFrame(self.X)
data['yvalue'] = self.Y
# 计算每个y分类的数目
d_y = data['yvalue'].value_counts()
# p(y) = y分类数目/总数目
m_y = d_y/(len(data))
# p(x|y),m_xy最终结构,第一层index是各特征的index,第二层index是各特征的取值,
#columns是y分类
m_xy = DataFrame([],columns = data['yvalue'].unique())
for i in range(len(data.columns)-1):
#按照y和第i个特征计数
d_xy = pd.crosstab(data[i],data['yvalue'])
# p(x|y)
d_xy = d_xy/d_y
d_xy['feature'] = i
m_xy = pd.concat([m_xy,d_xy])
m_xy.set_index(['feature',m_xy.index],inplace=True)
return {'m_y':m_y,'m_xy':m_xy}
def predict(self,x):
# 最终y分类
py = ''
# y分类对应的最大概率
maxp = 0
# 循环y分类,计算概率
for y in self.model['m_y'].index:
p = self.model['m_y'][y]
for i_feature in range(len(x)):
p*=self.model['m_xy'].loc[(i_feature,x[i_feature]),y]
if maxp < p:
py = y
maxp = p
print('预测结果为:',py,',得到概率为:',maxp)
x=[[1,'s'],[1,'m'],[1,'m'],[1,'s'],[1,'s'],[2,'s'],[2,'m'],[2,'m'],[2,'l'],[2,'l'],[3,'l'],[3,'m'],[3,'m'],[3,'l'],[3,'l']]
y=[-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1]
n = naive_bayes(x,y)
n.predict([2,'s'])