机器学习原理到Python代码实现之NaiveBayes【朴素贝叶斯】

news2024/9/20 8:52:33

Naive Bayes 朴素贝叶斯算法

该文章作为机器学习的第二篇文章,主要介绍的是朴素贝叶斯算法的原理和应用。学习本章内容建议对概率论中的联合概率以及先验概率、后验概率有初步的学习和掌握。

难度系数:⭐⭐⭐

更多相关工作请参考:Github

算法介绍

朴素贝叶斯算法是一种基于概率论的分类算法 ,它假设特征之间是独立的,即特征之间没有关联关系。朴素贝叶斯算法通过计算每个类别的概率来对新的样本进行分类。

算法原理解析

贝叶斯定理

贝叶斯定理是概率论中的核心概念,用于描述当存在新的信息或数据时,如何更新对某一事件或参数的信念。具体来说,它提供了从条件概率和先验概率推导出后验概率的公式。

贝叶斯定理的公式为: P ( A ∣ B ) = ( P ( B ∣ A ) ∗ P ( A ) ) / P ( B ) P(A|B) = (P(B|A) * P(A)) / P(B) P(AB)=(P(BA)P(A))/P(B)。这个公式用于计算在给定事件B发生的情况下,事件A发生的概率,即后验概率。

其中:

  • P ( A ∣ B ) P(A|B) P(AB): 这是我们要求的后验概率,即在事件B已经发生的情况下,事件A发生的概率。
  • P ( B ∣ A ) P(B|A) P(BA): 这是条件概率,表示在事件A发生的情况下,事件B发生的概率。
  • P ( A ) P(A) P(A): 这是事件A的先验概率,即在没有任何额外信息的情况下,事件A发生的概率。
  • P ( B ) P(B) P(B): 这是事件B的先验概率,即在没有任何额外信息的情况下,事件B发生的概率。

贝叶斯定理的公式用于计算后验概率,即根据新的证据或数据,更新对事件A发生的信念。通过使用先验概率和条件概率,贝叶斯定理可以帮助我们在给定新信息的情况下,更准确地估计事件A发生的概率。

接下来是笔者的一些公式推导,在事件相互独立的情况下:

在B事件发生的情况下,A事件发生的概率为:

P ( A ∣ B ) = P ( A ∩ B ) / P ( B ) P(A|B) = P(A \cap B) / P(B) P(AB)=P(AB)/P(B)

在A事件发生的情况下,B事件发生的概率为:

P ( B ∣ A ) = P ( A ∩ B ) / P ( A ) P(B|A) = P(A \cap B) / P(A) P(BA)=P(AB)/P(A)

通过 P ( A ∩ B ) P(A \cap B) P(AB)作为桥梁,化简公式,我们便得到的公式:

P ( A ∣ B ) = ( P ( B ∣ A ) ∗ P ( A ) ) / P ( B ) P(A|B) = (P(B|A) * P(A)) / P(B) P(AB)=(P(BA)P(A))/P(B)

传统版本

朴素贝叶斯算法是一种基于贝叶斯定理与特征条件独立假设的分类方法。这种算法有坚实的数学基础,分类效率相对稳定。从数学角度看,朴素贝叶斯算法主要应用了贝叶斯定理。

朴素贝叶斯算法利用了贝叶斯定理来计算样本属于某个类别的概率。具体来说,对于一个样本 x x x,假设它属于类别 c c c的概率 P ( c ∣ x ) P(c|x) P(cx)可以由以下公式计算:
P ( c ∣ x ) = P ( c ) ∗ P ( x ∣ c ) / P ( x ) P(c|x) = P(c) * P(x|c) / P(x) P(cx)=P(c)P(xc)/P(x)
其中 P ( c ) P(c) P(c)是类别 c c c的先验概率,即该类别在训练集中的比例; P ( x ∣ c ) P(x|c) P(xc)是在类别 c c c的条件下 x x x出现的概率; P ( x ) P(x) P(x) x x x在训练集中的总概率。

朴素贝叶斯算法的核心思想是假设特征之间相互独立,即 P ( x ∣ c ) P(x|c) P(xc)可以分解为各个特征的条件概率的乘积。具体来说,如果 x x x是一个 n n n维特征向量,即 x = ( x 1 , x 2 , . . . , x n ) x=(x1,x2,...,xn) x=(x1,x2,...,xn),那么 P ( x ∣ c ) P(x|c) P(xc)可以表示为:
P ( x ∣ c ) = P ( x 1 ∣ c ) ∗ P ( x 2 ∣ c ) ∗ . . . ∗ P ( x n ∣ c ) P(x|c) = P(x1|c) * P(x2|c) * ... * P(xn|c) P(xc)=P(x1∣c)P(x2∣c)...P(xnc)
其中 P ( x i ∣ c ) P(xi|c) P(xic)是在类别 c c c的条件下特征 x i xi xi出现的概率。

故事版本

首先,朴素贝叶斯算法是一种基于贝叶斯定理的分类方法。贝叶斯定理是用来计算某个事件发生的概率,基于这个事件已经发生和还没有发生的概率。

为了让你更好地理解,让我们用生活中的一个例子来说明:

假设你有一个朋友,他是个图书管理员。他可以根据一本书的封面来判断这本书是否是儿童书。怎么做到的呢?

  1. 属性选择:他首先会看书的几个关键特征,例如书的颜色、封面的图案和标题等。这些都是他判断的“属性”。
  2. 概率计算:基于他的经验,他知道某种颜色或图案更有可能出现在儿童书中。这就是他基于这些属性计算出的不同类型书籍的概率。
  3. 分类决策:当一本书放在他面前时,他会根据这些属性(颜色、图案等)来判断这本书是否是儿童书。

这就是朴素贝叶斯算法的核心思想:基于已知属性来预测或分类一个事件或对象。

但为什么叫“朴素”呢?因为这种方法有一个前提假设,那就是每个属性之间是相互独立的。这意味着书的不同属性(例如颜色和图案)不会相互影响,也就是说,一个书不会因为它是红色且有一个星星图案就更有可能是儿童书,如果这两个特征在之前的样本中没有同时出现过,这个假设就不成立。但为了简化计算,我们通常会做这个假设。

数学原理

基于离散特征的朴素贝叶斯算法

我们要从数学角度推导如何在具备 N N N个特征的数据集上,通过朴素贝叶斯实现分类。

首先,我们需要了解几个关键概念:

特征:数据集中的每个独立变量。
类别:数据集中的目标变量或分类。
概率:某一事件发生的可能性。
朴素贝叶斯:基于贝叶斯定理和特征独立假设的分类方法。
现在,我们开始推导:

第一步,设数据集有 N N N个特征,记作 ( X 1 , X 2 , . . . , X N ) (X_1, X_2, ..., X_N) (X1,X2,...,XN)

第二步,设目标类别有M种,记作 ( C 1 , C 2 , . . . , C M ) (C_1, C_2, ..., C_M) (C1,C2,...,CM)

第三步,基于贝叶斯定理,对于给定的类别 ( C k ) (C_k) (Ck),一个样本 ( X ) (X) (X) 属于 ( C k ) (C_k) (Ck) 的概率可以表示为:
P ( C k ∣ X 1 , X 2 , . . . , X N ) = P ( C k ) × P ( X 1 ∣ C k ) × P ( X 2 ∣ C k ) × . . . × P ( X N ∣ C k ) P ( X 1 ) × P ( X 2 ) × . . . × P ( X N ) P(C_k | X_1, X_2, ..., X_N) = \frac{P(C_k) \times P(X_1 | C_k) \times P(X_2 | C_k) \times ... \times P(X_N | C_k)}{P(X_1) \times P(X_2) \times ... \times P(X_N)} P(CkX1,X2,...,XN)=P(X1)×P(X2)×...×P(XN)P(Ck)×P(X1Ck)×P(X2Ck)×...×P(XNCk)
其中, P ( C k ) P(C_k) P(Ck) 是类别 C k C_k Ck 的先验概率, P ( X i ∣ C k ) P(X_i | C_k) P(XiCk) 是特征 ( X i ) (X_i) (Xi) 在类别 ( C k ) (C_k) (Ck) 下的条件概率。

第四步,由于我们假设特征之间是独立的,所以:
P ( X ∣ C ) = P ( X 1 ∣ C ) × P ( X 2 ∣ C ) × . . . × P ( X N ∣ C ) P(X | C) = P(X_1 | C) \times P(X_2 | C) \times ... \times P(X_N | C) P(XC)=P(X1C)×P(X2C)×...×P(XNC)
P ( X ) = P ( X 1 ) × P ( X 2 ) × . . . × P ( X N ) P(X) = P(X_1) \times P(X_2) \times ... \times P(X_N) P(X)=P(X1)×P(X2)×...×P(XN)

第五步,将第四步的结论代入第三步的公式,得到:
P ( C k ∣ X ) = P ( C k ) × P ( X ∣ C k ) P ( C 1 ) × P ( X ∣ C 1 ) + P ( C 2 ) × P ( X ∣ C 2 ) + . . . + P ( C M ) × P ( X ∣ C M ) P(C_k | X) = \frac{P(C_k) \times P(X | C_k)}{P(C_1) \times P(X | C_1) + P(C_2) \times P(X | C_2) + ... + P(C_M) \times P(X | C_M)} P(CkX)=P(C1)×P(XC1)+P(C2)×P(XC2)+...+P(CM)×P(XCM)P(Ck)×P(XCk)
第六步,由于我们通常无法得知真实的概率值,因此需要使用已知的训练数据集来估计这些概率。具体来说,对于类别 ( C k ) (C_k) (Ck) 和特征 ( X i ) (X_i) (Xi),我们有:
P ( C k ) = 样本中属于 C k 的样本数 总样本数 P(C_k) = \frac{\text{样本中属于} C_k \text{的样本数}}{\text{总样本数}} P(Ck)=总样本数样本中属于Ck的样本数
P ( X i ∣ C k ) = 属于 C k 且具有 X i 的样本数 属于 C k 的样本数 P(X_i | C_k) = \frac{\text{属于} C_k \text{且具有} X_i \text{的样本数}}{\text{属于} C_k \text{的样本数}} P(XiCk)=属于Ck的样本数属于Ck且具有Xi的样本数
第七步,最后,为了得到每个类别被选中的概率,我们将每个类别的概率除以所有类别的概率之和。即:
P ( C k ∣ X ) = P ( C k ) P ( C 1 ) + P ( C 2 ) + . . . + P ( C M ) × P ( X ∣ C k ) P(C_k | X) = \frac{P(C_k)}{P(C_1) + P(C_2) + ... + P(C_M)} \times P(X | C_k) P(CkX)=P(C1)+P(C2)+...+P(CM)P(Ck)×P(XCk)
这就是朴素贝叶斯分类器的数学推导过程。通过这个过程,我们可以使用已知的训练数据集来估计每个类别的概率和每个特征在每个类别下的条件概率,然后使用这些估计值来预测新的未知样本的类别。

基于连续特征的朴素贝叶斯算法

对于连续特征,朴素贝叶斯分类器可以采用两种方式进行处理。第一种方法是将连续的数据离散化,然后用相应的离散区间替换连续数值。然而,这种方法对于划分离散区间的粒度要求较高,不能太细,也不能太粗。

第二种方法是假设连续数据服从某个概率分布,使用训练数据估计分布参数。通常我们用高斯分布(正态分布)来表示连续数据的类条件概率分布。具体来说,我们可以计算每个特征在每个类别中的均值和标准差,然后使用这些参数来评估给定特征值在该类别中的概率。这种方法在计算后验概率时更加准确。

如果数据是连续的并且特征之间存在顺序关系(例如身高、体重、脚掌长度等),可以假设这些特征服从正态分布,并通过计算训练样本中各个类别中此特征的均值和标准差来得到正态分布的密度函数。然后使用该密度函数来评估给定特征值的概率。

数据集介绍

鸢尾花(Iris)数据集是一个常用的分类实验数据集,由Fisher在1936年收集整理。该数据集包含150个样本,每个样本有四个属性:花萼长度、花萼宽度、花瓣长度和花瓣宽度,这四个属性用于预测鸢尾花属于Setosa、Versicolour或Virginica三个种类中的哪一类。

鸢尾花数据集的特点是具有多重变量,即每个样本都有多个特征,这使得它成为进行多元分类任务的一个理想选择。通过分析这些特征,可以了解不同鸢尾花品种之间的差异,并建立分类器来自动识别未知样本的种类。

鸢尾花数据集的来源是实际的鸢尾花测量数据,因此它具有实际背景和应用价值。这个数据集经常被用于机器学习和数据挖掘算法的实验和验证,因为它提供了多变量分析的一种有效方式。

在本次朴素贝叶斯分类中,我们计划采用这个数据集作为我们的实验对象。

代码实现

# 准备好我们需要使用的第三方包
import os
import numpy as np
import pandas as pd
from scipy.stats import norm
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap

数据分析

首先,我们加载数据集,并展示一下数据的格式:

column_names=['SepalLength','SepalWidth','PetalLength', 'PetalWidth','Species']
train_dataset = pd.read_csv('dataset\\iris_training.csv', header=0, names=column_names)
test_dataset = pd.read_csv('dataset\\iris_test.csv', header=0, names=column_names)
train_dataset.info()
train_dataset.head()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 120 entries, 0 to 119
Data columns (total 5 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   SepalLength  120 non-null    float64
 1   SepalWidth   120 non-null    float64
 2   PetalLength  120 non-null    float64
 3   PetalWidth   120 non-null    float64
 4   Species      120 non-null    int64  
dtypes: float64(4), int64(1)
memory usage: 4.8 KB
SepalLengthSepalWidthPetalLengthPetalWidthSpecies
06.42.85.62.22
15.02.33.31.01
24.92.54.51.72
34.93.11.50.10
45.73.81.70.30

接下来,我们可以对每个维度的特征进行统计分析,例如计算每个维度的均值、标准差、最大值、最小值等。并通过作图的方式来展示特征与类别之间的关系:

def feature_analysis(X, Y):
    """输入特征X与类别标签Y,分析特征的均值、标准差、最大值、最小值,
    并绘制散点图来表示每个维度特征与类别之间的关系存在四个特征,
    故制作一个画布,绘制一张2x2的子图来展示每个特征

    Args:
        X (pd.DataFrame): 输入的特征数据
        Y (pd.DataFrame): 特征对应的标签
    """
    # 设置颜色及子图的大小
    color = ListedColormap(['red', 'green', 'blue'])
    fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 10))
    data_info = {}
    # 遍历每个特征
    for i, feature in enumerate(X.columns):
        data_info[feature] = {
            "mean": X[feature].mean(),
            "std": X[feature].std(),
            "min": X[feature].min(),
            "max": X[feature].max()
        }
        # 绘制散点图来表示每个维度特征与类别之间的关系存在四个特征
        axes[i // 2, i % 2].scatter(X[feature], Y, c=Y, cmap=color)
        axes[i // 2, i % 2].set_title(feature)
        axes[i // 2, i % 2].set_xlabel(feature)
        axes[i // 2, i % 2].set_ylabel('Species')
    plt.tight_layout()
    plt.show()

    # 绘制两两特征之间的散点图
    fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(12, 9))
    for i, feature_x in enumerate(X.columns):
        for j, feature_y in enumerate(X.columns):
            if i != j:
                y = i if i < j else i-1
                axes[j, y].scatter(X[feature_x], X[feature_y], c=Y, cmap=color)
                axes[j, y].set_title(feature_x + ' vs ' + feature_y)
                axes[j, y].set_xlabel(feature_x)
                axes[j, y].set_ylabel(feature_y)
    plt.tight_layout()
    plt.show()


    for key, value in data_info.items():
        print("[%12s] mean:%7.5f std:%7.5f max:%7.5f min:%7.5f" % (key, value['mean'], value['std'], value['max'], value['min']))
    

feature_analysis(train_dataset.iloc[:, :-1], train_dataset.iloc[:, -1])


在这里插入图片描述
在这里插入图片描述

[ SepalLength] mean:5.84500 std:0.86858 max:7.90000 min:4.40000
[  SepalWidth] mean:3.06500 std:0.42716 max:4.40000 min:2.00000
[ PetalLength] mean:3.73917 std:1.82210 max:6.90000 min:1.00000
[  PetalWidth] mean:1.19667 std:0.78204 max:2.50000 min:0.10000

从展示的图像中我们可以看到不同特征与类别之间的关系。也可以看出两两特征在组合后所呈现的特征关系,这些都与我们后续的朴素贝叶斯算法有关系。

构建朴素贝叶斯算法

我们将继续从自己构建和调用sklearn两种模式来为大家呈现这个算法的实现。

基础实现

朴素贝叶斯算法在自我实现的时候需要考虑到,我们在构建NaiveBayes模型的时候,需要考虑到有以下的功能:

  1. 算法的训练
  2. 算法的预测
  3. 算法的评估

接下来,我们开始构建属于我们自己的朴素贝叶斯算法:

class NaiveBayes:
    def __init__(self):
        self.class_prob = None
        self.class_cond_prob = None
        self.discretization = None
        self.n_classes = None

    # 该函数将输入某一个维度的连续特征,将返回服从高斯分布的特征参数
    def gaussian_process(self, feature):
        # feature是pd.DataFrame
        mean = feature.mean()
        std = feature.std()
        return mean, std
    
    # 该函数将输入某一个维度的连续特征,将返回划分区域的area个区域,同时需要考虑到在feature分布外的数据[-inf, inf]
    def zoning_process(self, feature, area=5):
        # feature是pd.DataFrame
        min_value = feature.min() - 0.01
        max_value = feature.max() + 0.01
        step = (max_value - min_value) / (area - 2)
        # 划分区域
        zones = []
        for i in range(area):
            if i == 0:
                zones.append([float("-inf"), min_value])
            elif i == area-1:
                zones.append([max_value, float("inf")])
            else:
                zones.append([min_value + (i-1) * step, min_value + i * step])
        return zones

    # 模型的训练
    def fit(self, X, Y, discretization=False, area=0):
        # X是pd.DataFrame,Y是pd.Series
        self.discretization = discretization
        # 计算class_prob
        self.class_prob = Y.value_counts(normalize=True).to_dict()
        self.n_classes = len(self.class_prob.keys())

        # 计算class_mean
        self.class_cond_prob = {}
        for i in self.class_prob.keys():
            self.class_cond_prob[i] = {}
            for j, feature_name in enumerate(X.columns):
                if discretization and X[feature_name].dtype == "float64":
                    # 通过self.zoning的方法,将特征转换成离散的片段
                    # self.zoning的返回是Nx2的列表,代表区间的最小值和最大值
                    zones = self.zoning_process(X[feature_name], area)
                    self.class_cond_prob[i][feature_name] = {"type": "zoning", "zoning": {}}
                    for k, zone in enumerate(zones):
                        zone = tuple(zone)
                        self.class_cond_prob[i][feature_name]["zoning"][zone] = 0
                        # 筛选出Y中符合i的下标以及对应的X中的特征
                        index = (Y == i) & (X[feature_name] >= zone[0]) & (X[feature_name] < zone[1])
                        self.class_cond_prob[i][feature_name]["zoning"][zone] = X[feature_name][index].shape[0] / (Y == i).sum()
                elif not discretization and X[feature_name].dtype == "float64":
                    # 通过self.gaussian_process函数获得特征的均值和方法,获得高斯分布的特性
                    index = (Y == i)
                    mean, std = self.gaussian_process(X[feature_name][index])
                    self.class_cond_prob[i][feature_name] = {"type": "gaussian", "mean": mean, "std": std}
                else:
                    # 特征本身就是离散的
                    self.class_cond_prob[i][feature_name] = {"type": "discrete"}
                    for value in X[feature_name].unique():
                        self.class_cond_prob[i][feature_name][value] = 0
                        index = (Y == i) & (X[feature_name] == value)
                        self.class_cond_prob[i][feature_name][value] = X[feature_name][index].shape[0] / (Y == i).sum()

    def predict(self, X):
        # 通过朴素贝叶斯的方法预测结果
        # X是pd.DataFrame
        prediction = []
        for i in range(X.shape[0]):
            prob = np.ones(self.n_classes)
            for j in range(self.n_classes):
                for feature_name in X.columns:
                    if feature_name not in self.class_cond_prob[j]:
                        continue
                    if self.class_cond_prob[j][feature_name]["type"] == "discrete":
                        prob[j] *= self.class_cond_prob[j][feature_name][X.iloc[i, :][feature_name]]
                    elif self.class_cond_prob[j][feature_name]["type"] == "zoning":
                        for area, sub_prob in self.class_cond_prob[j][feature_name]["zoning"].items():
                            if X.iloc[i, :][feature_name] >= area[0] and X.iloc[i, :][feature_name] < area[1]:
                                prob[j] *= sub_prob
                    elif self.class_cond_prob[j][feature_name]["type"] == "gaussian":
                        mean = self.class_cond_prob[j][feature_name]["mean"]
                        std = self.class_cond_prob[j][feature_name]["std"]
                        prob[j] *= norm.pdf(X.iloc[i, :][feature_name], mean, std)
            prediction.append(np.argmax(prob))
        return pd.DataFrame(prediction)
    
    def score(self, pred, target):
        assert len(pred) == len(target), "The length of predictions and targets must be equal."
        # 计算pred 和 target 中相同元素的个数
        return (pred == target).sum() / len(pred)


以上是我们复现的朴素贝叶斯算法的代码,对于特征,我们提供了三种模式,其中对于离散特征,我们仅需要
将其映射到对应的类别即可;对于连续特征,我们提供了两种模式分别是gaussian_processzoning_process

  1. 对于zoning_process,我们将连续特征划分为不同的区间,然后在每个区间内使用不同的概率分布来建模。
  2. 对于gaussian_process,我们使用高斯分布来建模模拟概率分布。

以下是我们调用自己实现的朴素贝叶斯方法的流程:

naivebayes = NaiveBayes()
train_X, train_Y = train_dataset.iloc[:, :-1], train_dataset.iloc[:, -1]

# 采用zoning_process,划分5区间的朴素贝叶斯
naivebayes.fit(train_X, train_Y, discretization=True, area=4)
pred = naivebayes.predict(test_dataset.iloc[:, :-1])
score = naivebayes.score(pred.iloc[:, 0], test_dataset.iloc[:, -1])

print("zoning_process area:4 acc:", score)

# 采用zoning_process,划分5区间的朴素贝叶斯
naivebayes.fit(train_X, train_Y, discretization=True, area=8)
pred = naivebayes.predict(test_dataset.iloc[:, :-1])
score = naivebayes.score(pred.iloc[:, 0], test_dataset.iloc[:, -1])

print("zoning_process area:8 acc:", score)

# 采用zoning_process,划分5区间的朴素贝叶斯
naivebayes.fit(train_X, train_Y, discretization=True, area=12)
pred = naivebayes.predict(test_dataset.iloc[:, :-1])
score = naivebayes.score(pred.iloc[:, 0], test_dataset.iloc[:, -1])

print("zoning_process area:12 acc:", score)

# 采用gaussian_process方法处理
naivebayes.fit(train_X, train_Y, discretization=False)
pred = naivebayes.predict(test_dataset.iloc[:, :-1])
score = naivebayes.score(pred.iloc[:, 0], test_dataset.iloc[:, -1])

print("gaussian_process acc:", score)
zoning_process area:4 acc: 0.7
zoning_process area:8 acc: 1.0
zoning_process area:12 acc: 0.9
gaussian_process acc: 0.9666666666666667

由实验结果可知,并不是说划分区间的越多,分类的准确率越高。在采用划分区域方法的时候选择合适的区域数,比如在划分5区间的朴素贝叶斯中,选择8个区域数,分类的准确率最高。同时,在采用高斯分布方法处理数据的时候,分类的准确率会较高,但也不一定完全优于划分区域的方法。

sklearn调用朴素贝叶斯

接下来我们演示一下朴素贝叶斯在sklearn中的使用。

from sklearn.naive_bayes  import GaussianNB
clf = GaussianNB()
clf.fit(train_X, train_Y)
pred = clf.predict(test_dataset.iloc[:, :-1])
score = clf.score(test_dataset.iloc[:, :-1], test_dataset.iloc[:, -1])
print("Accuracy:", score)
Accuracy: 0.9666666666666667

需要注意的是,朴素贝叶斯的算法强调了每个特征之间是相互独立的,但现实中,特征之间可能存在一定的关联关系。故在使用时需要注意。

高阶实验

最后我们这里提供了一个全新的数据集Mobile_phone_price_range_estimate;相较于之前的数据集,这个数据集的属性更多,并且属性之间存在一定的关联关系。该数据集主要作用是用来对比朴素贝叶斯和其他算法的性能的,为大家对算法侧重有一定的理解。

train_dataset = pd.read_csv('dataset\\Mobile_phone_price_range_estimate_train.csv')
test_dataset = pd.read_csv('dataset\\Mobile_phone_price_range_estimate_test.csv')

naivebayes = NaiveBayes()

train_X, train_Y = train_dataset.iloc[:, 1:-1], train_dataset.iloc[:, -1]
# 采用zoning_process,划分5区间的朴素贝叶斯
naivebayes.fit(train_X, train_Y, discretization=True, area=4)
pred = naivebayes.predict(test_dataset.iloc[:, 1:-1])
score = naivebayes.score(pred.iloc[:, 0], test_dataset.iloc[:, -1])

print("zoning_process area:4 acc:", score)

# 采用zoning_process,划分8区间的朴素贝叶斯
naivebayes.fit(train_X, train_Y, discretization=True, area=8)
pred = naivebayes.predict(test_dataset.iloc[:, 1:-1])
score = naivebayes.score(pred.iloc[:, 0], test_dataset.iloc[:, -1])

print("zoning_process area:8 acc:", score)


# 采用zoning_process,划分12区间的朴素贝叶斯
naivebayes.fit(train_X, train_Y, discretization=True, area=12)
pred = naivebayes.predict(test_dataset.iloc[:, 1:-1])
score = naivebayes.score(pred.iloc[:, 0], test_dataset.iloc[:, -1])

print("zoning_process area:12 acc:", score)

# 采用gaussian_process方法处理
naivebayes.fit(train_X, train_Y, discretization=False)
pred = naivebayes.predict(test_dataset.iloc[:, 1:-1])
score = naivebayes.score(pred.iloc[:, 0], test_dataset.iloc[:, -1])

print("gaussian_process acc:", score)
zoning_process area:4 acc: 0.5375
zoning_process area:8 acc: 0.7275
zoning_process area:12 acc: 0.715
gaussian_process acc: 0.7725

总结

朴素贝叶斯算法是一种基于贝叶斯定理的分类方法,其核心思想是利用已知的一组条件独立假设,将复杂的联合概率分布简化,从而更高效地进行分类。该算法在许多领域都有广泛的应用,如文本分类、垃圾邮件过滤、情感分析等。

朴素贝叶斯算法的主要优点包括:

  1. 简单易理解: 朴素贝叶斯算法基于贝叶斯定理,因此其原理相对简单,容易理解。
  2. 高效: 由于该算法使用了条件独立假设,因此在计算概率时可以大大减少计算量,特别是当特征数量很大时,其效率更高。
  3. 对缺失值不敏感: 由于使用了条件独立假设,朴素贝叶斯算法对特征之间的相关性要求不高,因此对缺失值不敏感。
  4. 可扩展性强: 对于大量数据集,朴素贝叶斯算法可以很容易地进行扩展和改进。

然而,朴素贝叶斯算法也存在一些局限性:

  1. 对特征独立性假设的限制: 朴素贝叶斯算法的核心在于假设特征之间是独立的,但在实际应用中,这个假设往往不成立。这可能导致算法的性能受到限制。
  2. 对参数的依赖性: 朴素贝叶斯算法的性能高度依赖于参数的选择,如平滑参数的选择等。选择合适的参数值对于获得最佳分类效果至关重要。
  3. 对连续型特征的处理能力有限: 对于连续型特征,朴素贝叶斯算法通常采用离散化或分段的方式进行处理,这可能影响分类的准确性。

尽管存在这些局限性,朴素贝叶斯算法仍然是一种非常有价值的分类方法。在实际应用中,根据具体问题和数据集的特点,可以选择不同的朴素贝叶斯模型(如多项式朴素贝叶斯、伯努利朴素贝叶斯或高斯朴素贝叶斯)进行分类。同时,可以通过调整参数、特征选择和交叉验证等方法来提高算法的性能和准确性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1367696.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ELK的搭建—Elasticsearch-8.11.3的安装及集群的搭建

es的安装及其集群的搭建 一、Elasticsearch服务的安装部署1. Elasticsearch的rpm包下载2. 安装Elasticsearch服务3. 设置系统资源及内存大小分配4. Elasticsearch的配置修改 二、建立Elasticsearch集群1. 安装Elasticsearch主节点server12. 配置server1&#xff0c;及配置文件的…

Linux文件系统与日志服务管理

目录 一.Linux文件系统 1.inode表和block &#xff08;1&#xff09;inode &#xff08;2&#xff09;block 2.查看inode号命令 3.Linux系统文件三种主要时间属性 4.磁盘空间还剩余很多但无法继续创建文件 5.inode大小 二.日志 1.日志保存位置 2.日志文件的分类 &a…

Making Large Language Models Perform Better in Knowledge Graph Completion

Making Large Language Models Perform Better in Knowledge Graph Completion 基本信息 博客贡献人 鲁智深 作者 Yichi Zhang, Zhuo Chen, Wen Zhang, Huajun Chen 隶属于浙江大学计算机学院和软件学院 摘要 本文主要探讨了如何将有用的知识图谱结构信息融入大语言模型中…

使用Redhat操作系统下载MySQL

一、本地下载安装 方法一 ①在虚拟机火狐浏览器中搜索MySQL官网&#xff08;选择第一个下载&#xff09; ②下载完毕使用xshell远程连接解压及安装 [rootlocalhost ~]# cd /Downloads/ [rootlocalhost Downloads]# mkdir /mysql/ [rootlocalhost Downloads]# mv mysql-8.0.3…

12.字符串和正则表达式

使用正则表达式 正则表达式相关知识 在编写处理字符串的程序或网页时&#xff0c;经常会有查找符合某些复杂规则的字符串的需要&#xff0c;正则表达式就是用于描述这些规则的工具&#xff0c;换句话说正则表达式是一种工具&#xff0c;它定义了字符串的匹配模式&#xff08;…

25 心形按钮

效果演示 实现了一个心形的心形图案&#xff0c;当用户点击图案时&#xff0c;图案会旋转并缩小&#xff0c;同时背景颜色会变成白色。 Code <div class"love"><input id"switch" type"checkbox"><label class"love-heart&…

窗口超出屏幕拉不出来或移到屏幕边上的解决办法

前言 由于一些原因&#xff0c;比如进行远程电脑时屏幕大小不同&#xff0c;导致一些程序窗口超出屏幕拉不出来或移到屏幕边上&#xff0c; 我是在公司有个大屏幕&#xff0c;抱着笔记本回去之后&#xff0c;有个软件打开之后啥也没有。估计是跑到屏幕外了。 以下附上解决方法…

软件工程概论---内聚性和耦合性

目录 一.耦合性 1.内容耦合 2.公共耦合 4.控制耦合 5.标记耦合&#xff08;特征耦合&#xff09; 6.数据耦合 7.非直接耦合 二.内聚性 1.偶然内聚 2.逻辑内聚 3.时间内聚 4.过程内聚 5.通信内聚 6.顺序内聚 7.功能内聚 一.耦合性 耦合性是指软件结构中模块相互…

React 类组件和函数组件

组件component 一.概念 Element VS Component (元素与组件) //不成文的约定:元素小写&#xff0c;组件大写 const divReact.createElement(div,...) 这是一个React元素(小写) const Div()>React.createElement(div,...) 这是一个React组件(大写) 什么是组件? 能跟其他…

解决:已经安装open3d,还是报错No module named ‘open3d‘的问题

首先示例&#xff0c;我是如何安装又是如何被报错的过程。 报错过程&#xff1a; 网上普遍的安装指令就是下面这个&#xff1a; pip install open3d 我是直接python页面的终端安装的&#xff1a; 安装完&#xff0c;检查列表已安装文件是否有open3d&#xff0c; 输入指令 …

Linux:进程的通信

目录 进程间的通信 管道 1.概念 2.匿名管道 3.命名管道 4.匿名管道与命名管道的区别 5.总结管道的特点 共享内存 1.原理 2.共享内存的建立 3.代码 1.相关函数 2.总结 进程间的通信 1.进程间通信目的 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程…

flex弹性盒子常用的布局属性详解

想必大家在开发中经常会用到flex布局。而且还会经常用到 justify-content 属性实现分栏等等 接下来给大家分别讲一下 justify-content 的属性值。 以下是我敲的效果图大家可以清晰看出区别 space-between 属性值可以就是说两端对齐 space-evenly 属性值是每个盒子之间的…

攀登者1 - 华为OD统一考试

OD统一考试 分值: 100分 题解: Java / Python / C++ 题目描述 攀登者喜欢寻找各种地图,并且尝试攀登到最高的山峰。 地图表示为一维数组,数组的索引代表水平位置,数组的元素代表相对海拔高度。其中数组元素0代表地面。 例如:[0,1,2,4,3,1,0,0,1,2,3,1,2,1,0],代表如下…

如何顺滑使用华为云编译构建平台?

这两年平台构建服务需求越来越大&#xff0c;却一直苦于找不到一些指南&#xff0c; 这里特意写了一篇&#xff0c; 对在学习代码阶段和新手程序员朋友也蛮友好&#xff0c; 配置真的也不难&#xff0c; 也特别适合想尝试从0到1做个APP的朋友了。 以华为云的CodeArts Build为例…

鸿蒙系统应用开发之开发准备

今天我们来聊一聊鸿蒙系统应用开发之前&#xff0c;要做什么准备工作&#xff0c;如下图所示&#xff0c;我们要做的就是安装DevEco Studio&#xff0c;然后配置开发环境。 老规矩&#xff0c;拍拍手&#x1f44f;&#xff0c;上菜。 安装DevEco Studio 首先我们打开链接HUAWEI…

【Linux Shell】12. 文件包含

和其他语言一样&#xff0c;Shell 也可以包含外部脚本&#xff0c;这样可以很方便的封装一些公用的代码作为一个独立的文件。可以理解为在第2个文件中包含第1个文件&#xff0c;执行第1个文件的代码。 被包含的文件 不需要可执行权限 。Shell 文件包含的语法格式如下&#xff1…

Git将本地项目上传到Gitee仓库

1.右键点击文件&#xff0c;点击Git Bash Here,进入git窗口 2.初始化本地仓库 git init3.将本地仓库与远程仓库建立连接 git remote add origin 远程仓库地址远程仓库地址在gitee仓库复制即可 4.将远程仓库的文件拉到本地仓库中 git pull origin master5.将本地文件全部上传…

探索C语言中的水仙花数及其计算方法

在计算机科学与数学的交叉领域中&#xff0c;有一种特殊的整数被称为“水仙花数”&#xff0c;它是指一个三位数&#xff0c;其各位数字立方和等于该数本身。例如&#xff0c;153是一个典型的水仙花数&#xff0c;因为1 5 3 1 125 27 153。 下面&#xff0c;我们通过一段…

0_项目git地址——正点原子minifly与crazyflie

1、说明&#xff1a; 在每个专栏的第一篇文章&#xff0c;笔者都会贴出项目的git地址&#xff0c;方便后来者学习和复现&#xff1b; 下面介绍两个项目的官网资料和git地址&#xff0c;最后给出两者的对比&#xff1b; 2、正点原子minifly (1)minifly官网资料下载中心&#…

【sgPasswordInput】自定义组件:带前端校验密码强度的密码输入框,能够提供密码强度颜色提示和文字提示

特性&#xff1a; 有密码强度颜色提示密码强度进度条提示支持设置默认输入提示和密码长度 sgPasswordInput源码 <template><div :class"$options.name" style"width: 100%"><el-inputstyle"width: 100%"ref"psw"type&…