机器学习作业4——朴素贝叶斯分类器

目录

一、理论

一个例子:

二、代码

对于代码的解释:

1.fit函数:

2.predict函数:

三、实验结果

原因分析:


一、理论

朴素贝叶斯分类器基于贝叶斯定理进行分类,通过后验概率来判断将新数据归为哪一类。通过利用贝叶斯定理计算后验概率,并选择具有最高后验概率的类别作为预测结果,朴素贝叶斯分类器能够在考虑了先验概率和观察到的数据特征后,做出基于统计推断的分类决策,从而实现有效的分类。

步骤:

1.计算先验概率:先验概率表示了在没有任何其他信息的情况下,一个数据点属于每个类别的概率。

2.计算条件概率:条件概率表示了在给定某一类别的情况下,某个特征取某个值的概率。

3.计算后验概率:当有一个新的数据点需要分类时,朴素贝叶斯根据该数据点的特征值,利用贝叶斯定理计算每个类别的后验概率。后验概率表示了在考虑了新的观察结果后,每个类别的概率。

4.做出分类:根据计算得到的后验概率,选择具有最高后验概率类别作为预测结果

先验概率:

P(Y=c_k) = \frac{|D_{c_k}|}{|D|}

其中:ck是类别,D是数据数量,Dck是类别为ck的数据数量。

条件概率:

P(X^{(i)}=a_{i,j}|Y=c_k) = \frac{|D_{c_k}^{(i)}(a_{i,j})|}{|D_{c_k}|}

其中:Xi代表第i个特征,ai,j代表第i个特征中第j个类型,D_{c_k}^{(i)}(a_{i,j})代表在类别为ck时,在第i个特征中的第j个类型的数量。

后验概率:

P(Y=c_k|X=x) = \frac{P(Y=c_k) \cdot \prod_{j=1}^{n} P(X^{(j)}=x^{(j)}|Y=c_k)}{\sum_{i=1}^{K} P(Y=c_i) \cdot \prod_{j=1}^{n} P(X^{(j)}=x^{(j)}|Y=c_i)}

因为我们只需要分类,因为不同后验概率分母都相同,所以可以把分母去掉只需要比较分子的大小即可,即:

P(Y=c_k|X=x) = {P(Y=c_k) \cdot \prod_{i=1}^{n} P(X^{(i)}=x^{(i)}|Y=c_k)}

其中:\prod_{i=1}^{n} P(X^{(i)}=x^{(i)}|Y=c_k)代表当前测试数据的每个类型为xi,在ck类别下的条件概率的连乘积。

可以看到公式简洁了不少。

一个例子:

假设数据集:

特征1特征2类别
11A
10A
01B
01A
10B

现在预测一个特征11特证21的测试元组是什么类别。

首先计算类别的先验概率和所有条件概率:

P(A)= 3/5,P(B)= 2/5

对于特征1:
P1(1∣A)= 2/3,P1(1 | B)= 1/2,

对于特征2:

P2(1 | A) = 2/3,P2(1 | B) = 1/2

然后计算预测为A和B的后验概率,并比较大小,得出结果

P(A|X) = P(A)*P1(1∣A)*P2(1 | A) = 4/15
P(B|X) = P(B)*P1(1 | B)*P2(1 | B) = 1/10

可以看到P(A|X)比较大,所以是A类​

 

二、代码

import numpy as np  
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score class NaiveBayesClassifier:def __init__(self):self.class_prior = {}  # 存储类别的先验概率self.feature_prob = {}  # 存储特征在各个类别下的条件概率def fit(self, X, y):n_samples, n_features = X.shape  # 获取样本数和特征数self.classes = np.unique(y)  # 获取目标标签中的唯一类别值print("计算先验概率:")for c in self.classes:# 统计每个类别在目标标签中的出现次数,并除以样本总数,得到先验概率self.class_prior[c] = np.sum(y == c) / n_samplesprint("先验概率: 类别, 概率 "+repr(c)+" "+repr(self.class_prior[c]))# 外层循坏遍历类别,内层循环遍历每个特征,内层循环每次要计算出每个特征下不同取值的在当前类别下的条件概率,存放到[c][feature_index]下print("计算条件概率:")for c in self.classes:self.feature_prob[c] = {}  # 初始化存储特征条件概率的字典for feature_index in range(n_features):# 对于每个特征,统计在当前类别下的取值及其出现次数,并除以总次数,得到条件概率# values是feature_index列中不同的取值,counts是这些不同取值的个数(在类别为C下的)values, counts = np.unique(X[y == c, feature_index], return_counts=True)self.feature_prob[c][feature_index] = dict(zip(values, counts / np.sum(counts)))#dict是变为以values和counts/np.sum的字典,zip就是一个方便的操作for i in range(len(counts)):print("条件概率:P(" + repr(values[i]) + "|" + repr(c) + ") = " + repr(self.feature_prob[c][feature_index][values[i]]))def predict(self, X):predictions = []  # 存储预测结果的列表#对于测试集中的每个元素cnt = 0for x in X:print("\n对于第" + repr(cnt) + "个测试集:")cnt+=1max_posterior_prob = -1  # 最大后验概率初始化为-1predicted_class = None  # 预测类别初始化为空#对于每个类别for c in self.classes:# 计算后验概率,先验概率乘以各个特征的条件概率posterior_prob = self.class_prior[c]print("对于类别"+repr(c)+" = "+"[先验"+repr(self.class_prior[c])+"]", end = '')#对于每个特征for feature_index, feature_value in enumerate(x):if feature_value in self.feature_prob[c][feature_index]:print(" * [P("+ repr(feature_value) + "|" + repr(c) + ") = " + repr(self.feature_prob[c][feature_index][feature_value]) + "]", end = '')posterior_prob *= self.feature_prob[c][feature_index][feature_value]else:print(" * 1")# 更新预测值print(" = " + repr(posterior_prob))if posterior_prob > max_posterior_prob:max_posterior_prob = posterior_probpredicted_class = cpredictions.append(predicted_class)  # 将预测结果添加到列表中return predictions  # 返回预测结果列表data = {'outlook': ['sunny', 'sunny', 'overcast', 'rain', 'rain', 'rain', 'overcast', 'sunny', 'sunny', 'rain', 'rain', 'overcast', 'overcast', 'rain'],'temperature': ['hot', 'hot', 'hot', 'mild', 'cool', 'cool', 'cool', 'mild', 'cool', 'mild', 'mild', 'mild', 'hot', 'mid'],'humidity': ['high', 'high', 'high', 'high', 'normal', 'normal', 'normal', 'high', 'normal', 'normal', 'normal', 'high', 'normal', 'high'],'wind': ['weak', 'strong', 'weak', 'weak', 'weak', 'strong', 'strong', 'weak', 'weak', 'weak', 'strong', 'strong', 'weak', 'strong'],'playtennis': ['no', 'no', 'yes', 'yes', 'yes', 'no', 'yes', 'no', 'yes', 'yes', 'yes', 'yes', 'yes', 'no']
}
#创建DataFrame
df = pd.DataFrame(data)
X = df.drop('playtennis', axis=1)#axis=1删除列,=0删除行
y = df['playtennis']# 将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=3)
X_train = X_train.values#化为二维数组,便于遍历
X_test = X_test.values
y_train = y_train.values
y_test = y_test.valuesprint("训练集:")
for i in range(len(y_train)):print(repr(i)+": "+repr(X_train[i])+"  "+repr(y_train[i]))
print("测试集:")
for i in range(len(y_test)):print(repr(i)+": "+repr(X_test[i])+"  "+repr(y_test[i]))nb_classifier = NaiveBayesClassifier()
nb_classifier.fit(X_train, y_train)y_pred = nb_classifier.predict(X_test)
print("预测结果:")
for i in range(len(y_pred)):print(repr(i)+"正确,预测: "+repr(y_test[i])+", "+repr(y_pred[i]))accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred, pos_label='yes')
recall = recall_score(y_test, y_pred, pos_label='yes')
f1 = f1_score(y_test, y_pred, pos_label='yes')
print("准确率:", accuracy)  
print("精确率:", precision)  
print("召回率:", recall)  
print("f1:", f1)  

对于重要代码的解释:

1.fit函数:

      训练测试集的主要代码,先把训练集中所有的条件概率和先验概率算出来,在后面的预测中会使用到。

先验概率:

print("计算先验概率:")for c in self.classes:# 统计每个类别在目标标签中的出现次数,并除以样本总数,得到先验概率self.class_prior[c] = np.sum(y == c) / n_samplesprint("先验概率: 类别, 概率 "+repr(c)+" "+repr(self.class_prior[c]))

所有条件概率:

print("计算条件概率:")for c in self.classes:self.feature_prob[c] = {}  # 初始化存储特征条件概率的字典for feature_index in range(n_features):# 对于每个特征,统计在当前类别下的取值及其出现次数,并除以总次数,得到条件概率# values是feature_index列中不同的取值,counts是这些不同取值的个数(在类别为C下的)values, counts = np.unique(X[y == c, feature_index], return_counts=True)self.feature_prob[c][feature_index] = dict(zip(values, counts / np.sum(counts)))for i in range(len(counts)):print("条件概率:P(" + repr(values[i]) + "|" + repr(c) + ") = " + repr(self.feature_prob[c][feature_index][values[i]]))

 结果:

2.predict函数:

这个函数用于测试集的预测,对于测试集中的每个元组,都要对于所有类别,计算一次该类别下的后验概率,然后选择所有类别中后验概率最大的,作为预测结果,而每个后验概率,通过该元组下的每个特征下的类型对应的条件概率的累乘和该类别的先验概率的乘积来确定。

对于每个元组:

for x in X:print("\n对于第" + repr(cnt) + "个测试集:")cnt+=1max_posterior_prob = -1  # 最大后验概率初始化为-1predicted_class = None  # 预测类别初始化为空

对于每个类别:

for c in self.classes:posterior_prob = self.class_prior[c]

对于每个特征:

for feature_index, feature_value in enumerate(x):if feature_value in self.feature_prob[c][feature_index]:print(" * [P("+ repr(feature_value) + "|" + repr(c) + ") = " + repr(self.feature_prob[c][feature_index][feature_value]) + "]", end = '')posterior_prob *= self.feature_prob[c][feature_index][feature_value]else:print(" * 1")

每次计算完后,维护最大值以及类型:

if posterior_prob > max_posterior_prob:max_posterior_prob = posterior_probpredicted_class = c

每个元组计算完后,添加到预测数组中,最后返回预测数组即可。

三、实验结果

上图是最好的一个实验结果,所有指标为1,其他的实验结果准确率较低

原因分析:

        这个训练集数据过小,但是特征和每个特征中的类型又比较多,再加上测试集一共就13条,数据使用不同的随机种子会使得一些测试集中的特征在不同类别下的条件概率没有出现过,因为没有出现过,直接就不处理这个特征了,就容易出现误差。

例如:

当随机种子为1时:

当随机种子为4时:

朴素贝叶斯分类器优缺点分析:

优点:

  1. 适用广:朴素贝叶斯算法在处理大规模数据时表现良好,适用于许多实际问题。

  2. 对小规模数据表现良好:即使在小规模数据集上,朴素贝叶斯分类器也能有好的结果。

  3. 对缺失数据不敏感:朴素贝叶斯算法对缺失数据不敏感,即使有部分特征缺失或者未出现,仍然可以有效地进行分类。

缺点:

  1. 假设过于简化:朴素贝叶斯假设特征之间相互独立,在现实中,数据一般难以是真正独立的,因此会导致结果不准确。

  2. 处理连续性特征较差:朴素贝叶斯算法通常假设特征是离散的,对于连续性特征的处理不够灵活,可能会影响分类性能。

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

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

相关文章

MFC的CPen与CBush画图对象使用步骤

在MFC中,CPen和CBrush是两个常用的绘图对象,分别用于定义画笔和画刷,可以用于绘制图形、填充区域等。下面我会详细介绍如何在MFC中使用CPen和CBrush来绘制和填充图形。 使用 CPen 绘制图形: 创建 CPen 对象: 首先&am…

桥梁监控可视化大屏:现代桥梁管理的必备呀。

桥梁监控上可视化有几个重要的原因: 01.实时监控: 可视化的监控系统可以实时显示桥梁的各项监测数据,包括结构变形、振动、温度等,使监控人员能够实时了解桥梁的状态,及时发现异常情况并采取相应的措施。 02.数据分析…

MySQL前缀索引、脏页和干净页、COUNT(*)讨论、表删除内存问题

文章目录 如何加索引如何给身份证号添加索引 SQL语句变慢脏页 (Dirty Pages)干净页 (Clean Pages)为何区分脏页和干净页处理脏页管理策略 flush如何控制 为什么删除表数据后表文件大小不变问题背景核心原因数据存储方式参数影响 解决方案1. 调整innodb_file_per_table设置2. 使…

MATLAB实现遗传算法优化选址-路径LRP问题(Location-Routing Problem)

MATLAB实现遗传算法优化选址-路径LRP问题(Location-Routing Problem) 一、模型 选址车辆路径问题(Location-Routing Problem, LRP)是一个组合优化问题,旨在同时优化设施位置的选择和车辆的配送路径。在这个问题中,我们考虑一个由…

机器学习 - 决策树

1. 决策树基础 定义与概念 决策树是一种监督学习算法,主要用于分类和回归任务。它通过学习从数据特征到输出标签的映射规则,构建一个树形结构。在分类问题中,决策树的每个叶节点代表一个类别。 案例分析 假设我们有一个关于天气和是否进行…

并发-守护线程setDaemon()

目录 为什么存在 什么是守护线程 创建守护线程 在使用守护线程时需要注意以下几点 可以使用isDaemon()方法来检查线程是否是守护线程 例1:上面提到当JVM中只剩下守护线程的时候,JVM就会退出,那么写段代码测试下 例2:thread…

小红的字符串构造和小红的排列构造

小红的字符串构造 小红希望你构造一个长度为nnn的、仅包含小写字母的字符串,其中恰好有kkk个长度大于1的回文子串。你能帮帮她吗?输入两个整数n,k,用空格隔开。 1≤n≤10^5,0≤k≤n/2.一个字符串。如果有多解输出任意即可。 可以证明&#x…

[Bug]:由于中国防火墙,无法连接 huggingface.co

问题描述 : OSError: We couldnt connect to https://huggingface.co to load this file, couldnt find it in the cached files and it looks like youscan/ukr-roberta-base is not the path to a directory containing a file named config. Json. Checkout your internet …

[AIGC] 几道 redis数据结构相关面试题

文章目录 7. 数据类型的实现8. 什么是空间预分配以及惰性空间释放,SDS 是怎么实现的9. 为什么说 SDS 是二进制安全的呢10. 说说 redis 里的对象11. 使用 RedisObject 的好处12. RedisObject 的具体结构是什么 7. 数据类型的实现 8. 什么是空间预分配以及惰性空间释放…

练习题(2024/5/12)

1二分查找 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 示例 1: 输入: nums [-1,0,3,5,9,12], target 9 输出: 4…

如何远程访问?

远程访问是指在不同的地理位置之间通过网络连接来实现对目标设备或系统的访问。无论是在个人生活还是商业领域,远程访问都起到了重要的作用,帮助人们实现高效的工作和便捷的生活。本文将介绍一款名为【天联】的组网产品,它是一款强大的异地组…

Linux与Windows互传文件【笔记】

Linux与Windows互传文件【笔记】 前言前言推荐Linux与Windows互传文件首先确保Windows安装ssh如何传送文件问题 最后 前言 这是陈旧已久的草稿2023-05-10 00:01:24 这个是准备把计组课程华为智能计组的,传输文件。 最后发现,好像没有实现了。 现在202…

汽车线控转向系统介绍

汽车线控转向系统由方向盘总成、转向执行总成和主控制器(ECU)三个主要部分以及自动防故障系统、电源等辅助系统组成。 线控转向系统(Steering-By-Wire),取消了方向盘和转向车轮之间的机械连接部件,彻底摆脱了机械固件的限制,完全由电能来实现…

什么是数据平台——企业构建Data+AI的基础数据底座需要的决策参考

什么是数据平台 标准的解释是这样的 Wikipedia A data platform usually refers to a software platform used for collecting and managing data, and acting as a data delivery point for application and reporting software. 数据平台是指将各类数据进行整合、存储、处…

你知道C++多少——默认成员函数

🌈个人主页:小新_- 🎈个人座右铭:“成功者不是从不失败的人,而是从不放弃的人!”🎈 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 🏆所属专栏&#xff1…

Python vs MATLAB:选择深度学习的首选编程语言

Python vs MATLAB:选择深度学习的首选编程语言 在深度学习领域,编程语言的选择对于初学者的学习路径和未来的职业发展至关重要。目前,Python和MATLAB都是进行科学计算和数据分析的流行工具,但它们在深度学习社区中的应用和受欢迎…

ipa 分区算法分析,图解

参考 Room Segmentation: Survey, Implementation, and Analysis. 分区算法调查,实现以及评估对比 相关论文 分区算法 New Brooms Sweep Clean - An Autonomous Robotic Cleaning Assistant for Professional Office Cleaning 形态分割 Interactive SLAM using …

NOR FLASH介绍

参考 http://t.csdnimg.cn/gHcrG 一、NOR FLASH简介 XIP技术:https://blog.csdn.net/ffdia/article/details/87437872?fromshareblogdetail NOR Flash 和 NAND Flash 的特点和应用举例: NOR Flash: 特点: 支持随机访问,可以直接…

QT作业4

1、思维导图 2、使用定时器完成闹钟 头文件&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QLineEdit> #include <QLabel> #include <QPushButton> #include <QTextEdit> #include <QDebug> #include <…

Py深度学习基础|关于Batch Normalization

1. 为什么需要Batch Normalization 通常我们会在输入层进行数据的标准化处理&#xff0c;这是为了让模型学习到更好的特征。同样&#xff0c;在模型的中间层我们也可以进行normalize。在神经网络中, 数据分布对训练会产生影响。 比如我们使用tanh作为激活函数&#xff0c;当输入…