9.4. 双向循环神经网络

要点
  • 双向 RNN 主要的想法是认为后面的词也会影响前面的词的理解,适合做句子的特征提取,例如翻译,而不能用在文本生成或者预测未来

在前面单向循环神经网络中,都是用前面的词来预测下一个词,但有的任务中(例如完形填空),后面的词对也同样重要:

根据可获得的信息量,我们可以用不同的词填空,如“很高兴”(“happy”)、“不”(“not”)和“非常”(“very”)。所以,后面的词同样会影响前面的词理解

1. 双向模型

双向循环神经网络(bidirectional RNNs) 添加了反向传递信息的隐藏层,以便更灵活地处理此类信息。

9.4. 双向循环神经网络.png|center|400 双向循环神经网络架构
9.4. 双向循环神经网络-1.png|center|700 一个时间步下双向循环网络计算示意图,两边的状态横着 concat 起来进行训练(相当于把神经元堆叠)

对于任意时间步 t, 给定一个小批量的输入数据 XtRn×d (样本数 n, 每个示例中的输入数 d ), 并且令隐藏层激活函数为 ϕ 。在双向架构中, 我们设该时间步的前向和反向隐状态分别为 HtRn×hHtRn×h, 其中 h 是隐藏单元的数目。前向和反向隐状态的更新如下:

Ht=ϕ(XtWxh(f)+Ht1Whh(f)+bh(f))Ht=ϕ(XtWxh(b)+Ht+1Whh(b)+bh(b))Ht=[Ht,Ht]

其中, 权重 Wxh(f)Rd×h,Whh(f)Rh×h,Wxh(b)Rd×h,Whh(b)Rh×h 和偏置

接下来, 将前向隐状态 Ht 和反向隐状态 Ht 连接起来, 获得需要送入输出层的隐状态 HtRn×2h 。在具有多个隐藏层的深度双向循环神经网络中, 该信息作为输入传递到下一个双向层。最后, 输出层计算得到的输出为 OtRn×qq 是输出单元的数目):

Ot=HtWhq+bq.

这里, 权重矩阵 WhqR2h×q 和偏置 bqR1×q 是输出层的模型参数。事实上, 这两个方向可以拥有不同数量的隐藏单元。

2. 双向 RNN 的简洁实现与错误运用

如果要手动实现双向 RNN,直接在每个批计算的时候将序列逆序,再把对应的前向隐状态 Ht 和反向隐状态 Ht concat 起来,就可以计算 forward 函数。

这里用框架实现:

import torch
from torch import nn
from d2l import torch as d2l

# 加载数据
batch_size, num_steps, device = 32, 35, d2l.try_gpu()
train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps)
# 通过设置“bidirective=True”来定义双向LSTM模型
vocab_size, num_hiddens, num_layers = len(vocab), 256, 2
num_inputs = vocab_size
lstm_layer = nn.LSTM(num_inputs, num_hiddens, num_layers, bidirectional=True)
model = d2l.RNNModel(lstm_layer, len(vocab))
model = model.to(device)
# 训练模型
num_epochs, lr = 500, 1
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)
perplexity 1.1, 131129.2 tokens/sec on cuda:0
time travellerererererererererererererererererererererererererer
travellerererererererererererererererererererererererererer

9.4. 双向循环神经网络-3.png|center|400 预测的时候是没有未来的信息的,虽然 loss 很低,但几乎没有推理能力

参考文献



© 2023 yanghn. All rights reserved. Powered by Obsidian