朴素贝叶斯

朴素贝叶斯算法概念

贝叶斯方法

贝叶斯方法是以贝叶斯原理为基础,使用概率统计的知识对样本数据集进行分类。由于其有着坚实的数学基础,贝叶斯分类算法的误判率是很低的。贝叶斯方法的特点是结合先验概率和后验概率,即避免了只使用先验概率的主观偏见,也避免了单独使用样本信息的过拟合现象。贝叶斯分类算法在数据集较大的情况下表现出较高的准确率,同时算法本身也比较简单。

朴素贝叶斯

朴素贝叶斯算法(Naive Bayesian algorithm) 是应用最为广泛的分类算法之一。
朴素贝叶斯方法是在贝叶斯算法的基础上进行了相应的简化,即假定给定目标值时属性之间相互条件独立。也就是说没有哪个属性变量对于决策结果来说占有着较大的比重,也没有哪个属性变量对于决策结果占有着较小的比重。虽然这个简化方式在一定程度上降低了贝叶斯分类算法的分类效果,但是在实际的应用场景中,极大地简化了贝叶斯方法的复杂性。

条件概率

条件分布试图回答这样一个问题,当我们知道 X X X必须取某个值 x x x时, Y Y Y上的概率分布是什么?在离散情况下,给定 Y Y Y的条件概率质量函数是简单的:
p Y ∣ X ( y ∣ x ) = p X Y ( x , y ) p X ( x ) p_{Y | X}(y | x)=\frac{p_{X Y}(x, y)}{p_{X}(x)} pYX(yx)=pX(x)pXY(x,y)
假设分母不等于0。

在连续的情况下,在技术上要复杂一点,因为连续随机变量的概率等于零。忽略这一技术点,我们通过类比离散情况,简单地定义给定 X = x X = x X=x的条件概率密度为:
f Y ∣ X ( y ∣ x ) = f X Y ( x , y ) f X ( x ) f_{Y | X}(y | x)=\frac{f_{X Y}(x, y)}{f_{X}(x)} fYX(yx)=fX(x)fXY(x,y)
假设分母不等于0。

全概率公式

全概率公式是概率论中的重要工具,用于将复杂事件的概率分解为多个简单事件概率的组合,从而简化计算。它的核心思想是 “分而治之”,通过将样本空间划分为若干互斥且完备的事件组,间接求出目标事件的概率。

P ( A ) = ∑ i = 1 n P ( B i ) ⋅ P ( A ∣ B i ) P(A) = \sum\limits_{i=1}^n P(B_i) \cdot P(A|B_i) P(A)=i=1nP(Bi)P(ABi)

贝叶斯定理

贝叶斯理论认为任意未知量θ都可以看作一个随机变量,对该未知量的描述可以用一个概率分布π(θ)来概括,这是贝叶斯学派最基本的观点。当这个概率分布在进行现场试验或者抽样前就已确定,便可将该分布称为先验分布,再结合由给定数据集X计算样本的似然函数L(θ|**X)**后,即可应用贝叶斯公式计算该未知量的后验概率分布。
P ( c ∣ x ) = P ( x ∣ c ) P ( c ) 似然函数  类先验概率 ∑ P ( x ∣ c ) P ( c ) 全概率 P(c|x)=\frac{\overset{\text{似然函数 } \text{ 类先验概率}}{P(x|c)P(c)}}{\underset{\text{全概率}}{\sum P(x|c)P(c)}} P(cx)=全概率P(xc)P(c)P(xc)P(c)似然函数  类先验概率

为什么“朴素”

“朴素” 体现在朴素贝叶斯算法假定特征条件之间相互独立。在现实世界中,很多特征之间往往存在关联,但朴素贝叶斯为简化计算和模型构建,做出了这一相对 “简单粗暴” 的假设 。

这是朴素贝叶斯 “朴素” 之处。假设在给定类别 c 的条件下,各个特征x1,x2,x3,…,xn之间相互独立。基于此假设,(P(x|c)) 可展开为:
P ( x ∣ c ) = P ( x 1 ∣ c ) P ( x 2 ∣ c ) ⋯ P ( x n ∣ c ) P(x|c) = P(x_1|c)P(x_2|c)\cdots P(x_n|c) P(xc)=P(x1c)P(x2c)P(xnc)
比如在文本分类中,假设每个词的出现都不依赖于其他词(实际不完全如此,但该假设简化计算)。

基于此假设,在计算给定类别下特征出现的联合概率时,可将其转化为各个特征条件概率的乘积,大幅降低计算复杂度。例如在文本分类里,正常情况下词语间存在语义关联、语法搭配等关系,但朴素贝叶斯假设每个词的出现都不依赖于其他词,从而简化模型,使其在很多场景下仍能有效工作。 正是因为这种对特征独立性的简化假设,该算法被称为 “朴素” 的贝叶斯算法。

典型用例——邮件分类

贝叶斯定理基础公式

P ( c ∣ x ) = P ( x ∣ c ) P ( c ) P ( x ) P(c|x) = \frac{P(x|c)P(c)}{P(x)} P(cx)=P(x)P(xc)P(c)

特征条件独立假设下的似然函数展开

P ( x ∣ c ) = P ( x 1 ∣ c ) P ( x 2 ∣ c ) ⋯ P ( x n ∣ c ) P(x|c) = P(x_1|c)P(x_2|c)\cdots P(x_n|c) P(xc)=P(x1c)P(x2c)P(xnc)

类先验概率计算

P ( c ) = N c N P(c)=\frac{N_c}{N} P(c)=NNc

后验概率计算(省略归一化因子)

P ( c ∣ x ) ∝ P ( c ) ∏ i = 1 n P ( x i ∣ c ) P(c|x) \propto P(c)\prod_{i = 1}^{n}P(x_i|c) P(cx)P(c)i=1nP(xic)

垃圾邮件分类示例中的具体计算

类先验概率

P ( c 1 ) = 0.3 , P ( c 2 ) = 0.7 P(c_1) = 0.3, \quad P(c_2) = 0.7 P(c1)=0.3,P(c2)=0.7

条件概率
  • 垃圾邮件中出现“促销”的概率: P ( x 1 ∣ c 1 ) P(x_1|c_1) P(x1c1)
  • 正常邮件中出现“促销”的概率: P ( x 1 ∣ c 2 ) P(x_1|c_2) P(x1c2)
  • 垃圾邮件中未出现“免费”的概率: P ( ¬ x 2 ∣ c 1 ) P(\neg x_2|c_1) P(¬x2c1)
  • 正常邮件中未出现“免费”的概率: P ( ¬ x 2 ∣ c 2 ) P(\neg x_2|c_2) P(¬x2c2)
后验概率比较

P ( c 1 ∣ x ) ∝ P ( c 1 ) ⋅ P ( x 1 ∣ c 1 ) ⋅ P ( ¬ x 2 ∣ c 1 ) P(c_1|x) \propto P(c_1) \cdot P(x_1|c_1) \cdot P(\neg x_2|c_1) P(c1x)P(c1)P(x1c1)P(¬x2c1)
P ( c 2 ∣ x ) ∝ P ( c 2 ) ⋅ P ( x 1 ∣ c 2 ) ⋅ P ( ¬ x 2 ∣ c 2 ) P(c_2|x) \propto P(c_2) \cdot P(x_1|c_2) \cdot P(\neg x_2|c_2) P(c2x)P(c2)P(x1c2)P(¬x2c2)

分类决策规则

c ^ = arg ⁡ max ⁡ c ∈ { c 1 , c 2 } P ( c ∣ x ) \hat{c} = \arg\max_{c \in \{c_1, c_2\}} P(c|x) c^=argc{c1,c2}maxP(cx)

代码实现

使用numpy

# 使用numpy实现朴素贝叶斯
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

### 构造数据集
### 来自于李航统计学习方法表4.1
x1 = [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3]
x2 = ['S','M','M','S','S','S','M','M','L','L','L','M','M','L','L']
y = [-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1]

df = pd.DataFrame({'x1':x1, 'x2':x2, 'y':y})

X = df[['x1','x2']]
y = df[['y']]
y[y.columns[0]].unique()

def nb_fit(X, y):
    # 获取所有类别标签
    classes = y[y.columns[0]].unique()
    print(classes)

    # 计算每个类别的样本数量
    class_count = y[y.columns[0]].value_counts()

    # 计算每个类别的先验概率(类别概率)
    class_prior = class_count/len(y)

    # 初始化条件概率字典
    prior = dict()

    # 遍历每个特征列
    for col in X.columns:
        # 遍历每个类别
        for j in classes:
            # 获取当前类别下该特征列的值统计
            p_x_y = X[(y==j).values][col].value_counts()

            # 遍历该特征列的所有可能取值
            for i in p_x_y.index:
                # 计算条件概率 P(X_i|Y_j)
                # 即:在类别j下,特征col取值为i的概率
                prior[(col, i, j)] = p_x_y[i]/class_count[j]

    # 返回:类别列表、类别先验概率、条件概率字典
    return classes, class_prior, prior

classes, class_prior, prior = nb_fit(X, y)

def predict(X_test):
    res = []
    for c in classes:
        p_y = class_prior[c]
        p_x_y = 1
        for i in X_test.items():
            p_x_y *= prior[tuple(list(i)+[c])]
        res.append(p_y*p_x_y)
    return classes[np.argmax(res)]

X_test = {'x1': 2, 'x2': 'S'}
print('测试数据预测类别为:', predict(X_test))

使用Sklern

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
gnb = GaussianNB()
y_pred = gnb.fit(X_train, y_train).predict(X_test)
print("Accuracy of GaussianNB in iris data test:", 
      accuracy_score(y_test, y_pred))
Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐