RNN循环网络层

news2025/1/10 10:47:43

文章目录

  • 1、简介
  • 2、RNN 网络原理
  • 3、PyTorch RNN 层的使用
    • 3.1、RNN送入单个数据
    • 3.2、RNN层送入批量数据
  • 4、RNN三个维度
    • 4.1、解释
    • 4.2、输入数据的组织
    • 4.3、示例
    • 4.4、为什么需要这种格式?
    • 4.5、小结

🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学习,擅长web应用开发、数据结构和算法,初步涉猎人工智能和前端开发。
🦅个人主页:@逐梦苍穹
📕所属专栏:人工智能
🌻gitee地址:xzl的人工智能代码仓库
✈ 您的一键三连,是我创作的最大动力🌹

1、简介

学习目标:

  • 掌握RNN网络原理
  • 掌握PyTorch RNN api

上一篇讲了词嵌入层,可以将文本数据映射为数值向量,进而能够送入到网络进行计算。

不清楚的可以复习一下:https://xzl-tech.blog.csdn.net/article/details/140942295

但是,还存在一个问题,文本数据是具有序列特性的,如果颠倒了顺序,那么可能就会表达不同的意思。
为了能够表示出数据的序列关系我们需要使用循环神经网络(Recurrent Nearal Networks, RNN) 来对数据进行建模,RNN 是一个 具有记忆功能的网络,它作用于处理带有序列特点的样本数据。
本文将会带着大家深入学习 RNN 循环网络层的原理、计算过程,以及在 PyTorch 中如何使用 RNN 层。

2、RNN 网络原理

当我们希望使用循环网络来对 “我爱你” 进行语义提取时,RNN 是如何计算过程是什么样的呢?
image.png
上图中 h 表示隐藏状态, 每一次的输入都会有包含两个值:上一个时间步的隐藏状态、当前状态的输入值,输出当前时间步的隐藏状态。
上图中,为了更加容易理解,虽然我画了 3 个神经元, 但是实际上只有一个神经元

“我爱你” 三个字是重复输入到同一个神经元中。
接下来,我们举个例子来理解上图的工作过程,假设我们要实现文本生成,也就是输入 “我爱” 这两个字,来预测出 “你”,其如下图所示:
image.png
我们将上图展开成不同时间步的形式,如下图所示:
image.png
我们首先初始化出第一个隐藏状态,一般都是全0的一个向量,然后将 “我” 进行词嵌入,转换为向量的表示形式,送入到第一个时间步,然后输出隐藏状态 h1,
然后将 h1 和 “爱” 输入到第二个时间步,得到隐藏状态 h2,
将 h2 送入到全连接网络,得到 “你” 的预测概率。
那么,你可能会想,循环网络只能有一个神经元吗?
我们的循环网络网络可以有多个神经元,如下图所示:
image.png
我们依次将 “我爱你” 三个字分别送入到每个神经元进行计算,
假设 词嵌入时,“我爱你” 的维度为 128,经过循环网络之后,“我爱你” 三个字的词向量维度就会变成 4
所以, 我们理解了循环神经网络的的神经元个数会影响到输出的数据维度
每个神经元内部是如何计算的呢?
隐藏状态 h t h_t ht的更新公式: h t = tanh ⁡ ( W i h x t + b i h + W h h h ( t − 1 ) + b h h ) h_t = \tanh(W_{ih} x_t + b_{ih} + W_{hh} h_{(t-1)} + b_{hh}) ht=tanh(Wihxt+bih+Whhh(t1)+bhh)
上述公式中:

  1. W i h W_{ih} Wih 表示输入数据的权重
  2. b i h b_{ih} bih 表示输入数据的偏置
  3. W h h W_{hh} Whh 表示输入隐藏状态的权重
  4. b h h b_{hh} bhh 表示输入隐藏状态的偏置

最后对输出的结果使用 tanh 激活函数进行计算,得到该神经元 的输出。

3、PyTorch RNN 层的使用

接下来,我们学习 PyTorch 的 RNN 层的用法。
先牢记一下RNN的图:

注意:RNN 层输入的数据为三个维度:(seq_len, batch_size, input_size)【下文详解
下面是代码的操作,首先先导包:
image.png

3.1、RNN送入单个数据

代码:

# 1. RNN 送入单个数据
def test01():  # 定义一个名为test01的函数,用于测试RNN输入单个数据样本
    # 输入数据维度 128, 输出维度 256
    rnn = nn.RNN(input_size=128, hidden_size=256)  # 创建一个RNN实例,指定输入特征维度为128,隐藏层维度为256

    # 第一个数字: 表示句子长度
    # 第二个数字: 批量个数
    # 第三个数字: 表示数据维度
    inputs = torch.randn(1, 1, 128)  # 生成一个形状为(1, 1, 128)的随机张量,表示单个时间步长、批量大小为1的数据输入
    print("inputs: ", inputs)
    print('-' * 82)
    hn = torch.zeros(1, 1, 256)  # 生成一个形状为(1, 1, 256)的零张量,初始化RNN的初始隐藏状态
    print("hn: ", hn)
    print('-' * 82)
    output, hn = rnn(inputs, hn)  # 将输入数据和隐藏状态传递给RNN,获取输出和更新后的隐藏状态
    print(output.shape)  # 打印输出张量的形状
    print(hn.shape)  # 打印更新后的隐藏状态张量的形状

输出:

E:\anaconda3\python.exe D:\Python\AI\神经网络\17-RNN.py 
inputs:  tensor([[[-0.0542,  1.3374,  0.6276,  1.6742, -1.6218,  1.4523, -0.5415,
           0.3223, -0.3032, -0.8091, -0.0138, -0.5916,  1.4253, -1.8918,
           1.2403, -1.2810,  0.3545, -0.8638,  0.1027, -0.2377,  1.1074,
           0.2798, -0.1968,  0.2442, -0.2380,  0.7400, -0.2120, -0.9833,
          -0.2811,  1.2074,  0.7339, -1.0456,  0.0399,  0.0785, -0.4130,
          -0.0441,  1.3400,  0.2237, -0.1764,  0.6922,  1.9262, -0.5288,
          -1.4500, -0.7859, -0.5073, -0.5422, -1.5230,  0.5099, -1.6504,
           0.1390,  1.6283, -0.4893, -2.3036,  1.0457, -0.2375, -0.9426,
           1.0307, -0.6329, -1.1034,  0.5635, -0.7559, -0.7063, -2.2348,
          -0.3007, -0.1424,  0.1728, -0.9499,  0.5152, -0.1789, -0.5752,
          -1.5950,  1.5423, -1.0990, -0.2535,  0.8160,  1.7046, -1.0907,
          -0.1915,  0.3198,  1.6223, -0.9377, -0.0530,  0.0468,  1.5816,
           0.2329,  1.0485,  1.2564, -0.7583,  1.1509,  0.1335,  0.2903,
          -0.8026,  0.1386,  1.0963,  0.0977, -0.1860,  1.6175,  0.7091,
          -0.7990,  0.3834, -0.9230,  0.2036, -0.3008,  1.2413,  0.1448,
          -0.0353,  1.7380, -0.3530, -0.7767,  0.6136, -0.6987,  0.4963,
          -1.3560, -1.8029, -1.2748, -0.3501,  0.5846, -1.4234, -0.7564,
           0.6593, -0.6481, -0.7269, -0.1935,  1.7772,  1.9999,  0.8682,
          -2.1852, -0.2099]]])
----------------------------------------------------------------------------------
hn:  tensor([[[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
          0., 0., 0.]]])
----------------------------------------------------------------------------------
torch.Size([1, 1, 256])
torch.Size([1, 1, 256])

Process finished with exit code 0

3.2、RNN层送入批量数据

代码:

# 2. RNN层送入批量数据
def test02():  # 定义一个名为test02的函数,用于测试RNN输入批量数据样本
    # 输入数据维度 128, 输出维度 256
    rnn = nn.RNN(input_size=128, hidden_size=256)  # 创建一个RNN实例,输入特征维度为128,隐藏层维度为256

    # 第一个数字: 表示句子长度
    # 第二个数字: 批量个数
    # 第三个数字: 表示数据维度
    # TODO 32批, 每批128
    inputs = torch.randn(1, 32, 128)  # 生成形状为(1, 32, 128)的随机张量,表示单个时间步长、批量大小为32的数据输入
    print("inputs.shape: ", inputs.shape)
    print("inputs: ", inputs)
    print('-' * 82)
    hn = torch.zeros(1, 32, 256)  # 生成形状为(1, 32, 256)的零张量,初始化RNN的初始隐藏状态
    print("hn.shape: ", hn.shape)
    print("hn: ", hn)
    print('-' * 82)

    output, hn = rnn(inputs, hn)  # 将批量输入数据和隐藏状态传递给RNN,获取输出和更新后的隐藏状态
    print(output.shape)  # 打印输出张量的形状
    print(hn.shape)  # 打印更新后的隐藏状态张量的形状

输出:

E:\anaconda3\python.exe D:\Python\AI\神经网络\17-RNN.py 
inputs.shape:  torch.Size([1, 32, 128])
inputs:  tensor([[[-0.3927, -1.7682,  0.7539,  ...,  0.7423,  0.6973, -1.1517],
         [-0.5867, -2.2071,  1.6128,  ..., -0.0758,  0.3444,  1.2695],
         [ 1.7433,  0.4850,  1.2588,  ..., -0.8928,  0.0400, -0.9688],
         ...,
         [-0.2075, -0.6588, -0.4446,  ...,  0.9307,  0.4107,  0.1857],
         [ 0.6601, -1.3952,  0.5381,  ...,  1.3603,  1.4538,  0.6282],
         [ 0.5128, -0.1883, -0.8761,  ..., -0.5208,  1.4437,  0.4713]]])
----------------------------------------------------------------------------------
hn.shape:  torch.Size([1, 32, 256])
hn:  tensor([[[0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         ...,
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.]]])
----------------------------------------------------------------------------------
torch.Size([1, 32, 256])
torch.Size([1, 32, 256])

Process finished with exit code 0

4、RNN三个维度

在使用循环神经网络(RNN)时,输入数据的维度通常是一个非常重要的考虑因素。RNN层期望的数据格式通常为三维张量 (seq_len, batch_size, input_size)。以下是对这三个维度的详细解释:

4.1、解释

  1. seq_len(序列长度)
    • 定义seq_len 是每个输入序列中的时间步数,或者说每个输入序列包含的元素数量。
    • 例子:在文本处理中,seq_len 可能表示句子或文本的长度(例如,一个句子有多少个词)。在时间序列数据中,它表示时间步的数量(例如,股票价格的每日记录数)。
  2. batch_size(批次大小)
    • 定义batch_size 是同时处理的序列数量。神经网络通常会批量处理数据,以提高计算效率。
    • 例子:如果您的数据集一次性处理10个序列,batch_size 就是10。这意味着网络会同时处理这10个序列的输入,进行并行计算。
  3. input_size(输入大小)
    • 定义input_size 是每个时间步的输入特征数,表示每个输入向量的维度。
    • 例子:在文本处理中,input_size 通常是词嵌入的维度。例如,如果每个词用一个128维的向量表示,input_size 就是128。在多变量时间序列中,这可能是每个时间步的特征数量。

4.2、输入数据的组织

RNN层输入的数据组织方式使得网络可以有效处理批量数据和序列数据。具体来讲:

  • 批处理:通过批处理多个序列,模型能够利用硬件的并行计算能力,提升训练和预测速度。
  • 序列处理:通过在序列的每个时间步上操作,RNN可以捕捉到输入序列中的时间依赖性和顺序信息。

4.3、示例

假设有一个包含5个单词的句子,每个单词用300维的词向量表示,并且您一次处理20个句子。
则输入张量的维度为 (5, 20, 300)

  • seq_len = 5:表示每个句子有5个单词。
  • batch_size = 20:表示同时处理20个句子。
  • input_size = 300:表示每个单词的词向量是300维。

4.4、为什么需要这种格式?

  • 时间序列特性:RNN的结构设计是为了在时间序列中处理数据,因此要求输入数据在第一个维度上具有时间依赖性(序列长度)。
  • 批处理效率:通过 batch_size 维度,RNN可以同时处理多个样本,提高训练速度和资源利用效率。
  • 灵活的输入input_size 使得RNN可以适应不同维度的输入特征(例如,不同任务中词向量的维度)。

4.5、小结

理解输入数据的三维格式对于成功应用RNN至关重要。这种格式不仅确保了RNN能够处理和学习数据的时序信息,还能够提高模型在大型数据集上的计算效率。构建RNN模型时,确保数据的预处理步骤符合这一输入格式是关键的一步。

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

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

相关文章

【博士每天一篇文献-算法】持续学习经典算法之LwF: Learning without forgetting

1 介绍 年份:2017 作者:Zhizhong Li,Amazon AWS Rekognition;Derek Hoiem,伊利诺伊大学计算机科学教授 会议:IEEE transactions on pattern analysis and machine intelligence 引用量:4325 Li…

【NXP-MCXA153】开发板救砖教程

前言 新手接触到NXP的板子时,一个不留神把调试的GPIO(RXD、TXD)改掉,很容易出现MDK Keil无法识别CMSIS-DAP调试器的情况;主控进入了莫名其妙模式导致调试器无法识别了,你根本无法下载程序,想改…

大数据-67 Kafka 高级特性 分区 分配策略 Ranger、RoundRobin、Sticky、自定义分区器

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

虚拟机Centos7 minimal版本安装docker

1、在 CentOS 7 上启用 EPEL 软件包存储库; (删除epel软件包和其他操作可参考:如何在 CentOS 7 上使用 EPEL (linux-console.net)) 1.1: 要安装epel前会报错,如下所示: 先参照这个链接安装&a…

【python】OpenCV—Image Super Resolution

文章目录 1、背景介绍2、准备工作3、EDSR4、ESPCN5、FSRCNN6、LapSRN7、汇总对比8、参考 1、背景介绍 图像超分,即图像超分辨率(Image Super Resolution,简称SR),是指由一幅低分辨率图像或图像序列恢复出高分辨率图像…

HTML基础 - HTML5

目录 一. 简介 二. 新增元素 三. 拖放 地理定位 A、HTML5 拖放(Drag and Drop) B.HTML5 地理定位(Geolocation) 四. input 五. web存储 webSQL 六. 应用程序缓存 web workers 七. web socket 可以先看上篇HTML基础再来看…

RabbitMQ、Kafka对比(超详细),Kafka、RabbitMQ、RocketMQ的区别

文章目录 一、kafka和rabbitmq全面对比分析1.1 简介1.2 kafka和rabbitmq全面对比分析1.3 影响因素 二、RabbitMQ、Kafka主要区别2.1 详解/主要区别2.1.1 设计目标和适用场景2.1.2 架构模型方面2.1.3 吞吐量和性能2.1.4 消息存储和持久化2.1.5 消息传递保证2.1.6 集群负载均衡方…

理解二分搜索算法

一.介绍 在本文中,我们将了解二分搜索算法。二分搜索算法是一种在排序数组中查找特定元素的高效方法。它的工作原理是将搜索间隔反复分成两半,从而大大减少了找到所需元素所需的比较次数。该算法的时间复杂度为 O(log n),因此对于大型数据集…

CLOS架构

CLOS Networking CLOS Networking 是指使用 Clos 网络拓扑结构(Clos Network Topology)进行网络设计的一种方法。该方法是由贝尔实验室的工程师 Charles Clos 在1950年代提出的,以解决电路交换网络的可扩展性和性能问题。随着现代计算和网络…

SpringBoot基础(一):快速入门

SpringBoot基础系列文章 SpringBoot基础(一):快速入门 目录 一、SpringBoot简介二、快速入门三、SpringBoot核心组件1、parent1.1、spring-boot-starter-parent1.2、spring-boot-dependencies 2、starter2.1、spring-boot-starter-web2.2、spring-boot-starter2.3、…

YOLOv10改进 | 主干篇 | YOLOv10引入CVPR2023 顶会论文BiFormer用于主干修改

1. 使用之前用于注意力的BiFormer在这里用于主干修改。 YOLOv10改进 | 注意力篇 | YOLOv10引入BiFormer注意力机制 2. 核心代码 from collections import OrderedDict from functools import partial from typing import Optional, Union import torch import torch.nn as n…

C++:vector容器

概览 std::vector是C标准模板库(STL)中的一种动态数组容器。它提供了一种类似于数组的数据结构,但是具有动态大小和更安全的内存管理。 定义和基本特性 std::vector是C标准库中的一 个序列容器,它代表了能够动态改变大小的数组。与普通数组一样&#x…

酒店智能插座在酒店智慧化中的重要性

在当今数字化和智能化的时代,酒店行业也在不断追求创新和提升服务品质,以满足客人日益增长的需求。酒店智能插座作为酒店智慧化的重要组成部分,发挥着不可忽视的作用。 提升客人的便利性: 酒店智能插座能够为客人提供更加便捷的充…

使用 Java Swing 的 IMEI 验证器

一.介绍 本文档介绍如何使用 Java Swing 创建一个简单的 IMEI 验证器应用程序。 二.什么是 IMEI 号码 IMEI 代表国际移动设备识别码。IMEI 用于在移动设备连接到网络时对其进行识别。每个 GSM、CDMA 或卫星移动设备都有唯一的 IMEI 号码。此号码将印在设备电池组件内。用户可…

Flutter GPU 是什么?为什么它对 Flutter 有跨时代的意义?

Flutter 3.24 版本引入了 Flutter GPU 概念的新底层图形 API flutter_gpu ,还有 flutter_scene 的 3D 渲染支持库,它们目前都是预览阶段,只能在 main channel 上体验,并且依赖 Impeller 的实现。 Flutter GPU 是 Flutter 内置的底…

Python3 第六十六课 -- CGI编程

目录 一. 什么是 CGI 二. 网页浏览 三. CGI 架构图 四. Web服务器支持及配置 五. 第一个CGI程序 5.1. HTTP 头部 5.2. CGI 环境变量 六. GET和POST方法 6.1. 使用GET方法传输数据 6.1.1. 简单的url实例:GET方法 6.1.2. 简单的表单实例:GET方法…

暑期数据结构 空间复杂度

3.空间复杂度 空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度。 空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟…

SAM2:在图像和视频中分割任何内容

SAM 2: Segment Anything in Images and Videos 一、关键信息 1. SAM 2概述: SAM 2 是一种基础模型,设计用于在图像和视频中实现可提示的视觉分割。该模型采用变压器架构和流式内存进行实时视频处理。它在原始的Segment Anything Model(SAM…

自用 K8S 资源对象清单 YAML 配置模板手册-1

Linux 常用资源对象清单配置速查手册-1 文章目录 1、Pod 容器集合2、Pod 的存储卷3、Pod 的容器探针4、ResourceQuota 全局资源配额管理5、PriorityClass 优先级类 管理多个资源对象清单文件常用方法: 使用 sed 流式编辑器批量修改脚本键值进行资源清单的创建&am…

【高中数学/函数/值域】求f(x)=(x^2+1)^0.5/(x-1) 的值域

【问题】 求f(x)(x^21)^0.5/(x-1) 的值域 【来源】 《高中数学解题思维策略》P3 例1-1 杨林军著 天津出版传媒集团出版 【解答】 表达式说明f(x)(x^21)^0.5/(x-1)f(x)((x^21)/(x-1)^2)^0.5准备采用配方法f(x)(12/(x-1)2/(x-1)^2)^0.5(1)式f(x)(2*(1/(x-1)1/2)^21/2)^0.5(2)…