从发展历史视角解析Transformer:从全连接CNN到Transformer

2020-10-27 14:29:45 浏览数 (1)

编译 | bluemin

校对 | 陈彩娴

Transformer架构在机器学习领域(尤其是NLP里)是一项热门研究,为我们带来了许多重要成果,比如:GPT-2、GPT-3等写稿机器人;第一代GPT及其性能更优越的“继任者”BERT模型,在众多语言理解任务中以前所未有的数据利用效率获得了最准确的结果,而且几乎不需要调整任何参数,也就是在过去花费一个月做的事情、现在只需要花费30分钟,还达到了更好的效果;以及AlphaStar等。

由此可见,Transformer的威力真是不同凡响!

2017年,谷歌团队首先提出Transformer模型。该团队将Transformer概括为一句话:“Attention is All You Need.”但单单看这句话,人们并不能对Transformer模型建立直观的理解与认知。为此,作者希望从发展历史的角度对Transformer模型作一个直白的解释。

1

经典的全连接神经网络

在经典的全连接神经网络中,每个不同的输入变量都是独一无二的雪花算法(snowflake)。当全连接神经网络学会识别涉及某个特定变量或其集合时,它们不会对其他变量或其集合进行任何自动泛化。

当你在社科研究或医学研究项目中进行回归分析,输入可能是人口统计学变量(比如“年龄”或“每周饮酒量”)时,上述原理也讲得通。但如果输入变量包含某种已知的、结构化的关系,比如空间或时间布局,全连接神经网络的表现就会很差。

如果输入是图片中的像素,那么全连接网络就无法学习类似“左侧的像素较亮,右侧的像素较暗”的模式,而是必须分别学习“(0, 0) 比 (1, 0) 亮”,“(1, 0) 比 (2, 0) 亮”以及“ (0, 1) 比 (1, 1) 亮”等等。

2

卷积神经网络

卷积神经网络(CNN)了解输入的空间布局,并用相对的术语处理输入:CNN不学习“在位置(572,35)处的像素”,而是学习“我正看着的中心的像素”、“左边的像素”等等。然后,它们一边“看”向图像的不同部分一边滑动,在每个区域中寻找相对中心的相同图案。

CNN与全连接网络有两个不同点:权值共享(weight sharing)和局部性(locality)。

  • 权值共享:在中心位置有一些固定的计算方法,将这些计算应用到每个位置。
  • 局部性:每一次计算都只能看向距离中心位置相当近的事物。例如,你可能会在一个3x3或5x5的窗口中查找图案特征。

权值共享对于任何空间或时间构造的输入(包括文本)都是至关重要的。

然而,CNN的局部性却不适用于处理文本。

我是这样考虑的:图像中的每一个突出事物(狗,狗的鼻子,边缘,一小块颜色)都可以分开来独立理解,不需要观察该事物以外的内容。比方说,图像中不包含替代物,也不包括要求你观察其他事物来掌握某物本质的参考系统。

除非是在一些奇奇怪怪的场景,否则通常不会出现“哦,我现在看到一只狗,但我必须观察狗以外的事物才确认这是一只狗”的情况。所以,你可以从一些小细节入手,然后分层次深入思考:“啊,这是边缘部分–>啊,那是一个由边缘组成的长方形物体–>啊,那是狗的鼻子–>啊,那是狗的头部–>啊,那是一只狗。”物体的每个部位都是由它所包含的更小的特征来定义的。

但上述的方法并不能用于文本处理。例如,句子中的代词可能出现在句首,但是指代的先行词常常在句末。我们没有办法在不改变句意的前提下,将一个句子准确无误地分解成可以独立理解的分句,然后再相互链接。所以CNN的局部性原理不利于文本处理。不过,很多人在处理文本时都使用了CNN。CNN可以解决文本的很多问题,但在其他方面能够发挥的作用更大。

3

循环神经网络

循环神经网络(RNN)与CNN一样,按次序沿着输入“滑动”,在(权值共享的)每个位置执行大致相同的计算步骤。

但是,RNN并非观察当前位置以及位置周围的局部小窗口,而是观察下列信息:

  • 当前位置
  • 观察最后位置之后的输出

当输入是文本格式时,感觉就像“阅读”:RNN处理第一个单词,概括当时所收集到的所有信息;然后根据概括的信息处理第二个单词,更新概括的内容;再根据新的概括内容处理第三个单词,再次更新概括信息,循环往复。

人们通常使用的是能学习何时遗忘信息(将信息从简介中删除)以及学习何时传递信息的RNN架构(LSTMs或GRU)。举例而言,人们会特地记住“我还没有找出this所指代的事物”,然后将这条信息传递至尽可能广的范围内进行搜索,直至找到一个合适的先行词。

(3b) RNN可不容易对付

尽管RNN所做的工作有点像顺序阅读,但它本身还有一个棘手的任务要解决。

RNN每次只能沿一个方向“读取”,这就造成了不对称的问题:在句首附近,输出只能使用几个单词所构成的信息;在句尾附近,输出则可以使用所有单词构成的信息。(这一点与CNN相反,因为CNN对每个位置的信息的处理方式都是一样的。)

在这种情况下,如果一个句子开头的单词只能根据后面出现的单词来理解时,就会出现问题。RNN可以基于前面的单词理解后面的单词(这也是RNN的核心观点),但不能基于后面的单词来理解前面的单词。

这个问题可以通过两种方式在一定程度上进行回避:一是使用多个RNN层,其中较新的层类似“附加阅读通道”;二是用两个RNN分别从不同方向读取(这也是“BiLSTMs”的基本原理)。

但除此之外,RNN的结构仍然面临着一个根本难题:RNN只能使用长度有限的"scratchpad”(便签存储器)来处理单词之间的依赖关系,并且必须使用同一个“scratchpad”来处理所有短期和长期依赖关系。

大家不妨读一下下面这个句子:

It was a truly beautiful bike, and though there were bigger and sturdier hogs in Steve’s collection, he’d always favored that one just for the sheer aesthetics.

这并不是一个很难的句子,但其中关系纵横交错,引人深思。当我们按照“从左到右”的顺序阅读,一开始碰到“bike”这个单词时,我们可能会想到是“自行车”;只有当我们看到“hogs”时,才明白之前这个“bike”指的是“摩托车”,而且是通过间接暗示的方式表达的。那“hog”这个词本身是什么意思呢?单独来看,它可能表示一头猪。正如我们只能基于“hog”来理解“bike”一样,我们也只能基于“bike”来理解“hog”(或许还得益于“collection”这个词,虽然收集猪也并非绝无可能)。

这还仅仅是字面上的歧义。整个句子的含义也存在相似的交错分歧。只有当你读到“sheer aesthetics”时,你才会真正明白为什么这句话的开头表述是“it was a truly beautiful...”。也只有把全部信息联系起来,我们才能明白这个句子所表达的关于Steve、摩托车收藏和他的态度之间的关系。

RNN对这句话的理解会有些吃力:首先是把这句话存储在容量有限的scratchpad中,适当省略一些细节,但还得祈祷被删掉的细节是不重要的。这时候RNN的内心OS可能是:“好吧,还要记得这个‘it’需要一个先行词[scribbles]……我的存储容量很有限,可能会被‘beauty’和‘bicycles’分神——哦,天哪,这里还有一个‘though’引导的分句,呃,但这与‘pigs’有什么关系?(检查一遍信息后发现)我现在看到的是 ‘pretty bicycle past tense’(漂亮的车、过去时),但里面没有提到‘pigs’(猪)。那我就把‘pigs’加进来,看看后文有没有相关的解释……但这个‘though’到底想表达什么意思?哦,天哪……”

4

注意力机制

在作者看来,注意力机制的提出最初是为了处理成对的文本,比如文本蕴含(“句子1和句子2语义相近、语义相反,或既不相近也不相反?”)

在这种情况下,人们需要一个模型,将句子1与句子2中的每个词/短语进行比较,以找出哪些词/短语可能是指同一个主题或其他。

注意力机制如上所述。你有两个单词序列(或通常是“positions”),横轴和纵轴上各有一个序列,形成一个大网格,每个单元格包含一组可能的单词。然后,你可以采用某种方式来确定这些单词几时“匹配”,然后针对每个单词进行计算,将其与和它“匹配”的单词相结合。

如前所述,注意力机制是为了比较两种不同的文本而提出的。但注意力机制也可以用来比较同一个文本。(这被称为“自注意力机制”,但因为这个方法太常见了,所以人们逐渐就把“自”字去掉,将其统称为“注意力机制”了。)

注意力机制可以帮助解决代词或单词的歧义。有了注意力机制,你不用将有歧义的文段存储在容量有限的scratchpad内、然后坐等哪天有足够的存储空间,而是可以马上将单词A与其他可能会帮助诠释A的定义的单词联系起来。这时,代词和名词短语可以一步连接,例如将 “Bike”和“hog”一步连接。

(4b)介绍一个注意力运行方式

注意力机制运行的方式有很多。本文仅对在Transformer模型中使用的一种方式进行粗略概括。

想象一下:一个约会网站上的两个单词要配对。对于每个单词,你要计算:

关键信息:这个单词是“约会简介”(例如“bike”的简介可能包含“我是中性名词”)

查询信息:这个单词在查阅约会简介时,搜寻的是什么信息?(像“it”这类代词可能是:“我匹配的是中性名词”。)

价值信息:有关该词含义的其他信息,可能与匹配过程无关(例如,有关“bike”含义的其他信息)

对于每个单词,你可以利用关键信息和查询信息来确定该单词与自己本身的匹配度,以及与其他单词的匹配度。然后,你可以汇总价值信息,用“匹配分数”(match scores)进行加权。最后,你可能会得到一个既包含原单词的大多数价值、又包含其他单词的些许价值的结果,比如“我仍然是一个代词,但同时我还指代了这个名词,且表达的就是该名词的含义。”

由于单词可以有多种不同的关联方式,所以很难让每个单词只包含一条关键信息/查询信息/价值信息。其实大可不必!你想要在一个单词内包含多少条关键信息/查询信息/价值信息都可以!这被称为“多头注意力机制”(“multi-headed” attention),其中每个单词的关键信息/查询信息/价值信息的数量是注意力机制的“头”的数量。

(4c)注意力机制与CNN

注意力机制在某些方面与CNN相似。注意力机制在每个位置都会进行一次计算,把这个位置的信息和其他位置的信息结合起来,同时还能忽略周围大多数不相关的信息。

但与CNN不同的是,“其他信息”不需要在附近。(注意力机制不是“局部的”。)而且注意力机制的当前位置不是预定义的,也不是固定的(不像CNN具有固定的“windows”,尺寸规定为3x3或其他)。它们是基于所有输入进行动态计算。

5

Attention is all you need

首先,人们在使用“自注意力机制”时,通常只会用一次。可能是应用在一些RNN上,也可能是应用在其他地方。注意力机制被视为一种“调味剂”,可以“撒”在现有的模型上进一步改善模型的性能。“自注意力机制”通常不会作为核心功能单元。这与CNN或RNN的层数不同,前者叠加在一起就可以构成一个模型。

Transformer模型就是一种以attention为核心功能单元的架构。你可以将注意力的层堆叠,就像叠CNN或RNN的层一样。

更详细来说,Transformer模型的单个“块”或“层”会执行以下操作:

一个注意力步骤

这个步骤是对每个单词/位置进行局部计算,不使用其他区域的信息

然后,你只需要将这些块堆叠起来。第一个注意力步骤是给每个单词添加一些其他含义,这些含义是从其他可能与之相关的单词那得来的。第一个局部计算步骤会进行相关处理,可能就像是“好吧,我们似乎找到了两个可以匹配这个代词的不同名词;让我们来看看查询信息,看看要选那个名词吧。”然后,下一个注意力步骤是采用每个单词更易理解的新含义,并通过对上下文的深入理解重新赋予其他单词新的含义。这些步骤反复进行。

有趣的是,每一层的序列大小是一样的。每个单词(或“字块”、“字节”等并非根据单词来划分文本的模型)都会有一个位置。但是,每个位置存储的价值信息(最初只是以“单词”展开)开始变得更容易“理解”或更好“处理”信息,根据上下文中越来越复杂的理解需求表示单词含义。

(5b)位置编码;Transformer模型与CNN

Transformer模型的输入不仅包括每个位置的单词,还包括一个显示“这是单词#1”、“这是单词#2”等信息的运行计数器。

如果没有计数器,Transformer模型就无法辨别单词的顺序。Attention qua attention并不关注单词位置,而只想弄清楚单词的含义与单词“想要”什么。但是,由于Transformer模型的注意力可以看到运行计数器的内容,因此它可以执行诸如“此单词正在寻找附近的单词”之类的任务。

原则上,运行计数器能帮助Transformer模型学习CNN所用的同一个固定的局部过滤器。但这些行为会存在一定限制,比如注意力步骤会忽略单词而仅使用位置计数器。(另一个限制是注意力不包含单词被应用的位置计数器。)

我跳过了一些技术细节的讲解,但这就意味着,Transformer模型类是CNN模型类的超集。任何一组局部CNN滤波器都可以用特定的注意力计算过程表示,因此Transformer模型的空间包含CNN这个特例。这表明我们的文本数据丰富,至少对于预训练而言,用CNN处理文本数据会受到许多限制,应用更灵活的模型处理文本数据会更合适。我们不再需要归纳偏好;我们可以在适当时候学习那个样式。

6

1个模型就能“一统天下”

事实上,GPT、GPT-2和BERT,包括最新出来的GPT-3都属于同一种Transformer模型。(编者注:GPT的全称是“Generative Pre-trained Transformer”~)

在设计Transformer模型时,你的选择是有限的。你可以堆叠一些上文描述的“字块”。你可以选择堆叠块的数目。你可以选择在每个位置表征中存储多少数据(“隐藏尺寸”)。还有许多细节,这里不再赘述。

如果你堆叠了12块,隐藏层节点数(hidden size)为768,就会得到“GPT”、“GPT-2 small”或“BERT_BASE”。

如果你堆叠了24块,隐藏层节点数为1024,则构成“GPT-2 medium”或“BERT_LARGE”。(BERT_LARGE有16个注意力头,但据笔者所知,其他模型通常只有12个注意力头。)

还有“GPT-2 large”是有36个块,隐藏层节点数为1280。而完整的GPT-2模型堆叠块数达到48,隐藏层节点数为1600。(编者注:GPT-3的隐藏层节点数为2048)

以上这些模型的设计都没有超出原始的Transformer模型,只是把堆叠块和隐藏层节点数的数值调高了!

具有挑战性的部分是如何获得大量良好的训练数据以及如何实现良好的训练目标。OpenAI将GPT-2的成功归因于它的规模和基于Reddit的特殊训练语料库。

BERT没有使用Reddit语料库进行训练,规模也只有GPT-2的一半大。但是BERT的训练目标与GPT-2不同,它不是通过分句预测下一个单词,而是从上下文中揭开单词的“面纱”。这样可以提高原始GPT进行单词预测时的准确度。(预测下一个单词的本质就是猜谜游戏:如果我们的单词完全是可预测的,那就没有再开口说话的理由了。但如果你是根据上下文填充缺失的单词,那么“猜测作者意图”的成分就少了。)

有人将BERT的训练目标与GPT-2的语料库有机结合,我很期待这会擦出什么样的火花。【注:BERT具有编码注意力机制掩蔽结构,GPT-n具有解码注意力机制掩蔽结构。在粗略的框架介绍中,编码与解码的差异很小,可能不足为道,但也有所区别。】

6.1 进一步说明

BERT最令人兴奋的是:一个已经在语料库中训练过、并已具备丰富的语言知识的BERT模型,可以给你解决手上所有特殊的NLP任务。Attention is all you need.

你所要做的就是,把BERT模型中的一个输出,连接到你感兴趣的目标上,然后进行反向传播。反向传播不需要太多,因为Transformer模型中的权重已经掌握它们需要掌握的大部分知识。你需要对数据集进行2到4次调整,学习率在2e-5和5e-5之间,批处理大小为16或32。有了大小合理的数据集之后,你就可以在一天之内利用普通GPU来尝试所有的组合情况。

这居然是一个可行的方法,真神奇。更神奇的是,完全相似的模型以其出色的写作能力镇住了我们所有人。三年前,我们还需要对许多复杂架构的超参数进行调整。现在我们有了Transformer模型,它只是形状相同的注意力块的堆叠。这就好比你从架子上取下一个Transformer模型,将其输出与目标连接起来,按下按钮,然后去吃午饭。当你吃完午饭回来的时候,你会发现,与2016届研究生精心制作的、复杂艰深的、针对特定任务的模型相比,你的模型是占据绝大优势的。

原文链接:

https://nostalgebraist.tumblr.com/post/185326092369/the-transformer-explained

0 人点赞