文章目录

  • Transformer
    • 1.1 模型
    • 1.2基于位置的前馈网络
    • 1.3残差连接和层规范化
    • 1.3编码器
    • 1.4解码器
    • 1.5小结

Transformer

Transformer模型完全基于注意力机制,没有任何卷积层后循环神经网络层。尽管transform最初是应用于文本数据上的序列到序列学习,但现在已经推广到各种现代的深度学习中,列如语言、视觉、语音和强化学习领域。

1.1 模型

Transformer作为编码器-解码器架构的一个实例,其整体架构图在下图中展示。正如所见到的,transformer是由编码器和解码器组成的。transformer的编码器和解码器是基于自注意力的模块叠加而成的,源(输入)序列和目标(输出)序列的嵌入(embedding)表示将加上位置编码(positional encoding),再分别输入到编码器和解码器中。

上图中概述了transformer的架构。从宏观角度来看,transformer的编码器是由多个相同的层叠加而成的,每个层都有两个子层(子层表示为sublayer\mathrm{sublayer}sublayer)。第一个子层是多头自注意力(multi-head self-attention)汇聚;第二个子层是基于位置的前馈网络(positionwise feed-forward network)。具体来说,在计算编码器的自注意力时,查询、键和值都来自前一个编码器层的输出。受残差网络的启发,每个子层都采用了残差连接(residual connection)。在transformer中,对于序列中任何位置的任何输入x∈Rd\mathbf{x} \in \mathbb{R}^dxRd,都要求满足sublayer(x)∈Rd\mathrm{sublayer}(\mathbf{x}) \in \mathbb{R}^dsublayer(x)Rd,以便残差连接满足x+sublayer(x)∈Rd\mathbf{x} + \mathrm{sublayer}(\mathbf{x}) \in \mathbb{R}^dx+sublayer(x)Rd。在残差连接的加法计算之后,紧接着应用层规范化(layer normalization)。因此,输入序列对应的每个位置,transformer编码器都将输出一个维表示向量。

Transformer解码器也是由多个相同的层叠加而成的,并且层中使用了残差连接和层规范化。除了编码器中描述的两个子层之外,解码器还在这两个子层之间插入了第三个子层,称为编码器-解码器注意力(encoder-decoder attention)层。在编码器-解码器注意力中,查询来自前一个解码器层的输出,而键和值来自整个编码器的输出。在解码器自注意力中,查询、键和值都来自上一个解码器层的输出。但是,解码器中的每个位置只能考虑该位置之前的所有位置。这种掩蔽(masked)注意力保留了自回归(auto-regressive)属性,确保预测仅依赖于已生成的输出词元。

1.2基于位置的前馈网络

基于位置的前馈网络对序列中的所有位置的表示进行变换时使用的是同一个多层感知机(MLP),这就是称前馈网络是基于位置的(positionwise)的原因。在下面的实现中,输入X的形状(批量大小,时间步数或序列长度,隐单元数或特征维度)将被一个两层的感知机转换成形状为(批量大小,时间步数,ffn_num_outputs)的输出张量。

#@save
class PositionWiseFFN(nn.Module):"""基于位置的前馈网络"""def __init__(self, ffn_num_input, ffn_num_hiddens, ffn_num_outputs,**kwargs):super(PositionWiseFFN, self).__init__(**kwargs)self.dense1 = nn.Linear(ffn_num_input, ffn_num_hiddens)self.relu = nn.ReLU()self.dense2 = nn.Linear(ffn_num_hiddens, ffn_num_outputs)def forward(self, X):return self.dense2(self.relu(self.dense1(X)))

1.3残差连接和层规范化

层规范化和批量规范化的目标相同,但层规范化是基于特征维度进行规范化。尽管批量规范化在计算机视觉中被广泛应用,但在自然语言处理任务中(输入通常是变长序列)批量规范化通常不如层规范化的效果好。

现在我们可以使用残差连接和层规范化来实现AddNorm类。暂退法也被作为正则化方法使用。

#@save
class AddNorm(nn.Module):"""残差连接后进行层规范化"""def __init__(self, normalized_shape, dropout, **kwargs):super(AddNorm, self).__init__(**kwargs)self.dropout = nn.Dropout(dropout)self.ln = nn.LayerNorm(normalized_shape)def forward(self, X, Y):return self.ln(self.dropout(Y) + X)

残差连接要求两个输入的形状相同,以便加法操作后输出张量的形状相同。

1.3编码器

有了组成transformer编码器的基础组件,现在可以先实现编码器中的一个层。下面的EncoderBlock类包含两个子层:多头自注意力和基于位置的前馈网络,这两个子层都使用了残差连接和紧随的层规范化。

#@save
class EncoderBlock(nn.Module):"""transformer编码器块"""def __init__(self, key_size, query_size, value_size, num_hiddens,norm_shape, ffn_num_input, ffn_num_hiddens, num_heads,dropout, use_bias=False, **kwargs):super(EncoderBlock, self).__init__(**kwargs)self.attention = d2l.MultiHeadAttention(key_size, query_size, value_size, num_hiddens, num_heads, dropout,use_bias)self.addnorm1 = AddNorm(norm_shape, dropout)self.ffn = PositionWiseFFN(ffn_num_input, ffn_num_hiddens, num_hiddens)self.addnorm2 = AddNorm(norm_shape, dropout)def forward(self, X, valid_lens):Y = self.addnorm1(X, self.attention(X, X, X, valid_lens))return self.addnorm2(Y, self.ffn(Y))

正如我们所看到的,transformer编码器中的任何层都不会改变其输入的形状。

X = torch.ones((2, 100, 24))
valid_lens = torch.tensor([3, 2])
encoder_blk = EncoderBlock(24, 24, 24, 24, [100, 24], 24, 48, 8, 0.5)
encoder_blk.eval()
encoder_blk(X, valid_lens).shape

torch.Size([2, 100, 24])

1.4解码器

transformer解码器也是由多个相同的层组成。在DecoderBlock类中实现的每个层包含了三个子层:解码器自注意力、“编码器-解码器”注意力和基于位置的前馈网络。这些子层也都被残差连接和紧随的层规范化围绕。

正如在本节前面所述,在掩蔽多头解码器自注意力层(第一个子层)中,查询、键和值都来自上一个解码器层的输出。关于序列到序列模型(sequence-to-sequence model),在训练阶段,其输出序列的所有位置(时间步)的词元都是已知的;然而,在预测阶段,其输出序列的词元是逐个生成的。因此,在任何解码器时间步中,只有生成的词元才能用于解码器的自注意力计算中。为了在解码器中保留自回归的属性,其掩蔽自注意力设定了参数dec_valid_lens,以便任何查询都只会与解码器中所有已经生成词元的位置(即直到该查询位置为止)进行注意力计算。

class DecoderBlock(nn.Module):"""解码器中第i个块"""def __init__(self, key_size, query_size, value_size, num_hiddens,norm_shape, ffn_num_input, ffn_num_hiddens, num_heads,dropout, i, **kwargs):super(DecoderBlock, self).__init__(**kwargs)self.i = iself.attention1 = d2l.MultiHeadAttention(key_size, query_size, value_size, num_hiddens, num_heads, dropout)self.addnorm1 = AddNorm(norm_shape, dropout)self.attention2 = d2l.MultiHeadAttention(key_size, query_size, value_size, num_hiddens, num_heads, dropout)self.addnorm2 = AddNorm(norm_shape, dropout)self.ffn = PositionWiseFFN(ffn_num_input, ffn_num_hiddens,num_hiddens)self.addnorm3 = AddNorm(norm_shape, dropout)def forward(self, X, state):enc_outputs, enc_valid_lens = state[0], state[1]# 训练阶段,输出序列的所有词元都在同一时间处理,# 因此state[2][self.i]初始化为None。# 预测阶段,输出序列是通过词元一个接着一个解码的,# 因此state[2][self.i]包含着直到当前时间步第i个块解码的输出表示if state[2][self.i] is None:key_values = Xelse:key_values = torch.cat((state[2][self.i], X), axis=1)state[2][self.i] = key_valuesif self.training:batch_size, num_steps, _ = X.shape# dec_valid_lens的开头:(batch_size,num_steps),# 其中每一行是[1,2,...,num_steps]dec_valid_lens = torch.arange(1, num_steps + 1, device=X.device).repeat(batch_size, 1)else:dec_valid_lens = None# 自注意力X2 = self.attention1(X, key_values, key_values, dec_valid_lens)Y = self.addnorm1(X, X2)# 编码器-解码器注意力。# enc_outputs的开头:(batch_size,num_steps,num_hiddens)Y2 = self.attention2(Y, enc_outputs, enc_outputs, enc_valid_lens)Z = self.addnorm2(Y, Y2)return self.addnorm3(Z, self.ffn(Z)), state

现在我们构建了由num_layers个DecoderBlock实例组成的完整的transformer解码器。最后,通过一个全连接层计算所有vocab_size个可能的输出词元的预测值。解码器的自注意力权重和编码器解码器注意力权重都被存储下来,方便日后可视化的需要。

class TransformerDecoder(d2l.AttentionDecoder):def __init__(self, vocab_size, key_size, query_size, value_size,num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens,num_heads, num_layers, dropout, **kwargs):super(TransformerDecoder, self).__init__(**kwargs)self.num_hiddens = num_hiddensself.num_layers = num_layersself.embedding = nn.Embedding(vocab_size, num_hiddens)self.pos_encoding = d2l.PositionalEncoding(num_hiddens, dropout)self.blks = nn.Sequential()for i in range(num_layers):self.blks.add_module("block"+str(i),DecoderBlock(key_size, query_size, value_size, num_hiddens,norm_shape, ffn_num_input, ffn_num_hiddens,num_heads, dropout, i))self.dense = nn.Linear(num_hiddens, vocab_size)def init_state(self, enc_outputs, enc_valid_lens, *args):return [enc_outputs, enc_valid_lens, [None] * self.num_layers]def forward(self, X, state):X = self.pos_encoding(self.embedding(X) * math.sqrt(self.num_hiddens))self._attention_weights = [[None] * len(self.blks) for _ in range (2)]for i, blk in enumerate(self.blks):X, state = blk(X, state)# 解码器自注意力权重self._attention_weights[0][i] = blk.attention1.attention.attention_weights# “编码器-解码器”自注意力权重self._attention_weights[1][i] = blk.attention2.attention.attention_weightsreturn self.dense(X), state@propertydef attention_weights(self):return self._attention_weights

1.5小结

  • transformer是编码器-解码器架构的一个实践,尽管在实际情况中编码器或解码器可以单独使用。
  • 在transformer中,多头自注意力用于表示输入序列和输出序列,不过解码器必须通过掩蔽机制来保留自回归属性。
  • transformer中的残差连接和层规范化是训练非常深度模型的重要工具。
  • transformer模型中基于位置的前馈网络使用同一个多层感知机,作用是对所有序列位置的表示进行转换。

Transformer注意力相关推荐

  1. 从零开始快速入门Transformer注意力机制

    1 目的 本文提供相关视频和笔记,以便初学者快速入门Transformer注意力机制. 2 重要模块 2.1 基础公式 Transformer的常见基础公式为 Attention(X)=Attenti ...

  2. Talk | 微软亚洲研究院宋恺涛南大余博涛:面向文本/音乐序列任务的Transformer注意力机制设计

    本期为TechBeat人工智能社区第456期线上Talk! 北京时间11月22日(周二)20:00,微软亚洲研究院研究员--宋恺涛与南京大学硕士研究生--余博涛的Talk将准时在TechBeat人工智 ...

  3. Transformer——注意力模型分析及应用

    一.概要 特点:Transformer注意力模型解决了RNN中的attention效率低.训练时变形的问题. 目的:机器翻译 二.基本组成 encoder和decoder是可叠加的. 解码器拿到编码器 ...

  4. 自己挖坑自己填,谷歌大改Transformer注意力,速度、内存利用率都提上去了

    机器之心报道 机器之心编辑部 考虑到 Transformer 对于机器学习最近一段时间的影响,这样一个研究就显得异常引人注目了. Transformer 有着巨大的内存和算力需求,因为它构造了一个注意 ...

  5. 谷歌大改Transformer注意力,速度、内存利用率都提上去了

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 转载自:机器之心 考虑到 Transformer 对于机器学习最近一段时间的影响,这样 ...

  6. 谷歌大改Transformer注意力,速度大涨,显存大降!

    源 | 机器之心 导读 考虑到 Transformer 对于机器学习最近一段时间的影响,这样一个研究就显得异常引人注目了. Transformer 有着巨大的内存和算力需求,因为它构造了一个注意力矩阵 ...

  7. 谷歌大改Transformer注意力,速度、内存利用率都提上去了-新的 Transformer 架构——Performer

    原文地址:https://www.jiqizhixin.com/articles/2020-10-28-10 Transformer 有着巨大的内存和算力需求,因为它构造了一个注意力矩阵,需求与输入呈 ...

  8. 创新!谷歌大改Transformer注意力

    点上方蓝字计算机视觉联盟获取更多干货 在右上方 ··· 设为星标 ★,与你不见不散 仅作学术分享,不代表本公众号立场,侵权联系删除 转载于:机器之心 AI博士笔记系列推荐 周志华<机器学习> ...

  9. 空间注意力机制sam_自己挖坑自己填,谷歌大改Transformer注意力,速度、内存利用率都提上去了...

    考虑到 Transformer 对于机器学习最近一段时间的影响,这样一个研究就显得异常引人注目了. 机器之心报道,机器之心编辑部. Transformer 有着巨大的内存和算力需求,因为它构造了一个注 ...

  10. Transformer-Based Attention Networks for Continuous Pixel-Wise Prediction 基于Transformer注意力网络连续像素级与估计

    仅作学习交流~包含重点翻译,要点归纳,部分扩展 论文地址 GitHub - ygjwd12345/TransDepth: Code for Transformers Solve Limited Rec ...

最新文章

  1. 图书抄袭何时休,技术人的版权在哪里?
  2. 怎么把video文件改成mp4_如何把视频转换成mp4格式?
  3. mysql1300错误什么意思_mysql error 1201-1300错误大全
  4. Web Services简单介绍
  5. php链表和联表的区别,PHP_浅谈PHP链表数据结构(单链表),链表:是一个有序的列表,但 - phpStudy...
  6. 安装Ubuntu版本linux过程中没有提示设置root用户密码问题的解决办法
  7. 解决使用adb卸载应用失败的问题
  8. 动画原理——用户交互:移动物体
  9. Win32汇编---控件的超类化感想
  10. SQL注入漏洞入门(操作实现)
  11. 用Java代码实现学生管理系统
  12. java开发微信公众号支付全流程
  13. 入门篇——解析Python机器学习中三类无监督学习算法和两个应用实例
  14. javaweb之统计网站访问量小案例
  15. python3.7打包exe后有显示no utf-8_pyinstaller打包py文件时出现错误SyntaxError: Non-UTF-8 code starting with '\xb3'...
  16. k8s使用命令报错:error: You must be logged in to the server (Unauthorized)
  17. 抑郁症自我测试皮肤软件,皮肤瘙痒像虫子爬竟是抑郁症
  18. [100天挑战100个前端效果]第十九天---人物介绍卡片效果(猜猜是哪三个大佬?)
  19. java中float和double为什么会转为科学记数法?
  20. Docker与Ros-kinetic-desktop-full

热门文章

  1. 三角波发生器电路原理分析
  2. 今日头条2019春季暑期实习笔试题(非自己做)4-14
  3. 爷青回|用Python重构【超级马里奥】制作过程+解析|快收藏起来跟小伙伴一起拯救公主吧~
  4. Web浏览器与Web服务器之间的通信过程
  5. Mysql上周,上月,去年同期年周数
  6. 强连通分量入门——Trajan算法
  7. 先验 超验_经验、先验、超验
  8. 求梯形面积python
  9. Android微信app支付
  10. 如何剪裁证件照大小?2寸证件照片怎么制作?