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

本文详细介绍了朴素贝叶斯分类算法的原理,包括贝叶斯定理、条件独立性假设,以及在文本分类、情感分析等领域的应用实例。通过实例演示了如何构建和使用朴素贝叶斯模型,并讨论了拉普拉斯校正的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

原理

贝叶斯定理

假设 X,YX,YX,Y 是一对随机变量,它们的联合概率 p(X=x,Y=y)p(X=x,Y=y)p(X=x,Y=y) 是指 XXX 取值 xxxYYY 取值 yyy 的概率。条件概率 p=(X=x∣Y=y)p=(X=x|Y=y)p=(X=xY=y) 是指 YYY 在取值 yyy 的情况下,变量 XXX 取值 xxx 的概率。且 XXXYYY 的联合概率和条件概率满足
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)
假设 XXX 代表样本,YYY 代表样本的类别标签,贝叶斯定理是一种把先验知识和从样本获取的证据相结合的统计原理。其中 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) 称为后验分布。

朴素贝叶斯模型

给定带类标签的数据集 DDD 中的样本分布于 mmm 个类别 C1,C2,…,CmC_1,C_2,…,C_mC1,C2,,Cm,每一个样本以 ddd 维属性向量形式表示,X=(x1,x2,…,xd)X=(x_1,x_2,…,x_d)X=(x1,x2,,xd)
贝叶斯分类器的目标:
计算后验概率 P(Ci∣X)P(C_i|X)P(CiX),确定最大的一个 P(Ck∣X)P(C_k|X)P(CkX)CkC_kCk 即为样本 XXX 的类别
P(Ci∣X)=P(X∣Ci)P(Ci)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=1mP(X∣Ci)P(Ci)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∣Ci)P(Ci)P(X|C_i)P(C_i)P(XCi)P(Ci) 即可。
P(Ci)P(C_i)P(Ci):可近似为 ∣Ci,D∣/∣D∣|C_{i,D}|/|D|Ci,D/DCi,DC_{i,D}Ci,DDDD 中类别为 CiC_iCi 的样本的数量。
P(X∣Ci)P(X|C_i)P(XCi):朴素的假设——假定各个属性之间相互独立,因此
P(X∣Ci)=∏P(xk∣Ci)P(X|C_i)=\prod{P(x_k|C_i)}P(XCi)=P(xkCi)
分类属性 fffP(xk∣Ci)P(x_k|C_i)P(xkCi)可近似为count(f=xk)/∣Ci,D∣count(f=x_k)/|C_{i,D}|count(f=xk)/Ci,D,其中 count(f=xk)count(f=x_k)count(f=xk) 为属性 fff 取值为 sks_ksk 的样本的数量。
连续值属性 fff:假定其值服从均值为 μ\muμ 标准差为 σ\sigmaσ 的高斯分布,即
g(x,μ,σ)=12πσe−x−μ2σ2g(x,\mu,\sigma)=\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{x-\mu}{2\sigma^2}}g(x,μ,σ)=2πσ1e2σ2xμ

P(xk∣Ci)=g(xk,μCi,σCi)P(x_k|C_i)=g(x_k,\mu_{C_i},\sigma_{C_i})P(xkCi)=g(xk,μCi,σCi)
其中 μci\mu c_iμciσci\sigma c_iσci 分别为类别 CiC_iCi 中样本属性 fff 的均值和标准差。
对上式的解释: g(x,μ,σ)g(x,\mu,\sigma)g(x,μ,σ) 是高斯分布的概率密度函数。对于连续值属性 fffP(f=xk)P(f=x_k)P(f=xk) 的值接近于0。如:P(Height=70)=?P(Height=70)=?P(Height=70)=?,可计算 P(69≤Height≤70)P(69\leq Height\leq 70)P(69Height70)P(70≤Height≤71)P(70\leq Height\leq 71)P(70Height71)
一般计算的是 fff 的取值落入 xkx_kxk 附近很小的邻域内的概率,即
P(xk−ϵ/2≤f≤xk+ϵ/2)≈ϵ×g(xk,μ,σ)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∣Ci)=∏k=1nP(xk∣Ci)P(X|C_i)=\prod^{n}_{k=1}P(x_k|C_i)P(XCi)=k=1nP(xkCi)
P(Ci∣X)=P(X∣Ci)P(Ci)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=1mP(X∣Ci)P(Ci)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(xk∣Ci)=1∣Dch∣∑xj∈K(xk,xj[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)=12πe(a−b)22h2K(a,b)=\frac{1}{\sqrt{2\pi}}e^{\frac{(a-b)^2}{2h^2}}K(a,b)=2π1e2h2(ab)2
其中 hhh 为带宽

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

若训练集中类别 CiC_iCi 不包含 f=xkf=x_kf=xk 的样本,用公式 P(xk)=∣Ci,D∣/∣D∣P(x_k)=|C_{i,D}|/|D|P(xk)=Ci,D/D 估计概率,会得到 P(xk∣Ci)=0P(x_k|C_i)=0P(xkCi)=0
则样本 XXX 中只要包含 f=xkf=x_kf=xk 的属性,无论其他属性如何取值,P(X∣Ci)p(Ci)P(X|C_i)p(C_i)P(XCi)p(Ci) 均为0。
拉普拉斯校正方法:
P(xk∣Ci)=count(Ak=xk)+1∣Ci,D∣+count(Ak)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
其中 count(f)count(f)count(f) 为属性 fff 的不同取值的数目。
例如训练集中类别 CiC_iCi 包含1000个样本,其中
income=′low′(0)income='low'(0)income=low(0)
income=′medium′(990)income='medium'(990)income=medium(990)
income=′high′(10)income='high'(10)income=high(10)

P(income=′low′∣Ci)=1/1003P(income='low'|C_i)=1/1003P(income=lowCi)=1/1003
P(income=′medium′∣Ci)=991/1003P(income='medium'|C_i)=991/1003P(income=mediumCi)=991/1003
P(income=′high′∣Ci)=11/1003P(income='high'|C_i)=11/1003P(income=highCi)=11/1003

举例

数据:

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

代码实现

朴素贝叶斯模型

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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值