【深度学习|基础算法】快速入门Transformer教程(小白友好向)

一、前言

  我本身是从事图像算法行业的,在之前主要是做传统的图像算法,后来接触了基于CNN的神经网络图像算法,包括图像分类,目标检测,图像分割等场景。对于Transformer的了解,我一直停留在其在NLP领域的优异表现,对于图像算法中的应用,知之甚少,因此对于基于该框架的模型,也是一直没有下定决心好好去学习。然而现在在视觉应用中,Transformer也同样大放异彩,逐步的刷新着人们对于智能的认知,尤其是在自动驾驶,机器人领域,大模型的普遍应用,也让我不得不来窥探一下这其中究竟有着怎么样的绝妙的算法设计,虽然道路是艰苦的,但是我想行,只要经过不断的坚持努力,没有啃不下来的硬骨头,Transformer同样也能成为我工作中的攻城利器!


二、初识Transformer

  在网上搜索之后,发现了一篇针对transformer讲解的非常好的一篇博客,是一位国外的大神写的全英文的博客,因此我的笔记内容会将参考他的文章来进行我个人的一个理解总结,由于本人英语水平有限,如果我的理解有什么不到位的地方,希望大家能在评论区帮我指出问题,我们一起探讨一起进步~~

2.1 总览

  我们首先将transformer模型视为一个黑匣子,在机器翻译任务场景下,它将接收一种语言的句子,并以另一种语言输出翻译的结果,如下图所示。
在这里插入图片描述
我们再打开transformer进入内部看一下,我们可以看到它是由一个encoders组件和一个decoders组件组成的,并且两者之间是存在联系的(耦合),如下图所示。
在这里插入图片描述
事实上,encoders组件是一个由多个单独的encoder堆栈组成的一个结构,他们是一个自下而上的顺序流结构,在作者的paper中使用了六个这样的encoder来进行堆叠,当然,6并没有特别的讲究之处,你也可以用不同数量的encoder来堆叠你的encoders组件。同样的,decoders组件用同样个数的decoder进行堆叠,如下图所示。
在这里插入图片描述

2.2 encoder

  每一个encoder在结构上都是相同的,但是他们不共享权重,各自拥有独立的权重,每一个都可以被拆分成两个子部分:self-attentionFeed Forward Neural Network(FFNN)
在这里插入图片描述
encoder的输入首先流过self-attention层,这个层的作用是帮助encoder关注于句子中的特定单词,我们将会在下面的部分详细的介绍自注意力层自注意力层的输出将会作为输入喂到FFNN中作为输入。

自注意力层的输出将会被喂到一个前馈神经网络中去。完全相同的前馈网络被独立的应用在每一个位置(即相同的前馈网络但是不相同的权重)。

2.3 decoder

decoder拥有完全相同的这些层(即self-attention层和FFPN层,仅结构上相同),但是在decoder中介于这两者之间还有一个注意力层来帮助decoder来关注输入句子的相关部分(与seq2seq模型的注意力类似)。
在这里插入图片描述


三. 流程与细节

  在上一节中,我们已经大概了解了transformer的总体架构,接下去我们将带入向量/张量并观察他们是如何在这些组成部分中流动并最终从输入得到我们的输出的。

1、输入

  与一般的NLP应用场景一样,我们先从使用词嵌入算法将每个输入单词转成一个个向量开始(这里以boxes的形式来代替词嵌入后的向量来展示我们的输入):
在这里插入图片描述
这里的每一个单词都被嵌入成了一个长度为512的向量。用4个boxes来表示这个向量。

这样的词嵌入仅仅会发生在最底层的encoder,对于所有的encoder而言,他们的输入都是一个将每一个单词都嵌入成512长度的向量的列表集合,但是不同的是,只有最底层的encoder接受的输入是通过词嵌入算法转化而来的,而其他层的encoder的输入都将是上一个encoder的输出。而这个列表的大小是一个我们可设置的超参数,即我们的训练数据集中最长句子的长度。

将每一个单词嵌入我们的输入序列中之后,每个单词都会分别流经encoder的两个层,得到encoder的输出吗,如下图所示:
在这里插入图片描述
这里,我们开始看到Transformer的一个重要的属性——每个位置上的单词都会有在encoder中拥有自己的流经路径。self-attention层中,这些路径存在互相依赖的关系。而FFNN中的路径并不存在这些依赖关系,因此,在流经FFNN的路径中可以并行处理。接下去我们将以一个更短的句子作为输入,来看看在encoder的内部到底发生了些什么。

正如我们前文所提及的,一个encoder将会接收一个向量组成的列表来作为输入。encoder将这个列表传入到self-attention中来处理其中的词向量,然后将这些词向量输入到FFNN中去,然后将每个输出r1,r2作为下一个encoder的输入:
在这里插入图片描述

2、self-attention

Vector Calculation

假设下面的句子是我们想要翻译的输入句子:
”The animal didn’t cross the street because it was too tired”
问题来了,句子中的it到底代表的是什么意思呢?它是指向street呢还是指向animal呢?这对于人类来说是一个很简单的问题,但是对于算法而言,这一点都不简单。

当模型处理单词it时,self-attention会将它与animal联系在一起。当模型处理每个单词时(句子中的每个位置),self-attention允许它在输入序列的其他位置寻找线索,这些线索可以帮助它更好地编码这个单词。如果你熟悉RNN,那么可以想想我们应该如何去探寻这个隐藏的联系,即将之前处理过的单词/向量的表示与当前正在处理的单词/向量的表示结合起来。self-attention是Transformer用来将对其他相关单词的“理解”转化为我们当前正在处理的单词的方法。
在这里插入图片描述
记得查看Tensor2Tensor笔记本,在那里面您可以加载Transformer模型,并使用这个可视化来查看。

让我们首先来看看它是如何使用self-attention来使用向量,然后进一步解释它是如何使用矩阵来进行计算的。


计算self-attention第一步是根据encoder的每一个输入向量创建三个向量(在这个例子中,每一个输入向量是输入句子中的每一个被词嵌入的单词)。然后针对每一个单词,我们得到一个Query向量,一个key向量,一个value向量。这些向量是根据我们的输入的词嵌入向量乘以我们刚才创建的三个参数可训练的矩阵得到的。

注意到,这些新的向量在维度上是小于词嵌入的向量的,他们的维度是长度为64的向量,而词嵌入或者encoder输入/输出的向量长度是512。这些新的向量没有必要变得更小,这是一种为了让多头注意力的计算变得更加流畅的方式。

在这里插入图片描述

那么什么是q,k,v向量呢?

他们是一种对计算和关联注意力非常有帮助的抽象概念。一旦你继续阅读下面的注意力是如何计算的,你就会知道所有你需要知道的关于这些向量所扮演的角色。(这个作者很喜欢吊胃口~~)


我们现在已经知道了计算self-attention的第一步是先得到q,k,v三个向量。现在,第二步是计算一个分数。假设我们现在正在计算第一个单词“Thinking”的self-attention,我们会得到这个单词的分数,这个分数决定了当我们在句子中的某一个特定的位置经行编码时,我们会投入多少的关注度在输入句子的其他部分。这个分数是通过计算q,k向量的点积求得的。因此,当我们处理第一个位置的单词“Thinking”时,第一个位置的分数将会是q1,k1的点积,当我们处理第二个位置的单词“Machines”时,第二个位置的分数将会是q2,k2的点积,如下图所示:
在这里插入图片描述


第三,四步分别是将每个位置得到的分数除以dk的平方根(正如前文所说的,k向量在文中的定义的一维方向的维度是dk=64,因此平方根为8),在这里,就用每个位置得到的分数再除以8,这一步操作的目的是为了让反向传播时的梯度更加稳定可靠。然后使用softmax将每个位置上的分数进行归一化,因此最后每个分数都是正的,并且相加等于1,如下图所示:
在这里插入图片描述
对于每一个特定的位置,其他位置上的单词都会与它有一个softmax处理后的分数,这个分数反映的也是其他位置与这个特定位置的关联程度,很明显自己位置上的分数肯定是最高的,但是其他位置上单词有时也会获得很高的分数,即句子中与这个特定位置的单词关系较大的单词。


第五步是将每个位置得到的v向量乘以该位置上的softmax分数(准备将所有乘后的v向量进行一个相加得到该位置的z向量)。这里给我们的感觉就是,尽可能保持我们关注的单词的值不变,然后将我们不关注的单词的值尽可能的减小,比如乘以0.001。


第六步是将第五步得到的加权后的==v==向量的值进行相加,这就产生了``self-attention``在这个单词位置上的输出,如下图所示:

在这里插入图片描述

self-attention的计算到此就完成了,接下去就会将输出的这个向量z作为输入传递给FFNN作为输入。在实际的计算中,一般都是以矩阵的形式进行计算,能够比用向量计算有更快的速度,那么,刚才将句子拆分成一个个独立的向量的例子想必已经帮助大家对与self-attention是如何计算的已经有了一个较为深刻的认识,接下去我们将用矩阵计算展开。

Matrix Calculation

有了上面的基础,现在可以简单的快速的讲清楚self-attention中进行矩阵运算时到底发生了些什么。


第一步是计算得到Q,K,V三个矩阵,我们会把我们的输入句子处理成一个矩阵,方式很简单,先将每个位置上的单词进行词嵌入成向量,然后拼接成矩阵的形式X,并且将其分别与权重矩阵WQ,WK,WV(可训练参数)进行相乘,如下图所示:
在这里插入图片描述
这里的话需要说明一下,我们用了4个boxes来表示一个单词的词嵌入后的向量的长度,而实际上是高为句子长度,宽为512的向量,权重矩阵用了长度为3的boxes来表示,实际上是一个高为512,宽为64的矩阵,因此相乘之后得到的是高为句子长度,宽为64的Q,K,V矩阵。


最后,我们将按照上文的相同的方式来处理这些矩阵,唯一的不同是,不像向量最后需要将所有位置上的z进行相加,这里我们已经把z按照矩阵的形式拼接起来了,那么可以得到self-attention的计算公式如下图所示:
在这里插入图片描述

3、多头self-attention

  paper中进一步指出可以通过multi-head的方式来进一步改进self-attention层。这个方法主要在下面两个方面来增强注意力层的性能:

  • a、它扩展了模型关注语句中不同位置的能力。在我们上面提及的例子中,z1包含了一点句子中其他位置单词的编码信息,但是z1依旧是被自身对应的单词的意思所主导的。因此当我们在翻译这句话时“The animal didn’t cross the street because it was too tired”,此时我们更关注它与句子中其他位置的单词关联的意思而并不是“它”本身的含义了。
  • b、多头给注意力层提供了多个可以表示的子空间。正如我们接下去将看到的,对于多头注意力机制,我们不再是仅有一组WQ/WK/WV的权重矩阵了,而是拥有多组的WQ/WK/WV权重矩阵(paper中指出使用了八个注意力头,因此后面的每一个encoder/decoder都会拥有八个注意力头)。每个集合都是随机初始化的,然后经过训练之后,每个Q/K/V的集合用于将输入编码投影到不同的表示子空间中,下图展示了“Thinking Machines”这句话在其中两个注意力头的子空间中经过权重矩阵WQ01/WK01/WV01之后得到的Q01/K01/V01矩阵:

在这里插入图片描述
如果我们按照上述所提及的方式做同样的工作,需要八次用不同的权重矩阵进行相同的操作,我们就可以得到八组表示的子空间z(针对句子中的同一个位置):
在这里插入图片描述
这给我们带来了一点挑战。对于FFNN来说,它并不希望输入八个矩阵,而是希望输入一个矩阵,因此我们需要将这八个矩阵压缩成一个矩阵然后输入给FFNN
我们可以这样做,将八个子空间中的表示在列的方向上拼接成一个大矩阵,然后设计一个额外的权重矩阵WO(可训练的参数)来让这个大矩阵乘以这个权重矩阵,那么可以想到,在我们这个案例中,这个WO矩阵应该是512 * 512的维度:

第一个512是因为最后的输出应该是512维度的词向量(在列方向上),第二个512则是64 * 8 = 512(行方向上):
在这里插入图片描述

以上就是multi head self-attention的全部内容,这里包含了相当多的矩阵运算,我们来将他们放在同一张图中查看一下:
在这里插入图片描述
现在让我们来回顾一下之前所给出的例子,可以让我们看到不同的注意力头所关注的位置,这里我们以我们输入中的it为例子来展示:
在这里插入图片描述
当我们对“it”这个词进行编码时,一个注意力头主要关注“动物”,而另一个注意力头主要关注“累”——从某种意义上说,模型对“it”这个词的表征融合了“动物”和“累”的一些表征。

4、位置编码

  到目前为止,我们所讲的内容还没有包含句子中单词的位置信息编码。为了解决这个问题,Transformer向每个输入都嵌入了一个位置向量,这些位置向量遵循模型学习的特定模式,这将会帮助模型学习到每个单词的位置信息以及不同单词之间的距离。这里给我的感觉是当这些位置编码在与权重矩阵进行点积时,他们会被映射到Q/K/V矩阵中,因此加入这些位置嵌入对于位置信息的保留有着很大的作用。
在这里插入图片描述

为了让模型了解单词的顺序,我们添加了位置编码向量——其值遵循特定的模式

如果我们假设嵌入的维度是4,那么实际的位置编码有可能是这个样子的:
在这里插入图片描述
在这种编码模式下,不同位置的编码会组成什么形式呢?
在下面这张图中,每一行的编码是该行索引在句子中对应索引的单词的词嵌入向量。因此第一行的则是我们输入序列中的第一个单词的词嵌入向量。每一行都包含了512个值,值域为[-1,1]。我们将其进行颜色编码来可视化这一模式:
在这里插入图片描述
这张图片是以20个单词为例(行),每个单词用512维度的词嵌入来进行表示(列)。你可以发现这张图片从中间被分成了两部分。这是因为左半部分的值是通过sin函数计算出来的,右半部分的值是通过cos来计算出来的,然后将他们连接起来形成每个位置的编码向量。

在transformer论文中的3.5节介绍了位置编码的公式。并且在get_timing_signal_1d()中可以看到实现。它可以扩展到我们无法预料的序列长度去进行翻译。

上图显示的位置编码是来自Transformer的Tensor2Tensor实现。论文中展示的方法略有不同,因为它不是直接连接,而是将两个信号交织在一起,如下图所示:
在这里插入图片描述

5、残差结构

  在继续往下探究之前,我们还需要说明一个结构上的细节,那就是在encoder的每个子层(self-attentionFFNN)中,除了正常的流向之外,还有一个残差边的路径,然后伴随的是layer Norm,如下图所示。
在这里插入图片描述
将向量带入encoder内部之后我们再查看一下内部的流程:
在这里插入图片描述
解码器也是这样的结构组成,如果我们考虑一个由2个堆叠的编码器和解码器组成的Transformer,它看起来是这样的:
在这里插入图片描述

6、解码器

  现在我们已经涵盖了编码器方面的大部分概念,我们基本上也知道了解码器的组件是如何工作的。让我们来看看它们是如何协同工作的。

堆叠的顶部编码器的输出z会经过变换得到K/V矩阵,然后K/V矩阵将会作为输入传递给堆叠的每个解码器,作为他们的K/V矩阵,将会应用在这些解码器中的Encoder-Decoder Attention层中使用,这将帮助解码器关注序列中的适当位置。
请添加图片描述
以下步骤重复该过程,直到达到一个特殊符号,表明变压器解码器已完成其输出。每一步的输出在下一个时间步中被馈送到底部的解码器,解码器像编码器一样将它们的解码结果气泡化。就像我们对编码器输入所做的那样,我们在这些解码器输入中嵌入并添加位置编码来指示每个单词的位置。

在这里插入图片描述
解码器中的自注意层与编码器中的自注意层的操作方式略有不同:
在解码器中,自注意层只允许关注输出序列中较早的位置。这是通过在自注意力计算的softmax步骤之前屏蔽还未进入的位置(将它们设置为-inf)来实现的。
Encoder-Decoder Attention层就像多头自注意层一样工作,不同的是,他的K/V矩阵来自编码器的输入的变换后得到K/V矩阵,Q矩阵则是通过下面的输入得到的。

7、最后的线性层和softmax层

解码器堆栈输出一个浮点数向量。我们怎么把它变成一个词?这是最后一个线性层的工作,然后是一个Softmax层。

线性层是一个简单的全连接神经网络,它将解码器堆栈产生的向量投影成一个更大的向量,称为logits向量。

让我们假设我们的模型知道从训练数据集中学习到的10,000个唯一的英语单词(我们模型的“输出词汇”)。这将使logits向量宽为10,000个单元格——每个单元格对应一个唯一单词的分数。这就是我们如何解释线性层之后的模型输出。

然后softmax层将这些分数转换为概率(所有分数都是正的,加起来是1.0)。选择概率最高的单元格,并生成与之关联的单词作为这一步的输出。
在这里插入图片描述

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
深度学习是近年来非常热门的技术领域,而预训练模型-transformer深度学习中一种非常受关注的模型。在MATLAB中实战应用预训练模型-transformer可以实现许多有趣的应用。 首先,预训练模型-transformer在自然语言处理领域有很好的应用。通过使用MATLAB中提供的transformer模型,我们可以对文本进行处理和分析。比如,可以利用transformer模型进行文本分类、情感分析、机器翻译等任务。通过使用预训练模型-transformer,我们可以获得更好的性能,并减少模型的训练时间和资源消耗。 其次,预训练模型-transformer还可以应用于图像处理和计算机视觉任务。在MATLAB中,我们可以使用transformer模型来进行图像分类、目标检测和图像生成等任务。通过利用预训练模型-transformer的强大表示能力,可以提高图像处理任务的准确性和效率。 此外,预训练模型-transformer还可以用于推荐系统和推荐算法中。在MATLAB中,我们可以使用transformer模型来构建个性化的推荐系统,根据用户的历史行为和兴趣来推荐相关的内容。通过使用预训练模型-transformer,可以提高推荐系统的精度和用户体验。 总的来说,MATLAB提供了丰富的工具和函数来实现预训练模型-transformer的应用。无论是在自然语言处理、图像处理还是推荐系统中,预训练模型-transformer都能够帮助我们实现更好的结果。通过深入学习和应用预训练模型-transformer,可以在实际项目中获得更好的效果,并提高工作效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

澄鑫

谢谢,将继续努力提供技术方案

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值