【深度学习实验】循环神经网络(二):使用循环神经网络(RNN)模型进行序列数据的预测

news2024/11/19 10:41:04

目录

一、实验介绍

二、实验环境

1. 配置虚拟环境

2. 库版本介绍

三、实验内容

0. 导入必要的工具包

1. RNN模型

a. 初始化__init__

b. 前向传播方法forward

2. 训练和预测

a. 超参数

b. 创建模型实例

c. 模型训练

d. 预测结果可视化

3. 代码整合


        经验是智慧之父,记忆是智慧之母。

——谚语

一、实验介绍

        本实验实现了一个简单的循环神经网络(RNN)模型,并使用该模型进行序列数据的预测,本文将详细介绍代码各个部分的实现,包括模型的定义、训练过程以及预测结果的可视化。

        在前馈神经网络中,信息的传递是单向的,这种限制虽然使得网络变得更容易学习,但在一定程度上也减弱了神经网络模型的能力.在生物神经网络中,神经元之间的连接关系要复杂得多.前馈神经网络可以看作一个复杂的函数,每次输入都是独立的,即网络的输出只依赖于当前的输入.但是在很多现实任务中, 网络的输出不仅和当前时刻的输入相关,也和其过去一段时间的输出相关.比如一个有限状态自动机,其下一个时刻的状态(输出)不仅仅和当前输入相关,也和当前状态(上一个时刻的输出)相关.此外,前馈网络难以处理时序数据,比如视频、语音、文本等.时序数据的长度一般是不固定的,而前馈神经网络要求输入和输出的维数都是固定的,不能任意改变.因此,当处理这一类和时序数据相关 的问题时,就需要一种能力更强的模型. 循环神经网络(Recurrent Neural Network,RNN)是一类具有短期记忆能力的神经网络

        在循环神经网络中,神经元不但可以接受其他神经元的信息,也可以接受自身的信息,形成具有环路的网络结构.和前馈神经网络相比,循环神经网络更加符合生物神经网络的结构.循环神经网络已经被广泛应用在语音识别、语言模型以及自然语言生成等任务上.循环神经网络的参数学习可以通过随时间反向传播算法[Werbos, 1990]来学习.随时间反向传播算法即按照时间的逆序将错误信息一步步地往前传递.

二、实验环境

        本系列实验使用了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

三、实验内容

0. 导入必要的工具包

import torch
from torch import nn
import matplotlib.pyplot as plt
import numpy as np

1. RNN模型

class Rnn(nn.Module):
    def __init__(self, input_size):
        super(Rnn, self).__init__()
        # 定义RNN网络
        ## hidden_size是自己设置的,取值都是32,64,128这样来取值
        ## num_layers是隐藏层数量,超过2层那就是深度循环神经网络了
        self.rnn = nn.RNN(
            input_size=input_size,
            hidden_size=32,
            num_layers=1,
            batch_first=True  # 输入形状为[批量大小, 数据序列长度, 特征维度]
        )
        # 定义全连接层
        self.out = nn.Linear(32, 1)

    # 定义前向传播函数
    def forward(self, x, h_0):
        r_out, h_n = self.rnn(x, h_0)
        # print("数据输出结果;隐藏层数据结果", r_out, h_n)
        # print("r_out.size(), h_n.size()", r_out.size(), h_n.size())
        outs = []
        # r_out.size=[1,10,32]即将一个长度为10的序列的每个元素都映射到隐藏层上
        for time in range(r_out.size(1)):
            # print("映射", r_out[:, time, :])
            # 依次抽取序列中每个单词,将之通过全连接层并输出.r_out[:, 0, :].size()=[1,32] -> [1,1]
            outs.append(self.out(r_out[:, time, :]))
            # print("outs", outs)
        # stack函数在dim=1上叠加:10*[1,1] -> [1,10,1] 同时h_n已经被更新
        return torch.stack(outs, dim=1), h_n

a. 初始化__init__

  • 定义了RNN网络和全连接层。
    • self.rnn是一个RNN层:使用nn.RNN创建。
      • input_size参数表示输入数据的特征维度
      • hidden_size表示隐藏状态的维度
      • num_layers表示RNN层的堆叠层数
      • batch_first=True表示输入的形状为[批量大小, 数据序列长度, 特征维度]。
    • self.out是一个全连接层,将RNN的输出映射到1维输出。

b. 前向传播方法forward

  • 接受输入数据x和初始隐藏状态h_0作为参数。
    • 将输入数据和隐藏状态传入RNN层,得到输出r_out和最终隐藏状态h_n
    • 通过循环将序列中的每个时间步的输出经过全连接层,并将结果添加到outs列表中。
    • 使用torch.stack函数将outs列表中的结果在维度1上叠加,得到最终的预测结果,并返回预测结果和最终隐藏状态。

2. 训练和预测

a. 超参数

    TIME_STEP = 10
    INPUT_SIZE = 1
    LR = 0.02
  • TIME_STEP表示序列的长度
  • INPUT_SIZE表示输入数据的特征维度
  • LR表示学习率

b. 创建模型实例

    model = Rnn(INPUT_SIZE)
    print(model)

c. 模型训练

        使用正弦和余弦序列数据作为输入和目标输出,通过迭代训练,模型通过反向传播和优化器来不断调整参数以最小化预测结果与目标输出之间的损失。

    loss_func = nn.MSELoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=LR)

    h_state = None  # 初始化h_state为None

    for step in range(300):
        # 人工生成输入和输出,输入x.size=[1,10,1],输出y.size=[1,10,1]
        start, end = step * np.pi, (step + 1) * np.pi
        # np.linspace生成一个指定大小,指定数据区间的均匀分布序列,TIME_STEP是生成数量
        steps = np.linspace(start, end, TIME_STEP, dtype=np.float32)
        # print("steps", steps)
        x_np = np.sin(steps)
        y_np = np.cos(steps)
        # print("x_np,y_np", x_np, y_np)
        # 从numpy.ndarray创建一个张量 np.newaxis增加新的维度
        x = torch.from_numpy(x_np[np.newaxis, :, np.newaxis])
        y = torch.from_numpy(y_np[np.newaxis, :, np.newaxis])
        # print("x,y", x,y)

        # 将x通过网络,长度为10的序列通过网络得到最终隐藏层状态h_state和长度为10的输出prediction:[1,10,1]
        prediction, h_state = model(x, h_state)
        h_state = h_state.data
        # 这一步只取了h_state.data.因为h_state包含.data和.grad 舍弃了梯度
        # print("precision, h_state.data", prediction, h_state)
        # print("prediction.size(), h_state.size()", prediction.size(), h_state.size())

        # 反向传播
        loss = loss_func(prediction, y)
        optimizer.zero_grad()
        loss.backward()
        # 更新优化器参数
        optimizer.step()
  • 损失函数loss_func为均方误差损失(MSELoss)。
  • 优化器optimizer,使用Adam优化算法来更新模型的参数。
  • 初始化隐藏状态h_state为None。
  • 进行训练循环,共迭代300次:
    • 生成输入数据和目标输出数据。通过在每个迭代步骤中生成一个时间步长范围内的正弦和余弦函数值来构造序列数据。
    • 将生成的数据转换为张量形式,并添加新的维度。
    • 将输入数据通过模型进行前向传播,得到预测结果和最终隐藏状态。
    • 计算预测结果与目标输出之间的损失。
    • 清零优化器的梯度。
    • 执行反向传播,计算梯度。
    • 更新优化器的参数。

d. 预测结果可视化

    plt.plot(steps, y_np.flatten(), 'r-')
    plt.plot(steps, prediction.data.numpy().flatten(), 'b-')
    plt.show()

        将真实的目标输出数据和模型的预测结果进行可视化展示。

3. 代码整合

# 导入必要的工具包
import torch
from torch import nn
import matplotlib.pyplot as plt
import numpy as np



# 定义RNN模型
class Rnn(nn.Module):
    def __init__(self, input_size):
        super(Rnn, self).__init__()
        # 定义RNN网络
        ## hidden_size是自己设置的,取值都是32,64,128这样来取值
        ## num_layers是隐藏层数量,超过2层那就是深度循环神经网络了
        self.rnn = nn.RNN(
            input_size=input_size,
            hidden_size=32,
            num_layers=1,
            batch_first=True  # 输入形状为[批量大小, 数据序列长度, 特征维度]
        )
        # 定义全连接层
        self.out = nn.Linear(32, 1)

    # 定义前向传播函数
    def forward(self, x, h_0):
        r_out, h_n = self.rnn(x, h_0)
        # print("数据输出结果;隐藏层数据结果", r_out, h_n)
        # print("r_out.size(), h_n.size()", r_out.size(), h_n.size())
        outs = []
        # r_out.size=[1,10,32]即将一个长度为10的序列的每个元素都映射到隐藏层上
        for time in range(r_out.size(1)):
            # print("映射", r_out[:, time, :])
            # 依次抽取序列中每个单词,将之通过全连接层并输出.r_out[:, 0, :].size()=[1,32] -> [1,1]
            outs.append(self.out(r_out[:, time, :]))
            # print("outs", outs)
        # stack函数在dim=1上叠加:10*[1,1] -> [1,10,1] 同时h_n已经被更新
        return torch.stack(outs, dim=1), h_n


if __name__ == '__main__':
    TIME_STEP = 10
    INPUT_SIZE = 1
    LR = 0.02
    model = Rnn(INPUT_SIZE)
    print(model)
    # 此处使用的是均方误差损失

    loss_func = nn.MSELoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=LR)

    h_state = None  # 初始化h_state为None

    for step in range(300):
        # 人工生成输入和输出,输入x.size=[1,10,1],输出y.size=[1,10,1]
        start, end = step * np.pi, (step + 1) * np.pi
        # np.linspace生成一个指定大小,指定数据区间的均匀分布序列,TIME_STEP是生成数量
        steps = np.linspace(start, end, TIME_STEP, dtype=np.float32)
        # print("steps", steps)
        x_np = np.sin(steps)
        y_np = np.cos(steps)
        # print("x_np,y_np", x_np, y_np)
        # 从numpy.ndarray创建一个张量 np.newaxis增加新的维度
        x = torch.from_numpy(x_np[np.newaxis, :, np.newaxis])
        y = torch.from_numpy(y_np[np.newaxis, :, np.newaxis])
        # print("x,y", x,y)

        # 将x通过网络,长度为10的序列通过网络得到最终隐藏层状态h_state和长度为10的输出prediction:[1,10,1]
        prediction, h_state = model(x, h_state)
        h_state = h_state.data
        # 这一步只取了h_state.data.因为h_state包含.data和.grad 舍弃了梯度
        # print("precision, h_state.data", prediction, h_state)
        # print("prediction.size(), h_state.size()", prediction.size(), h_state.size())

        # 反向传播
        loss = loss_func(prediction, y)
        optimizer.zero_grad()
        loss.backward()
        # 更新优化器参数
        optimizer.step()
    # 对最后一次的结果作图查看网络的预测效果
    plt.plot(steps, y_np.flatten(), 'r-')
    plt.plot(steps, prediction.data.numpy().flatten(), 'b-')
    plt.show()

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

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

相关文章

云服务器带宽对上传下载速度的影响

简单来说就是 云服务器收到数据代表入&#xff0c;带宽大小 < 10时&#xff0c;入带宽大小10 带宽大小 > 10时&#xff0c;出入带宽上限 等于实际购买时候的大小

2023Linux C/C++全栈开发知识技术合集(基础入门到高级进阶)

C/Linux服务器开发」别名可以叫「C后台开发」,目前BAT里面都是有大量的C开发岗位&#xff0c;鹅厂在c后台开发岗都是急需。虽然岗位对技术要求难度系数较高&#xff0c;但是有大厂情结的朋友们还是可以冲一冲的。 很多有c/c语言基础的朋友&#xff0c;在面试后台岗的时候都会有…

Response Status Code 301、302

目录 Information Django redirect Influence Information HTTP状态码301、302和304分别表示以下情况&#xff1a; codeinformation301&#xff08;Moved Permanently&#xff09; 永久重定向。当请求的资源已经被永久地移动到了一个新的URI时&#xff0c;服务器会返回这个…

登录认证,登录校验

一、基础登录功能 1.Controller层 import com.itheima.pojo.Emp; import com.itheima.pojo.Result; import com.itheima.service.EmpService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework…

ChatGLM2-6B微调实践-QLora方案

ChatGLM2-6B微调实践-QLora方案 环境部署Lora微调项目部署准备数据集修改训练脚本adapter推理模型合并与量化合并后的模型推理 参数调优微调过程中遇到的问题参考&#xff1a; 环境部署 申请阿里云GPU服务器&#xff1a; CentOS 7.6 64Anaconda3-2023.07-1-Linux-x86_64Pytho…

为什么力扣中std::sort的cmp函数不加static会出错?

今天在力扣上做题的时候出现了一个有意思的错误 题目&#xff1a;1005.K 次取反后最大化的数组和 错误信息&#xff1a;error: reference to non-static member function must be called sort(nums.begin(),nums.end(),cmp); 我自定义了sort的cmp函数&#xff0c;但是出错了…

计算时间复杂度

时间复杂度与语句被重复执行的次数息息相关。 一、单层循环 单层循环大致可以分为两种&#xff0c;一种是循环体内的语句不影响循环条件的判定。另一种就是循环体内的语句会影响循环条件的判定。 1、循环体内的语句不影响循环条件的判定 这种情况十分常见且简单&#xff0c…

Configuration Change派发到App进程

整体时序 // DisplayContent.java boolean updateDisplayOverrideConfigurationLocked(Configuration values,ActivityRecord starting, boolean deferResume,ActivityTaskManagerService.UpdateConfigurationResult result) {int changes 0;boolean kept true;mAtmService.d…

VUEX全网最详细讲解之一

目录 一.Vuex简介 二.vuex的存值取值 测试结果 三.vuex异步请求 测试结果 ​编辑 ​编辑 一.Vuex简介 Vuex 是一个用于 Vue.js 应用程序的状态管理模式和库。它以集中式存储管理应用的所有组件的状态&#xff0c;并提供可预测的状态变化。Vuex 主要解决了多个组件之间共享…

Springboot——集成jodconverter做文档转换

文章目录 前言jodconverter 简介下载安装 libreoffice代码演示1、创建springboot项目工程并引入依赖2、配置3、准备一个docx模板4、编写测试代码 运行后的样式linux 环境下安装 libreoffice 前言 公司项目开发中&#xff0c;早期使用docx4j进行word转pdf&#xff0c;出现了很多…

嵌入式养成计划-39----C++静态成员--继承--多继承

九十一、静态成员 静态成员变量是属于类的变量&#xff0c;而不是属于类的对象的。它们在类的所有实例中是共享的。它们具有类范围的生命周期&#xff0c;因此与全局变量有一些相似之处。 在数据成员前static ----->静态数据成员 在成员函数前static ------>静态成员函…

接口自动化测试 —— 工具、请求与响应

1.工具介绍 postman &#xff1a;很主流的API测试工具&#xff0c;也是工作里面使用最广泛的研发工具。 JMeter&#xff1a; ApiPost&#xff1a; 2.安装postman&#xff1a; 安装好直接打开&#xff0c;不用注册。 二、通信模式&#xff1a; 1、同步通信&#xff1a; …

【走方格的方案数】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 #include <iostream> using namespace std; int func(int m,int n) {if(m1||n1){return mn;}return func(m-1,n)func(m,n-1); } int main() {int m, n;while (cin >>m >>…

word行距怎么设置?专业排版,让文档更具吸引力!

Microsoft Word是最常用的文字处理工具之一&#xff0c;广泛用于学术写作、商务沟通和文档编辑。掌握Word的基本功能是高效使用它的关键。本文将介绍word行距怎么设置的3种方法&#xff0c;以确保您的文档格式清晰、易读&#xff0c;让您的文档更具吸引力&#xff01; 方法1&am…

C++ 命名空间-----namespace(超详细解析,小白必看系列)

目录 一、前言 &#x1f34e;什么是C 二、关键字 三、命名空间&#xff08;重点&#xff09; &#x1f350;C语言--命名冲突 &#x1f349;C--命名空间的定义 &#x1f353;C--命名空间的使用 四、C输入&输出 五、共勉 一、前言 既博主学过C语言后又一新的语言&a…

动手学强化学习第2章多臂老虎机

2.1简介 多臂老虎机问题可以被看作简化版的强化学习问题。但是其只有动作和奖励没有状态信息&#xff0c;算是简化版的强化学习问题。 2.2问题介绍 2.2.1问题定义 在多臂老虎机(MAB)问题中&#xff0c;有一个有K根拉杆的老虎机&#xff0c;拉动每一根拉杆都对应一个关于奖励…

简单使用 Hugo 博客

之前用过 hugo&#xff0c;本次来分享一波&#xff0c;确实简单好用&#xff0c;可以持续使用&#xff0c;尤其是喜欢 GO语言的同学 hugo Hugo是一个用 Go语言 编写的静态网站生成器&#xff0c;可以快速地生成高效、安全和易于管理的静态网站。Hugo具有速度快、可定制性强、…

Linux引导故障排除:从问题到解决方案的详细指南

1 BIOS初始化 通电->对硬件检测->初始化硬件时钟 2 磁盘引导及其修复 2.1 磁盘引导故障 磁盘主引导记录&#xff08;MBR&#xff09;是在0磁道1扇区位置&#xff0c;446字节。 MBR作用&#xff1a;记录grub2引导文件的位置 2.2 修复 步骤&#xff1a;1、光盘进…

Javascript笔记:Web页面中的事件处理

1 任务队列 2事件处理&#xff1a;⼀个只有宏任务的示例 3 Web⻚⾯中的事件处理 3.1 定时器与事件处理&#xff1a;一个实例 4 Web⻚⾯中的事件处理 5 事件在DOM中的传播 5.1 两个阶段

C++ (Chapter 1)

C (一) 1.C的命名空间 先来看一个C语言的例子: 下面这段代码是可以正常运行的. #include<stdio.h> int rand 0; int main() {printf("%d \n", rand);return 0; }但是,包含了一个头文件之后,甚至无法通过编译. #include<stdio.h> #include<stdli…