前馈神经网络(CNN,全连接网络)的流程是前向传播、反向传播和参数更新,存在以下不足:
之前的输入数据
,因此无法处理像语言、股票走势或天气预报等 序列化、时间依赖性强的数据针对前馈神经网络上述问题,RNN引入以下机制:
通过这两条机制,模型能够记忆之前的输入数据,捕捉序列的上下文信息
看完这几句话你一定在想,这说的是个啥?太晕了,没关系,慢慢往下看
接下来,讲讲具体原理,解决一下上面的迷惑。看下面这张图,分析一下
o
t
o_t
ot的表达式:
看完上面这张图,对于W是什么疑惑很大,我一开始学习的时候也是这样,W到底是啥呢?来看下面这张图:
看完这张图,对于W的描述一目了然。W是在不同的时间步
隐藏层之间
递归的权重
。在RNN中,不同时间步使用相同的W,为了保证信息能够传递下去。
其实这里还有一个疑惑,按照我之前的认知,神经网络可训练的参数w和b都是在神经元上的,例如下面这张图。那么问题来了,RNN隐藏层神经元上参数是啥样的呢?
输入序列和输出序列长度一样,即一个输入x对应一个输出y。常用于视频帧分类、词性标注等
整个输入序列被压缩成一个固定的输出,通常用来处理那些输入序列产生一个整体的输出的场景。例如序列分类(一段文本→判断积极or消极)、时间序列预测(给定过去 10 天的股价,预测第 11 天的股价)、异常检测(根据历史数据输出一个二分类结果)
1 to N 结构RNN,表示一个输入数据对应输出一个序列的模型,输入位置有两种形式,适用于图生文任务:
输入与输出序列不等长的结构。N和M分别为输入序列长度及输出序列长度,该结构我们采用一个N to 1结构作为encoder,一个1 to M结构作为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)机制
接下来看一下最简单的代码:
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])
标准的RNN存在梯度消失
和梯度爆炸
问题,无法捕捉长时间序列的关系。因此LSTM和GRU被提出
关于梯度消失和爆炸的原理,看我的另一篇博客
因篇幅问题不能全部显示,请点此查看更多更全内容