【深度学习实验】前馈神经网络(final):final

news2024/11/16 11:31:37

目录

一、实验介绍

 二、实验环境

1. 配置虚拟环境

2. 库版本介绍

三、实验内容

0. 导入必要的工具包

1. 构建数据集(IrisDataset)

2. 构建模型(FeedForward)

a. __init__(初始化)

b. forward(前向传播)

3.整合训练、评估、预测过程(Runner)

4. 模型评价(Accuracy)

5. 代码整合


一、实验介绍

      

 二、实验环境

    本系列实验使用了PyTorch深度学习框架,相关操作如下:

1. 配置虚拟环境

conda create -n DL python=3.7 
conda activate DL
pip install torch==1.8.1+cu102 torchvision==0.9.1+cu102 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
conda install matplotlib
 conda install scikit-learn

2. 库版本介绍

软件包本实验版本目前最新版
matplotlib3.5.33.8.0
numpy1.21.61.26.0
python3.7.16
scikit-learn0.22.11.3.0
torch1.8.1+cu1022.0.1
torchaudio0.8.12.0.2
torchvision0.9.1+cu1020.15.2

三、实验内容

ChatGPT:

        前馈神经网络(Feedforward Neural Network)是一种常见的人工神经网络模型,也被称为多层感知器(Multilayer Perceptron,MLP)。它是一种基于前向传播的模型,主要用于解决分类和回归问题。

        前馈神经网络由多个层组成,包括输入层、隐藏层和输出层。它的名称"前馈"源于信号在网络中只能向前流动,即从输入层经过隐藏层最终到达输出层,没有反馈连接。

以下是前馈神经网络的一般工作原理:

  1. 输入层:接收原始数据或特征向量作为网络的输入,每个输入被表示为网络的一个神经元。每个神经元将输入加权并通过激活函数进行转换,产生一个输出信号。

  2. 隐藏层:前馈神经网络可以包含一个或多个隐藏层,每个隐藏层由多个神经元组成。隐藏层的神经元接收来自上一层的输入,并将加权和经过激活函数转换后的信号传递给下一层。

  3. 输出层:最后一个隐藏层的输出被传递到输出层,输出层通常由一个或多个神经元组成。输出层的神经元根据要解决的问题类型(分类或回归)使用适当的激活函数(如Sigmoid、Softmax等)将最终结果输出。

  4. 前向传播:信号从输入层通过隐藏层传递到输出层的过程称为前向传播。在前向传播过程中,每个神经元将前一层的输出乘以相应的权重,并将结果传递给下一层。这样的计算通过网络中的每一层逐层进行,直到产生最终的输出。

  5. 损失函数和训练:前馈神经网络的训练过程通常涉及定义一个损失函数,用于衡量模型预测输出与真实标签之间的差异。常见的损失函数包括均方误差(Mean Squared Error)和交叉熵(Cross-Entropy)。通过使用反向传播算法(Backpropagation)和优化算法(如梯度下降),网络根据损失函数的梯度进行参数调整,以最小化损失函数的值。

        前馈神经网络的优点包括能够处理复杂的非线性关系,适用于各种问题类型,并且能够通过训练来自动学习特征表示。然而,它也存在一些挑战,如容易过拟合、对大规模数据和高维数据的处理较困难等。为了应对这些挑战,一些改进的网络结构和训练技术被提出,如卷积神经网络(Convolutional Neural Networks)和循环神经网络(Recurrent Neural Networks)等。

本系列为实验内容,对理论知识不进行详细阐释

(咳咳,其实是没时间整理,待有缘之时,回来填坑)

977468b5ae9843c6a88005e792817cb1.png

0. 导入必要的工具包

import torch
from torch import nn
import torch.nn.functional as F
# 绘画时使用的工具包
import matplotlib.pyplot as plt
# 导入鸢尾花数据集
from sklearn.datasets import load_iris
# 构建自己的数据集,继承自Dataset类
from torch.utils.data import Dataset, DataLoader

1. 构建数据集(IrisDataset)

【深度学习实验】前馈神经网络(七):批量加载数据(直接加载数据→定义类封装数据)_QomolangmaH的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_63834988/article/details/133181882?spm=1001.2014.3001.5501

2. 构建模型(FeedForward)

        依靠深度学习框架,构建一个简单的两层前馈神经网络。这个前馈神经网络和前文实现的MLP类最大的区别在于,我们实现类中使用了自己写的激活函数,该激活函数不能通过反向传播更新参数,但深度学习框架已经帮我们完成了这个功能。(其实通过简单的改动,我们的激活函数也可以反传梯度)

【深度学习实验】前馈神经网络(三):自定义多层感知机(激活函数logistic、线性层算Linear)_QomolangmaH的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_63834988/article/details/133097102?spm=1001.2014.3001.5501

class FeedForward(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(FeedForward,self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.fc2 = nn.Linear(hidden_size, output_size)
        self.act = nn.Sigmoid()
    
    def forward(self, inputs):
        outputs = self.fc1(inputs)
        outputs = self.act(outputs)
        outputs = self.fc2(outputs)
        return outputs

a. __init__(初始化)

  • 三个参数:
    • input_size(输入大小)
    • hidden_size(隐藏层大小)
    • output_size(输出大小)
  • 调用父类nn.Module的初始化方法super(FeedForward, self).init(),确保正确地初始化该类作为一个nn.Module。
  • 两个线性层self.fc1和self.fc2:
    • self.fc1的输入大小为input_size,输出大小为hidden_size;
    • self.fc2的输入大小为hidden_size,输出大小为output_size。
  • 一个激活函数self.act,这里使用的是nn.Sigmoid(),即Sigmoid激活函数。

b. forward(前向传播)

  • 接受一个输入张量inputs。在前向传播过程中,
    • 输入经过self.fc1线性层,
    • 然后通过self.act激活函数进行非线性变换,
    • 再经过self.fc2线性层得到最终的输出张量outputs

3.整合训练、评估、预测过程(Runner)

4. 模型评价(Accuracy)

【深度学习实验】前馈神经网络(八):模型评价(自定义支持分批进行评价的Accuracy类)_QomolangmaH的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_63834988/article/details/133186305?spm=1001.2014.3001.5501

5. 代码整合

# 导入必要的工具包
import torch
from torch import nn
import torch.nn.functional as F
# 绘画时使用的工具包
import matplotlib.pyplot as plt
# 导入鸢尾花数据集
from sklearn.datasets import load_iris
# 构建自己的数据集,继承自Dataset类
from torch.utils.data import Dataset, DataLoader


# 此函数用于加载鸢尾花数据集
def load_data(shuffle=True):
    x = torch.tensor(load_iris().data)
    y = torch.tensor(load_iris().target)

    # 数据归一化
    x_min = torch.min(x, dim=0).values
    x_max = torch.max(x, dim=0).values
    x = (x - x_min) / (x_max - x_min)

    if shuffle:
        idx = torch.randperm(x.shape[0])
        x = x[idx]
        y = y[idx]
    return x, y
class IrisDataset(Dataset):
    def __init__(self, mode='train', num_train=120, num_dev=15):
        super(IrisDataset, self).__init__()
        x, y = load_data(shuffle=True)
        if mode == 'train':
            self.x, self.y = x[:num_train], y[:num_train]
        elif mode == 'dev':
            self.x, self.y = x[num_train:num_train + num_dev], y[num_train:num_train + num_dev]
        else:
            self.x, self.y = x[num_train + num_dev:], y[num_train + num_dev:]

    def __getitem__(self, idx):
        return self.x[idx], self.y[idx]

    def __len__(self):
        return len(self.x)

class FeedForward(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(FeedForward, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.fc2 = nn.Linear(hidden_size, output_size)
        self.act = nn.Sigmoid()

    def forward(self, inputs):
        outputs = self.fc1(inputs)
        outputs = self.act(outputs)
        outputs = self.fc2(outputs)
        return outputs


# 支持分批进行模型评价的 Accuracy 类
class Accuracy:
    def __init__(self, is_logist=True):
        # 正确样本个数
        self.num_correct = 0
        # 样本总数
        self.num_count = 0
        self.is_logist = is_logist

    def update(self, outputs, labels):
        # 判断是否为二分类任务
        if outputs.shape[1] == 1:
            outputs = outputs.squeeze(-1)
            # 判断是否是logit形式的预测值
            if self.is_logist:
                preds = (outputs >= 0).long()
            else:
                preds = (preds >= 0.5).long()
        else:
            # 多分类任务时,计算最大元素索引作为类别
            preds = torch.argmax(outputs, dim=1).long()

        # 获取本批数据中预测正确的样本个数
        labels = labels.squeeze(-1)
        batch_correct = (preds == labels).float().sum()
        batch_count = len(labels)
        # 更新
        self.num_correct += batch_correct
        self.num_count += batch_count

    def accumulate(self):
        # 使用累计的数据,计算总的评价指标
        if self.num_count == 0:
            return 0
        return self.num_correct / self.num_count

    def reset(self):
        self.num_correct = 0
        self.num_count = 0


class Runner(object):
    def __init__(self, model, optimizer, loss_fn, metric, **kwargs):
        self.model = model
        self.optimizer = optimizer
        self.loss_fn = loss_fn
        # 用于计算评价指标
        self.metric = metric

        # 记录训练过程中的评价指标变化
        self.dev_scores = []
        # 记录训练过程中的损失变化
        self.train_epoch_losses = []
        self.dev_losses = []
        # 记录全局最优评价指标
        self.best_score = 0

    # 模型训练阶段
    def train(self, train_loader, dev_loader=None, **kwargs):
        # 将模型设置为训练模式,此时模型的参数会被更新
        self.model.train()

        num_epochs = kwargs.get('num_epochs', 0)
        log_steps = kwargs.get('log_steps', 100)
        save_path = kwargs.get('save_path', 'best_mode.pth')
        eval_steps = kwargs.get('eval_steps', 0)
        # 运行的step数,不等于epoch数
        global_step = 0

        if eval_steps:
            if dev_loader is None:
                raise RuntimeError('Error: dev_loader can not be None!')
            if self.metric is None:
                raise RuntimeError('Error: Metric can not be None')

        # 遍历训练的轮数
        for epoch in range(num_epochs):
            total_loss = 0
            # 遍历数据集
            for step, data in enumerate(train_loader):
                x, y = data
                logits = self.model(x.float())
                loss = self.loss_fn(logits, y.long())
                total_loss += loss
                if log_steps and global_step % log_steps == 0:
                    print(f'loss:{loss.item():.5f}')

                loss.backward()
                self.optimizer.step()
                self.optimizer.zero_grad()
            # 每隔一定轮次进行一次验证,由eval_steps参数控制,可以采用不同的验证判断条件
            if (epoch + 1) % eval_steps == 0:

                dev_score, dev_loss = self.evaluate(dev_loader, global_step=global_step)
                print(f'[Evalute] dev score:{dev_score:.5f}, dev loss:{dev_loss:.5f}')

                if dev_score > self.best_score:
                    self.save_model(f'model_{epoch + 1}.pth')

                    print(
                        f'[Evaluate]best accuracy performance has been updated: {self.best_score:.5f}-->{dev_score:.5f}')
                    self.best_score = dev_score

                # 验证过程结束后,请记住将模型调回训练模式
                self.model.train()

            global_step += 1
            # 保存当前轮次训练损失的累计值
            train_loss = (total_loss / len(train_loader)).item()
            self.train_epoch_losses.append((global_step, train_loss))

        print('[Train] Train done')

    # 模型评价阶段
    def evaluate(self, dev_loader, **kwargs):
        assert self.metric is not None
        # 将模型设置为验证模式,此模式下,模型的参数不会更新
        self.model.eval()
        global_step = kwargs.get('global_step', -1)
        total_loss = 0
        self.metric.reset()

        for batch_id, data in enumerate(dev_loader):
            x, y = data
            logits = self.model(x.float())
            loss = self.loss_fn(logits, y.long()).item()
            total_loss += loss
            self.metric.update(logits, y)

        dev_loss = (total_loss / len(dev_loader))
        self.dev_losses.append((global_step, dev_loss))
        dev_score = self.metric.accumulate()
        self.dev_scores.append(dev_score)
        return dev_score, dev_loss

    # 模型预测阶段,
    def predict(self, x, **kwargs):
        self.model.eval()
        logits = self.model(x)
        return logits

    # 保存模型的参数
    def save_model(self, save_path):
        torch.save(self.model.state_dict(), save_path)

    # 读取模型的参数
    def load_model(self, model_path):
        self.model.load_state_dict(torch.load(model_path, map_location=torch.device('cpu')))

batch_size = 16

# 分别构建训练集、验证集和测试集
train_dataset = IrisDataset(mode='train')
dev_dataset = IrisDataset(mode='dev')
test_dataset = IrisDataset(mode='test')

train_loader = DataLoader(train_dataset, batch_size=batch_size,shuffle=True)
dev_loader = DataLoader(dev_dataset, batch_size=batch_size)
test_loader = DataLoader(test_dataset, batch_size=1, shuffle=True)

input_size = 4
output_size = 3
hidden_size = 6
# 定义模型
model = FeedForward(input_size, hidden_size, output_size)
# 定义损失函数
loss_fn = F.cross_entropy
# 定义优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.2)
# 定义评价方法
metric = Accuracy(is_logist=True)
# 实例化辅助runner类
runner = Runner(model, optimizer, loss_fn, metric)
# 模型训练
runner.train(train_loader, dev_loader, num_epochs=50, log_steps=10, eval_steps=5)

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

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

相关文章

Mojo:新型AI语言中的7个令人惊叹的Python升级,用简单的英语解释人工智能

Mojo:新型AI语言中的7个令人惊叹的Python升级 编程之美 用简单的英语解释人工智能 编程之美 由Coding Beauty设计的图像,使用Mojo标志和Python标志。 它比C更快,与Python一样简单,但速度提高了35000倍。 进入Mojo:一种…

冒泡排序与选择排序(最low的两兄弟)

个人主页:Lei宝啊 愿所有美好如期而遇 前言: 在我们的生活中,无处不在用到排序,比如说成绩的排名,淘宝,京东等等商品在各个方面的排序,这样看来一个好的算 法很重要,接下来我们要先…

深度学习自学笔记四:浅层神经网络(一)

一、神经网络概述 神经网络是一种模仿人脑神经系统结构和功能的计算模型。它由大量相互连接的人工神经元组成,并通过这些神经元之间的信息传递来进行计算和学习。 神经网络的基本组成单元是神经元,也称为节点或单元。每个神经元接收来自其他神经元的输…

第一百五十二回 自定义组件综合实例:游戏摇杆三

文章目录 内容回顾优化性能示例代码我们在上一章回中介绍了 如何实现游戏摇杆相关的内容,本章回中将继续介绍这方面的知识.闲话休提,让我们一起Talk Flutter吧。 内容回顾 我们在前面章回中介绍了游戏摇杆的概念以及实现方法,并且通过示例代码演示了实现游戏摇杆的整个过程…

取消github向邮箱推送邮件及修改密码

取消或者说禁止github向邮箱推送邮件,因为量太大了,没多久就上万封邮件,于是取消订阅或者推送。 1、登录github 2、点击右上角头像,然后点击Settings 3、点击Notifications(通知) 4、取消各种推送&#x…

SpringBoot开发实战(微课视频版)

ISBN: 978-7-302-52819-7 编著:吴胜 页数:311页 阅读时间:2023-06-24 推荐指数:★★★★☆ 本文介绍SpringBoot 2.0.5 、JDK 1.8,虽然现在已经不维护了,但是大体的流程还是对口的, 而且书里面讲…

新手学习:ArcGIS对shp文件裁剪

新手学习:ArcGIS对SHP文件裁剪 新手学习 记录每个步骤,因为有很多控件可能刚开始还不熟悉,根本不知道在哪里,所以写的比较详细。 1.添加要裁剪的shp文件 2.查看shp文件的地理坐标系 双击shp文件,就可以查看shp文件的…

LeetCode【174. 地下城游戏】

一片丹心图报国,两行清泪为忠家。——于谦 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士的初始健康…

【Linux】系统编程基于环形队列生产者消费者模型(C++)

目录 【1】引入POSIX信号量 【1.1】初始化信号量 【1.2】销毁信号量 【1.3】等待信号量 【1.4】发布信号量 【2】基于环形队列的生产消费模型 【2.1】生产消费模型打印数字模型 【2.2】生产消费模型计算公式模型 【2.3】生产消费模型计算公式加保存任务模型 【1】引入…

###Data Structure###考研重点

顺序表 顺序表 (此代码i是序号而非角标) 结构体: 插入:从最后一个元素逐个往后移一位 删除:从删除位置的下一个把每个提前一位 顺序(循环)队列 结构体 判断队满 (总结&#xff…

Dependency ‘org.redisson:redisson:‘ not found解决方法 三种刷新Maven项目的方法

报错情况 在pom中导入redisson包 <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId> </dependency> 爆红&#xff0c;还显示Dependency org.redisson:redisson: not found。 由于报错已经解决&#xff0c;…

postgresql-触发器

postgresql-触发器 触发器概述创建触发器管理触发器删除触发器事件触发器创建事件触发器修改触发器删除事件触发器 触发器概述 PostgreSQL 触发器&#xff08;trigger&#xff09;是一种特殊的函数&#xff0c;当某个数据变更事件&#xff08;INSERT、UPDATE、 DELETE 或者 TR…

6 年大厂程序员跟你聊聊,算法其实没那么难,要怎么准备比较好

说起算法&#xff0c;许多程序员都会一顿哀嚎&#xff0c;为啥面试要靠算法这个东西。不过这个不是咱们讨论的重点。&#xff08;我们无法改变这种现状&#xff0c;那就改变自己&#xff09; 今天&#xff0c;我们一起来聊一下&#xff0c;程序员面试的时候该如何准备算法。 …

数字图像基础,数字图像处理中的基础内容(数字图像处理概念 P2)

文章目录 人类视觉系统构造数字图像生成采样和量化像素之间的基本关系 人类视觉系统构造 锥状体&#xff1a;明亮的视野杆状体&#xff1a;微光或暗视野图像成像原理&#xff1a;类似照相机亮度适应现象&#xff1a;人的视觉不能同时在一个范围内工作同时对比现象&#xff1a;…

怒刷LeetCode的第14天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;动态规划 方法二&#xff1a;栈 方法三&#xff1a;双指针 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;二分查找 方法二&#xff1a;线性扫描 方法三&#xff1a;递归 第三题 题目来源 …

【WSL】仅适用于装C盘情况-用WSL在win10安装LInux

研究了一点点伪分布式的内容。决定搞一个Linux系统玩一下 参考来自微软官方安装步骤&#xff1a; 旧版 WSL 的手动安装步骤 https://learn.microsoft.com/zh-cn/windows/wsl/install-manual WSL全称为&#xff0c;Windows Subsystem for Linux 法一&#xff1a;应用商店装 查…

你写过的最蠢的代码是?

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

RestTemplate:简化HTTP请求的强大工具

文章目录 什么是RestTemplateRestTemplate的作用代码示例 RestTemplate与HttpClient 什么是RestTemplate RestTemplate是一个在Java应用程序中发送RESTful HTTP请求的强大工具。本文将介绍RestTemplate的定义、作用以及与HttpClient的对比&#xff0c;以帮助读者更好地理解和使…

资料分析笔记

统计术语 现期&#xff1a;现在的时间 基期&#xff1a;之前的时间 现期量 基期量 增长量&#xff08;有正负&#xff09; 增长率 【增幅、增速、r】&#xff08;有正负&#xff09; 同比&#xff1a;例&#xff1a;2014年5月 和 2013年5月 环比&#xff1a;例&#xff1a;20…

Vue通过配置代理解决跨域问题

VueCli2.0版本 1.找到config文件目录下的dev.env.js以及prod.env.js文件 dev.env.js是配置本地环境的 prod.env.js是配置正式环境的 分别在这两个文件下的API_URL中写下对应的正式服测试服域名 下面的是正式服的域名 2.配置跨域 //vue2.0 //config -> index.js proxyt…