人人能懂的深度学习【第一课】: 序列模型,自注意力和Transformer
前言
花了点时间整理了这个超级棒的MIT深度学习入门讲座(MIT Introduction to Deep Llearning)。
如视频版本的题目,这个50分钟的纯技术讲座从零到一的讲解了神经网络AI模型最核心的技术原理,深入浅出到连大一的文科生都可以听懂。
《第一课》同名电影其实是作者最喜欢的X Man系列电影。当下,无论是关乎个人工作抑或关乎全体人类未来,似乎都隐隐开始有了个新的假想敌:越来越万能的生成式大语言AI模型。
关于AI安全和人类未来的讨论方兴未艾,AI教父Hinton几天前在“MIT科技评论“峰会上所做的一个经典阐述是,AI可以并行分布式的学习知识和分享结果,而人类却无法互相复制权重(知识)。
回归当下,我们不妨积极拥抱AI,知己知彼。尽管作为人类无法直接复制知识,但无私的知识分享传播和积极学习的心态是人类进步(和对抗 万恶的分布式ai模型, 笑...)的正确打开方式。
感激MIT的分享精神,尽管有幸去这个殿堂深造的只是极少数天骄,但所有人都有机会聆听到精彩的知识传授。
重要的是,在见证历史的AI时代,我们都要终身学习。
深度学习的人,才能对抗深度学习的AI:)
就让我们开始吧。
回顾和介绍
大家好,我是Ava。
在这这堂课中,我们将专注于序列建模的问题,探讨如何构建可以处理和学习来自顺序数据的神经网络。
之前一堂课介绍了神经网络的基本原理,从感知器开始,逐步建立前馈模型,以及如何实际训练这些模型和开始考虑部署它们。
现在我们将把注意力转向涉及数据顺序处理的特定问题类型。我们将了解为什么这些问题类型需要一种不同的方式来实现和构建神经网络。
我认为这堂课的一些内容可能一开始会让人感到困惑或畏惧,但我真正想做的是从基础开始建立这个理解,一步一步地走过来,培养直观感,直到理解数学和操作背后的原理,了解这些网络是如何运作的。
好的,让我们开始吧。
首先,我想谈一下,当我们在谈论顺序数据或顺序建模时,到底是什么意思。
从一个非常简单的直观示例开始:假设我们有一个球的图片,你的任务是预测这个球接下来会移动到哪里。
如果你没有关于球的轨迹、运动和历史的任何先验信息,那么关于它下一个位置的猜测或预测将完全是一个随机猜测。
然而,除了球当前的位置之外,如果我还给你一些关于它过去移动的信息,现在这个问题就变得容易多了。我想我们都能同意,最有可能的下一个预测是这个球在下一帧会向右前方移动。
这是一个非常简单的例子,但事实上,顺序数据无处不在,正如我现在所说的,从我的嘴里发出的单词形成了一个声波序列 定义了音频,我们可以将其拆分为顺序处理。
类似地,文本语言可以分解成字符序列或单词序列。
还有许多其他例子中存在顺序数据和顺序处理,如医学信号(例如心电图)、金融市场和股票价格预测、生物序列中的DNA编码、气候模式、运动模式,等等。
那么现在,希望你已经对这些问题的类型以及它们在现实世界中的相关性有了一些了解。当我们考虑在现实世界中应用顺序建模时,我们可以想到很多不同的问题定义,我们可以拥有这些问题定义并合作解决。
之前介绍了分类和回归的概念,谈到了前馈模型;这个固定的静态环境中,对给定一个输入预测一个输出,二元分类的例子。
在这里,没有顺序的概念,没有时间的概念。
顺序数据和顺序处理
现在,如果我们引入顺序组件的想法,我们可以处理可能是顺序的输入,产生顺序或基于时间的输出。
例如,我们可以考虑文本语言,也许我们想生成一个预测,给定一段文本,分类这个消息是正面情绪还是负面情绪。
或者,我们可以有一个输入,比如说一张图片,我们的目标现在可能是生成文本,或者描述这个图像的顺序,给定这个扔球的棒球运动员的图片,我们能否构建一个神经网络生成这样一个语言标题?
最后,我们还可以考虑应用和问题,其中我们有序列输入,序列输出。例如,如果我们想在两种语言之间进行翻译。实际上,这种思考方式和架构类型就是驱动机器翻译任务的力量。在你的手机里的谷歌翻译和还有很多其他例子。
所以希望,这已经给你展示了什么是顺序数据,这些问题定义类型可能是什么样子。从这个开始,我们将开始建立我们的理解,构建和训练针对这些问题类型的网络。
从递归的概念开始
首先,我们要从递归的概念开始,从那里定义已知的循环网络;在最后一部分课程中,我们将讨论支撑Transformer架构的基本机制,这在处理顺序数据方面会非常非常非常强大。
正如我一开始说的,这堂课的主题是逐步建立理解,从基本原理和直觉开始。
为了做到这一点,我们要回顾感知器,从那里继续前进。
我们在第一堂课学习了感知器。
感知器由这个单一的神经元操作定义,我们有一组输入,比如说X1到Xm,这些数字被乘以相应的权重,通过一个非线性激活函数,然后生成一个预测输出y hat。在这里,我们可以引入多个输入,以生成我们的输出。但是这些输入仍然不是顺序序列中的点或者序列中的时间步长。
即使我们扩展这个感知器,并开始堆叠多个感知器在一起,定义了前馈神经网络,能够翻译并转换多个输入,应用这些权重操作,应用这种非线性来定义多个预测输出,我们仍然没有所谓“时间处理”或“顺序信息”的概念。
因此,在查看此图时,在左边和蓝色部分,您可以看到输入;在右边和紫色部分,您可以看到输出;绿色表示单个神经网络层,将这些输入转换为输出。
接下来,我将简化此图表,我将将这些堆叠的感知器折叠在一起,并用这个绿色块表示,仍然是相同的操作,我们有一个输入向量被转换为预测的输出向量。
现在,我引入了这里的新变量t,用它表示一个单一的时间步长。
可以在一个单一的时间步长输入,并使用我们的神经网络生成一个与该输入相对应的单一输出。
现在,我们如何基于这个概念,开始扩展并考虑多个时间步长,以及我们如何可能处理一系列信息?
好吧,如果我们拿这个图表,我所做的就是将其旋转90度,我们仍然有这个输入向量,输入生成一个输出向量。
我们是不是可以复制这个网络并多次执行此操作,以处理相应的不同时间的输入?
我们有一个单独的时间步长 从t 0开始,我们可以为下一个时间步长做同样的事情,再次将其视为一个孤立的实例,并不断重复这个过程。
你可能已经注意到,所有这些模型只是彼此的副本,只是在这些不同的时间步长有不同的输入。这个具体在特定t时间步长里预测输出y hat of t是 X of t 的函数,也是由我们的神经网络权重定义的函数。
好吧,我们的目标是试图理解顺序数据,并进行顺序建模。但是上面这个图表可能显示了什么问题?
(学生回答)
没错,说得对。所以回答是x1可能与Xt不相关,并且我们需要有时间依赖性,但这些孤立的副本根本没有捕捉到这一点。这完美地回答了这个问题。
在这里,在一个较晚的时间步长上的预测输出可能取决于之前时间步长的输入。
如果这真的是一个具有时间依赖性的顺序问题,那么如何考虑这个问题呢?
我们如何定义一个关系,将网络在特定时间步长的计算与来自先前时间步长的历史记忆联系起来?
我们简单地将网络所理解的计算和信息通过我们称之为递归关系的方式链接到其他副本。
这意味着在特定时间的网络计算的某些方面被传递给稍后的时间步长。
我们通过这个变量H来定义这个内部状态,或者您可以将其视为神经元网络维护的记忆项,这是这个状态从一个时间步长被传递到另一个时间步长,我们读取并处理这个顺序信息。
这意味着网络的输出、预测和计算不仅是输入数据X 的函数,而且还有这个其他变量H。它捕获了状态的概念,捕获了网络计算和传递在时间上的记忆概念。
具体来说,这个预测输出y hat of t不仅取决于某个时间的输入,还取决于过去的记忆、过去的状态。正是这种时间依赖性和递归性的联系定义了这种循环神经元的概念。
我已经展示了这种在时间上展开的连接,但我们也可以用一个循环来描绘这种关系,这种计算与这个内部状态变量H of t随着时间的推移被迭代更新,并在这个递归关系中反馈到神经元的计算中,这就是我们定义的方式。
这些递归单元组成了循环神经网络,或者说RNN。
关键在于,我们有这种递归关系的概念,捕捉了这种周期性时间依赖性。
实际上,这种想法确实是循环神经网络RNN背后的直观基础。
循环神经网络RNN
让我们继续从这里构建我们的理解,并了解如何实际在数学上定义RNN,以及进行编码操作。
我们要做的就是将这种关系正式化一些,关键思想在于RNN 保持状态并在每个时间步长更新状态。
随着序列的处理。我们通过应用这个递归关系来实际更新内部状态H of t。
状态更新就像我们迄今为止介绍的任何其他神经网络操作。
我们再次学习一个函数,由一组权重W 定义,我们还是使用该函数更新状态H of t。新的组成部分在于,该函数既取决于输入也取决于先前的时间步长H of t -1。
你会注意到这个函数Fw是由一组权重定义的。不同的副本单元使用相同的一组权重参数,从一个时间步长到另一个时间步长,作为循环神经网络处理这个时间信息和顺序数据。
好的,关键思想希望在这里能传递给大家,这个RNN 状态更新操作在序列处理时将每次都做状态更新。
我们可在Python代码或者伪代码中思考实现RNN,以便能更好更直观地理解这些网络如何工作。
所以我们所做的就是开始定义了一个RNN。
我们开始初始化它的隐藏状态。我们有一些句子,比如说这是我们感兴趣的输入,我们可能对预测出现在这个句子里的下一个词感兴趣:
我们可以做的是,循环遍历我们时间输入的这些单词;在每一步,当我们循环遍历时,每个句子中的单词都被输入到RNN模型中,连同之前的隐藏状态。这就是为下一个单词生成预测的过程并依次更新RNN状态:
最后,我们对句子中的最后一个单词的预测,我们缺少的单词仅仅是在所有先前的单词通过模型输入后的RNN输出。
为神经网络编码自然语言
进入数值向量,我们可以把神经网络的输入表示为一个整数索引。
如果我们考虑一下这种嵌入概念如何应用于语言数据,让我们考虑一个我们语言中可能有的单词词汇表。我们的目标是能够将词汇表中的单个单词映射到固定大小的数值向量。我们可以通过以下方法实现这一点:
把所有所有可能出现的单词定义在这个词汇表中,然后对它们进行索引。每个不同的单词分配一个索引标签,一个对应于索引1的标签 ,一个对应于索引2的标签。。。依此类推。
这个索引将这些单词映射到唯一的索引数字。这些索引可以定义我们所谓的“嵌入向量”(Word Embedding),这是一个固定长度的编码,我们只是给出该词的索引处的一个值,这被称为一种OneHot嵌入。
所以,我们有了这个词汇表,固定长度的向量,以及每个词汇表实例对应于OneHot编码,在相应的索引处的一个热点。
这是一种非常稀疏的方法,它仅基于纯粹地计数索引,在这种基于向量的编码中没有语义信息的概念。
另一种常见的方法是使用神经网络学习编码,学习嵌入。
我们这里的目标是,学习一个神经网络 ,它在我们的输入数据中捕捉了一些固有的语义,并将相关的单词或相关的输入映射到在这个嵌入空间中更接近的地方,这意味着它们将具有更相似的数值向量。
以上是序列建模原理以及神经网络整体原理的一个非常基础的概念。
处理可变长度序列数据
好的,有了以上的准备,我们可以回到我们的设计准则,考虑我们希望具备的能力。
首先,我们需要能够处理可变长度的序列。
如果我们再次想要预测序列中的下一个词,我们可以有短序列,我们可以有长序列,我们甚至可以有更长的句子。我们的关键任务是要能够跟踪这些不同长度的依赖关系。
依赖关系是指序列中可能有很早的信息,但这些信息可能在序列后期才变得相关或出现。
我们需要能够跟踪这些依赖关系并在网络中保持这些信息。依赖关系与顺序有关,序列由顺序定义。
我们知道,完全不同顺序的相同单词具有完全不同的含义,对吧?
因此,我们的模型需要能够处理这些顺序差异以及可能导致不同预测输出的长度差异。
好的,希望通过以上这些例子,我们了解到了如何将输入数据转换为可以传入RNN的数值编码,以及哪些是我们想要满足的关键标准:
通过时间的反向传播机制
目前为止,我们已经描述了RNN,直观性的看到它们是如何工作的,它们的数学运算,以及它们需要满足的关键标准。
最后一部分,我们如何实际训练RNN中的权重,这是通过稍作改动的反向传播算法完成的,用以处理顺序信息。
回想一下,我们如何训练前馈神经网络模型?从输入开始,首先我们将这个输入在网络中,从输入到输出进行正向传播:
反向传播的关键是,将预测值和反向传播梯度回传到网络,并使用这个操作来定义和更新损失,逐渐调整参数网络的权重,以便最小化总损失。
现在对于RNN,如我们前面所提到的,我们有这个时间展开,这意味着我们在序列中的单个步骤有这些单独的损失,它们组成了总损失。
这意味着当我们进行反向传播时,我们现在需要的不是通过单个网络反向传播误差,而是通过这些单个时间步长反向传播损失。通过每个单独的时间步长,然后在所有时间步长上进行,从我们当前的时间t一直回到序列的开头。
这就是为什么这个算法叫做“通过时间反向传播”,对吧?因为正如你所看到的,数据和预测产生的误差沿着时间方向反馈,从我们目前所在的位置一直到输入数据序列的开头。
在实践中,通过时间反向传播实际上是一个非常棘手的算法。原因是,如果我们仔细观察梯度如何在RNN中流动,这个算法涉及到许多许多重复计算和矩阵相乘。
为了计算关于第一个时间步长的梯度,我们必须进行许多这种重复的矩阵相乘。
为什么这会成问题呢?
因为如果权重矩阵W非常非常大,这可能导致我们所谓的梯度爆炸问题,我们试图优化网络的梯度就是这个原因,它们炸了,变得非常大,使网络无法稳定地训练。
为了减轻这种情况,我们采用了一种简单的解决方案,称为梯度裁剪,实际上是缩放这些非常大的梯度,以便以更受限的方式约束它们。
相反,我们可能会遇到权重矩阵非常非常小的情况。如果这些权重矩阵非常非常小,由于这些重复的权重矩阵计算和这些重复的乘法,我们最终会得到一个非常非常小的值。这对于RNN尤其是一个非常真实的问题。
我们可能会陷入这个称为消失梯度的漏洞,现在你的梯度已经接近于零,同样你无法稳定地训练网络。
现在有一些特定的工具可以用来尝试减轻消失梯度问题。我们将简要介绍三种解决方案。
在此之前,我想再退一步,让你更直观地了解为什么消失梯度对于循环神经网络可能是一个真正的问题。
我一直试图重申这个概念:依赖关系在顺序数据中的含义,以及跟踪这些依赖关系意味着什么。
如果依赖关系是在一个很小的空间里,非常受限的时间分离,这个重复的梯度计算和重复的权重矩阵乘法就不是什么大问题了。
如果我们有一个非常短的序列,其中单词之间的关系非常紧密,下一个输出很明显是什么:
RNN可以使用过去的信息来进行预测。因此,如果相关信息在时间上彼此接近,学习有效权重的需求并不那么大。
相反,现在如果我们有一个句子,其中有更长期的依赖关系,这意味着我们需要从序列更远的地方开始预测,在序列末尾进行预测与当前位置相关的内容;与预测的距离变得越来越大,消失梯度问题日益加剧,这意味着RNN无法连接这些点并建立这种长期依赖关系,这都是因为消失梯度问题。
三种减轻梯度消失问题的方式
我们有三种方式可以实现对网络进行的修改以试图减轻这个梯度消失问题。
首先是我们可以简单地改变在每个神经网络层中的激活函数,这样它们可以在数据大于0的情况下有效地尝试减轻和防止梯度收缩。
这一点尤其适用于relu激活函数。原因是在所有x大于0的情况下,使用ReLU函数 导数为1。因此它不小于1,因此它有助于减轻消失梯度问题。
另一个技巧是我们如何初始化网络中的参数以防止它们过快地收缩到0。
有一些数学方法可以做到这一点,即通过将权重初始化为单位矩阵,这在实践中有助于防止权重更新过快收缩到0。
然而,解决消失梯度问题的最有效方法是引入一个稍微复杂一点的循环神经单元,以便更有效地跟踪和处理数据中的长期依赖关系。这就是门控的概念:
这个概念是通过有选择地控制信息流进入神经元,以便过滤掉不重要的信息同时保留重要的信息。
关键并且最流行的实现这种门控计算的循环单元称为LSTM或长短时记忆网络。
LSTM核心概念
今天我们不打算详细讨论LSTM的数学细节和操作等,但我想传达关于这些LSTM在跟踪长期依赖关系方面有效的关键思想和直观想法。
核心是LSTM能够通过这些门控制信息流,更有效地过滤掉不重要的东西并存储重要的东西。
你可以在张量流中实现LSTM,就像你实现RNN一样,但我希望你在思考LSTM时记住的核心概念是这个通过门控制信息流的想法。
简单地说 LSTM的工作方式是通过维护一个单元状态,就像标准的RNN一样,这个单元状态与直接输出的内容是独立的。
单元状态的更新方式是,根据这些门控制信息流动,忘记和消除不相关的信息,存储相关的信息,相应地更新单元状态,然后过滤这个更新的单元状态以产生预测的输出,就像标准的RNN一样。
我们同样可以使用反向传播算法训练LSTM,但是LSTM的定义方式允许梯度完全无阻地流动。这大大消除了之前提到的消失梯度问题。
再次,如果你对了解更多关于LSTM的数学和细节感兴趣,请在讲座后与我们讨论,这里只是强调LSTM操作的核心概念和直观理解。
RNN的应用和局限性
好了,到目前为止,我们已经涵盖了很多内容。我们已经了解了RNN的基本工作原理架构、训练它们被应用到的问题类型。
我想通过考虑一些具体的例子来结束这部分内容。那就是在音乐生成的任务中,努力构建一个RNN可以预测序列中的下一个音符并用它生成从未实现过的全新音乐序列。
给一个可以尝试的质量和类型输出的例子:几年前有一个作品在一组古典音乐数据上训练了一个RNN,有名的作曲家舒伯特写了一首著名的未完成交响曲的两个乐章,但他在去世前无法完成他的交响曲,留下了第三乐章未完成。
几年前,一个小组训练了一个基于RNN的模型,来尝试生成舒伯特著名的未完成交响曲第三乐章。如果有任何古典音乐迷,希望您能欣赏一下生成的质量。
在音乐质量这方面,已经是几年前的事了。正如我们在接下来将看到的那样,自从我们第一次播放音乐例子以来,这些算法的能力已经取得了的巨大进步,特别是在你知道一系列的领域。
除了RNN音乐生成,我们还可以考虑一下输入序列到单个输出的简单示例。
比如用于情感分类,我们可以考虑例如推文文本,并根据网络学到的内容为这些文本示例分配正面或负面标签。
好的,这部分内容基本上总结了RNN。我认为这是相当了不起的,使用我们迄今为止讨论过的所有基本概念和操作,我们已经尝试构建了处理顺序建模复杂问题的网络。
但是,像任何技术一样,RNN并非没有局限性。那么这些局限性是什么?使用RNN甚至LSTM可能出现的问题是什么?
第一个是在编码和依赖关系方面。我们试图处理的数据在时间分离。RNN需要一步一步输入顺序信息并处理,这会导致我们称之为编码瓶颈的现象。
当我们试图编码大量的内容,例如一个非常大的文本的时候,我们输入很多不同的单词,并在最后一个时间步里得到一个单一的输出。如何确保在那个最后的时间步之前,所有的这些信息都被适当地维护并被网络编码和学习了呢? 实际上,这非常非常具有挑战性,很多信息可能会丢失。
另一个限制是,基于这种一步一步的处理,RNN可能相当慢,没有一个简单的方法并行计算。
最后一个限制,这些编码瓶颈的组件需要逐步处理此数据,导致了最大的问题:内存。
当我们谈论长期记忆时,RNN和LSTM的容量实际上并不那么长,我们不能真正处理几十万个或者更多的数据,所以我们无法在一个丰富的数据源中有效地学习完整的信息和模式。
超越"逐步递归处理"概念
正因为以上的这些问题,最近有很多关注,如何超越这个“逐步递归处理”的概念,以便构建更强大的架构来处理顺序数据。
要理解我们如何开始做到这一点,先让我们大步后退,想想最初的这个序列建模的目标。
一开始我介绍了,给定某个输入序列数据,我们想要构建一个特征编码,并使用我们的神经网络学习它,然后将该特征编码转换为预测输出。
我们看到的是RNN使用了这种递归的概念维护和逐步处理信息。
但是正如我刚才提到的,我们有这3个关键的RNN瓶颈,我们真正想要实现的是,超越这些瓶颈并实现模型在这些能力方面更高的水平,而不是有一个编码瓶颈。
理想情况下,我们希望把需要输入信息作为连续信息流来处理,而不是缓慢的递归;我们希望使用并行计算以加快处理速度;最后,我们的主要目标是真正尝试建立可行的长期记忆,以便对顺序数据实现丰富而多样的理解。
RNN有根本局限性以至于无法实现以上这些能力的原因是,它们需要按时间“逐步处理”。
那么,如果我们能超越这一点呢?如果我们可以完全消除递归的需求,而不必处理一个一个的顺序处理数据呢?
一个最初步和天真的方法是,只需将所有数据压缩在一起,将所有时间步骤一起处理,创建一个有效的连续向量:
这样,时间步骤被消除了,现在只有一个输入流,有一个向量输入了所有时间点的数据,然后被送入模型计算某个特征向量,然后生成一些希望有意义的输出。
因为我们把所有的时间步骤压缩在一起了,于是可以考虑简单构建一个前馈网络来直接进行此计算,这样我们就消除了对递归的需求。
但我们仍然面临一个问题,它不可扩展,因为密集的前馈网络必须定义为由许多连接组成的非常大的网络。
并且,关键的是,我们通过盲目地将所有内容压缩在一起,因此我们完全丢失了顺序,丢失了信息之间的时间依赖性,于是又陷入了我们试图建立的长期记忆能力的问题。
那么,如果我们仍考虑将时间步骤放在一起,但在输入数据提取信息时,试图做得更聪明一些呢?
关键的想法是,,在一个序列中能够识别和关注什么是重要的信息流。这就是注意力/自注意力的概念。
注意力机制
注意力机制是一个非常非常强大的概念。在现代深度学习和人工智能中,我无法强调这个概念有多强大。
注意力是Transformer架构的基本机制。你们中的许多人可能已经听说过。
有时候Transformer可能会让人望而却步,因为有时候会用一些非常复杂的图表表示或者部署在复杂的应用程序中。
你可能会想好吧,我甚至从何开始理解这个呢?
在Transformer的核心里,这个关键的“注意力”操作其实是一个非常直观的想法。
在这个演讲的最后部分,我们将一步一步地分解它,看看为什么它如此强大,以及如何将其作为更大的神经网络如Transformer的一部分。
具体来说,我们将讨论并关注这个自注意力的想法:关注输入序列中最重要的部分。
让我们考虑一个图像,我认为首先考虑一个图像是最直观的:
这是一个钢铁侠的照片。如果我们的目标是尝试从这个钢铁侠形象中提取重要的信息,我们可以使用我们的眼睛天真地扫描在这个图像上像素点接像素点。
我们的大脑可能在内部正在进行类似这样的计算,但只需看这个图像并能够关注重要的部分。
我们可以看到这是钢铁侠,然后我们可以更进一步关注钢铁侠的哪些细节可能是重要的。
关键是你的大脑正在确定哪些部分是关注的对象,然后提取那些值得高度关注的特征。
这个问题的第一部分(哪些细节是最重要的)实际上是最有趣和具有挑战性的一个。
它与搜索的概念非常相似,实际上,这就是搜索所做的事情:从一些较大的信息体中提取并确定重要部分。
让我们继续研究一下,搜索是如何工作的?
比如,你思考在这个课程里,如何学习更多关于神经网络的知识呢?在这个时代,除了来这里和我们一起学习之外,你可能会做的一件事情是:上网 ,看所有的视频,进行搜索操作去尝试找到匹配的内容。
所以你有一个巨大的数据库比如YouTube,你想找一个视频,你输入你的查询关键词“深度学习”,然后出来的是一些可能的输出。
对于数据库中的每个视频,都会有一些与该视频相关的关键信息,比如说标题。
现在要进行的搜索任务就是,在数据库里找到那些和查询关键词相匹配的标题的数据库键(Key)。
我们想要计算一个相似性度量以及相关性,这些键与我们想要的查询有多相似?
我们可以一步一步地完成这个过程。
比如说关于优雅的巨大海龟的第一个选项与我们关于深度学习的查询相差甚远;我们的第二个选择深度学习简介这是这堂课的第一堂导论课是的非常相关;第三个选择是关于已故的伟大的科比·布莱恩特的视频与我们的查询不太相关。
这里的关键操作是,将查询和键放在一起,做一个相似性计算。
最后一步,现在我们已经确定了哪个键是相关的,提取相关信息,我们想要关注的东西称之为“值(Value)”。
因为搜索得当,我们成功地找到了关于深度学习的你想要关注的相关内容。
这个直观的想法给出了一个查询,试图找到相似性,试图提取相关值,这其实就是自注意力的基础以及神经网络(如Transformer)中的工作原理。
具体回到我们的文本,我们的语言示例:
用这个句子,我们的目标是识别并关注输入中的特征,这与句子的语义含义相关。
现在第一步,我们有顺序数据,我们消除递归,一次输入所有的时间步。
不过我们仍然需要一种方法来编码,用于捕捉关于顺序的信息以及这种位置依赖性。完成这个的方法是位置编码的概念。它捕捉了一些序列中存在的固有顺序信息。
我只是简单地谈一谈位置编码,但这个想法与我之前介绍的嵌入的想法有关。使用神经网络层来编码位置信息,捕捉这段文本中关于顺序的相对关系。这是一个高层次的概念。
我们可以一次处理这些时间步,这里没有时间步的概念;相反,数据是独立的,我们学习了这个位置编码,捕捉了位置顺序信息。
现在,我们的下一步是,用这个编码来找出要关注什么。
就像我用YouTube示例介绍的搜索操作一样,提取查询(Query),提取键(Key),提取值(Value)并将它们联系起来。
我们使用神经网络层来完成这个:
给定这个位置编码,注意力机制所做的是应用神经网络层转换生成查询(Query)。
我们再使用另一个神经网络层,这是一组不同的权重,一组不同的参数,然后以不同的方式转换位置嵌入,生成第二个输出键(Key)。
最后,用第三层重复这个操作,第三套权重,生成值(Value)。
现在有了这三个关键矩阵:查询(Q)、键(K)和值(V),我们可以将它们彼此比较,试图找出在自我输入中网络应该关注哪里,什么是重要的。
这是这个相似性度量背后的关键思想,你可以把它看作注意力得分,我们所做的是计算相似性得分。
记住,这些查询和键值只是数字,我们可以将它们定义为数字数组,把它们看作空间中的向量:查询向量值是一个向量,键值是另一个向量。
在数学上,我们可以通过取点积来比较这两个向量,了解它们有多相似,使用点积来衡量它们是否指向同一个方向。这是相似性度量,如果你熟悉一点线性代数,这也被称为余弦相似性。
对于矩阵,这个操作完全相同,如果我们将这个点积操作应用于查询矩阵和键矩阵,得到了这个相似性矩阵。
现在,下一步非常关键:计算注意力权重,以决定神经网络应该关注输入的哪些部分。
这个操作给了我们一个分数,定义了输入数据的各部分彼此之间的关系。
给出一个句子,当我们计算这个相似性分数指标时,我们可以开始考虑这个顺序数据的组成部分彼此之间的关系权重:
例如 在这个文本句子的例子中“He tossed the tennies ball to serve”。分数的目标是序列中彼此相关的单词应该有高的注意力权重(上图,越深的颜色代表越高的权重):比如“球(ball)”与“扔(tossed)“以及“网球(tennis)”有关,这个矩阵本身就是我们的注意力权重。
我们所做的是将这个相似性得分通过一个Softmax函数处理,它所做的只是将这些值约束在0和1之间。你可以把它们看作是相对分数,相对注意力权重。
最后,我们有了这个矩阵,捕捉到了这种相似性的概念以及这些内部自我关系,最终我们可以使用这个矩阵去提取那些值得高度关注的特征,这正是自注意力机制中的最后一步:
我们拿着注意力权重矩阵,将其与值矩阵相乘,得到一个输出,这个输出会反映出值的高度关注的相关特征。
好吧,让我们喘口气,让我们回顾一下我们迄今为止所涵盖的内容。
这个想法的目标是用自注意力(Transformer的核心)消除递归,并关注输入数据的整体架构中最重要的特征。
这个想法实际上如何部署实现呢?
首先我们拿输入数据,我们计算这些位置编码;神经网络层变成三部分,将位置编码转换为每个查询,键和值矩阵。
接着我们用之前提到的点积操作,计算自注意力权重得分;然后,用这些自注意力得分信息来提取(原数据中)应该给予高度关注的特征。
这种方法如此强大,是因为“注意力权重和值放在一起,来提取高度关注的特征”这个操作。
以上定义了一个单一的自注意力头,多个这样的自注意力头可以链接在一起,形成更大的网络架构。
你可以想象,这些不同的自注意力头会试图去提取信息输入的不同相关部分,这样就可以以一个非常非常丰富的编码来表示和解析我们正在处理的数据。
直观地回到我们的钢铁侠例子,看看这个多自注意力头的想法可以如何提出数据中不同的显著特征和信息。
首先,可能会考虑钢铁侠注意力头1(提取了钢铁侠人物本身)。除此之外,可能还有其他注意力头部正在挑选出其他相关的数据部分,也许是我们以前都没有意识到的,例如,建筑物或者在背景中追赶钢铁侠的飞船。
这就是许多许多强大架构的关键构建模块。我要再次强调这个机制是多么强大。
我们刚刚建立和理解的这个“自注意力”的支柱想法,是一些今天已知的最强大的神经网络和深度学习模型的关键:
比如像GPT3这样的非常强大的大语言模型,能够以非常类似于人类的方式合成自然语言,消化大量的文本信息,了解文本中的关系;再比如用于生物学和医学应用的极具影响力的模型 AlphaFold 2,它使用自注意力的概念查看蛋白质序列数据,并能够仅仅根据序列信息预测蛋白质的三维结构;甚至现在到了计算机视觉,最初的注意力的想法已经开始改变计算机视觉领域。
使用这个“自注意力”的关键概念,我们可以关注输入中的重要特征,并构建这些非常丰富和复杂表示的高维数据。
最后
今天的讲座马上要结束了。
我知道我们在相当短的时间内涵盖了很多领域,但这就是这个训练营项目的内容。
希望今天你已经有了一些关于人工神经网络的基础感觉。
我们谈论了RNN,看它们如何适用于顺序数据;如何使用反向传播来训练它们;如何将它们应用于不同的应用程序。
最后,我们如何超越递归,建立自注意力机制,为深度学习和序列建模构建越来越强大的模型。
希望各位喜欢。