Advertisement

循环神经网络进阶(门控循环神经网络、LSTM、深度循环神经网络、双向循环神经网络)

阅读量:

文章目录

    • 门控循环神经网络GRU
    • 长短期记忆LSTM
    • 深度循环神经网络
    • 双向循环神经网络

门控循环神经网络GRU

该网络的提出也同样是为了应对普通RNN的梯度问题
基本原理看这一篇就能懂:转载自知乎
简单来说,GRU就是通过一个重置门控和一个更新门控来实现对原隐藏信息的选择性遗忘 和对当前节点信息的选择性记忆
在这里插入图片描述
可以看到其中的r和z分别是重置门控和更新门控,首先由上一层的隐藏信息ht-1和当先层的输入分别得到门控r和z,激活函数选择sigmoid
在这里插入图片描述
接着使用重置门控r来重置上一层的隐藏信息ht-1得到ht-1’
在这里插入图片描述
这个运算符号是指Hadamard Product,也就是操作矩阵中对应的元素相乘,因此要求两个相乘矩阵是同型的。然后将更新后的ht-1’与输入X拼接,运用tanh得到h’。
在这里插入图片描述
然后就可以更新记忆了
在这里插入图片描述
首先再次强调一下,门控信号(这里的 z)的范围为0~1。门控信号越接近1,代表”记忆“下来的数据越多;而越接近0则代表”遗忘“的越多。

  • +前的式子表示表示对原本隐藏状态的选择性“遗忘”
  • +后的式子表示对包含当前节点信息的 h’进行选择性”记忆“

结合上述,这一步的操作就是忘记传递下来的ht-1中的某些维度信息,并加入当前节点输入的某些维度信息。

代码部分:
自己动手实现GRU的重点是初始化参数时,一共有11个参数需要生成:两个门控各三个,计算h’有三个,最后计算输出层还有两个。
在这里插入图片描述
初始化参数的代码:

复制代码
    num_inputs, num_hiddens, num_outputs = vocab_size, 256, vocab_size
    print('will use', device)
    
    def get_params():  
    def _one(shape):
        ts = torch.tensor(np.random.normal(0, 0.01, size=shape), device=device, dtype=torch.float32) #正态分布
        return torch.nn.Parameter(ts, requires_grad=True)
    def _three():
        return (_one((num_inputs, num_hiddens)),
                _one((num_hiddens, num_hiddens)),
                torch.nn.Parameter(torch.zeros(num_hiddens, device=device, dtype=torch.float32), requires_grad=True))
     
    W_xz, W_hz, b_z = _three()  # 更新门参数
    W_xr, W_hr, b_r = _three()  # 重置门参数
    W_xh, W_hh, b_h = _three()  # 候选隐藏状态参数
    
    # 输出层参数
    W_hq = _one((num_hiddens, num_outputs))
    b_q = torch.nn.Parameter(torch.zeros(num_outputs, device=device, dtype=torch.float32), requires_grad=True)
    return nn.ParameterList([W_xz, W_hz, b_z, W_xr, W_hr, b_r, W_xh, W_hh, b_h, W_hq, b_q])
    
    def init_gru_state(batch_size, num_hiddens, device):   #隐藏状态初始化
    return (torch.zeros((batch_size, num_hiddens), device=device), )

初始化参数后就可以动手实现GRU了,就是将公式自行翻译一遍,然后训练模型
使用Pytorch简洁实现GRU就不用自己初始化模型和写GRU公式了,直接创建nn.GRU层

复制代码
    num_hiddens=256
    num_epochs, num_steps, batch_size, lr, clipping_theta = 160, 35, 32, 1e2, 1e-2
    pred_period, pred_len, prefixes = 40, 50, ['分开', '不分开']#前缀
    
    lr = 1e-2 # 注意调整学习率
    gru_layer = nn.GRU(input_size=vocab_size, hidden_size=num_hiddens)
    model = d2l.RNNModel(gru_layer, vocab_size).to(device)
    d2l.train_and_predict_rnn_pytorch(model, num_hiddens, vocab_size, device,
                               corpus_indices, idx_to_char, char_to_idx,
                               num_epochs, num_steps, lr, clipping_theta,
                               batch_size, pred_period, pred_len, prefixes)

长短期记忆LSTM

LSTM原理简介
和GRU一样,LSTM也是为了应对长序列中存在的梯度爆炸、梯度消失问题,同样也是运用了门控来控制每一个LSTM单元

其中重要的地方在于LSTM比起普通RNN多出一个状态C(记忆细胞)
在这里插入图片描述接下来详细介绍LSTM的运作原理

  1. 首先使用LSTM的当前输入xt和上一个状态传递下来的ht-1拼接训练得到四个状态
    在这里插入图片描述
    其中z是作为状态ct的输入参数,下面三个分别是遗忘门、输入门、输出门
    在这里插入图片描述
    通过遗忘门zf对上一时间的状态c进行选择性遗忘,然后拼接输入门zi和输入z计算当前的状态c,然后使用输出门配合tanh函数计算当前状态h

以上,就是LSTM的内部结构。通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息。总体来说就是三阶段:选择遗忘阶段、选择记忆阶段、输出阶段,而状态c是其中的中间状态

但由于训练开销的问题,很多时候会用效果差不多但是参数较少的GRU

代码方面:代码和GRU差不多,只是初始化参数时要初始化更多的参数
在这里插入图片描述
这里的Ct上面以波浪线等同于上面的输入z

深度循环神经网络

在这里插入图片描述
相比于普通的RNN,深度循环神经网络相当于在中间多加了好几层,可以进行更为复杂的转换,代码只需要修改num_layersd的个数就行了

复制代码
    gru_layer = nn.LSTM(input_size=vocab_size, hidden_size=num_hiddens,num_layers=2)

但是层数越多并不一定效果会越好

双向循环神经网络

在这里插入图片描述
除了存在从下往上的时序顺序之外,还存在着从上往下的时序顺序,最后把两个方向的Ht堆叠得到最终的Ht作为最后输出的输入,代码上只要指定bidirectional=True

复制代码
    gru_layer = nn.GRU(input_size=vocab_size, hidden_size=num_hiddens,bidirectional=True)

全部评论 (0)

还没有任何评论哟~