【机器学习】朴素贝叶斯

目录

一、朴素贝叶斯的算法原理

[1.1 定义](#1.1 定义)

[1.2 贝叶斯定理](#1.2 贝叶斯定理)

[1.3 条件独立性假设](#1.3 条件独立性假设)

二、朴素贝叶斯算法的几种常见类型

[2.1 高斯朴素贝叶斯 (Gaussian Naive Bayes)](#2.1 高斯朴素贝叶斯 (Gaussian Naive Bayes))

[【训练阶段】 - 从数据中学习模型参数](#【训练阶段】 - 从数据中学习模型参数)

[【预测阶段】 - 对新样本 Xnew​ 进行分类](#【预测阶段】 - 对新样本 Xnew 进行分类)

[2. 2 多项式朴素贝叶斯 (Multinomial Naive Bayes)](#2. 2 多项式朴素贝叶斯 (Multinomial Naive Bayes))

[【训练阶段】 - 学习模型参数](#【训练阶段】 - 学习模型参数)

[【预测阶段】 - 对新样本 Xnew​ 进行分类](#【预测阶段】 - 对新样本 Xnew 进行分类)

[2.3 伯努利朴素贝叶斯 (Bernoulli Naive Bayes)](#2.3 伯努利朴素贝叶斯 (Bernoulli Naive Bayes))

[【训练阶段】 - 学习模型参数](#【训练阶段】 - 学习模型参数)

[【预测阶段】 - 对新样本 Xnew​ 进行分类](#【预测阶段】 - 对新样本 Xnew 进行分类)

三、实例:基于朴素贝叶斯的好瓜预测

[任务: 对一个给定的西瓜样本进行二分类(好瓜/坏瓜)](#任务: 对一个给定的西瓜样本进行二分类(好瓜/坏瓜))

1.训练数据

2.测试数据

3.计算步骤

4.代码实现

四、学习总结


一、朴素贝叶斯的算法原理

1.1 定义

朴素贝叶斯是一种基于 贝叶斯定理概率分类算法。它属于 监督学习 算法的一种,也就是说,它需要一个带有标签(即正确答案)的训练数据集来学习。

它的核心思想是:对于一个未知类别的数据样本,计算该样本 属于各个类别的概率,然后选择 概率最大的那个类别 作为它的预测类别。

1.2 贝叶斯定理

贝叶斯定理描述了在已知某些条件下,一个事件发生的概率。

在分类问题中,我们想知道的是:在看到了某个数据样本的特征(X)之后,这个样本属于某个类别(y)的概率是多少?

这个概率被称为 后验概率 (Posterior Probability),用数学公式表示就是 P(y∣X)。

贝叶斯定理的公式如下:

其中

P(y∣X): 后验概率 (Posterior Probability)

P(X∣y): 似然性 (Likelihood)

  • 假设样本属于类别 y 的前提下,观察到特征数据 X 的概率。

P(y): 先验概率 (Prior Probability)

  • 观察到任何特征数据 X 之前,认为样本属于类别 y 的概率。

P(X): 证据 (Evidence)

  • 观察到特征 X 的概率。这是一个归一化因子,确保所有类别的后验概率加起来等于1。在分类任务中,对于所有类别,P(X) 的值都是相同的。因此,在比较不同类别的后验概率 P(y∣X) 时,我们 只需要比较分子 P(X∣y)P(y) 的大小即可,可以忽略分母 P(X)。

所以,我们的目标简化为:计算每个类别 y 的 P(X∣y)P(y) 值,哪个类别的这个值最大,就预测样本属于哪个类别。

1.3条件独立性假设

计算似然性 P(X∣y) 看似简单,但 X 通常包含多个特征 (x1​,x2​,...,xn​)。

直接计算 P(x1​,x2​,...,xn​∣y) 是非常困难的,因为它需要考虑所有特征之间的复杂联合关系,这需要极大的数据集才能准确估计。

为了简化计算,"朴素"贝叶斯算法引入了一个关键的假设:

给定类别 y 的条件下,所有特征 X=(x1,x2,...,xn) 之间是相互条件独立的

这意味着:

二、朴素贝叶斯算法的几种常见类型

朴素贝叶斯算法的核心思想基于 贝叶斯定理特征条件独立性假设

不同的朴素贝叶斯变体主要是因为它们对 特征数据的概率分布 P(xi​∣y) 做出了不同的假设。

根据特征数据类型的不同,最常见的朴素贝叶斯分类器有以下三种:

  • 高斯朴素贝叶斯 (Gaussian Naive Bayes)
  • 多项式朴素贝叶斯 (Multinomial Naive Bayes)
  • 伯努利朴素贝叶斯 (Bernoulli Naive Bayes)

2.1 高斯朴素贝叶斯 (Gaussian Naive Bayes)

主要用于处理连续型特征

【训练阶段】 - 从数据中学习模型参数

1.计算先验概率 P(y)

  • 统计训练数据中每个类别 y出现了多少次。
  • 用每个类别的样本数除以总样本数,得到该类别的先验概率。
  • 公式:

2.按类别分组数据

  • 将训练数据按照类别标签分开,方便后续计算。

3.计算每个类别下每个特征的均值 μy,i​ 和标准差 σy,i​

对每一个类别 y:

  • 对该类别下的每一个连续特征 xi​:
    • 计算这个特征在 只属于类别 y 的样本 中的 平均值 μy,i
    • 计算这个特征在 只属于类别 y 的样本 中的 标准差 σy,i

​4.处理零标准差情况

  • 如果在某个类别 y 下,某个特征 xi 的所有值都完全相同,那么计算出的标准差 σy,i 会是 0。这在后续计算高斯概率密度时会导致除零错误。
  • 解决方法: 检查是否有 σy,i=0 的情况。如果存在,将其替换为一个非常小的正数,或者使用更复杂的方差平滑技术。

5.存储模型参数

  • 保存好计算出的所有类别的先验概率 P(y),以及每个类别下每个特征的均值 μy,i 和(处理过的)标准差 σy,i。

【预测阶段】 - 对新样本 Xnew​ 进行分类

假设新样本 Xnew​ 包含特征值 (x1​,x2​,...,xn​)

1.为每个可能的类别 y 计算得分

初始化得分: 通常取先验概率的对数:

累加特征的对数似然: 对于新样本中的 每一个连续特征 xi​

  • 取出训练阶段为类别 y 和特征 i 存储的均值 μy,i 和标准差 σy,i。
  • 使用 高斯概率密度函数 (PDF) 公式 计算该特征值 xi 在类别 y 模型下的概率密度:
  • 将计算得到的 logPDF(xi∣y) 加到对应类别 y 的得分上:

2.比较得分并预测

  • 对所有可能的类别 y 都执行完步骤 1 后,比较它们最终的 Score
  • 得分最高的那个类别,就是高斯朴素贝叶斯对新样本 Xnew 的预测结果。

2. 2 多项式朴素贝叶斯 (Multinomial Naive Bayes)

特征是离散的,通常表示某件事发生的次数或频率

【训练阶段】 - 学习模型参数

1.计算先验概率 P(y)

  • 同高斯朴素贝叶斯

2.按类别分组数据

  • 同高斯朴素贝叶斯

3.统计特征计数 Nyi​ 和总计数 Ny​

确定整个数据集的 特征词汇表(所有出现过的不同特征/单词)。

设词汇表大小(或总特征数)为 k。

对每一个类别 y:

  • 计算 Ny:该类别下 所有样本 中,所有特征 出现的 总次数 之和。
  • 对词汇表中的每一个特征 xi​:
    • 计算 Nyi:该类别下 所有样本 中,特征 xi 出现的 总次数

4.选择平滑参数 α

  • 通常使用拉普拉斯平滑,即 α=1

5.存储模型参数

保存先验概率 P(y),所有类别的总特征数 Ny​,每个类别下每个特征的计数 Nyi​,以及词汇表大小 k 和平滑参数 α。

【预测阶段】 - 对新样本 Xnew​ 进行分类

假设新样本 Xnew​ 由特征计数 (count(x1​),count(x2​),...,count(xk​)) 表示,其中 count(xi​) 是特征 i 在 Xnew​ 中出现的次数。

1.为每个可能的类别 y 计算得分

初始化得分:

累加特征的对数似然: 对于词汇表中的 每一个特征 xi​ (从 i=1 到 k):

  • 取出训练阶段为类别 y 存储的 Nyi, Ny
  • 使用 平滑公式计算条件概率 P(xi​∣y)
  • 获取该特征 xi 在 新样本 Xnew​ 中的计数 count(xi​)
  • 将该特征对得分的贡献(其计数值乘以其对数概率)累加到对应类别 y 的得分上:

这里体现了出现次数越多的特征,对总得分的影响越大

2.比较得分并预测

  • 比较所有类别的最终 Score
  • 得分最高的类别即为预测结果。

2.3 伯努利朴素贝叶斯 (Bernoulli Naive Bayes)

特征是二元的(0/1),表示某事物是否存在、发生与否。

【训练阶段】 - 学习模型参数

1.计算先验概率 P(y)

  • 同高斯朴素贝叶斯。

2.按类别分组数据

  • 同高斯朴素贝叶斯。

3.统计特征出现次数 Ny,xi​=1​ 和类别总数 Ny​

确定所有可能的二元特征列表

对每一个类别 y:

  • 计算 Ny:属于该类别的 样本总数

对每一个特征 xi​:

  • 计算 Ny,xi=1:在类别 y 的样本中,特征 xi 出现过(值为1)的样本数量

4.选择平滑参数 α

  • 通常 α=1

5.存储模型参数

  • 保存先验概率 P(y),每个类别下每个特征的出现次数 Ny,xi=1,以及每个类别的总样本数 Ny

【预测阶段】 - 对新样本 Xnew​ 进行分类

假设新样本 Xnew​ 由二元特征向量 (x1​,x2​,...,xk​) 表示,其中 xi​∈{0,1}。

1.为每个可能的类别 y 计算得分

初始化得分:

累加特征的对数似然: 对于 每一个特征 xi​ (从 i=1 到 k):

取出训练阶段为类别 y 存储的 Ny,xi​=1​ 和 Ny​

计算特征 i 在类别 y 下出现的概率 P(xi​=1∣y):

计算特征 i 在类别 y 下不出现的概率 P(xi​=0∣y)

根据新样本 Xnew​ 中特征 xi​ 的值,选择对应的概率并累加其对数:

  • 如果 Xnew 中 xi=1(特征出现),则
  • 如果 Xnew 中 xi=0(特征未出现),则

2.比较得分并预测

  • 比较所有类别的最终 Score
  • 得分最高的类别即为预测结果

三、实例:基于朴素贝叶斯的好瓜预测

目标是根据一系列已知特征,判断一个西瓜是"好瓜"(标记为"是")还是"坏瓜"(标记为"否")。

任务: 对一个给定的西瓜样本进行二分类(好瓜/坏瓜)

1.训练数据

数据集摘要:

  • 总样本数: 17
  • 好瓜 (是) 数量: 8
  • 坏瓜 (否) 数量: 9

2.测试数据

3.计算步骤

使用拉普拉斯平滑和高斯分布假设,方差使用N作为分母

计算后验概率

比较结果

计算出的 "好瓜=是" 的得分 (0.02177) 远大于 "好瓜=否" 的得分 (0.000036)

结论

根据朴素贝叶斯分类器的计算结果,对于测试样本 "测1"(特征为 青绿, 蜷缩, 浊响, 清晰, 凹陷, 硬滑, 密度=0.697, 含糖率=0.460),预测结果为 是 (好瓜)

4.代码实现

python 复制代码
import pandas as pd
import math

# 1. 数据准备 
data = {
    '色泽': ['青绿', '乌黑', '乌黑', '青绿', '浅白', '青绿', '乌黑', '乌黑', '乌黑', '青绿', '浅白', '浅白', '青绿', '浅白', '乌黑', '浅白', '青绿'],
    '根蒂': ['蜷缩', '蜷缩', '蜷缩', '蜷缩', '蜷缩', '稍蜷', '稍蜷', '稍蜷', '稍蜷', '硬挺', '硬挺', '蜷缩', '稍蜷', '稍蜷', '稍蜷', '蜷缩', '蜷缩'],
    '敲声': ['浊响', '沉闷', '浊响', '沉闷', '浊响', '浊响', '浊响', '浊响', '沉闷', '清脆', '清脆', '浊响', '浊响', '沉闷', '浊响', '浊响', '沉闷'],
    '纹理': ['清晰', '清晰', '清晰', '清晰', '清晰', '清晰', '稍糊', '清晰', '稍糊', '清晰', '模糊', '模糊', '稍糊', '稍糊', '清晰', '模糊', '稍糊'],
    '脐部': ['凹陷', '凹陷', '凹陷', '凹陷', '凹陷', '稍凹', '稍凹', '稍凹', '稍凹', '平坦', '平坦', '平坦', '凹陷', '凹陷', '稍凹', '平坦', '稍凹'],
    '触感': ['硬滑', '硬滑', '硬滑', '硬滑', '硬滑', '软粘', '软粘', '硬滑', '硬滑', '软粘', '软粘', '硬滑', '软粘', '硬滑', '软粘', '硬滑', '硬滑'],
    '密度': [0.697, 0.774, 0.634, 0.608, 0.556, 0.403, 0.481, 0.437, 0.666, 0.243, 0.245, 0.343, 0.639, 0.657, 0.360, 0.593, 0.719],
    '含糖率': [0.460, 0.376, 0.264, 0.318, 0.215, 0.237, 0.149, 0.211, 0.091, 0.267, 0.057, 0.099, 0.161, 0.198, 0.370, 0.042, 0.103],
    '好瓜': ['是', '是', '是', '是', '是', '是', '是', '是', '否', '否', '否', '否', '否', '否', '否', '否', '否']
}
df = pd.DataFrame(data)

# 定义离散和连续特征列名
discrete_cols = ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感']
continuous_cols = ['密度', '含糖率']
target_col = '好瓜'

# 2. 训练模型
# 计算先验概率 P(y)
prior_prob = df[target_col].value_counts(normalize=True).to_dict()

# 计算离散特征的条件概率 P(xi|y) - 使用拉普拉斯平滑
cond_prob_discrete = {}
for feature in discrete_cols:
    cond_prob_discrete[feature] = {}
    # 获取该特征的所有可能取值
    possible_values = df[feature].unique()
    k = len(possible_values) 

    for value in possible_values:
        cond_prob_discrete[feature][value] = {}
        for class_label in df[target_col].unique():
            # 获取目标类别的数据子集
            class_subset = df[df[target_col] == class_label]
            # 计算分子:(类别为y且特征为x的数量 + 1)
            count_feature_class = class_subset[class_subset[feature] == value].shape[0] + 1
            # 计算分母:(类别为y的数量 + k)
            count_class = class_subset.shape[0] + k
            cond_prob_discrete[feature][value][class_label] = count_feature_class / count_class

# 计算连续特征的均值和标准差,按类别分组
mean_std_continuous = {}
for feature in continuous_cols:
    mean_std_continuous[feature] = {}
    for class_label in df[target_col].unique():
        class_subset = df[df[target_col] == class_label]
        # 计算均值和标准差 (使用 N-1 作为分母,即样本标准差)
        mean = class_subset[feature].mean()
        std = class_subset[feature].std()
        # 防止标准差为0 (如果某类下某个连续特征值都一样)
        if std == 0:
            std = 1e-6 
        mean_std_continuous[feature][class_label] = {'mean': mean, 'std': std}

# 高斯概率密度函数
def gaussian_pdf(x, mean, std):
    exponent = math.exp(-((x - mean) ** 2 / (2 * std ** 2)))
    return (1 / (math.sqrt(2 * math.pi) * std)) * exponent

# 3. 预测函数 (Prediction Function)
def predict_watermelon(test_data):
    scores = {}
    # 遍历每个类别 ('是', '否')
    for class_label in prior_prob.keys():
        # 初始化得分为该类别的先验概率 P(y)
        score = math.log(prior_prob[class_label])

        # 计算离散特征的条件概率连乘 (对数形式下为连加)
        for feature in discrete_cols:
            value = test_data[feature]
            if value in cond_prob_discrete[feature]:
                 score += math.log(cond_prob_discrete[feature][value][class_label])
            else:
                score += math.log(1e-9) 


        # 计算连续特征的高斯概率密度连乘 (对数形式下为连加)
        for feature in continuous_cols:
            x = test_data[feature]
            stats = mean_std_continuous[feature][class_label]
            pdf = gaussian_pdf(x, stats['mean'], stats['std'])
            if pdf > 0:
                 score += math.log(pdf)
            else:
                 score += math.log(1e-9)

        scores[class_label] = score

    # 返回得分最高的类别
    prediction = max(scores, key=scores.get)
    return prediction, scores

# 4. 进行预测 
test_sample = {
    '色泽': '青绿',
    '根蒂': '蜷缩',
    '敲声': '浊响',
    '纹理': '清晰',
    '脐部': '凹陷',
    '触感': '硬滑',
    '密度': 0.697,
    '含糖率': 0.460
}

# 调用预测函数
prediction, scores = predict_watermelon(test_sample)

print(f"\n测试样本: {test_sample}")
print(f"预测结果: {prediction}")
print(f"各类别的对数得分: {scores}")

四、学习总结

通过学习,我清晰了整个朴素贝叶斯算法的运作流程:从训练数据中学习先验概率 P(y) 和所有特征的条件概率(或相关统计量)P(xi​∣y),到预测阶段将这些概率(通常是以对数形式来保证数值稳定性)组合起来,计算出每个类别的最终得分,最后基于得分比较做出分类决策。

朴素贝叶斯算法的优点在于简单高效、对小数据集表现良好、对噪声鲁棒,适合快速建模场景(如西瓜预测和垃圾邮件分类)。但其缺点也很明显:特征独立性假设不现实、对数据分布敏感、分类能力有限。针对这些缺点,可通过特征工程、分布变换或模型改进提升性能。

相关推荐
C_VuI3 分钟前
如何安装cuda版本的pytorch
人工智能·pytorch·python
Star abuse6 分钟前
机器学习基础课程-6-课程实验
人工智能·python·机器学习
代码小将23 分钟前
力扣992做题笔记
算法·leetcode
编程绿豆侠25 分钟前
力扣HOT100之二叉树:199. 二叉树的右视图
算法·leetcode·职场和发展
知舟不叙1 小时前
基于OpenCV的人脸微笑检测实现
人工智能·opencv·计算机视觉·人脸微笑检测
Panesle1 小时前
开源的跨语言GUI元素理解8B大模型:AgentCPM-GUI
人工智能·开源·大模型·多模态·生成模型
Seeklike1 小时前
本地部署Firecrawl+Dify调用踩坑记录
人工智能·aigc·dify·firecrawl
飞川撸码1 小时前
【LeetCode 热题100】17:电话号码的字母组合(详细解析)(Go语言版)
算法·leetcode·golang·dfs
蒟蒻小袁1 小时前
力扣面试150题--从前序与中序遍历序列构造二叉树
算法·leetcode·面试
说私域1 小时前
开源AI大模型等“神秘组合”,如何颠覆零售业数字化转型?
人工智能·小程序·开源·流量运营·零售