分享

Transformer原理及代码注释(Attention is all you need)

 netouch 2024-05-17 发布于北京

Transformer是谷歌针对NLP的机器翻译问题,2017年发表了一篇名为Attention Is All You Need 的论文中提出的模型。Transformer采用了机器翻译中通用的encoder-decoder模型,但摒弃了以往模块内部的RNN模型,只是完全依赖注意力机制来构建模型。其优点有以下几点:

  • 结构简单,抛弃RNN模型的优点在于没有了时序的限制,RNN限制了数据必须按照输入的顺序处理前后有依赖性,所以在面对数据量大的时候,耗时会很长。但Transformer的self-attention机制使得其可以进行并行计算来加速
  • 每个单词会考虑句子中所有词对其的影响,一定程度上改善了RNN中由于句子过长带来的误差,Transformer的翻译结果要比RNN好很多

下面会从原理和代码来解读Transformer模型:

1 Transformer 原理

首先按惯例上模型图(
在这里插入图片描述
显然其可以分成左右两部分,为了方便理解,我们把左边叫做Encoders,右边叫做Decoders。上图只是模型的示意图,实际上这两个部分分别由六个图示这样的基本结构堆叠起来,像这样:
在这里插入图片描述
为了更好的理解,我们按照数据输入之后在模型中的行走路线解释模型的原理。

0 位置编码

由于机器翻译需要考虑词序之间的关系,而且attention机制并没有考虑词序关系,所以我们要提前为单词加上位置编码,使得模型可以利用输入序列的顺序信息。位置编码的编码规则如下所示:
在这里插入图片描述
如果我们emdedding的维度为4,那么示例可以像下图(
在这里插入图片描述

1.1 Encoder

在这里插入图片描述
Encoder的作用是将输入经过注意力机制和前馈神经网络转变成编码,后期作为输入传入Decoder解码成另一种语言。输入的字符串已经预先变成了词嵌入矩阵形式(论文中使用的词向量维数是512维),词嵌入矩阵被输入最底层的Encoder,然后将其拆分成向量输入attention层进行计算,Attention层会输出同样是512维的向量列表,这两个矩阵经过多头Attention机制的整合,再进入前馈神经网络,前馈神经网络也输出一个为512维度的列表,然后将输出传到下一个Encoder。注意,每个Encoder模块的前馈神经网络都是独立且结构相同的。(给并行创造条件)

1.1.1 Transformer的Attention机制

首先我们先来看Attention部分,模型的attention其实由两部分组成:
在这里插入图片描述

1.1.1.1 Scaled Dot-Product Attention

首先是朴素的一看就不是并行的部分:D
在这里插入图片描述
计算self-attention首先从计算三个向量开始,对于每一个单词,我们都需要三个向量:Query, Key, Value。这些向量是通过当前单词与分别的训练矩阵相乘得到的,维度自拟(这里是64维)。另外,训练矩阵在这里假设是已经训练好给定的,具体来源我们下一节再解释。
然后有了材料我们就可以套公式了(雾):
在这里插入图片描述
首先我们用Q,K相乘得到的结果来相应单词的得分,举例如上上图,然后将得分除以8,也就是 s q r t ( d k ) sqrt(d_k) sqrt(dk),使得训练过程中具有更稳定的梯度(论文中说:对于 d k d_k dk很大的时候,点积得到的结果维度很大,使得结果处于softmax函数梯度很小的区域,这造成梯度很小,对反向传播不利。为了克服这个负面影响,除以一个缩放因子,可以一定程度上减缓这种情况???)。接下来再将输出乘V过softmax,得到权值的向量,然后将其累加到词向量中,产生此Attention层的输出。通俗来讲,公式大意是通过确定Q和K之间的相似程度来选择V

1.1.1.2 Multi-Head Attention

通过论文的图示,你一定看到了恍若虚影的东西,对,这就是玄学 可以并行计算的部分了。
在这里插入图片描述
公式如下:
在这里插入图片描述
多头Attention提供并训练了多个Q,K,V的训练矩阵,他们用于将词嵌入投影到不同的表示子空间(representation subspaces)中。通过此Attention层,我们为每一个header都独立维护了一套QKV训练矩阵,在经过上一节的attention层处理之后,因为我们有多个并行的attention,所以肯定会得到多个不同的Z矩阵,然后我们通过concat函数(将这几个矩阵简单相拼接)组合成一个大矩阵,之后与 W O W^O WO相乘,过线性模型得到的结果就可以进入前馈神经网络了。

下面是Attention过程的总结:
在这里插入图片描述

1.1.2 前馈神经网络

这是一个Position-wise的前馈神经网络,激活函数的顺序是线性模型-RELU-线性模型:
在这里插入图片描述

1.1.3 layer-normalization

在这里插入图片描述
可以看到,词向量除了喂入attention模型之外,还另外在喂入前馈神经网络中与Z进行了整合。

1.2 Decoder

在这里插入图片描述
Decoder的结构与Encoder其实是非常像的,只是多了一层E-D Attention机制,为了让decoder捕获输入序列的位置信息。但是与Encoder不同,Decoder的每一次输出都作为下一次的时序的输入,进入最底层的decoder:
在这里插入图片描述
另外,decoder的attention机制是按照输出序列中出现比较早的位置来排序的,与乱序的encoder不同。

1.3 输出

Decoder的输出是一个浮点数的向量列表,我们需要再将其通过线性层和softmax才可以将其变成输出的单词:
在这里插入图片描述

2 代码注释

'''
 code by Tae Hwan Jung(Jeff Jung) @graykode, Derek Miller @dmmiller612
 Reference : https://github.com/jadore801120/attention-is-all-you-need-pytorch
             https://github.com/JayParks/transformer
'''
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable
import matplotlib.pyplot as plt

dtype = torch.FloatTensor
# S: Symbol that shows starting of decoding input
# E: Symbol that shows starting of decoding output
# P: Symbol that will fill in blank sequence if current batch data size is short than time steps
sentences = ['ich mochte ein bier P', 'S i want a beer', 'i want a beer E']

# Transformer Parameters
# Padding Should be Zero index
src_vocab = {
   'P' : 0, 'ich' : 1, 'mochte' : 2, 'ein' : 3, 'bier' : 4}
src_vocab_size = len(src_vocab)

tgt_vocab = {
   'P' : 0, 'i' : 1, 'want' : 2, 'a' : 3, 'beer' : 4, 'S' : 5, 'E' : 6}
number_dict = {
   i: w for i, w in enumerate(tgt_vocab)}
tgt_vocab_size = len(tgt_vocab)

src_len = 5
tgt_len = 5

d_model = 512  # Em

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多