双向循环神经网络 Bi-RNN
2024-04-09 16:15:53  阅读数 9530

(一)双向循环神经网络

我们首先回顾一下前面学习的序列模型中的求某个时刻,该事件发生的概率的推导公式:

在时间t观察得到了一个数据x_t,那么得到T个不独立的随机变量(x_1, x_2, ..., x_T) ~ p(x)。使用条件概率展开(乘法法则):
p(a,b)=p(a)p(b|a)=p(b)p(a|b)

我们可以看这个公式在直观上的表达,也就是后续的概率是基于前面的概率的。当然也可以反过来。

我们知道计算这个概率的时候,可以选择从前往后看,也可以选择从后往前看。这就构成了双向循环神经网络的核心思想。

举个例子:
对于某个词的预测,可能后面的内容也很重要。

  • 填空的词取决于过去和未来的上下文
  • 目前的RNN都是只看过去
  • 在填空的时候我们可以看未来
(1)网络结构

这个图看起来挺复杂的,我们只看前两个。
正常情况下,x通过隐藏层H然后输出为O,然后隐状态向下传递。就是如图所示的x_1->H_1->O_1
接下来我们看x_2,除了正常情况,他还有一个箭头直接传向了逆H_2,然后将隐状态传向上一层的逆H_1然后与正向的H_1共同作用输出O_1
所以说一共有两条链,第一条是正向的,第二条是逆向的,他们共同作用输出结果,这就是双向RNN的网络结构了。

(2)训练和预测

训练是好训练的,但是那么我怎么用来预测呢?所以双向神经网络是不能用在预测下一个词的情况的。

这里没有实现从零开始写,但是说一下简单的操作流程:

  • 把输入复制一遍
  • 在前向传到的时候,正常输出第一个隐藏层的结果
  • 第二个隐藏层把输入反向,并输出反向
  • 然后把两个隐藏层的输出一一对应的连接

双向神经网络的主要作用是对一个句子做特征提取。例如,提取摘要、填空等。

(二)代码实现

(1)简洁实现

这个应用场景是错误的,因为双向神经网络无法用于预测未来,也就是说下面的网络是没有意义的。只是用来说明怎么使用。

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)