3

简洁实现GRU 门控循环单元 | #51CTO博主之星评选#

 2 years ago
source link: https://blog.51cto.com/Lolitann/5146270
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

简洁实现GRU 门控循环单元 | #51CTO博主之星评选#

原创

LolitaAnn 2022-03-25 00:03:35 ©著作权

文章标签 初始化 数据集 导包 文章分类 深度学习 人工智能 阅读数483

这个是接着上一个文章​ ​从零实现GRU门控循环单元​​写的,如果你没看上篇文章也没事,本篇文章是讲如何用pytorch直接实现GRU,和上一篇文章除了思路一样,其他没有任何参考意义。


import torch
from torch import nn
from d2l import torch as d2l
from torch.nn import functional as F

依旧是熟悉的配方熟悉的导包操作。

batch_size, num_steps = 32, 35
train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps)

这里和之前没区别,设定一些超参数并加载数据集。

  • 设定batch-size批量大小和时间步的长度num_step。这里需要注意时间步的长度是你一个要处理的序列的时间步有多少个。
  • 使用之前我们实现过的加载时光机器数据集。获得数据集的迭代器和词汇表的长度,这里为了方便,使用的是char进行分割,也就是说词汇表是a~z以及空格和<unk>。
class GRUModel(nn.Module):
def __init__(self, gru_layer, vocab_size, <strong>kwargs):
super(GRUModel, self).__init__(</strong>kwargs)
self.gru = gru_layer
self.vocab_size = vocab_size
self.num_hiddens = self.gru.hidden_size
if not self.gru.bidirectional:
self.num_directions = 1
self.linear = nn.Linear(self.num_hiddens,
self.vocab_size)
else:
self.num_directions = 2
self.linear = nn.Linear(self.num_hiddens * 2,
self.vocab_size)

def forward(self, inputs, state):
X = F.one_hot(inputs.T.long(), self.vocab_size)
X = X.to(torch.float32)
Y, state = self.gru(X, state)
output = self.linear(Y.reshape((-1, Y.shape[-1])))
return output, state

def begin_state(self, device, batch_size=1):
return torch.zeros((
self.num_directions * self.gru.num_layers,
batch_size, self.num_hiddens),
device=device)

RNN、GRU、LSTM一脉相承,用的类的都差不多,这个是适用于RNN和GRU的,但是不适用于LSTM。LSTM可以看我之后的文章,或者看前边的​ ​简洁实现RNN循环神经网络​​实现的那个RNNModule类,那个类是涵盖了RNN、GRU、LSTM的通用模型。

  • ​__init__​​​初始化这个类,这个类是继承了​​nn.Module​​的。
  • ​self.gru​​​设定计算层是GRU层,这里是需要参数的,你在下一段代码中会传入​​nn.GRU​​。
  • ​self.vocab_size​​​设定字典的大小,这里大小是28,因为我们使用的是字母进行分词,所以其中只有​​a~z​​​26个字母外加​​​和​​<unk>​​(空格和unknown)。
  • ​self.num_hiddens​​设置隐藏层的大小。普通的RNN是隐藏层,在这里是带隐状态的隐藏层。不是说有隐状态之后就没隐藏层了。
  • if-else语句是设定GRU是单双向的。
  • ​forward​​定义前向传播网络。

这里不用我们自己来实现计算过程了,​​nn.GRU​​会直接给我们计算。但是我们依旧需要对数据进行一下才操作。

  • 首先是将输入转化为对应的one-hot向量,这里​​F​​​看前边导包部分,是使用​​nn.functional​​。
  • ​torch.float32​​再将其类型转化为float。
  • ​Y​​​和​​state​​是计算隐状态的,​注意​​ 在这里​​Y​​不是 输出。这里Y是输出全部的隐状态,state是输出最后一个时间步的隐状态。

简洁实现GRU 门控循环单元  | #51CTO博主之星评选#_数据集

  • ​output​​是用于存储输出的。
  • ​begin_state​​是进行初始化。

这里初始化和RNN初始化一样,都是初始化为一个零张量。之后可以留意一下LSTM,LSTM是返回一个元组,元组中有两个张量。

vocab_size, num_hiddens, device = len(vocab), 256, d2l.try_gpu()
num_epochs, lr = 100, 1
num_inputs = vocab_size
gru_layer = nn.GRU(num_inputs, num_hiddens)
model = GRUModel(gru_layer, len(vocab))
model = model.to(device)
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)

设定一些基础数值:

  • ​vocab_size​​词典长度
  • ​num_hiddens​​隐藏层向量的长度
  • ​device​​在CPU还是GPU上执行
  • ​num_epochs​​训练的epoch数量
  • ​lr​​学习率learning rate

GRU层直接使用​​nn.GRU​​。

之后对其进行训练并测试。输出训练集的困惑度和前缀“time traveler”和“traveler”的预测序列结果。

简洁实现GRU 门控循环单元  | #51CTO博主之星评选#_初始化_02

  • 收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK