| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> 图解transformer | The Illustrated Transformer -> 正文阅读 |
|
[人工智能]图解transformer | The Illustrated Transformer |
文章目录写在最前边看transformer相关文章的时候发现很多人用了相同的图。直到我搜到作者的原文……于是厚着脸皮照找作者表示我要翻译他的文章。(图片见最后) 翻译讲究:信、达、雅。要在保障意思准确的情况下传递作者的意图,并且尽量让文本优美。但是大家对我一个理工科少女的语言要求不要太高,本文只能保证在尽量通顺的情况下还原原文。 注意本文的组成部分:翻译 + 我的注释。 添加注释是因为在阅读的过程中,我感觉有的地方可能表述的并不是特别详细。对于一些真正的小白,像我一样傻的来说,可能不太好理解。 正文在之前的文章中,我们讲了现代神经网络常用的一种方法——Attention机制。 本文章我们来介绍一下Transformer——用注意力机制来提高模型训练速度的模型。 Transformer是在这篇论文中提出的:Attention is All You Need. 官方版TensorFlow实现:https://github.com/tensorflow/tensor2tensor 哈佛大学NLP组Pytorch实现:http://nlp.seas.harvard.edu/2018/04/03/attention.html 在本文中,我们会逐个概念进行介绍,希望能帮助没接触过Transformer的人能够更容易的理解。 从高层面看我们先把整个Transformer模型看作是一个黑盒。在机器翻译中,它可以把句子从一种语言翻译成另一种语言。 再往里看一下,编码器模块是6个encoder组件堆在一起,同样解码器模块也是6个decoder组件堆在一起。(为什么选6个呢?没有什么原因,论文原文就是这么写的,你也可以换成别的层数)
6个编码器组件的结构是相同的(但是他们之间的权重是不共享的),每个编码器都可以分为2个子层。 自注意力层的输出会传递给一个前馈神经网络,每个编码器组件都是在相同的位置使用结构相同的前馈神经网络。 图解张量现在我们要开始了解整个模型了。 在一个已经训练好的Transformer模型中,输入是怎么变为输出的呢? 与其他的NLP项目一样,我们首先需要把输入的每个单词通过词嵌入(embedding)转化为对应的向量。 所有编码器接收一组向量作为输入,论文中的输入向量的维度是512。最底下的那个编码器接收的是嵌入向量,之后的编码器接收的是前一个编码器的输出。 向量长度这个超参数是我们可以设置的,一般来说是我们训练集中最长的那个句子的长度。 当我们的输入序列经过词嵌入之后得到的向量会依次通过编码器组件中的两个层。 接下来,我们用一个短句( 现在我们来看一下编码器上边我们已经说了,每个编码器组件接受一组向量作为输入。在其内部,输入向量先通过一个自注意力层,再经过一个前馈神经网络,最后将其将输出给下一个编码器组件。 自注意力不要一看“self-attention”就觉得这是个每个人都很很熟悉的词,其实我个人感觉,在看《Attention is all you need》之前我都没有真正理解自注意力机制。现在让我们看一下自注意力机制。 假设我们要翻译下边这句话: 这里 当模型处理 当模型编码每个位置上的单词的时候,自注意力的作用就是:看一看输入句子中其他位置的单词,试图寻找一种对当前单词更好的编码方式。 如果你熟悉RNNs模型,回想一下RNN如何处理当前时间步的隐藏状态:将之前的隐藏状态与当前位置的输入结合起来。 并将其融入到it的编码中。 可以去Tensor2Tensor ,自己体验一下上图的可视化。 细说自注意力机制先画图用向量解释一下自注意力是怎么算的,之后再看一下实际实现中是怎么用矩阵算的。 第一步 对编码器的每个输入向量都计算三个向量,就是对每个输入向量都算一个query、key、value向量。 注意,这三个向量维度是64,比嵌入向量的维度小,嵌入向量、编码器的输入输出维度都是512。这三个向量不是必须比编码器输入输出的维数小,这样做主要是为了让多头注意力的计算更稳定。 按这样的方法,最终我们给输入的每一个单词都计算出一个“query”、一个 “key"和一个 “value"。 什么是 “query”、“key”、“value” 向量? 这三个向量是计算注意力时的抽象概念,继续往下看注意力计算过程,看完了就懂了。 第二步 计算注意力得分。 假设我们现在在计算输入中第一个单词Thinking的自注意力。我们需要使用自注意力给输入句子中的每个单词打分,这个分数决定当我们编码某个位置的单词的时候,应该对其他位置上的单词给予多少关注度。 这个得分是query和key的点乘积得出来的。 举个栗子,我们要算第一个位置的注意力得分的时候就要将第一个单词的query和其他的key依次相乘,在这里就是
q
1
q_1
q1?
?
·
?
k
1
k_1
k1?,
q
1
q_1
q1?
?
·
?
k
2
k_2
k2?。 为什么选8?是因为key向量的维度是64,取其平方根,这样让梯度计算的时候更稳定。默认是这么设置的,当然也可以用其他值。 第四步 除8之后将结果扔进softmax计算,使结果归一化,softmax之后注意力分数相加等于1,并且都是正数。 第五步 将每个value向量乘以注意力分数。 在第一个单词位置得到新的 v 1 v_1 v1?。 第六步 将上一步的结果相加,输出本位置的注意力结果。 第一个单词的注意力结果就是
z
1
z_1
z1? 这就是自注意力的计算。计算得到的向量直接传递给前馈神经网络。但是为了处理的更迅速,实际是用矩阵进行计算的。接下来我们看一下怎么用矩阵计算。 用矩阵计算self-attention计算Query, Key, Value矩阵。直接把输入的向量打包成一个矩阵
X
X
X,再把它乘以训练好的
W
Q
W^Q
WQ、
W
K
W^K
WK、
W
V
W^V
WV。 我们看一下维度的差异:原文中嵌入矩阵的长度为 512 , q 、 k 、 v q、k、v q、k、v 矩阵的长度为 64 ; 在这里我们分别用 4 个格子表示和3个格子表示。 因为我们现在用矩阵处理,所以可以直接将之前的第二步到第六步压缩到一个公式中一步到位获得最终的注意力结果
Z
Z
Z 多头注意力论文进一步改进了自注意力层,增加了一个机制,也就是多头注意力机制。这样做有两个好处:
Transformer中的一个多头注意力(有8个head)的计算,就相当于用自注意力做8次不同的计算,并得到8个不同的结果
Z
Z
Z。 但是这会存在一点问题,多头注意力出来的结果会进入一个前馈神经网络,这个前馈神经网络可不能一下接收8个注意力矩阵,它的输入需要是单个矩阵(矩阵中每个行向量对应一个单词),所以我们需要一种方法把这8个压缩成一个矩阵。 怎么做呢?我们将这些矩阵连接起来,然后将乘以一个附加的权重矩阵
W
O
W^O
WO。 此时该模型对it的编码。除了it本身的表达之外,同时也包含了the animal和tired的相关信息 如果我们把所有的头的注意力都可视化一下,就是下图这样,但是看起来事情好像突然又复杂了。 使用位置编码表示序列的位置强烈安利一个详细解释位置编码的文章:Transforme 结构:位置编码详解。 到现在我们还没提到过如何表示输入序列中词汇的位置。 Transformer在每个输入的嵌入向量中添加了位置向量。这些位置向量遵循某些特定的模式,这有助于模型确定每个单词的位置或不同单词之间的距离。将这些值添加到嵌入矩阵中,一旦它们被投射到Q、K、V中,就可以在计算点积注意力时提供有意义的距离信息。 位置编码向量和嵌入向量的维度是一样的,比如下边都是四个格子: 一直说位置向量遵循某个模式,这个模式到底是什么。 在下面的图中,每一行对应一个位置编码。所以第一行就是我们输入序列中第一个单词的位置编码,之后我们要把它加到词嵌入向量上。 看个可视化的图: 可以看到图像从中间一分为二,因为左半部分是由正弦函数生成的。右半部分由余弦函数生成。 然后将它们二者拼接起来,形成了每个位置的位置编码。 你可以在get_timing_signal_1d()中看到生成位置编码的代码。 但是需要注意注意一点,上图的可视化是官方Tensor2Tensor库中的实现方法,将sin和cos拼接起来。但是和论文原文写的不一样,论文原文的3.5节写了位置编码的公式,论文不是将两个函数concat起来,而是将sin和cos交替使用。论文中公式的写法可以看这个代码:transformer_positional_encoding_graph,其可视化结果如下: 残差在继续往下讲之前,我们还需再提一下编码器中的一个细节:每个编码器中的每个子层(自注意力层、前馈神经网络)都有一个残差连接,之后是做了一个层归一化(layer-normalization)。 当然在解码器子层中也是这样的。 我们现在画一个有两个编码器和解码器的Transformer,那就是下图这样的: 解码器现在我们已经介绍了编码器的大部分概念,(因为encoder的decoder组件差不多)我们基本上也知道了解码器的组件是如何工作的。那让我们直接看看二者是如何协同工作的。 编码器首先处理输入序列,将最后一个编码器组件的输出转换为一组注意向量K和V。每个解码器组件将在“encoder-decoder attention”层中使用编码器传过来的K和V,这有助于解码器将注意力集中在输入序列中的适当位置: 在解码阶段每一轮计算都只往外蹦一个输出,在本例中是输出一个翻译之后的英语单词。 输出步骤会一直重复,直到遇到句子结束符 表明transformer的解码器已完成输出。 每一步的输出都会在下一个时间步喂给给底部解码器,解码器会像编码器一样运算并输出结果(每次往外蹦一个词)。 跟编码器一样,在解码器中我们也为其添加位置编码,以指示每个单词的位置。 在解码器中,自注意力层只允许关注已输出位置的信息。实现方法是在自注意力层的softmax之前进行mask,将未输出位置的信息设为极小值。 “encoder-decoder attention”层的工作原理和前边的多头自注意力差不多,但是Q、K、V的来源不用,Q是从下层创建的(比如解码器的输入和下层decoder组件的输出),但是其K和V是来自解码器最后一个组件的输出结果。 最后的线性层和softmax层Decoder输出的是一个浮点型向量,如何把它变成一个词? 这就是最后一个线性层和softmax要做的事情。 线性层就是一个简单的全连接神经网络,它将解码器生成的向量映射到logits向量中。 然后,softmax层将这些分数转化为概率(全部为正值,加起来等于1.0),选择其中概率最大的位置的词汇作为当前时间步的输出。 训练过程概述现在我们已经了解了Transformer的整个前向传播的过程,那我们继续看一下训练过程。 为了便于理解,我们假设预处理阶段得到的词汇表只包含六个单词(“a”, “am”, “i”, “thanks”, “student”, “<eos>”)。 一旦我们定义好了词汇表,我们就可以使用长度相同的向量(独热码,one-hot 向量)来表示词汇表中的每个单词。例如,我们可以用以下向量表示单词“am”: 接下来让我们讨论一下模型的损失函数,损失函数是我们在训练阶段优化模型的指标,通过损失函数,可以帮助我们获得一个准确的、我们想要的模型。 损失函数假设我们正要训练我们的模型。 假设现在是训练阶段的第一步,我们用一个简单的例子(一个句子就一个词)来训练模型:把 我们可以将其与实际输出进行比较,然后使用反向传播调整模型的权重,使输出更接近我们所需要的值。 如何比较两种概率分布?在这个例子中我们只是将二者相减。实际应用中的损失函数请查看交叉熵损失和Kullback–Leibler散度。 上述只是最最简单的一个例子。现在我们来使用一个短句子(一个词的句子升级到三三个词的句子了),比如输入 所以我们希望模型不是一次输出一个词的概率分布了,能不能连续输出概率分布,最好满足下边要求:
在足够大的数据集上训练模型足够长的时间后,我们希望生成的概率分布如下所示: 在这里你可以看到softmax的一个特性,就是即使其他单词并不是本时间步的输出, 也会有一丁点的概率存在,这一特性有助于帮助模型进行训练。 模型一次产生一个输出,在这么多候选中我们如何获得我们想要的输出呢?现在有两种处理结果的方法: 一种是贪心算法(greedy decoding):模型每次都选择分布概率最高的位置,输出其对应的单词。 另一种方法是束搜索(beam search):保留概率最高前两个单词(例如,“I”和“a”),然后在下一步继续选择两个概率最高的值,以此类推,在这里我们把束搜索的宽度设置为2,当然你也可以设置其他的束搜索宽度。 更多内容如果你想更深入了解Transformer:
Jay Alammar’s Blog
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 9:44:26- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |