0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

PyTorch教程-10.3. 深度递归神经网络

jf_pJlTbmA9 来源:PyTorch 作者:PyTorch 2023-06-05 15:44 次阅读

到目前为止,我们一直专注于定义由序列输入、单个隐藏 RNN 层和输出层组成的网络。尽管在任何时间步长的输入和相应的输出之间只有一个隐藏层,但从某种意义上说这些网络很深。第一个时间步的输入会影响最后一个时间步的输出T(通常是 100 或 1000 步之后)。这些输入通过T在达到最终输出之前循环层的应用。但是,我们通常还希望保留表达给定时间步长的输入与同一时间步长的输出之间复杂关系的能力。因此,我们经常构建不仅在时间方向上而且在输入到输出方向上都很深的 RNN。这正是我们在 MLP 和深度 CNN 的开发中已经遇到的深度概念。

构建这种深度 RNN 的标准方法非常简单:我们将 RNN 堆叠在一起。给定一个长度序列T,第一个 RNN 产生一个输出序列,也是长度T. 这些依次构成下一个 RNN 层的输入。在这个简短的部分中,我们将说明这种设计模式,并提供一个简单示例来说明如何编写此类堆叠 RNN。下面,在 图 10.3.1中,我们用L隐藏层。每个隐藏状态对顺序输入进行操作并产生顺序输出。此外,每个时间步的任何 RNN 单元(图 10.3.1中的白框 )都取决于同一层在前一时间步的值和前一层在同一时间步的值。

pYYBAGR9Ny2APxp9AAFWII8pJpk605.svg

图 10.3.1深度 RNN 的架构。

正式地,假设我们有一个小批量输入 Xt∈Rn×d(示例数量: n,每个示例中的输入数量:d) 在时间步 t. 同时step,让hidden state的 lth隐藏层(l=1,…,L) 是 Ht(l)∈Rn×h(隐藏单元的数量:h) 和输出层变量是 Ot∈Rn×q(输出数量: q). 环境Ht(0)=Xt, 的隐藏状态lth使用激活函数的隐藏层ϕl计算如下:

(10.3.1)Ht(l)=ϕl(Ht(l−1)Wxh(l)+Ht−1(l)Whh(l)+bh(l)),

权重在哪里 Wxh(l)∈Rh×h和 Whh(l)∈Rh×h, 连同偏差bh(l)∈R1×h, 是模型参数lth隐藏层。

最终输出层的计算只是根据最终的隐藏状态Lth隐藏层:

(10.3.2)Ot=Ht(L)Whq+bq,

重量在哪里Whq∈Rh×q和偏见bq∈R1×q是输出层的模型参数。

与 MLP 一样,隐藏层的数量L和隐藏单元的数量h是我们可以调整的超参数。常见的 RNN 层宽度 (h) 在范围内(64,2056), 和共同深度 (L) 在范围内(1,8). 此外,我们可以通过将(10.3.1)中的隐藏状态计算替换为来自 LSTM 或 GRU 的计算来轻松获得深度门控 RNN。

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

from mxnet import np, npx
from mxnet.gluon import rnn
from d2l import mxnet as d2l

npx.set_np()

import jax
from flax import linen as nn
from jax import numpy as jnp
from d2l import jax as d2l

import tensorflow as tf
from d2l import tensorflow as d2l

10.3.1。从零开始实施

要从头开始实现多层 RNN,我们可以将每一层视为RNNScratch具有自己可学习参数的实例。

class StackedRNNScratch(d2l.Module):
  def __init__(self, num_inputs, num_hiddens, num_layers, sigma=0.01):
    super().__init__()
    self.save_hyperparameters()
    self.rnns = nn.Sequential(*[d2l.RNNScratch(
      num_inputs if i==0 else num_hiddens, num_hiddens, sigma)
                  for i in range(num_layers)])

class StackedRNNScratch(d2l.Module):
  def __init__(self, num_inputs, num_hiddens, num_layers, sigma=0.01):
    super().__init__()
    self.save_hyperparameters()
    self.rnns = [d2l.RNNScratch(num_inputs if i==0 else num_hiddens,
                  num_hiddens, sigma)
           for i in range(num_layers)]

class StackedRNNScratch(d2l.Module):
  num_inputs: int
  num_hiddens: int
  num_layers: int
  sigma: float = 0.01

  def setup(self):
    self.rnns = [d2l.RNNScratch(self.num_inputs if i==0 else self.num_hiddens,
                  self.num_hiddens, self.sigma)
           for i in range(self.num_layers)]

class StackedRNNScratch(d2l.Module):
  def __init__(self, num_inputs, num_hiddens, num_layers, sigma=0.01):
    super().__init__()
    self.save_hyperparameters()
    self.rnns = [d2l.RNNScratch(num_inputs if i==0 else num_hiddens,
                  num_hiddens, sigma)
           for i in range(num_layers)]

多层正向计算只是逐层进行正向计算。

@d2l.add_to_class(StackedRNNScratch)
def forward(self, inputs, Hs=None):
  outputs = inputs
  if Hs is None: Hs = [None] * self.num_layers
  for i in range(self.num_layers):
    outputs, Hs[i] = self.rnns[i](outputs, Hs[i])
    outputs = torch.stack(outputs, 0)
  return outputs, Hs

@d2l.add_to_class(StackedRNNScratch)
def forward(self, inputs, Hs=None):
  outputs = inputs
  if Hs is None: Hs = [None] * self.num_layers
  for i in range(self.num_layers):
    outputs, Hs[i] = self.rnns[i](outputs, Hs[i])
    outputs = np.stack(outputs, 0)
  return outputs, Hs

@d2l.add_to_class(StackedRNNScratch)
def forward(self, inputs, Hs=None):
  outputs = inputs
  if Hs is None: Hs = [None] * self.num_layers
  for i in range(self.num_layers):
    outputs, Hs[i] = self.rnns[i](outputs, Hs[i])
    outputs = jnp.stack(outputs, 0)
  return outputs, Hs

@d2l.add_to_class(StackedRNNScratch)
def forward(self, inputs, Hs=None):
  outputs = inputs
  if Hs is None: Hs = [None] * self.num_layers
  for i in range(self.num_layers):
    outputs, Hs[i] = self.rnns[i](outputs, Hs[i])
    outputs = tf.stack(outputs, 0)
  return outputs, Hs

例如,我们在时间机器数据集上训练了一个深度 GRU 模型(与第 9.5 节相同)。为了简单起见,我们将层数设置为 2。

data = d2l.TimeMachine(batch_size=1024, num_steps=32)
rnn_block = StackedRNNScratch(num_inputs=len(data.vocab),
               num_hiddens=32, num_layers=2)
model = d2l.RNNLMScratch(rnn_block, vocab_size=len(data.vocab), lr=2)
trainer = d2l.Trainer(max_epochs=100, gradient_clip_val=1, num_gpus=1)
trainer.fit(model, data)

poYBAGR9NzaAa9twABGZ2lWRJEE214.svg

data = d2l.TimeMachine(batch_size=1024, num_steps=32)
rnn_block = StackedRNNScratch(num_inputs=len(data.vocab),
               num_hiddens=32, num_layers=2)
model = d2l.RNNLMScratch(rnn_block, vocab_size=len(data.vocab), lr=2)
trainer = d2l.Trainer(max_epochs=100, gradient_clip_val=1, num_gpus=1)
trainer.fit(model, data)

pYYBAGR9NzyAGI05ABE9SstdFcw019.svg

data = d2l.TimeMachine(batch_size=1024, num_steps=32)
rnn_block = StackedRNNScratch(num_inputs=len(data.vocab),
               num_hiddens=32, num_layers=2)
model = d2l.RNNLMScratch(rnn_block, vocab_size=len(data.vocab), lr=2)
trainer = d2l.Trainer(max_epochs=100, gradient_clip_val=1, num_gpus=1)
trainer.fit(model, data)

pYYBAGR9N0KAQmF-ABGkJ5uIgZU215.svg

data = d2l.TimeMachine(batch_size=1024, num_steps=32)
with d2l.try_gpu():
  rnn_block = StackedRNNScratch(num_inputs=len(data.vocab),
               num_hiddens=32, num_layers=2)
  model = d2l.RNNLMScratch(rnn_block, vocab_size=len(data.vocab), lr=2)
trainer = d2l.Trainer(max_epochs=100, gradient_clip_val=1)
trainer.fit(model, data)

poYBAGR9N0mAVQ3YABF5GnHpjBk788.svg

10.3.2。简洁的实现

幸运的是,实现多层 RNN 所需的许多逻辑细节都可以在高级 API 中轻松获得。我们的简洁实现将使用此类内置功能。该代码概括了我们之前在第 10.2 节中使用的代码,允许明确指定层数而不是选择单层的默认值。

class GRU(d2l.RNN): #@save
  """The multi-layer GRU model."""
  def __init__(self, num_inputs, num_hiddens, num_layers, dropout=0):
    d2l.Module.__init__(self)
    self.save_hyperparameters()
    self.rnn = nn.GRU(num_inputs, num_hiddens, num_layers,
             dropout=dropout)

Fortunately many of the logistical details required to implement multiple layers of an RNN are readily available in high-level APIs. Our concise implementation will use such built-in functionalities. The code generalizes the one we used previously in Section 10.2, allowing specification of the number of layers explicitly rather than picking the default of a single layer.

class GRU(d2l.RNN): #@save
  """The multi-layer GRU model."""
  def __init__(self, num_hiddens, num_layers, dropout=0):
    d2l.Module.__init__(self)
    self.save_hyperparameters()
    self.rnn = rnn.GRU(num_hiddens, num_layers, dropout=dropout)

Flax takes a minimalistic approach while implementing RNNs. Defining the number of layers in an RNN or combining it with dropout is not available out of the box. Our concise implementation will use all built-in functionalities and add num_layers and dropout features on top. The code generalizes the one we used previously in Section 10.2, allowing specification of the number of layers explicitly rather than picking the default of a single layer.

class GRU(d2l.RNN): #@save
  """The multi-layer GRU model."""
  num_hiddens: int
  num_layers: int
  dropout: float = 0

  @nn.compact
  def __call__(self, X, state=None, training=False):
    outputs = X
    new_state = []
    if state is None:
      batch_size = X.shape[1]
      state = [nn.GRUCell.initialize_carry(jax.random.PRNGKey(0),
          (batch_size,), self.num_hiddens)] * self.num_layers

    GRU = nn.scan(nn.GRUCell, variable_broadcast="params",
           in_axes=0, out_axes=0, split_rngs={"params": False})

    # Introduce a dropout layer after every GRU layer except last
    for i in range(self.num_layers - 1):
      layer_i_state, X = GRU()(state[i], outputs)
      new_state.append(layer_i_state)
      X = nn.Dropout(self.dropout, deterministic=not training)(X)

    # Final GRU layer without dropout
    out_state, X = GRU()(state[-1], X)
    new_state.append(out_state)
    return X, jnp.array(new_state)

Fortunately many of the logistical details required to implement multiple layers of an RNN are readily available in high-level APIs. Our concise implementation will use such built-in functionalities. The code generalizes the one we used previously in Section 10.2, allowing specification of the number of layers explicitly rather than picking the default of a single layer.

class GRU(d2l.RNN): #@save
  """The multi-layer GRU model."""
  def __init__(self, num_hiddens, num_layers, dropout=0):
    d2l.Module.__init__(self)
    self.save_hyperparameters()
    gru_cells = [tf.keras.layers.GRUCell(num_hiddens, dropout=dropout)
           for _ in range(num_layers)]
    self.rnn = tf.keras.layers.RNN(gru_cells, return_sequences=True,
                    return_state=True, time_major=True)

  def forward(self, X, state=None):
    outputs, *state = self.rnn(X, state)
    return outputs, state

选择超参数等架构决策与10.2 节中的决策非常相似。我们选择相同数量的输入和输出,因为我们有不同的标记,即vocab_size。隐藏单元的数量仍然是 32。唯一的区别是我们现在通过指定 的值来选择不平凡的隐藏层数量 num_layers。

gru = GRU(num_inputs=len(data.vocab), num_hiddens=32, num_layers=2)
model = d2l.RNNLM(gru, vocab_size=len(data.vocab), lr=2)
trainer.fit(model, data)

poYBAGR9N0-ACSs2ABGOdabS9XU405.svg

model.predict('it has', 20, data.vocab, d2l.try_gpu())

'it has a small the time tr'

gru = GRU(num_hiddens=32, num_layers=2)
model = d2l.RNNLM(gru, vocab_size=len(data.vocab), lr=2)

# Running takes > 1h (pending fix from MXNet)
# trainer.fit(model, data)
# model.predict('it has', 20, data.vocab, d2l.try_gpu())

gru = GRU(num_hiddens=32, num_layers=2)
model = d2l.RNNLM(gru, vocab_size=len(data.vocab), lr=2)
trainer.fit(model, data)

poYBAGR9N1aAfa6nABGh5DQiuQk744.svg

model.predict('it has', 20, data.vocab, trainer.state.params)

'it has wo mean the time tr'

gru = GRU(num_hiddens=32, num_layers=2)
with d2l.try_gpu():
  model = d2l.RNNLM(gru, vocab_size=len(data.vocab), lr=2)
trainer.fit(model, data)

poYBAGR9N12ATl3KABGrHVIDLJc752.svg

model.predict('it has', 20, data.vocab)

'it has and the time travel'

10.3.3。概括

在深度 RNN 中,隐藏状态信息被传递到当前层的下一个时间步和下一层的当前时间步。存在许多不同风格的深度 RNN,例如 LSTM、GRU 或普通 RNN。方便的是,这些模型都可以作为深度学习框架的高级 API 的一部分使用。模型的初始化需要小心。总的来说,深度 RNN 需要大量的工作(例如学习率和裁剪)来确保适当的收敛。

10.3.4。练习

用 LSTM 替换 GRU 并比较准确性和训练速度。

增加训练数据以包含多本书。你的困惑度可以降到多低?

在建模文本时,您想结合不同作者的来源吗?为什么这是个好主意?会出什么问题?

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 神经网络
    +关注

    关注

    42

    文章

    4771

    浏览量

    100752
  • pytorch
    +关注

    关注

    2

    文章

    808

    浏览量

    13221
收藏 人收藏

    评论

    相关推荐

    基于递归神经网络和前馈神经网络深度学习预测算法

    蛋白质二级结构预测是结构生物学中的一个重要问题。针对八类蛋白质二级结构预测,提出了一种基于递归神经网络和前馈神经网络深度学习预测算法。该算法通过双向
    发表于 12-03 09:41 9次下载

    PyTorch教程8.1之深度卷积神经网络(AlexNet)

    电子发烧友网站提供《PyTorch教程8.1之深度卷积神经网络(AlexNet).pdf》资料免费下载
    发表于 06-05 10:09 0次下载
    <b class='flag-5'>PyTorch</b>教程8.1之<b class='flag-5'>深度</b>卷积<b class='flag-5'>神经网络</b>(AlexNet)

    PyTorch教程之从零开始的递归神经网络实现

    电子发烧友网站提供《PyTorch教程之从零开始的递归神经网络实现.pdf》资料免费下载
    发表于 06-05 09:55 0次下载
    <b class='flag-5'>PyTorch</b>教程之从零开始的<b class='flag-5'>递归</b><b class='flag-5'>神经网络</b>实现

    PyTorch教程9.6之递归神经网络的简洁实现

    电子发烧友网站提供《PyTorch教程9.6之递归神经网络的简洁实现.pdf》资料免费下载
    发表于 06-05 09:56 0次下载
    <b class='flag-5'>PyTorch</b>教程9.6之<b class='flag-5'>递归</b><b class='flag-5'>神经网络</b>的简洁实现

    PyTorch教程10.3深度递归神经网络

    电子发烧友网站提供《PyTorch教程10.3深度递归神经网络.pdf》资料免费下载
    发表于 06-05 15:12 0次下载
    <b class='flag-5'>PyTorch</b>教程<b class='flag-5'>10.3</b>之<b class='flag-5'>深度</b><b class='flag-5'>递归</b><b class='flag-5'>神经网络</b>

    PyTorch教程10.4之双向递归神经网络

    电子发烧友网站提供《PyTorch教程10.4之双向递归神经网络.pdf》资料免费下载
    发表于 06-05 15:13 0次下载
    <b class='flag-5'>PyTorch</b>教程10.4之双向<b class='flag-5'>递归</b><b class='flag-5'>神经网络</b>

    PyTorch教程16.2之情感分析:使用递归神经网络

    电子发烧友网站提供《PyTorch教程16.2之情感分析:使用递归神经网络.pdf》资料免费下载
    发表于 06-05 10:55 0次下载
    <b class='flag-5'>PyTorch</b>教程16.2之情感分析:使用<b class='flag-5'>递归</b><b class='flag-5'>神经网络</b>

    使用PyTorch构建神经网络

    PyTorch是一个流行的深度学习框架,它以其简洁的API和强大的灵活性在学术界和工业界得到了广泛应用。在本文中,我们将深入探讨如何使用PyTorch构建神经网络,包括从基础概念到高级
    的头像 发表于 07-02 11:31 708次阅读

    递归神经网络是循环神经网络

    递归神经网络(Recurrent Neural Network,简称RNN)和循环神经网络(Recurrent Neural Network,简称RNN)实际上是同一个概念,只是不同的翻译方式
    的头像 发表于 07-04 14:54 759次阅读

    递归神经网络与循环神经网络一样吗

    递归神经网络(Recursive Neural Network,RvNN)和循环神经网络(Recurrent Neural Network,RNN)是两种不同类型的神经网络结构,它们在
    的头像 发表于 07-05 09:28 858次阅读

    rnn是递归神经网络还是循环神经网络

    RNN(Recurrent Neural Network)是循环神经网络,而非递归神经网络。循环神经网络是一种具有时间序列特性的神经网络,能
    的头像 发表于 07-05 09:52 577次阅读

    PyTorch神经网络模型构建过程

    PyTorch,作为一个广泛使用的开源深度学习库,提供了丰富的工具和模块,帮助开发者构建、训练和部署神经网络模型。在神经网络模型中,输出层是尤为关键的部分,它负责将模型的预测结果以合适
    的头像 发表于 07-10 14:57 500次阅读

    递归神经网络的实现方法

    递归神经网络(Recursive Neural Network,简称RNN)是一种特殊类型的神经网络,其特点在于能够处理具有层次或树状结构的数据,并通过递归的方式对这些数据进行建模。与
    的头像 发表于 07-10 17:02 325次阅读

    递归神经网络和循环神经网络的模型结构

    递归神经网络是一种旨在处理分层结构的神经网络,使其特别适合涉及树状或嵌套数据的任务。这些网络明确地模拟了层次结构中的关系和依赖关系,例如语言中的句法结构或图像中的层次表示。它使用
    的头像 发表于 07-10 17:21 657次阅读
    <b class='flag-5'>递归</b><b class='flag-5'>神经网络</b>和循环<b class='flag-5'>神经网络</b>的模型结构

    pytorch中有神经网络模型吗

    当然,PyTorch是一个广泛使用的深度学习框架,它提供了许多预训练的神经网络模型。 PyTorch中的神经网络模型 1. 引言
    的头像 发表于 07-11 09:59 700次阅读