分类模型:朴素贝叶斯原理及实现

朴素贝叶斯(Naive Bayes)算法是基于贝叶斯定理特征条件独立性假设(在给定样本类别的前提下,任意特征的取值与其他特征都不相关)的分类方法。适用于文本分类、情感分析、垃圾邮件分类等文本分析问题,此外朴素贝叶斯还应用于医学诊断和推荐系统。

原理

贝叶斯定理

假设 X , Y X,Y X,Y 是一对随机变量,它们的联合概率 p ( X = x , Y = y ) p(X=x,Y=y) p(X=x,Y=y) 是指 X X X 取值 x x x Y Y Y 取值 y y y 的概率。条件概率 p = ( X = x ∣ Y = y ) p=(X=x|Y=y) p=(X=xY=y) 是指 Y Y Y 在取值 y y y 的情况下,变量 X X X 取值 x x x 的概率。且 X X X Y Y Y 的联合概率和条件概率满足
p ( X , Y ) = p ( X ∣ Y ) p ( Y ) = p ( Y ∣ X ) p ( X ) p(X, Y)=p(X|Y)p(Y)=p(Y|X)p(X) p(X,Y)=p(XY)p(Y)=p(YX)p(X)
可得贝叶斯定理
p ( Y ∣ X ) = p ( X ∣ Y ) p ( Y ) p ( X ) p(Y|X)=\frac{p(X|Y)p(Y)}{p(X)} p(YX)=p(X)p(XY)p(Y)
假设 X X X 代表样本, Y Y Y 代表样本的类别标签,贝叶斯定理是一种把先验知识和从样本获取的证据相结合的统计原理。其中 p ( Y ) p(Y) p(Y) 称为先验分布, p ( X ∣ Y ) p(X|Y) p(XY) 称为似然函数, p ( X ) p(X) p(X) 称为证据, p ( Y ∣ X ) p(Y|X) p(YX) 称为后验分布。

朴素贝叶斯模型

给定带类标签的数据集 D D D 中的样本分布于 m m m 个类别 C 1 , C 2 , … , C m C_1,C_2,…,C_m C1,C2,,Cm,每一个样本以 d d d 维属性向量形式表示, X = ( x 1 , x 2 , … , x d ) X=(x_1,x_2,…,x_d) X=(x1,x2,,xd)
贝叶斯分类器的目标:
计算后验概率 P ( C i ∣ X ) P(C_i|X) P(CiX),确定最大的一个 P ( C k ∣ X ) P(C_k|X) P(CkX) C k C_k Ck 即为样本 X X X 的类别
P ( C i ∣ X ) = P ( X ∣ C i ) P ( C i ) P ( X ) P(C_i|X)=\frac{P(X|C_i)P(C_i)}{P(X)} P(CiX)=P(X)P(XCi)P(Ci)
其中 P ( X ) P(X) P(X) 可用全概率公式计算,即 P ( X ) = ∑ i = 1 m P ( X ∣ C i ) P ( C i ) P(X)=\displaystyle \sum^{m}_{i=1}{P(X|C_i)P(C_i)} P(X)=i=1mP(XCi)P(Ci)
由于 P ( X ) P(X) P(X) 对所有的类都相同,看作常量,只需要比较分子 P ( X ∣ C i ) P ( C i ) P(X|C_i)P(C_i) P(XCi)P(Ci) 即可。
P ( C i ) P(C_i) P(Ci):可近似为 ∣ C i , D ∣ / ∣ D ∣ |C_{i,D}|/|D| Ci,D/D C i , D C_{i,D} Ci,D D D D 中类别为 C i C_i Ci 的样本的数量。
P ( X ∣ C i ) P(X|C_i) P(XCi):朴素的假设——假定各个属性之间相互独立,因此
P ( X ∣ C i ) = ∏ P ( x k ∣ C i ) P(X|C_i)=\prod{P(x_k|C_i)} P(XCi)=P(xkCi)
分类属性 f f f P ( x k ∣ C i ) P(x_k|C_i) P(xkCi)可近似为 c o u n t ( f = x k ) / ∣ C i , D ∣ count(f=x_k)/|C_{i,D}| count(f=xk)/Ci,D,其中 c o u n t ( f = x k ) count(f=x_k) count(f=xk) 为属性 f f f 取值为 s k s_k sk 的样本的数量。
连续值属性 f f f:假定其值服从均值为 μ \mu μ 标准差为 σ \sigma σ 的高斯分布,即
g ( x , μ , σ ) = 1 2 π σ e − x − μ 2 σ 2 g(x,\mu,\sigma)=\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{x-\mu}{2\sigma^2}} g(x,μ,σ)=2π σ1e2σ2xμ

P ( x k ∣ C i ) = g ( x k , μ C i , σ C i ) P(x_k|C_i)=g(x_k,\mu_{C_i},\sigma_{C_i}) P(xkCi)=g(xk,μCi,σCi)
其中 μ c i \mu c_i μci σ c i \sigma c_i σci 分别为类别 C i C_i Ci 中样本属性 f f f 的均值和标准差。
对上式的解释: g ( x , μ , σ ) g(x,\mu,\sigma) g(x,μ,σ) 是高斯分布的概率密度函数。对于连续值属性 f f f P ( f = x k ) P(f=x_k) P(f=xk) 的值接近于0。如: P ( H e i g h t = 70 ) = ? P(Height=70)=? P(Height=70)=?,可计算 P ( 69 ≤ H e i g h t ≤ 70 ) P(69\leq Height\leq 70) P(69Height70) P ( 70 ≤ H e i g h t ≤ 71 ) P(70\leq Height\leq 71) P(70Height71)
一般计算的是 f f f 的取值落入 x k x_k xk 附近很小的邻域内的概率,即
P ( x k − ϵ / 2 ≤ f ≤ x k + ϵ / 2 ) ≈ ϵ × g ( x k , μ , σ ) P(x_k-\epsilon/2\leq f\leq x_k+\epsilon/2)\approx\epsilon\times g(x_k,\mu,\sigma) P(xkϵ/2fxk+ϵ/2)ϵ×g(xk,μ,σ)
带入公式
P ( X ∣ C i ) = ∏ k = 1 n P ( x k ∣ C i ) P(X|C_i)=\prod^{n}_{k=1}P(x_k|C_i) P(XCi)=k=1nP(xkCi)
P ( C i ∣ X ) = P ( X ∣ C i ) P ( C i ) P ( X ) P(C_i|X)=\frac{P(X|C_i)P(C_i)}{P(X)} P(CiX)=P(X)P(XCi)P(Ci)
P ( X ) = ∑ i = 1 m P ( X ∣ C i ) P ( C i ) P(X)=\displaystyle \sum^{m}_{i=1}{P(X|C_i)P(C_i)} P(X)=i=1mP(XCi)P(Ci)
可约去邻域大小 ϵ \epsilon ϵ。因此,只需计算概率密度函数的值。
若该属性的取值不服从高斯分布,可用核密度估计(KDE,Kernel density Estimation)方法计算其概率。
如高斯核的情况
P ( x k ∣ C i ) = 1 ∣ D c h ∣ ∑ x j ∈ K ( x k , x j [ f ] ) P(x_k|C_i)=\frac{1}{|D_ch|}\displaystyle \sum_{x_j\in }K(x_k,x_j[f]) P(xkCi)=Dch1xjK(xk,xj[f])
K ( a , b ) = 1 2 π e ( a − b ) 2 2 h 2 K(a,b)=\frac{1}{\sqrt{2\pi}}e^{\frac{(a-b)^2}{2h^2}} K(a,b)=2π 1e2h2(ab)2
其中 h h h 为带宽

0概率问题:拉普拉斯校正(Laplacian Smoothing)

若训练集中类别 C i C_i Ci 不包含 f = x k f=x_k f=xk 的样本,用公式 P ( x k ) = ∣ C i , D ∣ / ∣ D ∣ P(x_k)=|C_{i,D}|/|D| P(xk)=Ci,D/D 估计概率,会得到 P ( x k ∣ C i ) = 0 P(x_k|C_i)=0 P(xkCi)=0
则样本 X X X 中只要包含 f = x k f=x_k f=xk 的属性,无论其他属性如何取值, P ( X ∣ C i ) p ( C i ) P(X|C_i)p(C_i) P(XCi)p(Ci) 均为0。
拉普拉斯校正方法:
P ( x k ∣ C i ) = c o u n t ( A k = x k ) + 1 ∣ C i , D ∣ + c o u n t ( A k ) P(x_k|C_i)=\frac{count(A_k=x_k)+1}{|C_{i,D}|+count(A_k)} P(xkCi)=Ci,D+count(Ak)count(Ak=xk)+1
其中 c o u n t ( f ) count(f) count(f) 为属性 f f f 的不同取值的数目。
例如训练集中类别 C i C_i Ci 包含1000个样本,其中
i n c o m e = ′ l o w ′ ( 0 ) income='low'(0) income=low(0)
i n c o m e = ′ m e d i u m ′ ( 990 ) income='medium'(990) income=medium(990)
i n c o m e = ′ h i g h ′ ( 10 ) income='high'(10) income=high(10)

P ( i n c o m e = ′ l o w ′ ∣ C i ) = 1 / 1003 P(income='low'|C_i)=1/1003 P(income=lowCi)=1/1003
P ( i n c o m e = ′ m e d i u m ′ ∣ C i ) = 991 / 1003 P(income='medium'|C_i)=991/1003 P(income=mediumCi)=991/1003
P ( i n c o m e = ′ h i g h ′ ∣ C i ) = 11 / 1003 P(income='high'|C_i)=11/1003 P(income=highCi)=11/1003

举例

数据:

x 1 x_1 x1 x 2 x_2 x2 Y Y Y
11S-1
21M-1
31M1
41S1
51S-1
62S-1
72M-1
82M1
92L1
102L1
113L1
123M1
133M1
143L1
153L-1
  1. 训练结果:
    C 1 : Y = 1 C 2 : Y = − 1 C_1:Y=1 \qquad C_2:Y=-1 C1:Y=1C2:Y=1
    P ( C 1 ) = 9 / 15 P ( C 2 ) = 6 / 15 P(C_1)=9/15 \qquad P(C_2)=6/15 P(C1)=9/15P(C2)=6/15
    P ( x 1 = 1 ∣ C 1 ) = 2 / 9 P ( x 1 = 2 ∣ C 1 ) = 3 / 9 P ( x 1 = 3 ∣ C 1 ) = 4 / 9 P(x_1=1|C_1)=2/9\qquad P(x_1=2|C_1)=3/9\qquad P(x_1=3|C_1)=4/9 P(x1=1C1)=2/9P(x1=2C1)=3/9P(x1=3C1)=4/9
    P ( x 2 = S ∣ C 1 ) = 1 / 9 P ( x 2 = M ∣ C 1 ) = 4 / 9 P ( x 2 = L ∣ C 1 ) = 4 / 9 P(x_2=S|C_1)=1/9\qquad P(x_2=M|C_1)=4/9\qquad P(x_2=L|C_1)=4/9 P(x2=SC1)=1/9P(x2=MC1)=4/9P(x2=LC1)=4/9
    P ( x 1 = 1 ∣ C 2 ) = 3 / 6 P ( x 1 = 2 ∣ C 2 ) = 2 / 6 P ( x 1 = 3 ∣ C 2 ) = 1 / 6 P(x_1=1|C_2)=3/6\qquad P(x_1=2|C_2)=2/6\qquad P(x_1=3|C_2)=1/6 P(x1=1C2)=3/6P(x1=2C2)=2/6P(x1=3C2)=1/6
    P ( x 2 = S ∣ C 2 ) = 3 / 6 P ( x 2 = M ∣ C 2 ) = 2 / 6 P ( x 2 = L ∣ C 2 ) = 1 / 6 P(x_2=S|C_2)=3/6\qquad P(x_2=M|C_2)=2/6\qquad P(x_2=L|C_2)=1/6 P(x2=SC2)=3/6P(x2=MC2)=2/6P(x2=LC2)=1/6
  2. 验证
    对于 t = ( 2 , S ) t=(2,S) t=(2,S)
    P ( C 1 ∣ t ) = P ( C 1 ) P ( x 1 = 2 ∣ C 1 ) P ( x 2 = S ∣ C 1 ) = 9 / 15 ∗ 3 / 9 ∗ 1 / 9 = 1 / 45 P(C_1|t)=P(C_1)P(x_1=2|C_1)P(x_2=S|C_1)=9/15*3/9*1/9=1/45 P(C1t)=P(C1)P(x1=2C1)P(x2=SC1)=9/153/91/9=1/45
    P ( C 2 ∣ t ) = P ( C 2 ) P ( x 1 = 2 ∣ C 2 ) P ( x 2 = S ∣ C 2 ) = 6 / 15 ∗ 2 / 6 ∗ 3 / 6 = 1 / 15 P(C_2|t)=P(C_2)P(x_1=2|C_2)P(x_2=S|C_2)=6/15*2/6*3/6=1/15 P(C2t)=P(C2)P(x1=2C2)P(x2=SC2)=6/152/63/6=1/15
    所以 t = ( 2 , S ) t=(2,S) t=(2,S) 的标签 Y Y Y 的预测值为 − 1 -1 1

代码实现

朴素贝叶斯模型

class bayes:
    def __init__(self, lam=None):
        self.y_p = {}		# 存储不同标签的概率
        self.y_x_cnt = []	# 存储相同标签下不同属性值的数量
        self.lam = lam		# 是否使用拉普拉斯校正,为数值型数据
        self.y_x_p = []		# 存储相同标签下不同属性值的概率
        self.y_pre = []		# 存储预测结果
    
    def get_y_p(self, data):
        if self.lam == None:
            y_labels = np.unique(data[:, -1])
            for y_label in y_labels:
                self.y_p[y_label] = len(data[data[:, -1] == y_label]) / len(data)
        else:
            y_labels = np.unique(data[:, -1])
            for y_label in y_labels:
                self.y_p[y_label] = (len(data[data[:, -1] == y_label]) + self.lam) / (len(data) + self.lam*len(y_labels))
            
    def get_y_x_cnt(self, data):
        for y_label in self.y_p.keys():
            y_label_cnt = len(data[data[:, -1] == y_label])
            for x_k in range(0, data.shape[1]-1):
                x_k_count = Counter(data[data[:, -1] == y_label][:,x_k])
                self.y_x_cnt.append([y_label,y_label_cnt,x_k,dict(x_k_count)])
                
    def get_y_x_p(self):
        if self.lam == None:
            for i in range(0, len(self.y_x_cnt)):
                p = {}
                for key in self.y_x_cnt[i][3].keys():
                    p[key] = self.y_x_cnt[i][3][key] / self.y_x_cnt[i][1]
                self.y_x_p.append([self.y_x_cnt[i][0], self.y_x_cnt[i][1], self.y_x_cnt[i][2], p])
        else:
            for i in range(0, len(self.y_x_cnt)):
                p = {}
                length = len(self.y_x_cnt[i][3].keys())
                for key in self.y_x_cnt[i][3].keys():
                    p[key] = (self.y_x_cnt[i][3][key]+self.lam) / (self.y_x_cnt[i][1]+length*self.lam)
                self.y_x_p.append([self.y_x_cnt[i][0], self.y_x_cnt[i][1], self.y_x_cnt[i][2], p])
            
    def fit(self, data):
        data = np.array(data)
        self.get_y_p(data)
        self.get_y_x_cnt(data)
        self.get_y_x_p()
        
    def predict(self, y_test):
        y_test = np.array(y_test)
        y_x_p_arr = np.array(self.y_x_p)
        for j in range(0, len(y_test)):
            y = y_test[j]
            result = {}
            for key in self.y_p.keys():
                result[key] = 1*self.y_p[key]
                for i in range(0,len(y)):
                    result[key]=result[key]*y_x_p_arr[(y_x_p_arr[:,0]==key)&(y_x_p_arr[:,2]==i)][:,3][0][str(y[i])]
            self.y_pre.append(max(result, key=result.get))
        return self.y_pre

模型运用

数据集(使用原理介绍时的例子)
x = np.array([[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3],['S','M','M','S','S','S','M','M','L','L','L','M','M','L','L']])
y = np.array([-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1])
df = pd.DataFrame()
df["x1"] = x[0]
df["x2"] = x[1]
df["label"] = y
朴素贝叶斯
model1 = bayes()
model1.fit(df)

y_test = [[2, 'S'],[2, 'L']]
model1.predict(y_test)

在这里插入图片描述

使用拉普拉斯校正
model = bayes(lam = 1)
model.fit(df)

y_test = [[2, 'S'],[2, 'L']]
model.predict(y_test)

在这里插入图片描述

总结

优点

  1. 思想简单,易于实现
  2. 分类准确率高——即使在属性之间存在相关性的情况下
  3. 数学基础严密,结果可解释性强
  4. 可以增量式进行训练

缺点

  1. 朴素的假设不成立:实际数据的属性之间往往存在相关性
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值