GaussianNB原理解释和代码复现

本文介绍了GaussianNB(高斯朴素贝叶斯)算法,包括其概念、伪代码和计算过程。通过实例展示了如何计算先验概率、均值和方差,并封装成自定义分类器。此外,文章还使用sklearn库的GaussianNB进行比较,并对数据集进行训练和预测,以验证实现的正确性。
摘要由CSDN通过智能技术生成

前言

多加学习和理解不同机器学习算法,因此写下这篇关于GaussianNB(高斯朴素贝叶斯)算法的详细伪代码以及计算过程。


一、GaussianNB

1.1 GaussianNB是什么?

高斯朴素贝叶斯,特征变量是连续变量,符合高斯分布,比如说花的宽度高度以及寿命的长度。
在这里插入图片描述

1.2 GaussianNB伪代码

下面是 GaussianNB(高斯朴素贝叶斯)算法的详细伪代码和计算过程:

输入:训练集 D = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x n , y n ) } D = \{(x_1, y_1), (x_2, y_2), ..., (x_n, y_n)\} D={(x1,y1),(x2,y2),...,(xn,yn)},其中 x i = ( x i 1 , x i 2 , . . . , x i d ) x_i = (x_{i1}, x_{i2}, ..., x_{id}) xi=(xi1,xi2,...,xid) d d d 维特征向量, y i y_i yi 是样本的类别, y i ∈ { c 1 , c 2 , . . . , c k } y_i \in \{c_1, c_2, ..., c_k\} yi{c1,c2,...,ck}
输出:GaussianNB 分类模型。

  1. 对于每个类别 c j c_j cj

    • 计算先验概率 P ( y = c j ) = ∑ i = 1 n I ( y i = c j ) n P(y = c_j) = \frac{\sum_{i=1}^n I(y_i = c_j)}{n} P(y=cj)=ni=1nI(yi=cj),其中 I I I 是指示函数。
    • 对于每个特征维度 j j j
      • 计算该类别在每个特征维度上的均值 μ j = ∑ i = 1 n x i j I ( y i = c j ) ∑ i = 1 n I ( y i = c j ) \mu_{j} = \frac{\sum_{i=1}^n x_{ij} I(y_i = c_j)}{\sum_{i=1}^n I(y_i = c_j)} μj=i=1nI(yi=cj)i=1nxijI(yi=cj) 和方差 σ j 2 = ∑ i = 1 n ( x i j − μ j ) 2 I ( y i = c j ) ∑ i = 1 n I ( y i = c j ) \sigma_{j}^2 = \frac{\sum_{i=1}^n (x_{ij} - \mu_{j})^2 I(y_i = c_j)}{\sum_{i=1}^n I(y_i = c_j)} σj2=i=1nI(yi=cj)i=1n(xijμj)2I(yi=cj)
  2. 返回模型,包括先验概率 P ( y = c j ) P(y = c_j) P(y=cj) 和每个特征维度的高斯分布参数 ( μ j , σ j 2 ) (\mu_{j}, \sigma_{j}^2) (μj,σj2)

  3. 对于新样本 x ^ \hat{x} x^ 的分类:

    • 对于每个类别 c j c_j cj
      • 计算后验概率 P ( c j ∣ x ^ ) = P ( y = c j ) ∏ i = 1 d 1 2 π σ j i 2 exp ⁡ ( − ( x ^ i − μ j i ) 2 2 σ j i 2 ) P(c_j | \hat{x}) = P(y = c_j) \prod_{i=1}^d \frac{1}{\sqrt{2\pi\sigma_{ji}^2}} \exp\left(-\frac{(\hat{x}_i - \mu_{ji})^2}{2\sigma_{ji}^2}\right) P(cjx^)=P(y=cj)i=1d2πσji2 1exp(2σji2(x^iμji)2)
    • 返回具有最大后验概率的类别作为预测结果。

接下来,我们详细解释一下伪代码中各个步骤的计算过程:

  1. 计算先验概率 P ( y = c j ) P(y = c_j) P(y=cj)

    • 统计训练集中属于类别 c j c_j cj 的样本数量并除以总样本数 n n n
  2. 计算均值和方差:

    • 对于每个特征维度 j j j 和每个类别 c j c_j cj
      • 统计属于类别 c j c_j cj 的样本在特征维度 j j j 上的取值,并计算均值 μ j \mu_{j} μj 和方差 σ j 2 \sigma_{j}^2 σj2
        • 计算均值 μ j \mu_{j} μj:将属于类别 c j c_j cj 的样本在特征维度 j j j 上的取值求和,并除以属于类别 c j c_j cj 的样本数。
        • 计算方差 σ j 2 \sigma_{j}^2 σj2:将属于类别 c j c_j cj 的样本在特征维度 j j j 上的取值与均值 μ j \mu_{j} μj 的差的平方求和,并除以属于类别 c j c_j cj 的样本数。
  3. 返回模型:

    • 将先验概率 P ( y = c j ) P(y = c_j) P(y=cj) 和每个特征维度的高斯分布参数 ( μ j , σ j 2 ) (\mu_{j}, \sigma_{j}^2) (μj,σj2) 组成分类模型。
  4. 对于新样本 x ^ \hat{x} x^ 的分类:

    • 对于每个类别 c j c_j cj
      • 计算后验概率 P ( c j ∣ x ^ ) P(c_j | \hat{x}) P(cjx^)
        • 计算高斯概率密度函数 1 2 π σ j i 2 exp ⁡ ( − ( x ^ i − μ j i ) 2 2 σ j i 2 ) \frac{1}{\sqrt{2\pi\sigma_{ji}^2}} \exp\left(-\frac{(\hat{x}_i - \mu_{ji})^2}{2\sigma_{ji}^2}\right) 2πσji2 1exp(2σji2(x^iμji)2),其中 x ^ i \hat{x}_i x^i 是新样本在特征维度 i i i 上的取值, μ j i \mu_{ji} μji 是类别 c j c_j cj 在特征维度 i i i 上的均值, σ j i 2 \sigma_{ji}^2 σji2 是类别 c j c_j cj 在特征维度 i i i 上的方差。
        • 将每个特征维度上的高斯概率密度函数相乘,再乘以先验概率 P ( y = c j ) P(y = c_j) P(y=cj),得到后验概率 P ( c j ∣ x ^ ) P(c_j | \hat{x}) P(cjx^)
    • 返回具有最大后验概率的类别作为预测结果。

1.3 简化的数据集来说明 GaussianNB 算法的计算过程

假设我们有一个简单的数据集 D,包含两个特征 X1 和 X2,以及对应的类别标签Y。

训练数据集 D:D = { (x1=(0.5, 1.7), y=0), (x2=(1.2, 0.8), y=0), (x3=(2.0, 1.9), y=1), (x4=(3.3, 2.4), y=1) }

计算每个类别的先验概率 P(Y = c):在这个例子中,类别为 0 的样本数量为 2,类别为 1 的样本数量为 2,所以先验概率为 P(Y = 0) = 2/4 = 0.5,P(Y = 1) = 2/4 = 0.5。

计算每个类别在每个特征上的均值和方差:

对于特征 X1:
类别 0 在特征 X1 上的均值 mu[0][1] = (0.5 + 1.2) / 2 = 0.85
类别 0 在特征 X1 上的方差 sigma[0][1] = ((0.5 - 0.85)^2 + (1.2 - 0.85)^2) / 2 ≈ 0.1025
类别 1 在特征 X1 上的均值 mu[1][1] = (2.0 + 3.3) / 2 = 2.65
类别 1 在特征 X1 上的方差 sigma[1][1] = ((2.0 - 2.65)^2 + (3.3 - 2.65)^2) / 2 ≈ 0.7225

对于特征 X2:
类别 0 在特征 X2 上的均值 mu[0][2] = (1.7 + 0.8) / 2 = 1.25
类别 0 在特征 X2 上的方差 sigma[0][2] = ((1.7 - 1.25)^2 + (0.8 - 1.25)^2) / 2 ≈ 0.2025
类别 1 在特征 X2 上的均值 mu[1][2] = (1.9 + 2.4) / 2 = 2.15
类别 1 在特征 X2 上的方差 sigma[1][2] = ((1.9 - 2.15)^2 + (2.4 - 2.15)^2) / 2 ≈ 0.0425

对于测试样本 x=(2.8, 2.1),使用高斯朴素贝叶斯分类器进行预测:将 x=(2.8, 2.1) 带入高斯朴素贝叶斯分类器,计算其属于类别 0 和类别 1 的概率:

对于类别 0:
prob_0 = P(Y = 0) * P(X1 = 2.8 | Y = 0) * P(X2 = 2.1 | Y = 0)
≈ 0.5 * 0.6244 * 0.3492 ≈ 0.1089

对于类别 1:
prob_1 = P(Y = 1) * P(X1 = 2.8 | Y = 1) * P(X2 = 2.1 | Y = 1)
≈ 0.5 * 0.0074 * 0.1089 ≈ 0.00040125

由于 prob_0 > prob_1,所以预测样本 x=(2.8, 2.1) 属于类别 0。

二、复现并检验

2.1 复现并封装为类

代码如下(示例):

import numpy as np
from scipy.stats import norm
from sklearn.metrics import accuracy_score


class MYGaussianNB:
    def fit(self, X, y):
        #训练数据为一个二维数组,其中每一行是一个样本的特征向量。标签是一个一维数组
        self.classes = np.unique(y)                      # 类别
        self.class_priors = np.zeros(len(self.classes))  # 每个类别的先验概率
        self.means = {}                                  # 每个类别都有个array储存每个特征的均值
        self.variances = {}                              # 每个类别都有个array储存每个特征的方差

        for i, class_name in enumerate(self.classes):
            class_indices = y == class_name              # 为True的索引表示为是该类的样本所在的索引
            class_X = X[class_indices]                   # 根据索引获取该类所有样本
            self.class_priors[i] = len(class_X) / len(X) # 获取该类的先验概率
            self.means[class_name] = np.mean(class_X, axis=0) # 求出该类样本所有特征下的均值
            self.variances[class_name] = np.var(class_X, axis=0)# 求出该类样本所有特征下的方差

    def predict(self, X):
        y_pred = []  # 创建一个空列表,用于存储预测结果
        for x in X:  # 对输入的每个样本进行遍历
            class_scores = []  # 创建一个空列表,用于存储每个类别的得分
            for i, class_name in enumerate(self.classes): # 遍历每个类别和其索引
                prior = self.class_priors[i]              # 获取当前类别的先验概率
                mean = self.means[class_name]             # 获取当前类别的均值
                variance = self.variances[class_name]     # 获取当前类别的方差
                likelihood = norm.pdf(x, loc=mean, scale=np.sqrt(variance))  
                                                          # 计算当前样本在当前类别下的似然概率
                score = prior * np.prod(likelihood)       # 计算当前样本在当前类别下的得分(先验概率乘以似然概率)
                class_scores.append(score)                # 将当前类别的得分添加到列表中
            y_pred.append(self.classes[np.argmax(class_scores)])  # 将具有最高得分的类别作为预测结果添加到列表中
        return y_pred  # 返回预测结果列表

2.2 读入数据用作检验

代码如下(示例):

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# 加载燕尾花数据集
iris = load_iris()

# 获取特征数据和标签数据
X = iris.data
y = iris.target

# 将数据集切分为训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=3220822)

# 打印切分后的数据集大小
print("训练集大小:", x_train.shape[0])
print("测试集大小:", x_test.shape[0])

2.3 sklearn自带GaussianNB

from sklearn.naive_bayes import GaussianNB
# 创建高斯朴素贝叶斯模型对象
model = GaussianNB()
# 模型训练
model.fit(x_train, y_train)
# 预测
y_pred = model.predict(x_test)
# 评估模型
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

在这里插入图片描述

2.4 调用复现GaussianNB

# 创建 GaussianNB 分类器并训练
classifier = MYGaussianNB()
classifier.fit(x_train, y_train)

# 进行预测
y_pred = classifier.predict(x_test)
accuracy = accuracy_score(y_test, y_pred)
accuracy

在这里插入图片描述

总结

在这里给出了sklearn库的GaussianNB类与编写的MYGaussianNB类,使用了相同数据集进行验证。同时在前面给出了该算法的伪代码和实际小例运算,方便读者们更好的理解。

  • 16
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值