全面理解RNN(包括GRU、LSTM)以及对应pytorch实现

之前在学习RNN的时候,总是零零散散的搜一些东西。这次想要将关于RNN的知识总结起来,包括各种RNN网络的结构、输入输出以及pytorch代码实现。

文章目录

    • 单向RNN网络简介
      • Vanilla RNN / GRU 的结构
      • LSTM 的结构
    • 双向RNN网络简介
    • 单向和双向LSTM的pytorch代码实现
      • 单向LSTM
      • 双向LSTM
    • Reference

单向RNN网络简介

我们首先介绍单向RNN网络的结构,如下图所示。时间步 i i i 的输入为: x i x_i xi s i − 1 s_{i-1} si1,输出是 y i y_i yi s i s_i si。这里我们统一使用 s s s 代表隐藏层状态表示, y y y 则表示模型输出值。那么,单个神经元的运算为: ( y t , s t ) = f t ( x t , s t − 1 ) (y_t, s_t) = f_t(x_t, s_{t-1}) (yt,st)=ft(xt,st1)。其中, f t f_t ft 表示的该层的第 t t t 个神经元中的运算。
全面理解RNN(包括GRU、LSTM)以及对应pytorch实现_第1张图片
在上面介绍的基础上,接下来,会介绍三种RNN网络,分别是Vanilla RNN(即简单RNN),GRU,LSTM。对于这三种网络,我会从单个神经元、单层以及多层的方面展开介绍。因为Vanilla RNN和GRU的结构上是一样的,只是内部计算不同,所以这里将这两个放在一起介绍

Vanilla RNN / GRU 的结构

首先给出简单RNN/ GRU的单层和多层的网络结构,这里从单个神经元进行分析。网络结构图如下:
全面理解RNN(包括GRU、LSTM)以及对应pytorch实现_第2张图片
简介中我们用 s t s_t st表示隐层状态, y t y_t yt表示 t t t 时刻输出。那么,单层Vanilla RNN / GRU的隐层状态和输出就是: s t = h t s_t = h_t st=ht y t = h t y_t = h_t yt=ht。可以看出,Vanilla RNN / GRU的隐层状态和该时刻的输出是一样的。

对于多层Vanilla RNN / GRU来说,隐层状态和输出分别为: s t = ( h t − 1 ( 1 ) , h t − 1 ( 2 ) , ⋯   , h t − 1 ( l ) ) s_t = (h_{t-1}^{(1)}, h_{t-1}^{(2)}, \cdots, h_{t-1}^{(l)}) st=(ht1(1),ht1(2),,ht1(l)) y t = h t ( l ) y_t = h_t^{(l)} yt=ht(l)。中间层的输出 h t ( i ) h_{t}^{(i)} ht(i)直接用于下一层的输入,不会被直接输出出来。

LSTM 的结构

首先给出单层和多层LSTM的结构图,可以看出,相比Vanilla RNN和GRU,LSTM多了一个 c t − 1 c_{t-1} ct1的输入,这个表示cell的状态。
全面理解RNN(包括GRU、LSTM)以及对应pytorch实现_第3张图片
在单层LSTM中,隐层状态和输出分别对应于: s t = ( h t , c t ) s_t = (h_t, c_t) st=(ht,ct) y t = h t y_t = h_t yt=ht

在多层LSTM中,隐层状态和输出分别对应于: s t = ( ( h t ( 1 ) , c t ( 1 ) ) , ( h t ( 2 ) , c t ( 2 ) ) , ⋯   , ( h t ( l ) , c t ( l ) ) ) s_t = ((h_t^{(1)}, c_t^{(1)}), (h_t^{(2)}, c_t^{(2)}), \cdots, (h_t^{(l)}, c_t^{(l)})) st=((ht(1),ct(1)),(ht(2),ct(2)),,(ht(l),ct(l))) y t = h t ( l ) y_t = h_t^{(l)} yt=ht(l)

双向RNN网络简介

双向RNN就相当于在上面所讲单向RNN基础之上,再增加一层方向的相同结构网络。图示如下:
全面理解RNN(包括GRU、LSTM)以及对应pytorch实现_第4张图片
双向RNN就会出现两个输出,分别为 y t → \overrightarrow{y_t} yt y t ← \overleftarrow{y_t} yt ,通常这两个输出会concat在一起,作为整体输出。

知道了单向和双向RNN的结构之后,我们就来看看pytorch里怎样实现这样的网络,这里以LSTM为例,GRU类似,只是输入和输出的不同。

单向和双向LSTM的pytorch代码实现

单向LSTM

rnn = nn.LSTM(input_size=10, hidden_size=20, num_layers=2)#(input_size,hidden_size,num_layers)
input = torch.randn(5, 3, 10)#(seq_len, batch, input_size)
h0 = torch.randn(2, 3, 20) #(num_layers,batch,output_size)
c0 = torch.randn(2, 3, 20) #(num_layers,batch,output_size)
output, (hn, cn) = rnn(input, (h0, c0))

那么,output和hn,cn的维度是多少呢?

output.shape #(seq_len, batch, output_size)
torch.Size([5, 3, 20])
hn.shape #(num_layers, batch, output_size)
torch.Size([2, 3, 20])
cn.shape #(num_layers, batch, output_size)
torch.Size([2, 3, 20])

双向LSTM

rnn = nn.LSTM(input_size=10, hidden_size=20, num_layers=2,bidirectional=True)#(input_size,hidden_size,num_layers)
input = torch.randn(5, 3, 10)#(seq_len, batch, input_size)
h0 = torch.randn(4, 3, 20) #(num_layers,batch,output_size)
c0 = torch.randn(4, 3, 20) #(num_layers,batch,output_size)
output, (hn, cn) = rnn(input, (h0, c0))

output和hn,cn的维度是多少呢?

output.shape #(seq_len, batch, output_size*2)
torch.Size([5, 3, 40])
hn.shape #(num_layers*2, batch, output_size)
torch.Size([4, 3, 20])
cn.shape #(num_layers*2, batch, output_size)
torch.Size([4, 3, 20])

Reference

学会区分RNN的output和state
lstm理解与使用(pytorch为例)

你可能感兴趣的:(学习总结,RNN,人工智能)