人工智能实验(五)-基于神经网络的模式识别实验

ops/2025/1/15 17:17:56/

一、实验目的

理解BP神经网络的结构和原理,掌握反向传播算法对神经元的训练过程,了解反向传播公式。通过构建BP网络模式识别实例,熟悉BP网络的原理及结构


二、实验内容

基于提供的数据集,训练1个BP神经网络模型:
1. 模型参数:
- layer num(网络层数):4
- 网络每层节点数、激活函数、训练函数、学习率等: 自定义
2. 输出:
- 模型的准确率
3. 要求:
-选择合适的模型参数
-给出神经网络训练成功后的误差变化曲线图
-设置不同的学习率,如0.01、0.1、0.5、1。给出各学习率下的误差变化曲线图,分析学习率变化对训练结果的影响。
 

三、实验原理

BP算法的基本原理

BP算法是一种监督学习算法,利用梯度下降法(Gradient Descent)来优化神经网络的权重。其工作原理分为两个阶段:前向传播(Forward Propagation)*和*反向传播(Backward Propagation)。

1. 前向传播阶段:

在前向传播阶段,输入信号通过网络的各层逐层传递,直到输出层生成网络的输出。具体过程如下:

- 输入层接收外部输入数据,将输入值传递给第一隐藏层。

- 隐藏层对接收到的信号进行加权求和,并通过激活函数(如Sigmoid、ReLU、Tanh等)进行处理,传递到下一层。

- 输出层通过激活函数生成最终输出。

通过这个过程,神经网络得到一个预测值(网络输出)。

2. 反向传播阶段:

在反向传播阶段,神经网络通过计算输出误差,并将误差反向传播回各层,逐步调整各个层的权重。具体步骤如下:

- 计算误差:首先,计算网络的预测输出与真实标签之间的误差。常用的误差度量方法是均方误差(MSE)或交叉熵损失函数

- 计算输出层的误差:在输出层,误差被定义为目标输出与实际输出的差异,然后用来计算输出层的梯度。

- 反向传播误差:接着,误差从输出层反向传播到前一层,通过链式法则计算每一层的误差。

- 更新权重和偏置:一旦得到误差,利用梯度下降法来更新各层的权重和偏置,使得误差逐渐减小。

- 梯度的计算:梯度通过链式法则逐层计算得到,梯度的大小决定了权重更新的幅度。

3. 反向传播算法的总结:

- 前向传播:从输入层到输出层,计算每一层的输出。

- 反向传播:从输出层到输入层,计算每一层的误差并更新权重。

- 梯度下降:通过梯度下降法最小化误差函数,更新网络的参数(权重和偏置)。

BP算法的关键概念:

1. 误差反向传播(Backpropagation):指的是将输出误差反向传播到前一层,计算每一层的误差,然后根据这些误差更新权重。

2. 链式法则:在反向传播过程中,使用链式法则将误差逐层传播,计算每一层权重的梯度。

3. 梯度下降法:用来优化神经网络权重的算法,沿着梯度方向调整权重,使得误差最小化。常用的有批量梯度下降、随机梯度下降和小批量梯度下降。

BP算法的优缺点:

优点:

- 可适应复杂问题:BP算法能够训练多层神经网络,适应复杂的非线性问题。

- 全局优化:通过梯度下降法,BP算法可以有效地寻找最优解,尤其是在多层网络中,能够捕捉到更复杂的模式。

缺点:

- 容易陷入局部最优解:BP算法使用梯度下降法优化误差函数,容易受到初始权重和学习率的影响,可能陷入局部最优解。

- 梯度消失问题:在深层网络中,误差通过链式法则逐层反向传播时,梯度可能会变得非常小,导致前几层的权重几乎不更新,这就是所谓的“梯度消失”问题。

- 计算复杂度高:对于大规模神经网络,BP算法需要大量的计算资源,尤其是在训练深度神经网络时。


四、数据集:wdbc_data.mat(乳腺癌威斯康星州数据集)

- 1-30:属性特征
- 31:类别
- 实验训练集/测试集:4/1
- 数据集介绍:https://archive-beta.ics.uci.edu/dataset/17/breast+cancer+wisconsin+diagnostic

五、实验步骤

基于提供的数据集,训练1个BP神经网络模型:

1. 模型参数:

- layer num(网络层数):4

- 网络每层节点数、激活函数、训练函数、学习率等: 自定义

2. 输出:

- 模型的准确率

3. 要求:

-选择合适的模型参数

-给出神经网络训练成功后的误差变化曲线图

-设置不同的学习率,如0.01、0.1、0.5、1。给出各学习率下的误差变化曲线图,分析学习率变化对训练结果的影响。

六、分析与讨论

 神经网络结构和反向传播算法的理解

在本实验中,使用的是一个4层的BP神经网络(即输入层、两个隐藏层和输出层)。BP(反向传播)神经网络是通过不断调整权重和偏置,使得网络的输出接近真实标签,从而实现模式识别的目标。在反向传播的过程中,误差由输出层传回到输入层,通过计算梯度来更新网络的参数,从而降低损失函数值。

对于乳腺癌数据集来说,我们使用的是监督学习方法,目标是通过网络学习样本中的特征与标签之间的映射关系,最终实现对新样本的分类。

网络层数:4层网络:输入层、两个隐藏层、输出层。网络的层数和每一层的节点数决定了网络的复杂度。在这里,选择了4层结构,以便通过较复杂的网络结构来捕捉乳腺癌数据中的潜在模式。

激活函数选择:常用的激活函数有 Sigmoid、ReLU、Tanh 等。在这个实验中可以选择 Sigmoid 或 ReLU 激活函数。Sigmoid 函数有平滑的导数,适合用于二分类问题(如乳腺癌的良性或恶性分类),而 ReLU 在大规模训练时通常收敛速度较快,但可能会面临“死亡神经元”的问题。

七、源代码

# 导入所需的库
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifierdef norm(x):"""对输入数据进行归一化处理。将数据的每一列分别进行最小-最大归一化,使得每一列数据都在[0,1]范围内。参数:x: 待归一化的数据矩阵。返回:归一化后的数据矩阵。"""# 转置数据矩阵,方便按列处理x = x.Tnew_list = []for i in range(x.shape[0]):arr = x[i]Min = np.min(arr)  # 获取当前列的最小值Max = np.max(arr)  # 获取当前列的最大值# 对当前列进行最小-最大归一化new_list.append((arr - Min) / (Max - Min))# 将归一化后的列表转为numpy数组并转置回原始形状new_list = np.asarray(new_list).Treturn new_listdef get_model(hidden_layer_sizes, learning_rate):"""创建并返回一个MLPClassifier模型。该模型使用Adam算法进行梯度下降,内部使用relu激活函数。隐藏层有两层,神经元个数分别为64、32。返回:初始化的MLPClassifier模型。"""model = MLPClassifier(solver='adam',  # 使用Adam算法实现梯度下降activation='relu',  # 网络内部使用relu激活函数max_iter=1000,  # 最大迭代次数,控制模型的迭代速度alpha=1e-3,  # 正则化项参数hidden_layer_sizes=hidden_layer_sizes,  # 隐藏层神经元个数learning_rate_init=learning_rate  # 学习率)return modeldef get_my_data():"""加载并预处理数据。从文件中加载WDBC数据,将数据转换为numpy数组,并进行归一化处理。将诊断结果从字符型转换为0和1表示的数组。返回:处理后的数据矩阵和目标标签数组。"""# 使用pandas从文件加载WDBC数据my_cancer = pd.read_csv("breast+cancer+wisconsin+diagnostic/wdbc.data")# 转化为numpy数据矩阵my_cancer = my_cancer.to_numpy()# 除去无关的身份证ID数据内容(第一列)cancer_data = my_cancer[:, 2::]# 提取数据中的诊断结果,作为target(第二列)ori_cancer_target = my_cancer[:, 1]cancer_target = []  # 设定诊断结果的01矩阵# M,B英文字符转化为0,1for i in range(len(ori_cancer_target)):if ori_cancer_target[i] == 'M':cancer_target.append(0)else:cancer_target.append(1)# 将数组数据转化为numpy矩阵cancer_target = np.asarray(cancer_target)# 对数据进行归一化处理cancer_data = norm(cancer_data)return cancer_data, cancer_targetdef main():"""主函数。创建模型,加载数据,训练模型,并使用模型进行预测。最后,可视化真实标签和预测标签的数据分布,并打印预测准确率。"""# 加载并预处理数据cancer_data, cancer_target = get_my_data()# 将数据分为训练集和测试集(80%训练集,20%测试集)train_data, test_data = train_test_split(cancer_data, test_size=0.2, random_state=42)train_goal, test_goal = train_test_split(cancer_target, test_size=0.2, random_state=42)errors = {}  # 用于记录不同学习率下的误差变化while True:try:# 提示用户输入学习率lr_input = input("请输入学习率(0到1之间,输入'q'退出): ")if lr_input.lower() == 'q':  # 如果用户输入'q',退出循环breaklr = float(lr_input)  # 将输入转换为浮点数if lr < 0 or lr > 1:  # 检查学习率是否在合理范围内print("学习率必须在0到1之间,请重新输入。")continue# 创建并初始化BP神经网络模型bp_network = get_model(hidden_layer_sizes=(64, 32), learning_rate=lr)# 训练模型bp_network.fit(train_data, train_goal)# 使用模型进行预测predict_test_labels = bp_network.predict(test_data)# 计算并打印预测准确率score = bp_network.score(test_data, test_goal)print(f"学习率: {lr}, 预测准确率: {score:.4f}")# 记录误差变化曲线errors[lr] = bp_network.loss_curve_# 绘制误差变化曲线plt.figure(figsize=(12, 8))  # 创建一个新的图形对象,设置大小plt.plot(bp_network.loss_curve_, label=f'Learning Rate: {lr}')  # 绘制误差曲线plt.xlabel('Epochs')  # 设置x轴标签plt.ylabel('Error')  # 设置y轴标签plt.title(f'Error vs Epochs for Learning Rate: {lr}')  # 设置图表标题plt.legend()  # 显示图例plt.show()  # 显示图表except ValueError:print("输入无效,请输入一个有效的数字或'q'退出。")main()  # 调用主函数

八、结果


http://www.ppmy.cn/ops/150045.html

相关文章

深入详解DICOM医学影像定位线相关知识:理解定位线的概念、定位线的作用以及定位线显示和计算原理

DICOM医学影像中的定位线(Localization Line) 在医学影像学中,DICOM是用于存储和交换医学影像的标准格式。定位线(Localization Line)在医学影像的显示和分析中起着重要作用,它帮助医生和医学专业人员在影像中精确地标定重要的解剖结构、区域或特征,辅助进行定位、治疗计…

一个可以把玩的针对WebSocket分段的处理方案

市场上各种高级语言的WebSocket Echo的测试方案不少&#xff0c;但找来找去&#xff0c;愣是没有一个现成的可以针对分段&#xff08;fragmetation&#xff09;处理的Echo服务端。分段处理在一些对实时性要求较高的场合非常重要&#xff0c;比如流媒体&#xff0c;实时监控等场…

英伟达CES 2025重磅发布:RTX50系列显卡与AI新品全面梳理

引言 2025年国际消费电子展&#xff08;CES&#xff09;于1月7日至10日在美国拉斯维加斯举办&#xff0c;英伟达携重磅新品亮相。全新RTX 50系列显卡凭借突破性的Blackwell架构将游戏性能提升至新高度&#xff0c;配合DLSS 4技术实现了前所未有的画面质量。同时发布的AI芯片、…

uniapp火车票样式

<template><view class"train-ticket"><view class"header"><view class"header-left"><text class"logo">铁路</text><text class"ticket-type">电子客票</text></vie…

宁德时代C++后端开发面试题及参考答案

请阐述面向对象的三大特性。 面向对象编程有三大特性,分别是封装、继承和多态。 封装是指将数据和操作数据的方法绑定在一起,对数据的访问和操作进行限制。这样做的好处是可以隐藏对象的内部细节,只暴露必要的接口给外部。例如,我们可以把一个汽车类的内部引擎状态、速度等…

《零基础Go语言算法实战》【题目 2-4】一个函数中的多个值

《零基础Go语言算法实战》 【题目 2-4】一个函数中的多个值 Go 语言是否可以返回一个函数中的多个值&#xff1f;举例说明。 【解答】 Go 函数可以返回多个值&#xff0c;在 return 语句中值之间用逗号分隔。示例如下&#xff1a; package main import "fmt" func mu…

20_Spring Boot默认缓存管理

从这么模块开始给大家介绍Redis应用的相关知识。主要的学习目标见下: 了解Spring Boot的默认缓存管理掌握Spring Boot的常用缓存注解掌握Spring Boot如何整合Redis掌握Spring Boot中使用Redis实现缓存掌握Spring Boot中自定义Redis缓存序列化机制掌握StringRedisTemplate操作R…

用 Python 从零开始创建神经网络(二十):模型评估

模型评估 引言 引言 在第11章《测试或样本外数据》中&#xff0c;我们讨论了验证数据和测试数据之间的区别。对于目前的模型&#xff0c;我们在训练过程中进行了验证&#xff0c;但目前没有一个好的方法来对测试数据运行测试或进行预测。首先&#xff0c;我们将在Model类中添加…