一、机器学习算法与实践_03概率论与贝叶斯算法笔记

news2024/9/21 21:02:32

1、概率论基础知识介绍

人工智能项目本质上是一个统计学项目,是通过对 样本 的分析,来评估/估计 总体 的情况,与数学知识相关联

  • 高等数学 ——> 模型优化

  • 概率论与数理统计 ——> 建模思想

  • 线性代数 ——> 高性能计算

在机器学习中,许多算法都是基于概率模型进行构建的,这些模型使用概率来描述数据生成过程,从而能够对数据进行预测和分类,例如:

  • 朴素贝叶斯分类器:基于贝叶斯定理,使用概率来预测数据点的类别
  • 逻辑回归:虽然通常被视为线性分类器,但它本质上是一个概率模型,输出的是数据点属于某个类别的概率
  • 隐马尔可夫模型(HMMs):使用概率来描述状态转换和观测序列

所以,我们需要先了解概率论相关基础知识,为下面理解贝叶斯算法原理打下基础

1.1 概率与频率

在实际操作中,直接计算或得知某个事件的精确概率可能是困难的或不可能的,而频率作为一个可观测、可计算的量,为我们提供了一种近似估计概率的方法

1.1.1 定义

  • 概率(probability,又称或然率、置信度): 是数学中描述某个事件发生的可能性的量度,是一个理论上的度量,它通常是一个介于0和1之间的实数,其中0表示事件几乎不可能发生,1表示事件几乎肯定会发生

  • 频率(frequency): 是实际观测或实验中某一事件发生的次数与总试验次数之比,它是一个经验度量,反映了在一系列试验中事件实际发生的次数

1.1.2 用频率估概率

  • 大数定律:大数定律是概率论中的一个基本定理,它指出当试验次数足够多时,事件发生的频率将趋近于其真实概率,这意味着随着试验次数的增加,频率作为概率的估计会越来越准确

  • 实际应用:在实际应用中,尤其是数据科学和机器学习领域,我们经常使用频率来估计概率,例如:在训练模型时,我们可能使用大量数据来估计某个特征值出现的概率

  • 数据量与估计准确性:数据量越大,频率估计的准确性通常越高,这是因为大数定律保证了频率随试验次数增加而趋于稳定

1.1.3 工程实践中的处理

  • 数据驱动的决策:在工程实践中,尤其是在数据量很大的情况下,我们经常直接使用频率作为概率的替代,这种方法在处理大量数据时尤其有效,因为大数定律确保了估计的稳定性和可靠性

  • 模型训练:在机器学习模型训练中,我们通常使用大量数据来估计模型参数,这些参数的概率分布往往通过频率来估计

  • 统计推断:统计推断中,频率也被用来估计总体参数,例如:样本均值的分布可以用来估计总体均值

1.1.4 注意事项

  • 有限样本偏差:在样本量较小的情况下,频率可能不是概率的良好估计,因为小样本更易受到随机波动的影响

  • 数据质量:数据的质量和代表性也会影响频率估计的准确性,数据集中的偏差或不准确可能导致估计结果不可靠

1.2 概率的基本特性

  • 非负性: 概率的非负性是指任何事件发生的概率都不会是负数,即:

  • 规范性: 概率的规范性(或归一性)是指在一个完整样本空间内所有可能事件的概率之和等于1。这适用于所有可能的事件集合,包括所有可能的单一事件和它们的组合。对于一个包含所有可能结果的样本空间,存在:

    其中:表示样本空间中的第个事件,是事件的总数

  • 单调性:如果事件(即:当事件 A 发生时,事件 B 也同样会发生),那么

  • 可加性:对于两个互斥事件 A 和 B (即:它们不能同时发生),存在:

  • 连续性:对于一系列事件,如果这些事件是互斥的,并且覆盖了整个样本空间,那么对于任意事件包含在这些事件中的概率可以通过极限来定义

1.3 概率的计算方法

1.3.1 离散型变量

(1)特点: 有限个状态,状态之间无大小、程度等概念,状态之间是严格对立的

(2)示例:

  • 鸢尾花有山鸢尾、杂色鸢尾、长鞘鸢尾等不同类型的品种
  • 交通信号灯有红、绿、黄不同的颜色
  • 人类有男、女不同的性别
  • 骰子有1、2、3、4、5、6不同的点数

(3)编码: 连续型变量是指有限个状态,而状态大多数不是数值类型的数据,不易进行处理,所以需要对其进行编码(编码就是为了将非数值型数据转换为机器学习算法可以处理的数值型数据,方便进行处理)

离散型变量的常用编码方法分为Zero index编码和One hot编码这两种

  • ①Zero Index编码: 也称为索引编码或标签编码,是一种将类别变量转换为从0开始的连续整数的方法,每个类别被赋予一个唯一的整数标签。

    特点

    • 简单:实现简单,易于理解和操作。

    • 连续性:编码是连续的,从0开始,但这种连续性并不代表类别之间的任何顺序或等级关系。

    • 大小无内涵:编码的大小没有数学意义,例如,编码为1和编码为4的类别是平等的,它们之间没有内在的比较意义。

应用场景

  • 适用于那些类别之间没有顺序或等级关系的情况。

  • 常用于机器学习模型中,如决策树、随机森林等。

  • ②One Hot编码: 也称为一位有效编码,是一种将类别变量转换为二进制向量的方法,每个类别都分别由一个长度等于类别数的向量表示,并且在此向量中只有一个位置为1,其余位置均为0。

    特点

    • 向量表示:每个类别由一个唯一的二进制向量表示,向量中的1表示该类别的存在。

    • 平等性:所有类别在向量空间中是平等的,没有大小或顺序之分。

    • 无序性:One Hot编码不包含任何类别之间的顺序或等级信息。

应用场景

  • 适用于需要明确区分类别,且类别之间没有顺序或等级关系的情况。

  • 常用于自然语言处理、推荐系统、神经网络等场景。

  • ③示例: 假设有一个数据集,包含三个类别:苹果、香蕉、樱桃,则使用这两种编码方式可以表示如下:

    Zero Index编码

    • 苹果:0

    • 香蕉:1

    • 樱桃:2

One Hot编码

  • 苹果:[1, 0, 0]

  • 香蕉:[0, 1, 0]

  • 樱桃:[0, 0, 1]

(4)计算方法: 先转换为频率,然后数个数

  • 示例:求iris数据集中,三种鸢尾花出现的概率
# 引入load_iris,获取鸢尾花数据集
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)

# 查看所有y值(可以发现分别用0、1、2这三个编码代表了三种鸢尾花类型)
print(y)

# 求概率(可以发现在这个数据集中,三种鸢尾花出现的概率都是1/3,非常均衡,属于一个理想的数据集)
P0 = (y == 0).mean()
P1 = (y == 1).mean()
P2 = (y == 2).mean()

print(f"标签编码为0的鸢尾花出现的概率为:{P0}")
print(f"标签编码为1的鸢尾花出现的概率为:{P1}")
print(f"标签编码为2的鸢尾花出现的概率为:{P2}")

1.3.2 连续型变量

(1)特点: 无限个数值,数值之间有大小、程度等差异,数值之间的内涵是一致的

(2)例如:

  • 一个人的身高是一个连续变量,可以是 1.75 米、1.76 米、1.77 米等
  • 一个人的体重也是一个连续变量,可以有无数个可能的值
  • 气温是一个连续变量,可以是 23.5 度、23.6 度、23.7 度等
  • 商品的价格是一个连续变量,可以有小数点后的值
  • 一个人每天花费在上班通勤上的时间是一个连续变量,可以是 30.5 分钟、31 分钟、31.5 分钟等

(3)编码: 连续型变量通常不需要像离散型变量那样的编码,因为它们已经是数值型,可以直接用于大多数机器学习算法。然而,在某些情况下,对连续型变量进行特定的处理或转换可能是有益的,这些处理包括:

  • 归一化(Normalization):将数据缩放到一个特定的范围,通常是 [0, 1],或者转换为具有零均值和单位方差的形式,这有助于加快学习算法的收敛速度,并提高模型的性能

  • 标准化(Standardization):将数据转换为均值为 0,标准差为 1 的形式,这种方法对于假设数据分布为正态分布的算法(如线性回归、逻辑回归等)尤其重要

  • 离散化(Discretization):将连续变量分割成若干个区间或桶,将其转换为离散型变量,这在某些分类任务中可能有用,尤其是当连续变量的每个区间对预测结果有明显区别时

  • 特征工程:通过数学变换(如对数变换、平方根变换等)来改善模型的性能,或者创建新的特征,这些新特征可能更好地捕捉数据中的模式

  • 异常值处理:识别并处理异常值,因为极端的数值可能会对模型的性能产生负面影响

  • 降维:使用主成分分析(PCA)或其他方法来减少数据的维度,同时尽可能保留原始数据的信息

(4)计算方法: 通过对概率密度函数(PDF,Probability Density Function)的积分来求解

(概率密度函数是概率的导数,概率是概率密度函数的积分)

①计算步骤(理论数学):

  • 先找到概率密度函数(在概率论和统计学中,有多种类型的概率密度函数,用于描述不同类型连续型随机变量的概率分布,高斯分布函数就是其中的一种)

  • 再对概率密度函数求积分

高斯分布函数(也称为正态分布函数)是特定形式的一种概率密度函数,它描述了正态分布的变量的概率密度,其公式如下:(其中,μ是均值,可以用mean方法计算得出;σ是标准差,可以用std方法计算得出)

用matplotlib绘制高斯函数的图像:

# 引入numpy,为高斯分布函数提供π、e的值
import numpy as np
# 引入matplotlib的pyplot函数,为绘图做准备
from matplotlib import pyplot as plt
# 如果是用pycharm等后端工具绘图,需要指定图形用户界面工具包
# import matplotlib
# matplotlib.use('TkAgg')  # 设置绘图后端为 TkAgg

# 从-5到5,等差数列,生成100个x均分点
x = np.linspace(start=-5, stop=5, num=100)
# 创建高斯分布函数,设定返回结果为高斯分布函数的方程式
def normal(x, mu=0, sigma=1):
    # np.pi即为圆周率π,np.exp即为数学常数e
    return 1 / (((2 * np.pi) ** 0.5) * sigma) * np.exp(-((x - mu) ** 2) / (2 * (sigma ** 2)))
# 用plot方法折线图,label是图线的标签
plt.plot(x, normal(x, mu=0, sigma=1), label="$\mu=0,\sigma =1$")
plt.plot(x, normal(x, mu=1, sigma=1), label="$\mu=1,\sigma =1$")
plt.plot(x, normal(x, mu=0, sigma=2), label="$\mu=0,\sigma =2$")
# 用grid方法显示图像网格
plt.grid()
# 用legend方法显示图线的标签
plt.legend()
# 用show方法显示图表
plt.show()

绘制出来的图像如下图所示:(在任何一点的概率都是0,但中间的概率明显应该比两边的概率大,所以理论数学的计算是不可行的)

②计算步骤(工程数学):

  • 直接把连续型变量的分布看作是高斯分布

  • 直接拿概率密度函数的值代替概率

  • 示例:根据一天中每个小时的温度,来计算22摄氏度出现的概率

# 引入numpy,创建高斯分布函数,并返回函数的值
import numpy as np
def gauss(x, mu, sigma):
    return 1/(np.sqrt(2*np.pi)*sigma) * np.exp(-(x - mu)**2 / (2*sigma**2))

# 采样一天中24小时的温度数据
temperature = np.array([10, 9, 8, 7, 6, 5, 6, 7, 9, 12, 15, 18, 20, 22, 23, 22, 21, 19, 17, 15, 13, 11, 10, 9])
# 求均值
mu = temperature.mean()
# 求标准差
sigma = temperature.std()
# 求温度为22的概率
P_22 = gauss(x=22, mu=mu, sigma=sigma)
print(f'温度为22的概率为:{P_22}')

2、条件概率与贝叶斯算法基本介绍

2.1 定义

条件概率以贝叶斯定理为理论基础,指的是某事件已发生的前提下,另一事件发生的概率

例如: 假设我在做一道单选题,有A、B、C、D四个选项,但我不知道这道题的答案,只能猜一个选项

一般情况下,我能猜对答案的概率是1/4

此时,如果我已经排除了A、D两个选项,那么会存在以下情况:

  • A、D两项确实是错误答案,应该被排除,则在我已经排除A、D两项的前提下,我从B、C里面再去猜答案,猜对的概率是1/2

  • A、D两项其实有正确答案,不该被排除,则在我已经排除A、D两项的前提下,我从B、C里面再去猜答案,猜对的概率是0

2.2 公式推导

根据贝叶斯定理,B事件发生的前提下,A事件发生的概率为:

同理可得,A事件发生的前提下,B事件发生的概率为:

根据等式的乘法性质,可得:

因此:

进一步可推导出:

其中:

  • P(A∣B) 是后验概率(Posterior Probability),指的是在事件 B 发生的前提下,事件 A 发生的概率。
  • P(B∣A) 是似然概率(Likelihood),指的是在事件 A 发生的前提下,事件 B 发生的概率。
  • P(A) 是先验概率(Prior Probability),指的是在没有考虑任何额外证据或信息之前,某个事件发生的概率
  • P(B) 是边缘概率(Marginal Probability),指的是在考虑所有可能情况下,某个事件发生的总概率

在上述公式中,将A、B分别替换为机器学习模型中的标签y、特征X,可得:在特征X出现的前提下,标签y出现的概率为

由于条件概率模型通常是处理分类问题的,在分类问题中,同一组特征X,一般只会对应同一个标签y(如:y0、y1、y2...),所以上面公式可进一步推导出:

...

在处理分类问题时,条件概率模型不是非要算出一个具体的概率值,而是通过概率密度函数来比较大小,将概率最大的,视为特征样本的标签

既然是比大小,那么上面的公式应当还能化简,即:由于上面的式子都有除以P(X),所以与其比较除以P(X)之后的大小,不如直接比较不除以P(X)时的大小

例如:因为9>6>3,所以当9、6、3分别除以2之后,这个大小关系依然一致(9/2 > 6/2 > 3/2)

因此,上面的公式可进一步化简得:

...

由于X代表的是一组特征,包含X1,X2,X3,X4,...,Xn,所以可进一步推导得出:

...

因为X1、X2、X3、X4、...、Xn是独立特征,所以可以最终推导得出:

...

2.3 贝叶斯算法

贝叶斯算法是基于贝叶斯定理的一类算法,它提供了一种计算条件概率的方法,即:在已知其他事件发生的情况下,某事件发生的概率

朴素贝叶斯(Naive Bayes)和高斯贝叶斯(Gaussian Naive Bayes)都属于贝叶斯算法,但它们在处理数据和假设数据分布方面有所不同:

(1)朴素贝叶斯(Naive Bayes)

  • 是一种基于贝叶斯定理的简单概率分类器,它假设所有特征之间相互独立
  • 适用于文本分类、垃圾邮件检测等任务
  • 可以用于多种类型的数据分布,如多项式分布、伯努利分布等

(2)高斯贝叶斯(Gaussian Naive Bayes)

  • 是朴素贝叶斯的一个特例,它假设数据特征遵循高斯(正态)分布
  • 通常用于连续数据的特征,因为高斯分布是连续的
  • 在特征值近似正态分布时效果最好

3、高斯贝叶斯算法实践

以鸢尾花的分类任务为例,下面介绍通过高斯贝叶斯算法来进行预测

# 引入load_iris,获取鸢尾花数据集
from sklearn.datasets import load_iris
X,y = load_iris(return_X_y=True)

# 引入train_test_split,将数据集切分为训练集和测试集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

# 在python中,sklearn.naive_bayes是 sklearn 库中的一个模块,它实现了多种朴素贝叶斯分类器
# 在sklearn.naive_bayes中,GaussianNB就是用于实现高斯贝叶斯算法的分类器,所以我们需要先对其进行引入
from sklearn.naive_bayes import GaussianNB

# GaussianNB是一个类,所以应该用面向对象的思想对其进行使用(即:实例化对象)
gnb = GaussianNB()

# 训练模型时,需要将训练集(X_train和y_train)作为参数传入fit方法中
gnb.fit(X=X_train, y=y_train)
# 预测模型时,需要将测试集(X_test)作为参数传入predict方法中
y_pred = gnb.predict(X=X_test)

#将y_test与y_pred进行对比,看有多少个数是相等的,就可以得到预测的准确率
acc = (y_pred == y_test).mean()
print(f"预测的准确率为:{acc}")

4、自定义高斯贝叶斯分类器

在本文第三章节的高斯贝叶斯算法实践中,用的都是sklearn库中的标准模块和函数,为了理解其中的实现原理(贝叶斯公式和高斯函数都有运用),本章节将模仿sklearn,自定义一个高斯贝叶斯分类器

# 引入numpy,为高斯分布函数提供π、e的值,以及提供一些其他的科学计算方法
import numpy as np

# 定义一个MyGaussianNB类,实现高斯贝叶斯算法的fit和predict方法
class MyGaussianNB(object):
    """
        自定义高斯贝叶斯分类算法
    """
    def __init__(self):
        """
            初始化方法
        """
        pass

    def _gauss(self, x, mu, sigma):
        """
            定义一个内部方法,返回高斯分布函数值
        """
        return 1 / (((2 * np.pi) ** 0.5) * sigma) * np.exp(-((x - mu) ** 2) / (2 * (sigma ** 2)))

    def fit(self, X_train, y_train):
        """
            训练过程(高斯贝叶斯算法不是懒惰学习的方式,有训练过程)
            训练逻辑:
                Step1:将训练集中所有的y标签去重,得到总共有多少个y标签(比如鸢尾花标准数据集中有3个y标签)
                Step2:将训练集中的X样本按照这3个标签做切分,划分出每一类标签对应的所有X样本
                Step3:对于每一类标签的所有X样本,求出每一列特征的均值和标准差
                    标签值为0对应的所有X样本,第1列特征的均值和标准差、第2列特征的均值和标准差、第3列特征的均值和标准差、第4列特征的均值和标准差
                    标签值为1对应的所有X样本,第1列特征的均值和标准差、第2列特征的均值和标准差、第3列特征的均值和标准差、第4列特征的均值和标准差
                    标签值为2对应的所有X样本,第1列特征的均值和标准差、第2列特征的均值和标准差、第3列特征的均值和标准差、第4列特征的均值和标准差
                最终得到的结果示例:
                # [[{'mean': 5.02051282051282, 'std': 0.3596148132908301}, {'mean': 3.4025641025641025, 'std': 0.37654786836856813}, {'mean': 1.4615384615384615, 'std': 0.14253273958653637}, {'mean': 0.24102564102564095, 'std': 0.10553392629362397}], 
                #  [{'mean': 5.886486486486486, 'std': 0.513684182165048}, {'mean': 2.7621621621621624, 'std': 0.32244953625825373}, {'mean': 4.216216216216216, 'std': 0.4795907678447316}, {'mean': 1.324324324324324, 'std': 0.2018902637511686}], 
                #  [{'mean': 6.638636363636365, 'std': 0.6238501820042829}, {'mean': 2.9886363636363638, 'std': 0.328367801745452}, {'mean': 5.5659090909090905, 'std': 0.5426966262094999}, {'mean': 2.0318181818181817, 'std': 0.2538545819171491}]]                    
        """
        self.X_train = X_train
        self.y_train = y_train

        #找出训练集 y_train 中有多少个不重复的类别标签,并将其存储在 self.classes 中
        self.classes = np.unique(y_train)   

        # 定义一个空列表,存放每个标签对应的四列X特征数据中,每一列X特征数据的均值和标准差
        self.parameters = []

        # 对 self.classes 中的类别进行遍历,并将索引和对应的元素值分别赋给变量 i 和 y_now
        for i, y_now in enumerate(self.classes):
            # X_train[y_train == y_now],是将训练集中的 y 标签分别于当前循环中的标签做对比,找到有哪些组X是对应此标签的
            X_classes = X_train[y_train == y_now]
            # 往self.parameters中添加一个空列表,用于存放当前标签对应的所有训练集X样本中每一列特征的均值和标准差数据
            self.parameters.append([])

            # X_classes.T是将X_classes进行转置,方便求其每一列的均值和标准差
            # 假设X_classes=[[5.2 3.5 1.5 0.2]
            #               [5.7 3.8 1.7 0.3]
            #               [4.7 3.2 1.3 0.2]
            #               [5.  3.5 1.6 0.6]
            #               [5.4 3.7 1.5 0.2]
            #               [4.8 3.1 1.6 0.2]
            #               [5.3 3.7 1.5 0.2]
            #               [4.3 3.  1.1 0.1]
            #               [5.4 3.4 1.7 0.2]
            #               [5.7 4.4 1.5 0.4]
            #               [4.6 3.1 1.5 0.2]
            #               [4.6 3.4 1.4 0.3]
            #               [4.8 3.  1.4 0.1]
            #               [5.1 3.8 1.6 0.2]
            #               [4.8 3.4 1.6 0.2]
            #               [4.5 2.3 1.3 0.3]
            #               [4.9 3.  1.4 0.2]
            #               [4.4 3.2 1.3 0.2]]
            # 则X_classes.T=[[5.2 5.7 4.7 5.  5.4 4.8 5.3 4.3 5.4 5.7 4.6 4.6 4.8 5.1 4.8 4.5 4.9 4.4]
            #               [3.5 3.8 3.2 3.5 3.7 3.1 3.7 3.  3.4 4.4 3.1 3.4 3.  3.8 3.4 2.3 3.  3.2]
            #               [1.5 1.7 1.3 1.6 1.5 1.6 1.5 1.1 1.7 1.5 1.5 1.4 1.4 1.6 1.6 1.3 1.4 1.3]
            #               [0.2 0.3 0.2 0.6 0.2 0.2 0.2 0.1 0.2 0.4 0.2 0.3 0.1 0.2 0.2 0.3 0.2 0.2]]
            # 转置之后,遍历获取的就是每一个特征列的数据,需要分别求其均值和标准差,并添加到self.parameters中
            for col in X_classes.T:
                parameters = {"mean": col.mean(), "std": col.std()}
                self.parameters[i].append(parameters)

    def predict(self, X_test):
        """
            推理过程(此处是重点)
        """
        # 大致流程:
        # Step1:将测试数据集中的每一个特征值都与分别于训练数据集中每一列特征值的均值和标准差一一对应,求得当前测试数据对于每一类标签的概率密度函数值
        # Step2:取概率密度函数最大的值对应的标签值,作为当前测试数据预测出来的标签

        # 具体实现:
        # 1、定义一个列表,用于接收每个测试集预测出来的标签值
        results = []

        # 2、循环遍历测试集中的每一个样本,分别求其对应的标签值,并存放值results中
        for x_test in X_test:
            # 定义一个空列表,用于存放每个P(y_train_i|x_test_j)的概率结果
            posteriors = []

            # 对 self.classes 中的类别进行遍历,并将索引和对应的元素值分别赋给变量 i 和 y_now
            for i, y_now in enumerate(self.classes):
                # 计算先验概率P(y_train_i)
                prior = (self.y_train == y_now).mean()
                # 重置似然概率
                likelihood = 1
                # self.parameters=[[{'mean': 5.02051282051282, 'std': 0.3596148132908301}, {'mean': 3.4025641025641025, 'std': 0.37654786836856813}, {'mean': 1.4615384615384615, 'std': 0.14253273958653637}, {'mean': 0.24102564102564095, 'std': 0.10553392629362397}], 
                #                  [{'mean': 5.886486486486486, 'std': 0.513684182165048}, {'mean': 2.7621621621621624, 'std': 0.32244953625825373}, {'mean': 4.216216216216216, 'std': 0.4795907678447316}, {'mean': 1.324324324324324, 'std': 0.2018902637511686}], 
                #                  [{'mean': 6.638636363636365, 'std': 0.6238501820042829}, {'mean': 2.9886363636363638, 'std': 0.328367801745452}, {'mean': 5.5659090909090905, 'std': 0.5426966262094999}, {'mean': 2.0318181818181817, 'std': 0.2538545819171491}]]
                # 以i=0为例:
                # i=0 ==> self.parameters[i]=[{'mean': 5.02051282051282, 'std': 0.3596148132908301}, {'mean': 3.4025641025641025, 'std': 0.37654786836856813}, {'mean': 1.4615384615384615, 'std': 0.14253273958653637}, {'mean': 0.24102564102564095, 'std': 0.10553392629362397}]
                #     ==> j=0,param={'mean': 5.02051282051282, 'std': 0.3596148132908301},x_test[j]="测试集中第1列特征x的数据"
                #         j=1,param={'mean': 3.4025641025641025, 'std': 0.37654786836856813},x_test[j]="测试集中第2列特征x的数据"
                #         j=2,param={'mean': 1.4615384615384615, 'std': 0.14253273958653637},x_test[j]="测试集中第3列特征x的数据"
                #         j=3,param={'mean': 0.24102564102564095, 'std': 0.10553392629362397},x_test[j]="测试集中第4列特征x的数据"
                for j, param in enumerate(self.parameters[i]):
                    # 计算似然概率:P(x_test_1|y_train_i) · P(x_test_2|y_train_i) · P(x_test_3|y_train_i) · P(x_test_4|y_train_i)
                    likelihood *= self._gauss(x_test[j], param["mean"], param["std"])

                # 计算后验概率,P(x_test_1|y_train_i) · P(x_test_2|y_train_i) · P(x_test_3|y_train_i) · P(x_test_4|y_train_i) · P(y_train_i)
                posterior =  likelihood * prior
                # 将计算得到的概率都添加到posteriors列表中
                posteriors.append(posterior)

            # np.argmax是 NumPy 库中的一个函数,用于返回数组中最大值的索引
            # 由于每个概率的索引正好对应一个y标签,所以,可通过最大概率值的索引,从self.classes中获取到索引对应的标签值,作为预测值(y_pred),并添加到results结果集中
            results.append(self.classes[np.argmax(posteriors)])

        # 返回每个样本对应的标签值,方便后续与实际值之间做分析
        return results

使用自定义的高斯贝叶斯分类器处理【鸢尾花(iris)识别】任务:

# 引入load_iris,获取鸢尾花数据集
from sklearn.datasets import load_iris
X,y = load_iris(return_X_y=True)

# 引入train_test_split,将数据集切分为训练集和测试集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

# 调用自定义的高斯贝叶斯分类器,分别传入训练集和测试集
mygnb = MyGaussianNB()
mygnb.fit(X_train=X_train, y_train=y_train)
y_pred = mygnb.predict(X_test=X_test)

# 比较测试集的标签值和预测出来的标签值,计算预测的准确率
acc = (y_pred == y_test).mean()
print(f"预测的准确率为:{acc}")

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

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

相关文章

Qt窗口——对话框

文章目录 对话框自定义对话框对话框分类消息对话框QMessageBox使用示例自定义按钮快速构造对话框 颜色对话框QColorDialog文件对话框QFileDialog字体对话框QFontDialog输入对话框QInputDialog 对话框 对话框可以理解成一个弹窗,用于短期任务或者简洁的用户交互 Qt…

AIoT智能工控板

在当今竞争激烈的商业环境中,企业需要强大的科技力量来助力腾飞,AIoT智能工控板就是这样的力量源泉。 其领先的芯片架构设计,使得主板的性能得到了极大的提升。无论是数据的处理速度、图形的渲染能力,还是多任务的并行处理能力&a…

【Linux笔记】虚拟机内Linux内容复制到宿主机的Window文件夹(文件)中

一、共享文件夹 I、Windows宿主机上创建一个文件夹 目录:D:\Centos_iso\shared_files II、在VMware中设置共享文件夹 1、打开VMware Workstation 2、选择需要设置的Linux虚拟机,点击“编辑虚拟机设置”。 3、在“选项”标签页中,选择“共…

【BetterBench博士】2024年中国研究生数学建模竞赛 E题:高速公路应急车道紧急启用模型 问题分析

2024年中国研究生数学建模竞赛 E题:高速公路应急车道紧急启用模型 问题分析 更新进展 【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析 【BetterBench博士】2024年中国研究生数学建模竞赛 E题:高速公路应急车道紧急启用…

Remix在SPA模式下,出现ErrorBoundary错误页加载Ant Design组件报错,不能加载样式的问题

Remix是一个既能做服务端渲染,又能做单页应用的框架,如果想做单页应用,又想学服务端渲染,使用Remix可以降低学习成本。最近,在学习Remix的过程中,遇到了在SPA模式下与Ant Design整合的问题。 我用Remix官网…

简单多状态dp第三弹 leetcode -买卖股票的最佳时机问题

309. 买卖股票的最佳时机含冷冻期 买卖股票的最佳时机含冷冻期 分析: 使用动态规划解决 状态表示: 由于有「买入」「可交易」「冷冻期」三个状态,因此我们可以选择用三个数组,其中: ▪ dp[i][0] 表示:第 i 天结束后&#xff0c…

探索AI编程新时代:GitHub Copilot如何重塑开发者工作效率

在当今技术瞬息万变的时代,软件开发者们每天都在努力寻找更高效的编程方法。面对繁忙的工作日程和不断增加的项目压力,如何在编码过程中大幅提升效率成为了一个备受关注的话题。在众多工具中,GitHub Copilot以其强大的AI驱动能力脱颖而出&…

菜鸟也能轻松上手的Java环境配置方法

初学者学习Java这么编程语言,第一个难题往往是Java环境的配置,今天与大家详细地聊一聊,以便大家能独立完成配置方法和过程。 首先,找到“JDK”,点击“archive”: 向下滑,在“previous java rel…

HTTPS:构建安全通信的基石

HTTPS(Hypertext Transfer Protocol Secure),作为互联网上安全通信的基石,通过在HTTP基础上引入SSL/TLS协议层,实现了数据传输的加密,确保了信息的机密性、完整性和真实性。这一过程涉及多个精细设计的步骤…

【EasyBlog】基于React+AntD+NextJS+NestJS+MySQL打造的开源博客系统

Github项目地址:https://github.com/fecommunity/easy-blog, 欢迎Star。 Easy-Blog Easy-Blog 是一套集成文章发表、页面创建、知识库管理、博客后台管理等功能于一体的博客系统。 首页-浅色主题 首页-暗黑主题 文章阅读 后台管理 ✨ 特性 &#…

公司网站改版时,需要注意哪些细节?

在公司网站改版时,需要注意的细节非常多,这些细节将直接影响到网站的用户体验、SEO效果以及整体品牌形象。以下是一些关键的注意事项: 明确改版目标: 在改版前,要明确改版的目标是什么,比如提升用户体验、增…

【AcWing】873. 欧拉函数

#include<iostream> using namespace std;int main(){int n;cin>>n;while(n--){int x;cin>>x;int resx;for(int i2;i<x/i;i){if(x%i0){//resres*(1-1/i);整数1/i等于0&#xff0c;算不对且会溢出//以下几种都能ac//resres/i*(i-1);i*(1-1/i)i-1&#xff0…

通过标签实现有序:优化你的 FastAPI 生成的 TypeScript 客户端

在软件开发的世界里&#xff0c;API 客户端代码的质量直接影响着应用程序的性能和可维护性。随着项目规模的扩大&#xff0c;自动化生成的代码往往变得臃肿且难以管理。但幸运的是&#xff0c;通过一系列的优化策略&#xff0c;我们可以显著提升这些代码的优雅与效能。在本文中…

计算机网络(八) —— Udp协议

目录 一&#xff0c;再谈端口号 1.1 端口号 1.2 netsta命令 二&#xff0c;UDP协议 2.1 关于UDP 2.2 Udp协议格式 2.3 Udp协议特点 2.4 Udp的缓冲区 一&#xff0c;再谈端口号 http协议本质是“请求 - 响应”形式的协议&#xff0c;但是应用层需要先将数据交给传输层&…

2024/9/21 408 20题

a b 58-130-180-199-42-15&#xff1a;c d a 184-182-187-176-19941 c d a a c b d c a c b c c c

12V转100V低压升高压DC/DC电源GRB12-100D-100mA-Uz(0-3V)

特点 ● 效率高达75%以上 ● 1*2英寸标准封装 ● 单电压输出 ● 超高性价比 ● 电压控制输出,输出电压随控制电压的变化而线性变压 ● 工作温度: -40℃~75℃ ● 阻燃封装&#xff0c;满足UL94-V0 要求 ● 温度特性好 ● 可直接焊在PCB 上 应用 GRB 系列模块电源是一…

深度学习笔记17_TensorFlow实现咖啡豆识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 一、我的环境 1.语言环境&#xff1a;Python 3.9 2.编译器&#xff1a;Pycharm 3.深度学习环境&#xff1a;TensorFlow 2.10.0 二、GPU设置…

linux操作系统的基本命令

1.linux下的文件系统 在linux操作目录下没有像window操作系统下盘符的概念,只有一个根目录/,所有文件目录都在它的下面 linux的目录结构: 在Linux系统中: 文件都从跟目录开始的,用/表示文件名称区分大小写路径都是以/俩进行分隔(windown用\分隔)以.开头的文件为隐藏文件 Li…

Java反序列化利用链篇 | CC6链分析(通用版CC链)

文章目录 CC6和CC1之间的区别CC6的调用链构造CC6的payload完成TiedMapEntry.getValue()完成TiedMapEntry.hashCode()完成HashMap.hash()及HashMap.readObject()解决hash()方法提前触发的问题 系列篇其他文章&#xff0c;推荐顺序观看~ Java反序列化利用链篇 | JdbcRowSetImpl利…

LeetCode[中等] 215. 数组中的第 K 个最大元素

给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 思路&#xff1a;基于快排改进的快速…