56 门控循环单元(GRU)_by《李沐:动手学深度学习v2》pytorch版

系列文章目录


文章目录

  • 系列文章目录
  • 门控循环单元(GRU)
    • 门控隐状态
      • 重置门和更新门
      • 候选隐状态
      • 隐状态
    • 从零开始实现
      • 初始化模型参数
      • 定义模型
      • 训练与预测
    • 简洁实现
    • 小结
    • 练习


门控循环单元(GRU)

之前我们讨论了如何在循环神经网络中计算梯度,以及矩阵连续乘积可以导致梯度消失或梯度爆炸的问题。
下面我们简单思考一下这种梯度异常在实践中的意义:

  • 我们可能会遇到这样的情况:早期观测值对预测所有未来观测值具有非常重要的意义。
    考虑一个极端情况,其中第一个观测值包含一个校验和,目标是在序列的末尾辨别校验和是否正确。
    在这种情况下,第一个词元的影响至关重要。
    我们希望有某些机制能够在一个记忆元里存储重要的早期信息。
    如果没有这样的机制,我们将不得不给这个观测值指定一个非常大的梯度,因为它会影响所有后续的观测值。
  • 我们可能会遇到这样的情况:一些词元没有相关的观测值。
    例如,在对网页内容进行情感分析时,可能有一些辅助HTML代码与网页传达的情绪无关。
    我们希望有一些机制来跳过隐状态表示中的此类词元。
  • 我们可能会遇到这样的情况:序列的各个部分之间存在逻辑中断。
    例如,书的章节之间可能会有过渡存在,或者证券的熊市和牛市之间可能会有过渡存在。
    在这种情况下,最好有一种方法来重置我们的内部状态表示。

在学术界已经提出了许多方法来解决这类问题。
其中最早的方法是"长短期记忆"(long-short-term memory,LSTM),我们将在之后讨论。
门控循环单元(gated recurrent unit,GRU)是一个稍微简化的变体,通常能够提供同等的效果,并且计算的速度明显更快。
由于门控循环单元更简单,我们从它开始解读。

门控隐状态

门控循环单元与普通的循环神经网络之间的关键区别在于:
前者支持隐状态的门控。
这意味着模型有专门的机制来确定应该何时更新隐状态,以及应该何时重置隐状态。
这些机制是可学习的,并且能够解决了上面列出的问题。
例如,如果第一个词元非常重要,模型将学会在第一次观测之后不更新隐状态。
同样,模型也可以学会跳过不相关的临时观测。
最后,模型还将学会在需要的时候重置隐状态。
下面我们将详细讨论各类门控。

重置门和更新门

我们首先介绍重置门(reset gate)和更新门(update gate)。
我们把它们设计成 ( 0 , 1 ) (0, 1) (0,1)区间中的向量,这样我们就可以进行凸组合。(“凸组合”是一个数学概念,主要用于优化和几何领域。它指的是在给定的点(或向量)集合中,通过线性组合得到的点,其中每个点的系数都是非负的,并且所有系数的和为1。)
重置门允许我们控制“可能还想记住”的过去状态的数量;
更新门将允许我们控制新状态中有多少个是旧状态的副本。

我们从构造这些门控开始。
下图描述了门控循环单元中的重置门和更新门的输入,输入是由当前时间步的输入和前一时间步的隐状态给出。
两个门的输出是由使用sigmoid激活函数的两个全连接层给出。
在这里插入图片描述

我们来看一下门控循环单元的数学表达。对于给定的时间步 t t t,假设输入是一个小批量 X t ∈ R n × d \mathbf{X}_t \in \mathbb{R}^{n \times d} XtRn×d(样本个数 n n n,输入个数 d d d),上一个时间步的隐状态是 H t − 1 ∈ R n × h \mathbf{H}_{t-1} \in \mathbb{R}^{n \times h} Ht1Rn×h(隐藏单元个数 h h h)。
那么,重置门 R t ∈ R n × h \mathbf{R}_t \in \mathbb{R}^{n \times h} RtRn×h和更新门 Z t ∈ R n × h \mathbf{Z}_t \in \mathbb{R}^{n \times h} ZtRn×h的计算如下所示:

R t = σ ( X t W x r + H t − 1 W h r + b r ) , Z t = σ ( X t W x z + H t − 1 W h z + b z ) , \begin{aligned} \mathbf{R}_t = \sigma(\mathbf{X}_t \mathbf{W}_{xr} + \mathbf{H}_{t-1} \mathbf{W}_{hr} + \mathbf{b}_r),\\ \mathbf{Z}_t = \sigma(\mathbf{X}_t \mathbf{W}_{xz} + \mathbf{H}_{t-1} \mathbf{W}_{hz} + \mathbf{b}_z), \end{aligned} Rt=σ(XtWxr+Ht1Whr+br),Zt=σ(XtWxz+Ht1Whz+bz),

其中 W x r , W x z ∈ R d × h \mathbf{W}_{xr}, \mathbf{W}_{xz} \in \mathbb{R}^{d \times h} Wxr,WxzRd×h W h r , W h z ∈ R h × h \mathbf{W}_{hr}, \mathbf{W}_{hz} \in \mathbb{R}^{h \times h} Whr,WhzRh×h是权重参数, b r , b z ∈ R 1 × h \mathbf{b}_r, \mathbf{b}_z \in \mathbb{R}^{1 \times h} br,bzR1×h是偏置参数。
请注意,在求和过程中会触发广播机制,我们使用sigmoid函数(将输入值转换到区间 ( 0 , 1 ) (0, 1) (0,1)

候选隐状态

接下来,让我们将重置门 R t \mathbf{R}_t Rt
与 常规隐状态更新机制集成,得到在时间步 t t t候选隐状态(candidate hidden state) H ~ t ∈ R n × h \tilde{\mathbf{H}}_t \in \mathbb{R}^{n \times h} H~tRn×h

H ~ t = tanh ⁡ ( X t W x h + ( R t ⊙ H t − 1 ) W h h + b h ) , \tilde{\mathbf{H}}_t = \tanh(\mathbf{X}_t \mathbf{W}_{xh} + \left(\mathbf{R}_t \odot \mathbf{H}_{t-1}\right) \mathbf{W}_{hh} + \mathbf{b}_h), H~t=tanh(XtWxh+(RtHt1)Whh+bh),
:eqlabel:gru_tilde_H

其中 W x h ∈ R d × h \mathbf{W}_{xh} \in \mathbb{R}^{d \times h} WxhRd×h W h h ∈ R h × h \mathbf{W}_{hh} \in \mathbb{R}^{h \times h} WhhRh×h是权重参数, b h ∈ R 1 × h \mathbf{b}_h \in \mathbb{R}^{1 \times h} bhR1×h是偏置项,符号 ⊙ \odot 是Hadamard积(按元素乘积)运算符。
在这里,我们使用tanh非线性激活函数来确保候选隐状态中的值保持在区间 ( − 1 , 1 ) (-1, 1) (1,1)中。

与 一般的RNN相比, :eqref:gru_tilde_H中的 R t \mathbf{R}_t Rt H t − 1 \mathbf{H}_{t-1} Ht1的元素相乘可以减少以往状态的影响。
每当重置门 R t \mathbf{R}_t Rt中的项接近 1 1 1时,我们恢复一个如 :eqref:rnn_h_with_state中的普通的循环神经网络。
对于重置门 R t \mathbf{R}_t Rt中所有接近 0 0 0的项,候选隐状态是以 X t \mathbf{X}_t Xt作为输入的多层感知机的结果。
因此,任何预先存在的隐状态都会被重置为默认值。

:numref:fig_gru_2说明了应用重置门之后的计算流程。

在这里插入图片描述label:fig_gru_2

隐状态

上述的计算结果只是候选隐状态,我们仍然需要结合更新门 Z t \mathbf{Z}_t Zt的效果。
这一步确定新的隐状态 H t ∈ R n × h \mathbf{H}_t \in \mathbb{R}^{n \times h} HtRn×h在多大程度上来自旧的状态 H t − 1 \mathbf{H}_{t-1} Ht1和新的候选状态 H ~ t \tilde{\mathbf{H}}_t H~t。更新门 Z t \mathbf{Z}_t Zt仅需要在 H t − 1 \mathbf{H}_{t-1} Ht1 H ~ t \tilde{\mathbf{H}}_t H~t之间进行按元素的凸组合就可以实现这个目标。这就得出了门控循环单元的最终更新公式:

H t = Z t ⊙ H t − 1 + ( 1 − Z t ) ⊙ H ~ t . \mathbf{H}_t = \mathbf{Z}_t \odot \mathbf{H}_{t-1} + (1 - \mathbf{Z}_t) \odot \tilde{\mathbf{H}}_t. Ht=ZtHt1+(1Zt)H~t.

每当更新门 Z t \mathbf{Z}_t Zt接近 1 1 1时,模型就倾向只保留旧状态。
此时,来自 X t \mathbf{X}_t Xt的信息基本上被忽略,从而有效地跳过了依赖链条中的时间步 t t t
相反,当 Z t \mathbf{Z}_t Zt接近 0 0 0时,新的隐状态 H t \mathbf{H}_t Ht就会接近候选隐状态 H ~ t \tilde{\mathbf{H}}_t H~t
这些设计可以帮助我们处理循环神经网络中的梯度消失问题,并更好地捕获时间步距离很长的序列的依赖关系。
例如,如果整个子序列的所有时间步的更新门都接近于 1 1 1,则无论序列的长度如何,在序列起始时间步的旧隐状态都将很容易保留并传递到序列结束。

下图说明了更新门起作用后的计算流。

在这里插入图片描述label:fig_gru_3

总之,门控循环单元具有以下两个显著特征:

  • 重置门有助于捕获序列中的短期依赖关系;
  • 更新门有助于捕获序列中的长期依赖关系。

从零开始实现

为了更好地理解门控循环单元模型,我们从零开始实现它。
首先,我们读取时间机器数据集:

import torch
from torch import nn
from d2l import torch as d2lbatch_size, num_steps = 32, 35
train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps)

初始化模型参数

下一步是初始化模型参数。
我们从标准差为 0.01 0.01 0.01的高斯分布中提取权重,
并将偏置项设为 0 0 0,超参数num_hiddens定义隐藏单元的数量,
实例化与更新门、重置门、候选隐状态和输出层相关的所有权重和偏置。

def get_params(vocab_size, num_hiddens, device):num_inputs = num_outputs = vocab_sizedef normal(shape):return torch.randn(size=shape, device=device)*0.01def three():return (normal((num_inputs, num_hiddens)),normal((num_hiddens, num_hiddens)),torch.zeros(num_hiddens, device=device))W_xz, W_hz, b_z = three()  # 更新门参数W_xr, W_hr, b_r = three()  # 重置门参数W_xh, W_hh, b_h = three()  # 候选隐状态参数# 输出层参数W_hq = normal((num_hiddens, num_outputs))b_q = torch.zeros(num_outputs, device=device)# 附加梯度params = [W_xz, W_hz, b_z, W_xr, W_hr, b_r, W_xh, W_hh, b_h, W_hq, b_q]for param in params:param.requires_grad_(True)return params

定义模型

现在我们将[定义隐状态的初始化函数]init_gru_state
与从零实现RNN中定义的init_rnn_state函数一样,此函数返回一个形状为(批量大小,隐藏单元个数)的张量,张量的值全部为零。

def init_gru_state(batch_size, num_hiddens, device):return (torch.zeros((batch_size, num_hiddens), device=device), )

现在我们准备[定义门控循环单元模型],
模型的架构与基本的循环神经网络单元是相同的,只是权重更新公式更为复杂。
下面代码中的 @ @ @与torch.mm作用相同。

def gru(inputs, state, params):W_xz, W_hz, b_z, W_xr, W_hr, b_r, W_xh, W_hh, b_h, W_hq, b_q = paramsH, = stateoutputs = []for X in inputs:Z = torch.sigmoid((X @ W_xz) + (H @ W_hz) + b_z)R = torch.sigmoid((X @ W_xr) + (H @ W_hr) + b_r)H_tilda = torch.tanh((X @ W_xh) + ((R * H) @ W_hh) + b_h) # 注意这之前的H都是上一时刻,这时的H才是这一时刻的HH = Z * H + (1 - Z) * H_tildaY = H @ W_hq + b_qoutputs.append(Y)return torch.cat(outputs, dim=0), (H,)

训练与预测

训练和预测的工作方式与从零实现RNN完全相同。
训练结束后,我们分别打印输出训练集的困惑度,以及前缀“time traveler”和“traveler”的预测序列上的困惑度。

vocab_size, num_hiddens, device = len(vocab), 256, d2l.try_gpu()
num_epochs, lr = 500, 1
model = d2l.RNNModelScratch(len(vocab), num_hiddens, device, get_params,init_gru_state, gru)
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)
perplexity 1.1, 38401.1 tokens/sec on cuda:0
time travelleryou can show black is white by argument said filby
travelleryou can show black is white by argument said filby<Figure size 350x250 with 1 Axes>

在这里插入图片描述

简洁实现

高级API包含了前文介绍的所有配置细节,所以我们可以直接实例化门控循环单元模型。
这段代码的运行速度要快得多,因为它使用的是编译好的运算符而不是Python来处理之前阐述的许多细节。

num_inputs = vocab_size
gru_layer = nn.GRU(num_inputs, num_hiddens)
model = d2l.RNNModel(gru_layer, len(vocab))
model = model.to(device)
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)
perplexity 1.0, 389565.2 tokens/sec on cuda:0
time travelleryou can show black is white by argument said filby
traveller with a slight accession ofcheerfulness really thi<Figure size 350x250 with 1 Axes>

在这里插入图片描述

小结

  • 门控循环神经网络可以更好地捕获时间步距离很长的序列上的依赖关系。
  • 重置门有助于捕获序列中的短期依赖关系。
  • 更新门有助于捕获序列中的长期依赖关系。
  • 重置门打开时,门控循环单元包含基本循环神经网络;更新门打开时,门控循环单元可以跳过子序列。

练习

  1. 假设我们只想使用时间步 t ′ t' t的输入来预测时间步 t > t ′ t > t' t>t的输出。对于每个时间步,重置门和更新门的最佳值是什么?
  2. 调整和分析超参数对运行时间、困惑度和输出顺序的影响。
  3. 比较rnn.RNNrnn.GRU的不同实现对运行时间、困惑度和输出字符串的影响。
  4. 如果仅仅实现门控循环单元的一部分,例如,只有一个重置门或一个更新门会怎样?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/433982.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爬取元气手机壁纸简单案例(仅用于教学,禁止任何非法获利)

爬虫常用的库 爬虫&#xff08;Web Scraping&#xff09;是一种从网页上提取数据的技术。在 Python 中&#xff0c;有许多库可以帮助实现这一目标。以下是一些常用的爬虫库&#xff0c;以及对 BeautifulSoup 的详细介绍。 常用爬虫库 1.Requests ​ a.功能&#xff1a;用于发…

Mysql优化(常见优化)

插入数据 批量插入&#xff1a;因为一条条插入时&#xff0c;每一条数据的插入都要与数据库建立连接&#xff0c;并且关闭连接 手动提交事物&#xff1a; 主键顺序插入 大批量数据插入 如果一次性需要插入大批量数据&#xff0c;使用insert语句插入性能较低&#xff0c;此时可…

IDEA相关设置总结

目录 1.设置JDK 2.设置忽略大小写检查 3.设置字体大小 4.设置类的信息 5.包名分级 1.设置JDK 2.设置忽略大小写检查 3.设置字体大小 4.设置类的信息 5.包名分级 取消勾选

Mybatis(进阶部分)

四 Mybatis完成CURD&#xff08;二&#xff09; 4.5 多条件CRUD 之前的案例中&#xff0c;接口里方法的形参个数都是1个&#xff1b;如果方法形参是两个或者两个以上时&#xff0c;MyBatis又该如何获取获取参数呢&#xff1f; Mybatis提供了好几种方式&#xff0c;可以获取多…

erlang学习:Linux命令学习7

grep进阶&#xff0c;正则表达式初步学习 正则表达式简介 正则表达式是由一些具有特殊含义的字符组成的字符串&#xff0c;多用于查找、替换符合规则的字符串。在表单验证、Url映射等处都会经常用到,同样在linux中也能够用到。 元字符 元字符&#xff1a;即为有特定含义的字…

搭建基于H.265编码的RTSP推流云服务器

一、前言 网上能够找到的RTSP流地址&#xff0c;均是基于H.264编码的RTSP流地址&#xff0c;无法测试应用是否可以播放H265实时流为此&#xff0c;搭建本地的把H.264转码成H.265的RTSP服务器&#xff0c;不管是通过VLC搭建本地RTSP服务器&#xff0c;还是通过FFmpeg搭建本地RT…

自定义knife4j访问路径

文章目录 本文档只是为了留档方便以后工作运维&#xff0c;或者给同事分享文档内容比较简陋命令也不是特别全&#xff0c;不适合小白观看&#xff0c;如有不懂可以私信&#xff0c;上班期间都是在得 原由&#xff0c;嫌弃doc.html 太大众 直接重定向&#xff0c;直接上代码了 p…

数据结构:详解搜索二叉树

目录 一、搜索二叉树的概念 二、搜索二叉树的基本结构 三、搜索二叉树的插入 四、搜索二叉树的查找 五 、搜索二叉树的删除 一、搜索二叉树的概念 ⼆叉搜索树⼜称⼆叉排序树&#xff0c;它或者是⼀棵空树&#xff0c;或者是具有以下性质的⼆叉树&#xff1a; 若它的左子树…

smb文件夹共享设置

UOS统信三种不同场景的文件夹共享,分别是:1、UOS系统间的文件共享;2、Windows7系统访问UOS共享的文件;3、UOS系统访问Windows7共享的文件 文章目录 功能概述功能介绍第一种场景:UOS系统之间的文件共享设置步骤一:打开共享文件夹步骤二:共享管理步骤三:设置共享密码步骤…

【步联科技身份证】 身份证读取与解析———未来之窗行业应用跨平台架构

一、身份证解析代码 C# function 身份证数据解析_湖南步联科技(wzxx) {var result {};result[xm] wzxx.substr(0, 15);result[xbdm] wzxx.substr(15, 1);result[mzdm] wzxx.substr(16, 2);result[csrq] wzxx.substr(18, 8);result[dzmc] wzxx.substr(26, 35);result[gms…

【射频通信电子线路第六讲】射频信号与调制包括调幅和部分调频的内容

一、调制&#xff08;Modulation&#xff09;与解调&#xff08;Demodulation&#xff09; 1、相关概念 调制是指使一个信号&#xff08;如光信号、高频电磁振荡等&#xff09;的某些参数&#xff08;振幅、频率和相位&#xff09;按照另一个欲传输的信号的特点变化的过程。 …

普通二叉搜索树的模拟实现【C++】

二叉搜素树简单介绍 二叉搜索树又称二叉排序树&#xff0c;是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 它的左右子树也分别为二叉搜索树 注意…

[ComfyUI]Flux 出图背景太模糊?一招解决!

小伙伴们在使用 Flux 出图的时候&#xff0c;应该也遇到过大多数情况下背景都是比较模糊的&#xff0c;虽然大多数时候没啥影响&#xff0c;毕竟我们很多时候都只是看主体嘛。 但是也有些场景&#xff0c;我们希望整体的构图中背景也可以高清一些&#xff0c;这样在看整张图片…

【第十六章:Sentosa_DSML社区版-机器学习之生存分析】

【第十六章&#xff1a;Sentosa_DSML社区版-机器学习之生存分析】 16.1 加速失效时间回归 1.算子介绍 加速失效时间回归模型Accelerated failure time (AFT)是一个监督型参数化的回归模型&#xff0c;它可以处理删失数据。它描述了一个生存时间的对数模型&#xff0c;所以它通…

【CSS】透明度 、过渡 、动画 、渐变

opacity 透明度transition 过渡animation 动画background 渐变 ( 线性渐变 \ 径向渐变 \ 锥形渐变 ) opacity 透明度 设置元素的透明度&#xff0c;会影响元素及其所有子元素的透明度&#xff0c;值范围&#xff1a;0&#xff08;完全透明&#xff09;到 1&#xff08;完全不透…

经济不好,但是遍地都是赚钱的机会

现在职场越来越内卷&#xff0c;裁员风波也是不断&#xff0c;前些天看到一个帖子&#xff0c;裁员都裁到应届生头上了。 都说00后整治职场&#xff0c;在如今环境下也要掂量一下了。 大家都在抱怨环境&#xff0c;可是你有没有想过&#xff0c;有些人在闷声发着小财。 下面…

Pygame中Sprite实现逃亡游戏5

在《Pygame中Sprite实现逃亡游戏4》中通过碰撞检测实现了玩家、飞龙与飞火之间的碰撞处理&#xff0c;基本上实现了逃亡功能。最后&#xff0c;实现这个逃亡游戏中文字提示的功能。 1 操作提示 当进入游戏后&#xff0c;会在玩家下方的位置给出操作提示&#xff0c;如图1所示…

数据集-目标检测系列-鲨鱼检测数据集 shark >> DataBall

数据集-目标检测系列-鲨鱼检测数据集 shark >> DataBall 数据集-目标检测系列-鲨鱼检测数据集 shark 数据量&#xff1a;6k 数据样例项目地址&#xff1a; gitcode: https://gitcode.com/DataBall/DataBall-detections-100s/overview github: https://github.com/Te…

3款照片人物开口说话AI工具,跟真人说话一样~免费!短视频带货必备!(附教程)

大家好&#xff0c;我是画画的小强 今天给大家分享一个AI图片口播数字人讲认知思维&#xff0c;单号佣金赚5W的AI带货信息差玩法&#xff0c;许多小伙伴表示对这类AI带货玩法感兴趣。 说实话&#xff0c;现在AI照片人物对口型工具&#xff0c;越来越逼真&#xff0c;很难辨识出…

JAVA开源项目 技术交流分享平台 计算机毕业设计

本文项目编号 T 053 &#xff0c;文末自助获取源码 \color{red}{T053&#xff0c;文末自助获取源码} T053&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 新…