一、概念
RNN(Recurrent Neural Network),中文称作循环神经网络 它一般以序列数据为输入, 通过网络内部的结构设计有效捕捉序列之间的关系特征(比如语义,上下文),一般也是以序列形式进行输出。
RNN的循环机制使模型隐层上一时间步产生的结果, 能够作为当下时间步输入的一部分(当下时间步的输入除了正常的输入外还包括上一步的隐层输出)对当下时间步的输出产生影响。
RNN和ANN的区别:
ANN输入的语料单词都是互相独立的,无法联系上下文信息;
RNN能通过网络内部的结构设计有效捕捉序列之间的关系特征,然后进行信息预测。
二、作用
因为RNN结构能够很好利用序列之间的关系, 因此针对自然界具有连续性的输入序列, 如人类的语言, 语音等进行很好的处理, 广泛应用于NLP领域的各项任务, 如文本分类, 情感分析, 意图识别, 机器翻译等
三、分类
从输入输出的角度
N vs N - RNN :输入和输出序列是等长,对对联,古诗
N vs 1 - RNN:输出是一个单独的值,文本分类
1 vs N - RNN:输入不是序列而输出为序列,图生文
N vs M - RNN:不限输入输出长度,机器翻译(seq2seq架构)
从内部构造角度
传统RNN
LSTM
Bi-LSTM(双向LSTM)
GRU
Bi-GRU(双向GRU)
四、传统RNN模型的内部结构
1. 结构分析
公式
计算过程
组成输入数据:基于时间步组合当前的输入数据
输入:上一个时间步的隐藏状态h(t-1)+当前输入向量x(t)
输出:当前时间步输出h(t)
计算当前时间步结果:基于当前时间步的输入,经过线性层和激活函数,得到当前时间步输出h(t)
输入:拼接后的参数矩阵[h(t-1), x(t)]
输出:当前时间步输出 h(t)
2. 使用Pytorch构建RNN模型
input_size : 输入张量的维度,也是词向量的嵌入维度
hidden_size : 隐层维度
batch_size: 一个批次的大小
seq_len: 一个序列有多少个词
num_layer: RNN层数
代码实现
① 导包
② 定义函数名,并且给定参数
import torch
import torch.nn as nn
def dm01_rnn():
input_size = 8
hidden_size = 6
num_layers = 1
num_directions = 1
batch_size = 5
sequence_length = 1
(注意:下面各项参数的顺序)
③ 定义RNN模型(
第一个参数:input_size(输入张量x的维度)
第二个参数:hidden_size(隐藏层的维度, 隐藏层的神经元个数)
第三个参数:num_layer(隐藏层的数量)
)
④ 构建输入数据X(
第一个参数:batch_size(批次的样本数量)
第二个参数:sequence_length(输入的序列长度)
第三个参数:input_size(输入张量的维度)
)
⑤ 初始化隐藏层数据h0(
第一个参数:num_layer * num_directions(层数*网络方向)
第二个参数:batch_size(批次的样本数)
第三个参数:hidden_size(隐藏层的维度, 隐藏层神经元的个数)
)
# 1.定义RNN模型,传参
rnn = nn.RNN(input_size=input_size,hidden_size=hidden_size,num_layers=num_layers)
# 2.构建输入数据X,传参
X = torch.randn(batch_size,sequence_length,input_size)
# 3.初始化隐藏层数据h0,传参
h0 = torch.randn(num_layers*num_directions,batch_size,hidden_size)
⑥ 前向传播
注意:前向传播结果有两个,out是所有时间步hn的拼接,hn是最后一个时间步的隐层输出
out,hn = rnn(X,h0)
# 打印输出
print(out.shape)
# TODO 输出结果为(batch_size,sequence_length,hidden_size) 输出结果中的hidden_size会受num_directions影响
print(hn.shape)
# TODO 输出结果为(num_layers*num_directions,batch_size,hidden_size)
⑦ 主程序
if __name__ == '__main__':
dm01_rnn()
3. 传统RNN的优缺点
优势:结构简单,参数量小,短序列效果相对可以
缺点:处理长序列效果比较差, 容易梯度消失或者爆炸
梯度消失和梯度爆炸介绍
根据反向传播算法和链式法则, 梯度的计算可以简化为以下公式
Dn=σ′(z1)w1⋅σ′(z2)w2⋅⋯⋅σ′(zn)wn
参数说明:
σ′(zn):第n层
w_n:连接第 i 层与下一层的权重参数
其中sigmoid的导数值域是固定的, 在[0, 0.25]之间,
而一旦公式中的w也小于1, 那么通过这样的公式连乘后, 最终的梯度就会变得非常非常小, 这种现象称作梯度消失. 反之, 如果我们人为的增大w的值, 使其大于1, 那么连乘够就可能造成梯度过大, 称作梯度爆炸.
梯度消失或爆炸的危害:
如果在训练过程中发生了梯度消失,权重无法被更新,最终导致训练失败; 梯度爆炸所带来的梯度过大,大幅度更新网络参数,在极端情况下,结果会溢出(NaN值)