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

一、实验目的

理解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 MLPClassifier


def norm(x):
    """
    对输入数据进行归一化处理。
    将数据的每一列分别进行最小-最大归一化,使得每一列数据都在[0,1]范围内。

    参数:
    x: 待归一化的数据矩阵。

    返回:
    归一化后的数据矩阵。
    """
    # 转置数据矩阵,方便按列处理
    x = x.T
    new_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).T
    return new_list




def 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 model



def 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,1
    for 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_target


def 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',退出循环
                break
            lr = 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()  # 调用主函数

八、结果

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开发手札:.asmdef和RuntimeInitializeOnLoadMethod

最近为了快速响应临时小demo和老项目改造开发&#xff0c;思考了几种方式。 一般我们开发都是基于一套完善的unity框架进行的&#xff0c;完全建一个new project就是干&#xff0c;这样开发不仅慢而且乱。我们组框架代码都有现成的&#xff0c;而且组员都熟练使用了&…

九 RK3568 android11 MPU6500

一 MPU6500 内核驱动 1.1 查询设备连接地址 查看原理图, MPU6500 I2C 连接在 I2C4 上, 且中断没有使用 i2c 探测设备地址为 0x68 1.2 驱动源码 drivers/input/sensors/gyro/mpu6500_gyro.c drivers/input/sensors/accel/mpu6500_acc.c 默认 .config 配置编译了 mpu6550 …

Quinlan C4.5剪枝U(0,6)U(1,16)等置信上限如何计算?

之前看到Quinlan中关于C4.5决策树算法剪枝环节中,关于错误率e置信区间估计,为啥 当E=0时,U(0,1)=0.75,U(0,6)=0.206,U(0,9)=0.143? 而当E不为0时,比如U(1,16)=0.157,如图: 关于C4.5决策树,Quinlan写了一本书,如下: J. Ross Quinlan (Auth.) - C4.5. Programs f…

机器学习第一道菜(一):线性回归的理论模型

机器学习第一道菜&#xff08;一&#xff09;&#xff1a;线性回归的理论模型 一、问题&#xff1a;千金买笑1.1 散点图1.2 机器学习能搞啥 二、模型的建立2.1 线性回归2.2 回归模型 前面讲了机器学习的“四大绝技”&#xff0c;今天&#xff0c;开始研究第一绝技“回归”&…

Edge Scdn是什么,它如何提升网站安全性与访问速度?

随着网络攻击的日益猖獗&#xff0c;尤其是分布式拒绝服务&#xff08;DDoS&#xff09;攻击的频繁发生&#xff0c;如何保护网站的安全性并确保用户的访问体验变得极为重要。Edge Scdn&#xff08;内容分发网络&#xff09;作为一种新兴的技术方案&#xff0c;逐渐被越来越多的…

深入浅出Redis持久化

文章目录 前言RDB快照原理保存时机 AOF同步策略AOF重写 混合持久化总结 前言 redis作为内存数据库&#xff0c;数据都在内存里&#xff0c;如果突然宕机&#xff0c;则数据都会丢失&#xff08;这里假设不使用非易失性内存&#xff09;&#xff0c;redis提供了持久化机制来防止…

JAVA实现五子棋小游戏(附源码)

文章目录 一、设计来源捡金币闯关小游戏讲解1.1 主界面1.2 黑棋胜利界面1.3 白棋胜利界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载更多优质源码分享 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/145161039 JA…

无公网IP 实现外网访问本地 Docker 部署 Navidrome

Navidrome 是一款可以在 macOS、Linux、Windows以及 Docker 等平台上运行的跨平台开源音乐服务器应用&#xff0c;它支持传输常见的 MP3、FLAC、WAV等音频格式。允许用户通过 Web 界面或 API 进行音乐库的管理和访问。本文就介绍如何快速在 Linux 系统使用 Docker 进行本地部署…

JS后盾人--JS数组挖掘(少年篇)

数组引用类型分析 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </he…

VirtualBox环境中vscode报错:提取扩展时出错。Failed to fetch

问题现象&#xff1a; VSCode切换到扩展并筛选特色时(为了触发联网)&#xff0c;提示提取扩展时出错。Failed to fetch 拔网线复现不了&#xff0c;完全没有网络VSCode只会提示离线 虚拟机内Edge浏览器访问https://marketplace.visualstudio.com/直接报ERR_CONNECTION_REFUSED…

HTML文章翻页功能

效果展示&#xff1a; 效果原理&#xff1a; 1、引入CDN 2、绘制文章翻页样式&#xff0c;以及自动分段 3、获取窗口宽高&#xff0c;计算出当前文章总分段&#xff0c;并实现分页 4、完整代码 <!DOCTYPE html> <html><head><meta charset"utf-8&qu…

IDEA运行测试函数@Test注解旁边没有运行按钮

如图我想直接运行 testSaveShop 函数进行测试&#xff0c;但是旁边没有运行按钮。 解决办法&#xff1a;测试类需要加上public&#xff0c;系统才能识别到并调用运行。 位置如下&#xff0c;在类和方法都加上 public &#xff0c;然后就会出现运行按钮&#xff1a; 但是如果点…

计算机网络 (38)TCP的拥塞控制

前言 TCP拥塞控制是传输控制协议&#xff08;Transmission Control Protocol&#xff0c;TCP&#xff09;避免网络拥塞的算法&#xff0c;是互联网上主要的一个拥塞控制措施。 一、目的 TCP拥塞控制的主要目的是防止过多的数据注入到网络中&#xff0c;使网络能够承受现有的网络…

使用jupyter notebook没有正常打开浏览器的几种情况解决

迅速记录前期 1.下载 https://www.anaconda.com/products/individual 2.安装 直接默认安装就行 3.打开jupyter notebook 在开始菜单里面可以找到 4.遇到的问题解决 1.运行jupyter notebook&#xff0c;黑窗口自动关了 每次黑窗口迅速的加载完就自己关掉了 也没有打开新…

29、Spark写数据到Hudi时,同步hive表的一些坑

1.hudi的同步hive表没有comment 原以为hudi同步的hive表是根据数据写入的dataframe的schema创建的。就和spark write hive时类似&#xff0c;查看源码后发现不是。 1.1 hudi同步hive的模式 HMS , JDBC , HIVESQL。我这儿常用的是HMS和JDBC 各个同步模式对应的执行器&#x…

wordpress zibll 2025款新页脚-6ke论坛

演示地址&#xff1a;6KE论坛-综合开放交流论坛 [hidecontent type"reply" desc"隐藏内容&#xff1a;评论后查看"] [/hidecontent]

Freeswitch使用media_bug能力实现回铃音检测

利用freeswitch的media bug能力来在智能外呼时通过websocket对接智能中心的声音检测接口&#xff0c;来实现回铃音检测&#xff0c;来判断用户当前是否已响应&#xff0c;拒接&#xff0c;关机等。 1.回铃音处理流程 2.模块源码目录结构 首先新建一个freeswitch的源码的src/a…

基于SpringBoot的企业级工位管理系统【源码+文档+部署讲解】

系统介绍 基于SpringBootVue实现的企业级工位管理系统采用前后端分离架构方式&#xff0c;系统设计了管理员、员工两种角色&#xff0c;系统实现了用户登录与注册、个人中心、员工管理、部门信息管理、工位信息管理、使用情况管理、工位分配管理等功能。 技术选型 开发工具&…

keepalived双机热备(LVS+keepalived)实验笔记

目录 前提准备&#xff1a; keepalived1&#xff1a; keepalived2&#xff1a; web1&#xff1a; web2&#xff1a; keepalived介绍 功能特点 工作原理 应用场景 前提准备&#xff1a; 准备4台centos&#xff0c;其中两台为keepalived&#xff0c;两台为webkeepalive…

【Linux】12.Linux进程概念(1)

文章目录 1. 冯诺依曼体系结构2. 操作系统(Operator System)概念设计OS的目的胆小的操作系统定位如何理解 "管理"总结 3. 进程基本概念task_struct-PCB的一种task_ struct内容分类组织进程查看进程通过系统调用获取进程标示符通过系统调用创建进程-fork初识 1. 冯诺依…