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

news2025/1/14 13:19:22

一、实验目的

理解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()  # 调用主函数

八、结果

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

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

相关文章

【伪随机数】关于排序算法自测如何生成随机数而引发的……

以 Random 开始 可能一开始&#xff0c;你只是写到了排序算法如何生成随机数 public static void main(String[] args) {Random random new Random();int[] nums new int[10];for (int i 0; i < nums.length; i) {nums[i] random.nextInt(100);}System.out.println(&q…

【LeetCode】力扣刷题热题100道(26-30题)附源码 轮转数组 乘积 矩阵 螺旋矩阵 旋转图像(C++)

目录 1.轮转数组 2.除自身以外数组的乘积 3.矩阵置零 4.螺旋矩阵 5.旋转图像 1.轮转数组 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 class Solution { public:void rotate(vector<int>& nums, int k) …

IDEA中创建maven项目

1. IDEA中创建maven项目 在IDEA中创建Maven项目&#xff0c;前提是已经安装配置好Maven环境。如还未配置安装Maven的&#xff0c;请先下载安装。如何下载安装&#xff0c;可参考我另外篇文章&#xff1a;maven的下载与安装教程本篇教程是以创建基于servlet的JavaWeb项目为例子&…

【PyQt】如何在mainwindow中添加菜单栏

[toc]如何在mainwindow中添加菜单栏 如何在mainwindow中添加菜单栏 主要有两种方法&#xff1a; 1.直接创建mainwindow进行添加 2.使用ui文件加载添加 第二种方法更为常见&#xff0c;可以应用到实际 1.直接创建mainwindow进行添加 import sysfrom PyQt5.QtWidgets import …

Kubernetes1.28 编译 kubeadm修改证书有效期到 100年.并更新k8s集群证书

文章目录 前言一、资源准备1. 下载对应源码2.安装编译工具3.安装并设置golang 二、修改证书有效期1.修改证书有效期2.修改 CA 证书有效期 三、编译kubeadm四、使用新kubeadm方式1.当部署新集群时,使用该kubeadm进行初始化2.替换现有集群kubeadm操作 前言 kubeadm 默认证书为一…

Web前端:JavaScript标识符与变量

JavaScript介绍 JavaScript 是一种轻量级的脚本语言。所谓“脚本语言”&#xff0c;指的是它不具备开发操作系统的能力&#xff0c;而是只用来编写控制其他大型应用程序的“脚本”。 JavaScript 是一种嵌入式&#xff08;embedded&#xff09;语言。它本身提供的核心语法不算…

【从零开始使用系列】StyleGAN2:开源图像生成网络——环境搭建与基础使用篇(附大量测试图)

StyleGAN2 是英伟达团队 NVIDIA 提出的生成对抗网络&#xff08;GAN&#xff09;的一种改进版本。 它通过创新的网络架构&#xff0c;能够生成细节丰富、逼真的图像&#xff0c;特别在高频细节&#xff08;如皮肤纹理、光照等&#xff09;的表现上表现卓越。与传统 GAN 相比&am…

【时时三省】(C语言基础)经典笔试题2

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 题目 这个代码有什么问题&#xff1f; 过程&#xff1a; 从主函数开始进入Test函数&#xff0c;在这个Test函数里面&#xff0c;创建了一个str指针变量&#xff0c;str里面放了一个空指针&…

Therabody 与Garmin联手,共同推进运动恢复与健康科技新突破

本次合作以数据整合、人工智能驱动的数字教练与科学研究为重点&#xff0c;旨在更好地了解科学恢复对运动表现的影响 &#xff08;2025年1月13日&#xff0c;中国上海&#xff09;全球健康领导者Therabody宣布与智能手表品牌Garmin佳明建立战略合作关系&#xff0c;共同致力于…

vue城市道路交通流量预测可视化系统

项目亮点 编号&#xff1a;R09 &#x1f687; 网站大屏管理三大前端、vuespringbootmysql、前后端分离架构 &#x1f687; 流量预测道路查询流量查询 &#x1f687; echarts可视化、地图流量分析、限流分析、站点流量分析等 &#x1f687; 管理员可以进行、用户管理、道路信息…

云集电商:数据库的分布式升级实践|OceanBase案例

电商行业对数据库有哪些需求 云集电商作为一家传统电商企业&#xff0c;业务涵盖了美妆个护、服饰、水果生鲜、健康保健等多个领域&#xff0c;在创立四年后在纳斯达克上市&#xff08;股票代码&#xff1a;YJ&#xff09;。与京东、淘宝、拼多多等电商平台不同&#xff0c;云…

Lianwei 安全周报|2025.1.13

新的一周又开始了&#xff0c;以下是本周「Lianwei周报」&#xff0c;我们总结推荐了本周的政策/标准/指南最新动态、热点资讯和安全事件&#xff0c;保证大家不错过本周的每一个重点&#xff01; 政策/标准/指南最新动态 01 美国国土安全部发布《公共部门生成式人工智能部署手…

【江协STM32】11-2/3 W25Q64简介、软件SPI读写W25Q64

1. W25Q64简介 W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器&#xff0c;常应用于数据存储、字库存储、固件程序存储等场景存储介质&#xff1a;Nor Flash&#xff08;闪存&#xff09;时钟频率&#xff1a;80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI)存储容…

RNN之:LSTM 长短期记忆模型-结构-理论详解-及实战(Matlab向)

0.前言 递归&#xff01;循环神经网络Recurrent Neural Network 循环神经网络&#xff08;又称递归神经网络&#xff0c;Recurrent Neural Network&#xff0c;RNN&#xff09;。是一种用于处理序列数据的神经网络结构&#xff0c;具有记忆功能&#xff0c;能够捕捉序列中的时…

SOLID原则学习,接口隔离原则

文章目录 1. 定义2. 为什么要遵循接口隔离原则&#xff1f;3. 违反接口隔离原则的例子4. 遵循接口隔离原则的改进5. 总结 1. 定义 接口隔离原则&#xff08;Interface Segregation Principle, ISP&#xff09; 接口隔离原则是面向对象设计中的五大原则&#xff08;SOLID&#…

Qt WORD/PDF(五)使用Json一键填充Word表格

关于QT Widget 其它文章请点击这里: QT Widget 国际站点 GitHub: https://github.com/chenchuhan 国内站点 Gitee : https://gitee.com/chuck_chee 姊妹篇: 《Qt WORD/PDF&#xff08;一&#xff09;使用 QtPdfium库实现 PDF 操作》 《Qt WORD/PDF&#…

AIGC时代 | 探索AI Agent的奥秘:四种设计模式引领未来智能趋势

文章目录 1. 反思案例&#xff1a; 2. 工具使用案例&#xff1a; 3. 规划案例&#xff1a; 4. 多Agent协作案例&#xff1a; 总结作者简介&#xff1a;延伸阅读内容简介&#xff1a;目录 导读&#xff1a;AI Agent是指能够在特定环境中自主执行任务的人工智能系统&#xff0c;不…

消息队列使用中防止消息丢失的实战指南

消息队列使用中防止消息丢失的实战指南 在分布式系统架构里&#xff0c;消息队列起着举足轻重的作用&#xff0c;它异步解耦各个业务模块&#xff0c;提升系统整体的吞吐量与响应速度。但消息丢失问题&#xff0c;犹如一颗不定时炸弹&#xff0c;随时可能破坏系统的数据一致性…

Python爬虫-汽车之家各车系周销量榜数据

前言 本文是该专栏的第43篇,后面会持续分享python爬虫干货知识,记得关注。 在本专栏之前,笔者在文章《Python爬虫-汽车之家各车系月销量榜数据》中,有详细介绍,如何爬取“各车系车型的月销量榜单数据”的方法以及完整代码教学教程。 而本文,笔者同样以汽车之家平台为例,…

[C++]类与对象(上)

目录 &#x1f495;1.C中结构体的优化 &#x1f495;2.类的定义 &#x1f495;3.类与结构体的不同点 &#x1f495;4.访问限定符(public,private,protected) &#x1f495;5.类域 &#x1f495;6.类的实例化 &#x1f495;7.类的字节大小 &#x1f495;8.类的字节大小特例…