RNN(循环神经网络)详解

1️⃣ RNN介绍

前馈神经网络(CNN,全连接网络)的流程是前向传播、反向传播和参数更新,存在以下不足:

  • 无法处理时序数据:时序数据长度一般不固定,而前馈神经网络要求输入的维度是固定的,不能改变
  • 缺少记忆:前馈神经网络没有机制去记忆和处理之前的输入数据,因此无法处理像语言、股票走势或天气预报等 序列化时间依赖性强的数据

针对前馈神经网络上述问题,RNN引入以下机制:

  • 不同时间步的隐藏层之间是相连的
  • 在时刻t,隐藏层的输入包括两部分,当前时刻的输入 x t x_t xt和上一个时间步隐藏层的输出 s t − 1 s_{t-1} st1

通过这两条机制,模型能够记忆之前的输入数据,捕捉序列的上下文信息

看完这几句话你一定在想,这说的是个啥?太晕了,没关系,慢慢往下看

多说一句,RNN在很久之前就提出了,Jordan RNN于1986被提出,Elman RNN于1990年提出。


2️⃣ 原理介绍

接下来,讲讲具体原理,解决一下上面的迷惑。看下面这张图,分析一下 o t o_t ot的表达式:
在这里插入图片描述

  • x t x_t xt是t时刻的输入
  • s t s_t st是t时刻的记忆, s t = f ( U ⋅ x t + W ⋅ s t − 1 ) s_t=f(U\cdot x_t+W\cdot s_{t-1}) st=f(Uxt+Wst1),f表示激活函数, s t − 1 s_{t-1} st1表示t-1时刻的记忆
  • o t o_t ot是t时刻的输出, o t = s o f t m a x ( V ⋅ s t ) o_t=softmax(V\cdot s_t) ot=softmax(Vst)

看完上面这张图,对于W是什么疑惑很大,我一开始学习的时候也是这样,W到底是啥呢?来看下面这张图:
在这里插入图片描述

看完这张图,对于W的描述一目了然。W是在不同的时间步 隐藏层之间递归的权重。在RNN中,不同时间步使用相同的W,为了保证信息能够传递下去。

其实这里还有一个疑惑,按照我之前的认知,神经网络可训练的参数w和b都是在神经元上的,例如下面这张图。那么问题来了,RNN隐藏层神经元上参数是啥样的呢?
在这里插入图片描述
虽然下面的左图是这样画的,搞得好像参数U,W,V“漂浮在空中一般”,实际上,它们都在神经元上。准确的来说应该是右图的形式,U和W都在隐藏层神经元上,V在输出层神经元上。所以之前理解的神经元是一个神经元上只有一种参数。对于RNN来说,隐藏层神经元上有两种参数U和W。终于搞懂了,爽!
在这里插入图片描述
分析完RNN中参数的具体含义,来看看参数的尺寸:
U = 隐藏层神经元个数 × 输入尺寸 W = 隐藏层神经元个数 × 隐藏层神经元个数 V = 输出尺寸 × 隐藏层神经元个数 U=隐藏层神经元个数×输入尺寸\\ W=隐藏层神经元个数×隐藏层神经元个数\\ V=输出尺寸×隐藏层神经元个数 U=隐藏层神经元个数×输入尺寸W=隐藏层神经元个数×隐藏层神经元个数V=输出尺寸×隐藏层神经元个数
这样最简单的RNN就分析完了。


3️⃣ RNN结构

1. N to N结构

输入序列和输出序列长度一样,即一个输入x对应一个输出y。常用于视频帧分类、词性标注等
在这里插入图片描述
公式可以表示为:
h i = f ( U ⋅ x i + W ⋅ h i − 1 ) y i = g ( V ⋅ h i ) h_{i}=f(U\cdot x_{i}+W\cdot h_{i-1})\\y_{i}=g(V\cdot h_{i}) hi=f(Uxi+Whi1)yi=g(Vhi)

2. N to 1结构

整个输入序列被压缩成一个固定的输出,通常用来处理那些输入序列产生一个整体的输出的场景。例如序列分类(一段文本→判断积极or消极)、时间序列预测(给定过去 10 天的股价,预测第 11 天的股价)、异常检测(根据历史数据输出一个二分类结果)
在这里插入图片描述
公式可以表示为:
h N = f ( U ⋅ x N + W ⋅ h N − 1 ) y N = g ( V ⋅ h N ) h_{N}=f(U\cdot x_{N}+W\cdot h_{N-1})\\y_{N}=g(V\cdot h_{N}) hN=f(UxN+WhN1)yN=g(VhN)

3. 1 to N结构

1 to N 结构RNN,表示一个输入数据对应输出一个序列的模型,输入位置有两种形式,适用于图生文任务:

  • 只在首个时刻输入
    在这里插入图片描述
    h i = { f ( W ⋅ h i − 1 ) , i > 1 f ( U ⋅ x 1 + W ⋅ h 0 ) , i = 1 y i = g ( V ⋅ h i ) \begin{aligned} &\left.h_{i}=\left\{\begin{matrix}{f(W\cdot h_{i-1}) ,i>1}\\{f(U\cdot x_{1}+W\cdot h_{0}) ,i=1}\\\end{matrix}\right.\right.\\ &y_{i}=g(V\cdot h_{i}) \end{aligned} hi={f(Whi1),i>1f(Ux1+Wh0),i=1yi=g(Vhi)
  • 在每个时刻均输入
    在这里插入图片描述
    h i = f ( U ⋅ x 1 + W ⋅ h i − 1 ) y i = g ( V ⋅ h i ) h_{i}=f(U\cdot x_{1}+W\cdot h_{i-1})\\y_{i}=g(V\cdot h_{i}) hi=f(Ux1+Whi1)yi=g(Vhi)
    注意里面是 x 1 x_1 x1

4. N to M结构RNN模型(encoder-decoder、seq2seq)

输入与输出序列不等长的结构。N和M分别为输入序列长度及输出序列长度,该结构我们采用一个N to 1结构作为encoder,一个1 to M结构作为decoder来实现。
在这里插入图片描述
主要实现原理为在encoder和decoder之间,增加了一个上下文向量 c c c,向量 c c c中包含着输入系列的语义信息和序列化信息。在上图中, c c c作为decoder的输入数据。此外, c c c还可以作为decoder的隐层初始变量,如下图所示:
在这里插入图片描述

此外,还有第三种结构:
在这里插入图片描述

通过N to M结构RNN模型,可以适应各类序列处理任务,常见的如机器翻译、语音识别、文本摘要及阅读理解等任务。由于输入输出都是序列,该模型也称为seq2seq模型。向量 c c c的计算方法包括以下几种:
c = h N c = g ( h N ) c = g ( h 1 : : h N ) \begin{aligned} &\mathbf{c}=h_{N} \\ &\mathbf{c}=g(h_N) \\ &\mathbf{c}=g(h_1::h_N) \end{aligned} c=hNc=g(hN)c=g(h1::hN)
第一种计算方法:上下文向量 c c c就是Encoder最后一个时间步的隐藏状态 h N h_N hN
第二种计算方法:增加一个非线性变换函数
第三种计算方法:使用整个序列的隐藏状态 h 1 , h 2 , … , h N h_1,h_2,\ldots,h_N h1,h2,,hN来计算上下文向量 c c c

局限性: 编码和解码之间的唯一联系是固定长度的上下文向量 c c c。编码时,整个序列的信息需要被压缩进一个固定长度的 c c c中,这可能导致信息丢失或覆盖。因此,对于较长的输入序列,解码效果可能会受到影响

解决办法: 提出了注意力(Attention)机制


4️⃣ 代码

接下来看一下最简单的代码:

import torch
import torch.nn as nn

# 参数设置
input_size = 2    # 每个时间步的特征维度
hidden_size = 5   # 隐层神经元数量
num_layers = 1    # RNN层数
output_size = 3   # 假设输出的维度

# RNN对象实例化
rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True)

# U:输入到隐藏状态的权重矩阵
U = rnn.weight_ih_l0  # 输入到隐藏状态的权重矩阵
print("矩阵 U 的大小 (输入到隐藏层):", U.shape)  # 应为 (hidden_size, input_size)

# W:隐藏状态到隐藏状态的权重矩阵
W = rnn.weight_hh_l0  # 隐藏状态之间的递归权重矩阵
print("矩阵 W 的大小 (隐藏层到隐藏层):", W.shape)  # 应为 (hidden_size, hidden_size)

# V:输出层权重矩阵
# 在 PyTorch 中没有直接实现,可以添加一个 Linear 层来模拟
V_layer = nn.Linear(hidden_size, output_size)  # 定义线性层
V = V_layer.weight  # V 就是隐藏状态到输出层的权重矩阵
print("矩阵 V 的大小 (隐藏层到输出层):", V.shape)  # 应为 (output_size, hidden_size)

输出:

矩阵 U 的大小 (输入到隐藏层): torch.Size([5, 2])
矩阵 W 的大小 (隐藏层到隐藏层): torch.Size([5, 5])
矩阵 V 的大小 (隐藏层到输出层): torch.Size([3, 5])

5️⃣ 总结


5️⃣ 参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值