在序列学习中,我们以往假设的目标是: 在给定观测的情况下 (例如,在时间序列的上下文中或在语言模型的上下文中), 对下一个输出进行建模。 虽然这是一个典型情景,但不是唯一的。 还可能发生什么其它的情况呢? 我们考虑以下三个在文本序列中填空的任务:
我___
。
我___
饿了。
我___
饿了,我可以吃半头猪。
根据可获得的信息量,我们可以用不同的词填空, 如“很高兴”(”happy”)、“不”(”not”)和“非常”(”very”)。 很明显,每个短语的“下文”传达了重要信息(如果有的话), 而这些信息关乎到选择哪个词来填空, 所以无法利用这一点的序列模型将在相关任务上表现不佳。 例如,如果要做好命名实体识别 (例如,识别“Green”指的是“格林先生”还是绿色), 不同长度的上下文范围重要性是相同的。 为了获得一些解决问题的灵感,让我们先迂回到概率图模型。
这一小节是用来说明动态规划问题的, 具体的技术细节对于理解深度学习模型并不重要, 但它有助于我们思考为什么要使用深度学习, 以及为什么要选择特定的架构。
如果我们想用概率图模型来解决这个问题, 可以设计一个隐变量模型: 在任意时间步t,假设存在某个隐变量ht, 通过概率P(xt∣ht)控制我们观测到的xt。 此外,任何ht→ht+1转移 都是由一些状态转移概率P(ht+1∣ht)给出。 这个概率图模型就是一个隐马尔可夫模型(hidden Markov model,HMM)。
隐马尔可夫模型
总结:
在双向循环神经网络中,每个时间步的隐状态由当前时间步的前后数据同时决定。
双向循环神经网络与概率图模型中的“前向-后向”算法具有相似性。
双向循环神经网络主要用于序列编码和给定双向上下文的观测估计。
由于梯度链更长,因此双向循环神经网络的训练代价非常高。
代码:
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)
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) # bidirectional是双向参数
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) # 双向循环神经网络无法预测未来信息
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)
vocab_size, num_hiddens, num_layers = len(vocab), 256, 2
num_inputs = vocab_size
lstm_layer = nn.GRU(num_inputs, num_hiddens, num_layers, bidirectional=True) # bidirectional是双向参数
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) # 双向循环神经网络无法预测未来信息
LSTM 与GUR在处理改数据样本时,效果会更好一些。