白话机器学习-Transformer

2023-11-09

一 背景

大抵是去年底吧,收到了几个公众号读者的信息,希望能写几篇介绍下Attention以及Transformer相关的算法的文章,当时的我也是满口答应了,但是确实最后耽误到了现在也没有写。

前一阵打算写这方面的文章,不过发现一个问题,就是如果要介绍Transformer,则必须先介绍Self Attention,亦必须介绍下Attention,以及Encoder-Decoder框架,以及GRU、LSTM、RNN和CNN,所以开始漫长的写作之旅。

终于在这个五一假期完成了最后的四篇文章(总共八篇,从开始写到现在历经两个月左右的时间),也算是兑现了自己的承诺,俗话说的好,言必行,行必果吧。尤其是对于我这么一个爱好脸面的人,就更得兑现了。最近有一些感悟,很多事情有了很多不同的看法和理解。以前读《易经》觉得自己读懂了一些,现在看来压根是一点都没懂,而且还偏离的厉害,有些事情可能得重新去审视,有些念头需要重新去整理了。

其实吧,有时候不想写这些文章,这种大基本功的文章,可以说是投入产出比极低的。人们往往追求酷炫的技术,沉醉于貌似的理解中,但是对于这种大基本功缺视而不见,殊不知所有的酷炫如果没有大基本功都是空中楼阁。而且能够构建出这些酷炫技术的人,一定是基本功十分扎实的人,对于算法同学来说,不仅仅止于算法,还需要扎实深刻的架构知识。

好了,书归正传,截止目前,已经完成几篇文章的输出,罗列如下,组织方式都是按照学习的依赖进行构建的,喜欢的同学可以关于《秃顶的码农》公众号,选择机器学习算法系列进行学习。

  • 《白话机器学习-卷积神经网络CNN》
  • 《白话机器学习-循环神经网络RNN》
  • 《白话机器学习-长短期记忆网络LSTM》
  • 《白话机器学习-循环神经网络概述从RNN到LSTM再到GRU》
  • 《白话机器学习-Encoder-Decoder框架》
  • 《白话机器学习-Attention》
  • 《白话机器学习-Self Attention》
  • 《白话机器学习-Transformer》

终于把这个系列写到了最后一文,五一五天假期的第四天,嗯,怎么说呢!感觉自己过的很充实。在这里炫耀下,昨天买了个mac的触摸板,比起鼠标来,还真是好用,配合上我的大显示器、机器键盘,妥妥的提升生产力,我想我还能写几百篇 哈哈。

在前一篇文章中,我们讨论了注意力——现代深度学习模型中普遍存在的方法。注意力是一个有助于提高神经机器翻译应用程序性能的机制(并行化)。在这篇文章中,我们将讨论Transformer —— 利用注意力来提高训练速度的模型。Transformer在特定任务中优于谷歌神经机器翻译模型。其中最大的提升在于Transformer架构适合于并行化。事实上,谷歌Cloud建议使用Transformer作为参考模型来使用他们的云TPU产品。让我们把这个模型拆开来看看它是如何运作的。

Transformer是在Attention is all you need这篇论文中提出的,并且引起了业界的广泛的关注,仿佛你要不提下、不知道Transformer你就不是做算法的,可见其强大的影响力。

二 整体介绍

以语言机器翻译模型为例,从整体的角度来看在机器翻译过程中,流程主要是输入一种语言的一个句子,然后输出另一种语言的相应的译文。

前面的章节中,我们已经介绍过Encoder-Decoder框架,他主要包含量大组件:

  • 一个编码组件
  • 一个解码组件

通过编码组件与解码组件完成整个框架的搭建,进行模型的训练与预测。

下面我看一个例子,编码组件是一堆编码器(有六个编码器,一个叠一个——数字6没有什么神奇的,你肯定可以尝试其他的安排)。解码组件是具有相同数字的解码器的排列。

编码器在结构上都是相同的(但它们不共享权重)。每一个都被分成两个子层:

解码器有两层:

  • Self-Attention层:编码器的输入首先经过一个Self-Attention层——本层可以帮助编码器在对某个特定单词进行编码时查看输入句子中的其他单词与本单词的相关性,并且进行加权计算。
  • Feed Forward Neural Network:Self-Attention层的输出到前馈神经网络,完全相同的前馈网络独立地应用于每个位置。

三 使用向量形象表示

现在我们已经看到了模型的主要组成部分,让我们开始研究各种矢量/张量,以及它们如何在这些组成部分之间流动,从而将训练模型的输入转换为输出。

与一般的NLP应用程序一样,我们首先使用嵌入算法将每个输入单词转换为一个向量。

嵌入只发生在最底部的编码器中。所有编码器的共同抽象是,它们接收一个大小为512的向量列表——在底部的编码器中,这个词是“嵌入”,但在其他编码器中,它将是直接下面的编码器的输出。

在输入序列中嵌入单词后,每个单词都流经编码器的两层。

在这里,我们开始看到Transformer的一个关键属性,即每个位置的单词在编码器中都通过自己的路径流动。在自我注意层中,这些路径之间存在依赖关系。然而,前馈层没有这些依赖关系,因此各种路径可以在流经前馈层时并行执行。

正如我们已经提到的,编码器接收一个向量列表作为输入。它处理这个向量,将这些向量传递到“自我关注”层,然后进入前馈神经网络,然后将输出向上发送到下一个编码器,编码器可以是多层的。

四 Self Attention回顾

上一篇文章已经介绍过Self Attention,这里从另外的角度进行下阐述。其实注意力机制在现实生活中是大量存在的,而且人类社会也在一直使用。让我们提炼一下它是如何工作的。

假设下面的句子是我们想要翻译的输入句子:

“动物没有过马路,因为它太累了。”

这个句子中的“它”指的是什么?它指的是街道还是动物?这对人类来说是一个简单的问题,但对算法来说就不那么简单了。

当使用自我注意力机制的时候,模型处理“它”这个词时,自我注意力让它将“它”与“动物”联系起来。

当模型处理每个单词(输入序列中的每个位置)时,自我注意允许它查看输入序列中的其他位置,以寻找有助于对该单词进行更好编码的线索。

如果你对RNN很熟悉,想想如何维护一个隐藏状态让RNN将它之前处理过的单词/向量的表示与当前正在处理的单词/向量结合起来。自我关注是Transformer用来将其他相关词汇的“理解”融入到我们当前处理的词汇中,同样可以达到这个目标,同时由于其算法的特点可以无视距离,并且实现并行化的操作,提升计算性能。

五 Self-Attention细节

本节我们再复习下如何计算Self-Attention,本节不做过细的介绍,一律使用矩阵计算。

计算自我注意力的第一步是根据编码器的每个输入向量创建三个向量(在本例中,在训练过程中通过三个参数矩阵计算得到)。

这些新的向量比嵌入向量的维度要小。它们的维数为64,而嵌入向量和编码器输入输出向量的维数为512。向量的维度可以由大家自行定义,这里使用64。

什么是“查询”、“键”和“值”向量?

它们是对计算和思考注意力有用的抽象概念。一旦你继续阅读下面是如何计算注意力的,你就会差不多知道所有你需要知道的关于每个向量所起的作用。

计算自我注意力的第二步是计算分数。假设我们在计算这个例子中第一个单词“Thinking”的自我注意力。我们需要将输入句子中的每个单词与这个单词进行比较。分数决定了当我们在某个位置编码一个单词时,将多少注意力放在输入句子的其他部分。

分数是通过查询向量与我们打分的单词的关键向量的点积来计算的。如果我们处理位置1的单词的自我注意,第一个分数就是q1和k1的点积。第二个分数是q1和k2的点积。

第三步和第四步是将分数除以8(论文中使用的关键向量维数的平方根- 64),据说这样可以拥有更稳定的梯度。然后通过softmax操作传递结果。Softmax将这些分数归一化,使它们都是正的,加起来等于1。

这个softmax分数决定了在这个位置每个单词被歧途单词影响的程度。显然,在这个位置的单词将拥有最高的softmax分数,但有时关注与当前单词相关的另一个单词是非常有用的。

第五步是将每个值向量乘以softmax得分(准备将它们相加)。这里的直觉是保留我们想要关注的单词的值,并淹没不相关的单词(例如,通过将它们乘以很小的数字,如0.001),然后进行按元素相加,生成最终的表征向量。

第六步是对加权值向量求和。这在这个位置产生了自我注意层的输出(对于第一个单词)。

六 Self-Attention的矩阵运算形式

第一步是计算Query、Key和Value矩阵。我们通过将我们的嵌入投射到一个矩阵X中,并将其乘以我们训练过的权重矩阵(WQ, WK, WV)来实现。

最后可以将第二步到第六步压缩到一个公式中,以计算自我注意层的输出。

七 Multi Header Attention

本文进一步细化了自我注意层,增加了“多头”注意力机制。这从两个方面提高了注意力层的性能:

  • 它扩展了模型关注不同位置的能力。是的,在上面的例子中,z1包含了一些其他的编码,但是它可以被实际的单词本身支配。如果我们在翻译像“The animal didn 't cross The street because It was too tired”这样的句子,我们会想知道“It”指的是哪个词,这是很有用的。

  • 它给了注意层多个“表示子空间”。正如我们接下来将看到的,对于多头部注意,我们不仅有一个,而且有多个查询/键/值权重矩阵集(Transformer使用8个注意头部,因此我们最终为每个编码器/解码器提供8个注意头部集)。每个集合都是随机初始化的。然后,经过训练,每个集合用于将输入嵌入(或来自较低编码器/解码器的向量)投影到不同的表示子空间,通过不同的子空间挖掘更多的相互之间的关系。

如果我们做同样的自我注意计算,只是用不同的权重矩阵进行8次不同的计算,我们就得到了8个不同的Z矩阵。

这给我们留下了一点挑战。前馈层期望的不是8个矩阵——它期望的是单个矩阵(每个单词对应一个向量)。所以我们需要一种方法把这8个压缩成一个矩阵。

怎么做呢?我们将这些矩阵连接然后将它们乘以一个附加的权重矩阵WO。

我们将整体的流程合在一个图中,如下所示。

八 序列位置因素

正如我们目前所描述的,该模型缺少的一件事是解释输入序列中单词的顺序。Self—Attention无视距离,无视空间,但是位置信息还是非常重要的,下面我们看看如何解决这个问题。

为了解决这个问题,转换器在每个输入嵌入中添加一个向量。这些向量遵循模型学习的特定模式,这有助于模型确定每个单词的位置,或序列中不同单词之间的距离。这里的直觉是,将这些值添加到嵌入中,一旦它们被投射到Q/K/V向量中,在点积注意期间,就可以在嵌入向量之间提供有意义的距离。

如果我们假设嵌入的维度是4,实际的位置编码应该是这样的:

这个模式会是怎样的呢?

在下面的图中,每一行对应于一个向量的位置编码。所以第一行就是我们在输入序列中嵌入第一个单词时要加上的向量。每行包含512个值—每个值都在1到-1之间。我们用颜色标记了它们,这样图案就清晰可见了。

位置编码公式在Transformer的论文中描述(第3.5节)。您可以在get_timing_signal_1d()https://github.com/tensorflow/tensor2tensor/blob/23bd23b9830059fbc349381b70d9429b5c40a139/tensor2tensor/layers/common_attention.py中看到用于生成位置编码的代码。这不是位置编码的唯一可行方法。然而,它的优势在于能够缩放到序列中看不见的长度(例如,如果我们训练过的模型被要求翻译一个比我们训练集中的任何句子都长的句子)。

2020年7月更新:上面显示的位置编码来自Transformer的transformer2transformer实现。本文所示的方法略有不同,它不是直接串联,而是交织两个信号。下图显示了它的样子。下面是生成它的代码:https://github.com/jalammar/jalammar.github.io/blob/master/notebookes/transformer/transformer_positional_encoding_graph.ipynb

九 损失函数

介绍到这里,大家可能有个疑问,那就是Transformer的Loss是如何计算的?下面就一起探讨下:

假设我们正在训练我们的模型,这是我们训练阶段的第一步,我们正在用一个简单的例子来训练它——把“merci”翻译成“thanks”。

这意味着,我们希望输出是一个概率分布,表示“谢谢”这个词。但由于这个模型还没有经过训练,所以目前不太可能发生这种情况。

如何比较两个概率分布?我们只是简单地用一个减去另一个。要了解更多细节,请看交叉熵和Kullback-Leibler散度。

但请注意,这是一个过于简化的示例。更现实地说,我们会使用比一个单词更长的句子。例如-输入:“je suis étudiant”,期望输出:“i am a student”。这实际上意味着,我们希望我们的模型连续输出概率分布,其中:

  • 每个概率分布由宽度为vocab_size的向量表示(在我们的示例中为6,但更实际的是词库的大小,可能比较大如30000或50000)
  • 第一个概率分布在与单词“ i ”相关的单元格上的概率最高
  • 第二个概率分布在与单词" am "相关的单元格中概率最高
  • 以此类推,直到第5个输出分布指示‘<句子结束>’符号,它也有一个与10,000个元素词汇表相关联的单元格。

在一个足够大的数据集上训练模型足够长的时间后,可能生成的概率分布如下:

现在,由于该模型每次产生一个输出,我们可以假设该模型从该概率分布中选择了概率最高的单词,而丢弃了其余的。这是一种方法(称为贪婪解码)。另一种方法是,抓住最前面的两个单词(例如,‘I’和‘a’),然后在下一步中,运行模型两次:一次假设第一个输出位置是单词‘I’,另一次假设第一个输出位置是单词‘a’,并且考虑到位置#1和#2,保留产生较少错误的版本。我们对2号和3号位置重复这个动作。这个方法被称为“beam search”,在我们的例子中,beam_size为2(这意味着在任何时候,内存中都保留着两个部分假设。还有top_beams,这两个都是可以试验的超参数。

十 参考资料

  1. Attention Is All You Need (arxiv.org)
  2. Depthwise Separable Convolutions for Neural Machine Translation
  3. One Model To Learn Them All
  4. Discrete Autoencoders for Sequence Models
  5. Generating Wikipedia by Summarizing Long Sequences
  6. Image Transformer
  7. Training Tips for the Transformer Model
  8. Self-Attention with Relative Position Representations
  9. Fast Decoding in Sequence Models using Discrete Latent Variables
  10. Adafactor: Adaptive Learning Rates with Sublinear Memory Cost
  11. https://jalammar.github.io/illustrated-transformer/

十一 番外篇

介绍:杜宝坤,互联网行业从业者,十五年老兵。精通搜广推架构与算法,并且从0到1带领团队构建了京东的联邦学习解决方案9N-FL,同时主导了联邦学习框架与联邦开门红业务。
个人比较喜欢学习新东西,乐于钻研技术。基于从全链路思考与决策技术规划的考量,研究的领域比较多,从工程架构、大数据到机器学习算法与算法框架、隐私计算均有涉及。欢迎喜欢技术的同学和我交流,邮箱:baokun06@163.com

十二 公众号导读

自己撰写博客已经很长一段时间了,由于个人涉猎的技术领域比较多,所以对高并发与高性能、分布式、传统机器学习算法与框架、深度学习算法与框架、密码安全、隐私计算、联邦学习、大数据等都有涉及。主导过多个大项目包括零售的联邦学习,社区做过多次分享,另外自己坚持写原创博客,多篇文章有过万的阅读。公众号秃顶的码农大家可以按照话题进行连续阅读,里面的章节我都做过按照学习路线的排序,话题就是公众号里面下面的标红的这个,大家点击去就可以看本话题下的多篇文章了,比如下图(话题分为:一、隐私计算 二、联邦学习 三、机器学习框架 四、机器学习算法 五、高性能计算 六、广告算法 七、程序人生),知乎号同理关注专利即可。

一切有为法,如梦幻泡影,如露亦如电,应作如是观。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

白话机器学习-Transformer 的相关文章

随机推荐

  • matlplotlib绘图 之 函数legend()

    一 添加图例的两种方法 来自 https www cnblogs com kuangkuangduangduang p 10300506 html 1 推荐使用 在plot函数中增加label参数 然后在后面加上plt legend 不加p
  • 正点原子IMX6ULL阿尔法USB摄像头的远程调用(三)USB摄像头的连接与使用

    终于轮到摄像头了 IMX6ULL支持USB摄像头 直接插在USB口上就可以了 不过 下面介绍的方案要在Python中调用USB摄像头的数据 所以在IMX6ULL中需要移植MJPG Streamer 这个不太难 百度一下就OK 迅为的方案就可
  • HashMap工作原理

    HashMap是一个key value键值对的数据结构 它是由数组 链表 红黑树的形式实现的 默认长度是16 只能有一个key为null 可以有多个value为null 数组是一个个Node 数组 我们叫它hash桶数组 它上面存放的是ke
  • 上采样方法

    目录 上采样 Upsampling 方法 去池化 最近邻方法 钉床方法 最大去池化 双线性插值 反卷积 膨胀卷积 上采样 Upsampling 方法 上采样 是指将低分辨率的图像或特征图放大到原始分辨率的过程 在计算机视觉中 上采样通常用于
  • Bug的级别,按照什么划分

    Bug分类和定级 一 bug的定义 二 bug的类型 三 bug的等级 四 bug的优先级 一 bug的定义 一般是指不满足用户需求的则可以认为是bug 狭义指软件程序的漏洞或缺陷 广义指测试工程师或用户提出的软件可改进的细节 或与需求文档
  • CodePush 私有化部署

    安装 NodeJs 和 Npm 下载安装 NodeJs 安装 nodejs wget https nodejs org dist v6 9 4 node v6 9 4 tar gz configuremakemake install 安装
  • SIM卡与IEC 7816

    SIM卡与IEC 7816 SIM Subscriber Identification Module 又被称为用户身份识别卡 智能卡 SIM卡是一种物理载体 而相关的性能以及协议的规定都包含在IEC 7816协议中 IEC 7816规范 物
  • HJ103 Redraiment的走法 —— 华为机考练习题

    一 题目 描述 Redraiment是走梅花桩的高手 Redraiment可以选择任意一个起点 从前到后 但只能从低处往高处的桩子走 他希望走的步数最多 你能替Redraiment研究他最多走的步数吗 数据范围 每组数据长度满足 1 le
  • ag-grid-vue的配置

    public get gridOptions GridOptions const that this return headerHeight 30 表头高度 rowHeight 30 行高 columnDefs 列定义 headerName
  • 常用JS对象的方法总结

    String 方法 描述 charAt 返回在指定位置的字符 charCodeAt 返回在指定的位置的字符的 Unicode 编码 concat 连接字符串 indexOf 检索字符串 match 找到一个或多个正则表达式的匹配 repla
  • spring的后处理

    什么是spring的后处理器 spring的后处理是spring对开开发的重要扩展点 bean的许多的功能的增强就是通过后处理实现的 他可以允许我们产于到bean的实例化路程中去 两类后处理器 根据我们对于bean的实例化的认识 我们知道b
  • C中调用带参数的exe并接收返回值

    test exe c sharp view plain copy include
  • 高等数学知识点总结

    高等数学知识点总结 一 间断点 定义 1 f x 在处没有定义 则为间断点 2 f x 在处有定义 但是极限不存在 3 f x 在处有定义 极限也存在 但是不相等 分类 第一类间断点 左右极限都存在 1 可去间断点 2 跳跃间断点 第二类间
  • Android Service

    http www cnblogs com lwbqqyumidi p 4181185 html Service通常总是称之为 后台服务 其中 后台 一词是相对于前台而言的 具体是指其本身的运行并不依赖于用户可视的UI界面 因此 从实际业务需
  • 微信小程序使用wxParse解析html

    转 http www jianshu com p 3de027555e77 最近项目上遇到在微信小程序里需要显示新闻内容 新闻内容是通过接口读取的服务器中的富文本内容 是html格式的 小程序默认是不支持html格式的内容显示的 那我们需要
  • 内存管理<原理篇>(四、分段和分页)

    文章目录 4 1 分段 4 1 1 程序段介绍 4 1 2 各段放入内存信息 4 1 3 段表 4 1 4 总结 4 2 分页 4 2 1 概念介绍 4 2 2 各段加载进内存 4 2 3 例子分析 4 2 4 总结 4 1 分段 在上一篇
  • python 使用 passlib 库在 windows 平台实现 crypt

    今天同步代码的时候 发现别的同事往项目里新加了一行 import crypt 编译器提示有错 我就去检查了项目的requirements文件 但没找到新的依赖 然后我google了一下 原来这个文件是Unix 系统用来给密码加密的文件 并不
  • Coding pages 不见了

    Coding pages 不见了 起因 因为自己的这个博客 有时候访问还是比较慢的 原因是我的代码是在GitHub上托管的 GitHub是国外的网站 服务器都在国外 所以访问速度就特别慢 我就想找国内的既能实现代码托管 又能生成静态网页的平
  • Java实现方法中基本类型参数按地址传递

    参考了网上的一些资料 自己总结了一下 详细的可以去以下的博主看看 https www cnblogs com lixiaolun p 4311863 html http blog csdn net maoyeqiu article deta
  • 白话机器学习-Transformer

    一 背景 大抵是去年底吧 收到了几个公众号读者的信息 希望能写几篇介绍下Attention以及Transformer相关的算法的文章 当时的我也是满口答应了 但是确实最后耽误到了现在也没有写 前一阵打算写这方面的文章 不过发现一个问题 就是