6.5 循环神经网络的简洁实现
导入库并加载数据集
1 | import time |
定义模型
PyTorch中的nn
模块提供了循环神经网络的实现。下面构造一个含单隐藏层、隐藏单元个数为256的循环神经网络层rnn_layer
。
1 | num_hiddens = 256 |
与上一节中实现的循环神经网络不同,这里rnn_layer
的输入形状为(时间步数, 批量大小, 输入个数)。其中输入个数即one-hot向量长度(词典大小)。此外,rnn_layer
作为nn.RNN
实例,在前向计算后会分别返回输出和隐藏状态h,其中输出指的是隐藏层在各个时间步上计算并输出的隐藏状态,它们通常作为后续输出层的输入,也就是说,一次性计算出所有时间步的隐藏层的状态。需要强调的是,该“输出”本身并不涉及输出层计算,形状为(时间步数, 批量大小, 隐藏单元个数)。而nn.RNN
实例在前向计算返回的隐藏状态指的是隐藏层在最后时间步的隐藏状态:当隐藏层有多层时,每一层的隐藏状态都会记录在该变量中。关于循环神经网络(以LSTM为例)的输出,可以参考下图。
输出形状为(时间步数, 批量大小, 隐藏单元个数),隐藏状态h的形状为(层数, 批量大小, 隐藏单元个数)。
1 | num_steps = 35 |
接下来继承Module
类来定义一个完整的循环神经网络。它首先将输入数据使用one-hot向量表示后输入到rnn_layer
中,然后使用全连接输出层得到输出。输出个数等于词典大小vocab_size
。
1 | class RNNModel(nn.Module): |
训练模型
定义一个预测函数。这里的实现区别在于前向计算和初始化隐藏状态的函数接口。
1 | def predict_rnn_pytorch(prefix, num_chars, model, vocab_size, device, idx_to_char, |
接下来实现训练函数。算法同上一节的一样,但这里只使用了相邻采样来读取数据。
1 | def train_and_predict_rnn_pytorch(model, num_hiddens, vocab_size, device, |
使用和上一节实验中一样的超参数(除了学习率)来训练模型。
1 | num_epochs, batch_size, lr, clipping_theta = 250, 32, 1e-3, 1e-2 # 注意这里的学习率设置 |
输出:
1 | epoch 50, perplexity 10.340747, time 0.03 sec |