自然语言处理三大特征抽取器比较

这篇文章是对放弃幻想,全面拥抱Transformer:自然语言处理三大特征抽取器(CNN/RNN/TF)比较 - 知乎的摘抄。

NLP领域内经典的特征抽取器主要有三种:

  • CNN
  • RNN
  • Transformer

其中CNN和RNN可能会逐步退出历史的舞台,而Transformer则会替代他们成为最为主流的特征抽取器。

NLP任务的特点及任务类型

NLP任务特点

NLP任务的特点

寻找解决问题的方法首先需要思考需要解决的问题是什么?有什么特点?NLP任务的特点和图像有极大的不同,上图展示举了一个例子,NLP的输入往往是一句话或者一篇文章,所以它有以下几个特点:首先,输入是个一维线性序列;齐次,单词或者子句的相对位置关系很重要,两个单词位置互换可能导致完全不同的意思;另外,句子中的长距离特征对于理解语义也非常关键,例子参考上图标红的单词,特征抽取器能否具备长距离特征捕获能力这一点对于解决NLP任务来说也是很关键的。

上面几个特点请记清,一个特征抽取器是否适配问题领域的特点,有时候决定了它的成败,而很多模型改进的方向,其实就是改造得使它更匹配领域问题的特性。这也是为何在介绍RNN,CNN,Transformer等特征抽取器之前,先说明这些内容的原因。

NLP任务的分类

NLP是个很宽泛的领域,包含了几十个子领域,理论上只要跟语言处理相关,都可以纳入这个范围。但是如果对大量NLP任务进行抽象的话,会发现绝大多数NLP任务可以归结为几大类任务。两个看似差异很大的任务,在解决任务的模型角度,可能完全是一样的

NLP的四大类任务

通常而言,绝大部分NLP问题都可以归入上图所示的四类任务中:第一类是序列标注,这是最典型的NLP任务,比如中文分词,词性标注,命名实体识别,语义角色标注等都可以归入这一类问题,它的特点是句子中每个单词要求模型根据上下文都要给出一个分类类别。第二类是分类任务,包括文本分类和情感计算等。它的特点是不管文章有多长,总体给出一个分类类别即可。第三类任务是句子关系判断,比如Entailment、QA、语义改写,自然语言推理等任务都是这个模式,它的特点是给定两个句子,模型判断出两个句子是否具备某种语义关系;第四类生成式任务,比如机器翻译、文本摘要、写诗造句,看图说话等都属于这一类。它的特点是输入文本内容后,需要自主生成另外一段文字。

解决这些不同的任务,从模型角度讲最重要的是特征抽取器的能力。尤其是深度学习流行开来后,这一点更凸显出来。因为深度学习最大的优点是“端到端(end to end)”,意思是以前的研究人员得考虑设计抽取哪些特征,而端到端时代后,这些你完全不用管,把原始输入扔给好的特征抽取器,它自己会把有用的特征抽取出来。

算法工程师现在需要做的事情是:选择一个好的特征抽取器,输入大量的训练数据,设定好优化目标(loss function)来告诉它你想让它干嘛,然后花费大量的时间进行调参。其中可能最有意义的事情就是设计一个好的特征抽取器了。

下面分别介绍三种特征抽取器。

RNN

RNN

RNN的模型结构参考上图,核心是每个输入对应隐层节点,而隐层节点之间形成了线性序列,信息由前向后在隐层之间逐步向后传递。

RNN为何能够成为解决NLP问题的主流特征抽取器

RNN自从引入NLP界后,很快就成为最为闪耀的明星模型,在NLP各种任务中被广泛使用。但是原始的RNN同样存在着问题,它采取线性序列结构不断从前往后收集输入信息,但这种线性序列结构在反向传播的时候存在优化困难的问题,获得了很好的效果,于是很快LSTM和GRU成为RNN的标准模型。其实图像领域最早由 HighwayNet/Resnet 等导致模型革命的 skip connection 的原始思路就是从 LSTM 的隐层传递机制借鉴来的。经过不断优化,后来NLP又从图像领域借鉴并引入了 attention 机制(从这两个过程可以看到不同领域的技术相互借鉴与促进作用),叠加网络把层深作深,以及引入 Encoder-Decoder 框架,这些技术进展极大扩展了RNN的能力以及应用效果。下图展示的模型就是非常典型的使用RNN来解决NLP任务的通用框架技术大礼包,在更新的技术出现前,你可以在NLP各种领域见到这个技术大礼包的身影。

典型RNN技术大礼包

上述内容简单介绍了RNN在NLP领域的大致技术演进过程。那么为什么RNN能够这么快在NLP领域流行并且占据了主导地位呢?主要原因还是因为RNN的结构天然适配解决NLP的问题,NLP的输入往往是个不定长的线性序列句子,而RNN本身结构就是个可以接纳不定长输入的由前往后进行信息线性传导的网络结构,而且在LSTM引入三个门后,对于捕获长距离特征也是非常有效的。所以RNN特别适合NLP这种线性序列应用场景,这也是RNN为何在NLP界如此流行的根本原因。

RNN在新时代面临的两个严重问题

RNN在NLP领域一直流行了很多年(2014~2018),在2018年之前,大部分各个子领域的 State of Art 的结果都是通过RNN获得的,但如今RNN的地位正在被动摇。

主要两个原因:
第一个原因是一些后起之秀模型的崛起,比如经过特殊改造的CNN模型,以及Transformer。这些后起之秀尤其是 Transformer 的应用效果相比RNN来说具有明显的优势。
另一个原因是:RNN本身的序列依赖结构对于大规模并行计算来说相当之不友好。通俗点来说,就是RNN很难具备高效的并行计算能力,乍一看好像不是太大的问题,其实问题很严重。如果仅仅满足于通过改RNN发一篇论文的话,那这确实不是大问题,但是如果工业界进行技术选型时,在有快得多的模型可用的前提下,是不太可能选择RNN的。

那么问题来了:为什么RNN并行计算能力比较差?是什么原因造成的?解释RNN并行计算能力差

RNN之所以是RNN,能将其和其他模型区分开的最典型标志是:$T$时刻隐层状态的计算,依赖两个输入,一个是T时刻的句子输入单词$Xt$,这个并不算特点,所有模型都要接收这个原始输入;关键的是另外一个输入,$T$时刻的隐层状态$St$还依赖$T-1$时刻的隐层状态$S(t-1)$的输出类似于计组中的串行进位加法器),这是最能体现RNN本质特征的一点,RNN的历史信息是通过这个信息传输渠道往后传输的,参考上图。RNN的并行计算能力不行的问题就出在这里。因为$T$时刻的计算依赖$T-1$时刻的隐层计算结果,而$T-1$时刻的计算依赖$T-2$时刻的隐层计算结果以此类推,这就形成了所谓的序列依赖关系。用更为通俗的话说就是只能先把前一步的结果计算出来,才能计算下一步的结果,这就造成了RNN在这个角度上是无法并行计算的,只能一步一步地来。

而CNN和Transformer就不存在这种序列依赖问题,每个时间步的操作可以并行计算(可以类比为流水线)。

如果改造RNN使其具备并行计算能力?

RNN不能计算的症结所在,在于$T$时刻对于$T-1$时刻计算结果的依赖,而这体现在隐层之间的全连接网络上。既然症结在这里,那么想要解决问题,也得在这个环节下手才行。在这个环节能够做些什么来增加RNN的并行计算能力,可以想一想。

其实选项不多,有两个大的思路来改进,这两个思路是相对的:一种是仍然保留任意连续时间步($T-1$到$T$时刻)之间的隐层连接;而另一种是部分地打断连续时间步($T-1$到$T$时刻)之间的隐层连接。

先来看第一种方法,现在问题转化了:在保留任意连续时间步($T-1$到$T$时刻)之间的隐层连接的前提下要做到并行计算。需要做到这点需要摆脱序列依赖,如果是打算在不同时间步的输入之间并行可能无法做到,但是想到隐层也包含许多神经元,在这些隐层神经元之间并行计算是否可行。以下图为例进行说明。RNN并行计算的一种思路

上面的图只显示了各个时间步的隐层节点,每个时间步的隐层包含3个神经元,这是个俯视图,是从上往下看RNN的隐层节点的。另外,连接两个时间步的隐层神经元之间其实还有连接只是没有画出来而已。假设隐层神经元有3个,那么可以形成3路并行计算(红色箭头分隔开成了3路),而每一路因为仍然存在序列依赖问题,所以每一路内仍然是串行的。然而了解RNN结构的人可能还会存在这样一个疑问:隐层神经元之间的连接是全连接,就是说T时刻某个隐层神经元与$T-1$时刻所有隐层神经元都有连接,如果这样是无法做到在神经元之间并行计算的。其实解决这个问题很简单,就是对$T$时刻和$T-1$时刻的隐层神经元之间的连接关系进行改造,从之前的全连接改造成对应位置的神经元(就是上图被红箭头分隔到同一行的神经元之间)有链接,和其它神经元没有连接。这样就可以解决这个问题,在不同路的隐层神经元之间可以并行计算了(不太清楚这种简化是否合理,是否会对原神经网络产生的结果造成影响)。

第一种改造RNN并行计算能力的方法思路大致如上文所述,这种方法的代表就是论文”Simple Recurrent Units for Highly Parallelizable Recurrence”中提出的SRU方法,它最本质的改进是把隐层之间的神经云依赖由全连接改成了哈达马乘积,这样$T$隐层单元本来对$T-1$时刻所有隐层单元的依赖改成了只是对$T-1$对应单元的依赖(对应图中的同一行),于是可以在隐层单元之间进行并行计算,但是收集信息仍是按照时间序列进行的。所以其并行性是在隐层单元之间发生的,而不是在不同时间步之间发生的。

这其实是比较巧妙的一种方法,但是它的问题在于其并行程度上限是有限的,并行程度取决于隐层神经元个数,而一般这个数值往往不会太大,再增加并行性已经不太可能。另外每一路并行线路仍然需要序列计算,这也会拖慢整体速度。

SRU

第二种改进典型的思路是:为了能够在不同时间步输入之间进行并行计算,打断隐层之间的连接,但是又不能全打断,因为这样基本就无法捕获组合特征了,所以唯一能选的策略就是部分打断,比如每隔2个时间步打断一次,但是这样又会遇到别的问题:距离稍远的特征如何捕获?只能加深层深,通过层深来建立长特征之间的联系。代表性模型比如上图展示的 Sliced RNN。先看后面CNN部分回头再看这个模型会发现其实Sliced RNN就是简化版本的CNN。

经过这种改造的RNN速度改进如何?论文给出了速度对比实验,归纳起来,SRNN速度比GRU模型快5倍到15倍,看起来效果不错,但是跟对比模型DC-CNN模型速度比较起来,比CNN模型仍然平均慢了大约3倍。这很正常但是又有点说不太过去,说正常是因为本来这就是把RNN盖头换面成类似CNN的结构,而片段里仍然采取RNN序列模型,所以必然会拉满速度,比CNN慢再正常不过了。又说说不过去指的是:既然本质上是CNN,速度又比CNN慢,那么就没有改的意义了。事实上也是如此,此文的作者认为没有意义。

上面列举了两种大的改进RNN并行计算能力的思路,但效果都不是很好,主要是因为RNN本质特性决定了改进的选择特别少,无非是选择打断或者不打断隐层连接的问题。如果选择打断,就会面临上面的问题,会发现它可能已经不是RNN模型了,为了让它看上去还像是RNN,所以在打断片段里仍然采取RNN结构,这样无疑会拉满速度,所以这是个两难的选择,与其如此不如直接换成其他模型;如果选择不打断,似乎只能在隐层神经元之间进行并行,而这样做的缺点是:一方面并行能力上限很低;另外一方面里面依然存在的序列依赖估计仍然是个问题。至今还没有其他有效解决方法。

CNN

在一年多前,CNN是自然语言处理中除了RNN外最常见的深度学习模型。

NLP中早期的怀旧版CNN模型

早期CNN模型

最早将CNN引入NLP的是Kim在2014年做的工作,论文和网络结构参考上图。一般而言,输入的字或者词用 Word Embedding 的方式表达,这样本来一维的文本信息输入就变换成了二维的输入结构,假设输入$X$包含$n$个字符,而每个字符的 Word Embedding 的长度为$d$,那么输入就是$d \times n$的二维向量。

卷积层本质上是个特征抽取层,可以设定超参数$F$来指定卷积层包含多少个卷积核(Filter)。对于某个Filter来说,可以想象有一个$d \times k$大小的移动窗口从输入矩阵的第一个字开始不断往后移动,其中$k$是Filter指定的窗口大小,$d$是Word embedding长度。对于某个时刻的窗口,通过神经网络的非线性变换,将这个窗口内的输入值转换为某个特征值,随着窗口不断往后移动,随着窗口不断往后移动,这个Filter对应的特征值不断产生,形成了这个Filter的特征向量。这就是卷积核抽取特征的过程。卷积层内每个Filter都如此操作,就形成了不同的特征序列。Pooling 层则对Filter的特征进行了降维操作,形成最终的特征。一般在Pooling层之后连接全连接层神经网络,形成最后的分类过程。

这就是最早应用在NLP领域CNN模型的工作机制,用来解决NLP中的句子分类任务,看起来十分简洁,之后陆续出现了在此基础上的改进模型。这些怀旧版CNN模型在一些任务上也能和当时怀旧版本的RNN效果相当,所以在NLP某些子领域内也得以流行,但是在更多的其他子领域效果仍然比不上RNN。这其实是因为CNN从图像领域而来到了NLP领域没有针对新环境的特性作出针对性的改变。

CNN的进化

先看看怀旧版CNN存在哪些问题,再看看研究者是如何将CNN改造为目前看上去效果还算不错的现代版本CNN的。

CNN捕获到的是什么特征?从上述怀旧版本CNN卷积层的运行机制大概可以看出,关键在于卷积核覆盖的那个滑动窗口,CNN能捕获到的特征基本都体现在这个滑动窗口里了。它所捕获到的是单词的k-gram片段信息,这些k-gram片段就是CNN捕获到的特征,k的大小决定了能够捕获多远距离的特征。单卷积层无法捕获远距离特征
回头看看Kim版CNN的第一个问题:它只有一个卷积层,似乎深度不够。然而为什么要把CNN作深呢?其实作深是手段,不是目的。只有一个卷积层带来的问题是:对于长特征,单层CNN是无法捕获到的,如果滑动窗口k最大为2,而如果有个长距离特征距离是5,那么上多少个卷积核,都无法覆盖到长度为5的距离的输入,所以它是无法捕获长距离特征的。Dilated CNN捕获远距离特征

有两种典型的改进方法:一种是假设仍使用单个卷积层,滑动窗口大小k假设为3,就是只接受三个输入单词,但是想要捕获距离为5的特征。显然,如果卷积核窗口覆盖连续区域是无法完成任务的,这时想到可以跳着覆盖。这就是 Dilated 卷积的基本思想。

加深CNN网络来捕获远距离特征

另一种方法是把深度做起来。第一层卷积层,假设滑动窗口大小k为3,如果再往上叠一层卷积层,假设滑动窗口大小也是3,但是第二层窗口覆盖的是第一层窗口的输出特征,所以它其实能覆盖输入的距离达到了5。如果继续往上叠加卷积层,可以继续增大卷积核输入的长度。

上面是两种典型的解决CNN长特征捕获能力的方案,Dilated CNN 偏技巧一些,而且叠加卷积层时超参如何设置有些学问,因为连续跳接可能会错过一些特征组合,所以需要精心调节参数搭配,保证所有可能组合都被覆盖到。相对而言,把CNN作深是主流发展方法。然而事实证明,无论怎么做CNN做NLP问题就是做不深,做到2到3层卷积层就做不上去了,网络更深对任务效果没什么帮助。目前来看,还是深层网络参数优化手段不足导致的这个问题,而不是层深没有用。后来Resnet等图像领域的新技术出现后,很自然地,人们会考虑把 Skip Connection 及各种 Norm 等参数优化技术引入,这才能慢慢把CNN的网络深度做起来。

Kim版本CNN还有一个问题就是Max Pooling层,这块其实和CNN能否保持输入句子中单词的位置信息有关。思考一个问题:RNN是因为线性序列结构,梭子很自然地它会把位置信息编码进去;那么,CNN是否能够保留原始输入的相对位置信息呢?对于NLP问题,位置信息十分有用。其实CNN的卷积核是能保留特征之间的相对位置的,道理很简单,滑动串口从左到右滑动,捕获到的特征也是如此循序排列,所以它在结构上已经记录了相对位置信息了。但是如果卷积层后面立即街上 Pooling 层的话,Max Pooling 的操作逻辑是:从一个卷积核获得的特征向量里直选中并保留最强的那一个特征,所以到了Pooling层,位置信息就被扔掉了,这在NLP里其实是有信息损失的。所以在NLP领域里,目前CNN的一个发展趋势是抛弃 Pooling 层,靠全卷积层来叠加网络深度,这背后是有原因的(图像领域也是这个趋势)。

目前NLP界主流的CNN

上图展示了在NLP领域主流CNN的主体结构,通常由1-D卷积层来叠加深度,使用 Skip Connection 来辅助优化,也可以引入 Dilated CNN 等手段。比如 ConvS2S主体就是上图所示结构,Encoder包含了15和卷积层,卷积核 kernel size = 3,覆盖输入长度为25。当然对于ConvS2S来说,卷积核里引入GLU门控非线性函数也有重要帮助,GLU貌似是NLP里CNN模型必备的构建,值得掌握。再比如TCN(论文:An Empirical Evaluation of Generic Convolutional and Recurrent Networks for sequence Modeling),集成了几项技术:利用 Dilated CNN 扩展单层卷积层的输入覆盖长度,利用全卷积层堆积层深,使用 Skip Connection 辅助优化,引入 Casual CNN 让网络结构看不到T时间步后的数据。不过TCN的实验做得有两个明显问题:一个问题是任务除了语言模型外都不是典型的NLP任务,而是合成数据任务,所以论文结论很难直接说就适合NLP领域;另外一点,它用来进行效果比较的对比方法,没有用当时效果很好的模型来对比,比较基准低。所以TCN模型效果说服力不够。

除此外,简单谈一下CNN的位置编码问题和并行计算能力问题。上文说过,CNN的卷积层其实保留了相对位置信息,只要在设计模型时不要在中间层随意插入 Pooling 层,问题就不大,不专门在输入部分对 position 进行编码也行。也可以类似ConvS2S,专门在输入部分给每个单词增加一个 position embedding,将单词的 position embedding 和词向量 embedding 叠加起来形成单词输入,这样也可以,也是常规做法。

至于CNN的并行计算能力是非常强的,这也很好理解。从单层卷积层来看,首先对于某个卷积核来说,每个滑动窗口位置之间没有依赖关系,所以完全可以并行计算;另外,不同的卷积核之间也没什么相互影响,所以也可以并行计算。因此,CNN的并行度非常高,这也是CNN的一个非常好的优点。

CNN的进化方向总结成一句话说就是:把CNN的深度做起来,随着深度的增加,很多看似无关的问题就随之解决了。

Transformer

Transformer是谷歌在17年做机器翻译任务的”Attention is all you need”的论文中提出的,引起了相当大的反向。

本文所指Transformer

这里需要说明一下,本文所说的Transformer特征抽取器并非原始论文所指。“Attention is all you need”论文中说的Transformer指的是完整的 Encoder-Decoder框架,而本文是从特征提取器角度来说,可以理解为论文中的 Encoder 部分。因为 Encoder 部分目的比较单纯,就是从原始句子中提取特征,而 Decoder 部分则功能相对较多,除了特征抽取功能外,还包含语言模型功能,以及用 attention 机制表达的翻译模型功能。所以这里请注意,避免后续理解概念产生混淆。

Transformer的Encoder部分(不是上图的一个一个的标为 ENCODE 的模块,而是红框内的整体),是由若干个相同的 Transformer Block 堆叠成的。这个 Transformer Block 其实才是 Transformer 最关键的地方,核心就在此。

针对NLP任务的特点来说下 Transformer 的对应解决方法。首先,自然语言一般是个不定长的句子,那么这个不定长问题怎么解决呢?Transformer做法跟CNN是类似的,一般设定输入的最大长度,如果句子没那么长,则用Padding填充,这样整个模型输入起码看起来是定长的了。另外,NLP句子中单词之间的相对位置是包含很多信息的,上面提过,RNN因为结构就是线性序列的,所以会将位置信息编码进模型;而CNN的卷积层其实也是保留了位置相对信息的,所以问题也不大。但是对于 Transformer 来说,为了能够保留输入句子单词之间的相对位置信息,必须要做点什么。为什么要必须做点什么?因为输入的第一层网络是 Muli-head self-attention 层,self-attention 会让当前输入单词和句子中任意单词发生关系,然后集成到一个 embedding 向量里,但是当所有信息到了 embedding 后,位置信息并没有被编码进去。所以,Transformer 不像CNN或RNN,必须明确的在输入端将 Position 信息编码,Transformer 使用位置函数来进行位置编码的,而 Bert 等模型则给每个单词一个 Position embedding,将单词 embedding 和 单词对应的 position embedding 加起来形成单词的输入 embedding,类似上文讲的 ConvS2S的做法。而关于NLP句子中长距离依赖特征的问题,self-attention 天然就能解决这个问题,因为在集成信息的时候,当前单词和句子中任意单词都发生了联系,所以一步到位就把这个事情做掉了。不像RNN需要通过隐层节点序列往后传,也不像CNN需要通过增加网络深度来捕获长特征,Transformer 在这点上明显方案是相对简单直观的。

Transformer 有两个版本:Transformer base 和 Transformer Big。两者结构其实是一样的,主要区别是包含的 Transformer Block 数量不同,Transformer base 包含12个Block叠加,而 Transformer Big 则扩张一倍,包含24个Block。无疑 Transformer Big 在网络深度,参数量以及计算量相对 Transformer base 翻倍,所以是相对重的一个模型,但是效果也更好。

三大特征抽取器比较

结合NLP领域自身的特点,上面分别介绍了 RNN / CNN / Transformer 各自的特性。从上面的介绍来看,似乎三大特征抽取器在NLP领域各有所长。

事实是否如此,通过一些实验来说明这个问题。

为了更细致和公平地对三者进行比较,可以从几个不同的角度来分别进行对比:语义特征抽取能力;长距离特征捕获能力;任务综合特征抽取能力;上面三个角度是从NLP的特征抽取器能力强弱角度来评判,另外再加入并行计算能力及运行效率,这是从是否方便大规模实用化的角度来看的。

语义特征提取能力

语义特征抽取能力对比

从语义特征提取能力来说,目前实验支持如下结论:Transformer 在这方面的能力非常显著地超过RNN和CNN(在考察语义类能力的任务WSD中,Transformer 超过RNN和CNN大约4-8个绝对百分点),RNN和CNN两者能力差不太多。

长距离特征捕获能力

长距离特征捕获能力对比

在长距离特征捕获能力方面,目前在特定的长距离特征捕获能力测试任务中(主语-谓语一致性检测,比如we…are…),实验支持如下结论:原生CNN特征抽取器在这方面极为显著地弱于RNN和Transformer,Transformer微弱优于RNN模型(尤其在主语谓语距离小于13时)能力由强到弱排序为 Transformer > RNN >> CNN;但在比较远的距离上(主语谓语距离大于13),RNN微弱优于Transformer,所以综合来看,可以认为 Transformer 和 RNN在这方面能力差不太多,而CNN则显著弱于前两者。

为什么CNN在捕获长距离特征方面这么弱?这个在前文讲述CNN的时候说过,CNN解决这个问题是靠堆积深度来获得更长的输入长度的,所以CNN在这方面的表现与卷积核能够覆盖的输入距离最大长度有关系。如果通过增大卷积核的 kernel size,同时加深网络深度,以此来增加输入的长度覆盖,实验证明这能够明显提升CNN的 long-range 特征捕获能力。但是尽管如此,CNN在这方面仍然显著弱于RNN和Transformer,因为上述主语-谓语一致性任务很重,CNN的深度肯定可以覆盖13-25这个长度,但是表现仍然很差。

对于Transformer来说,Multi-head attention 的head 数量严重影响NLP任务中Long-range特征捕获能力:结论是 head 越多越有利于捕获 long-range 特征。在上页PPT写明的论文出来之间,有个工作(论文:Tran. The Importance of Being Recurrent for Modeling Hierarchical Structure)的结论和上述结论不一致:它的结论是在”主语-谓语一致性”任务上,Transformer表现是弱于LSTM的。如果综合两篇论文,看似得到了相互矛盾的结论,那究竟事实如何呢?Why Self-attention 的论文对此进行了探索,它的结论是:这个差异是由两个论文中 Transformer 的超参设置不同导致的,尤其是 multi-head 的数量对结果影响严重,而如果正确设置一些超参,那么之前 Trans 的论文结论是不成立的。也就是说,目前仍可以维持下面结论:在长特征捕获能力方面,Transformer和RNN能力相近,而CNN在这方面显著弱于前两者。

任务综合特征抽取能力

上面两项对比是从特征抽取的两个比较重要的单项能力角度来评估的,其实更重要的是在具体任务中引入不同特征抽取器,然后比较效果差异,以此综合评定三者的综合能力。这样就引出了一个问题:NLP中的任务很多哦,哪个任务是最具有代表性的?答案是机器翻译。实际上很多NLP的重要的创新模型都是在机器翻译任务上提出来的,这背后是有道理的,因为机器翻译基本上是对NLP各项处理能力综合要求最高的任务之一,要想获得高质量的翻译结果,对于梁总语言的词法、句法、语义、上下文处理能力、长距离特征捕获等各方面都需要考虑进来才行,这是为何看到很多比较工作时在机器翻译上作出的,这里给出个背后原因的解释,以避免被质疑任务单一,没有说服力。

综合特征抽取能力对比

先给出一个机器翻译任务方面的证据,仍然是 why self-attention 论文的结论,对比实验结果数据参考上图。在两个机器翻译任务中,可以看到,翻译质量指标BLEU证明了如下结论:Transformer综合能力要明显强于RNN和CNN,RNN和CNN表现基本相当,可能CNN表现略好一些。

再给出一个证据,该证据只对比了 Transformer 和 RNN,没有CNN。

综合特征抽取能力对比2

上面是GPT论文的实验结论,在8个不同的NLP任务中,在其他条件相同的情况下,只是把特征抽取器从Transformer换成了LSTM,平均下来8个任务得分掉了5个点以上。

需要强调一点,这部分所说的RNN和CNN指的是原生的RNN和CNN模型,就是说可以在经典的结构上增加attention,堆叠层次等各种改进,但是不包含对本身结构特别大的变动。得到的结论是:从综合特征抽取能力角度衡量,Transformer显著强于RNN和CNN,而RNN和CNN的表现差不多,如果非要在这两者之间进行比较的话,CNN的表现要稍微好于RNN的效果。

并行计算能力及运算效率

关于三个特征抽取的并行计算能力,在前文分述三个模型的时候都大致提过,在此仅做个归纳,结论如下:

RNN在并行计算方面有严重缺陷,这是它本身的序列依赖特性导致的,这是把双刃剑,线性序列依赖性使得RNN非常适合解决NLP任务,但是同时也是线性依赖特性导致它本身在并行计算方面受到了限制。

而对于CNN和Transformer来说,因为它们不存在网络中间状态不同时间步输入的依赖关系,所以可以非常方便及自由地做并行计算改造。

总结一下就是,并行计算能力由高到低排序如下:Transformer和CNN差不多,都远远强于RNN。

从另外一个角度来看,先抛开并行计算能力的问题,比较一下三个模型的计算效率。人们的直观印象是Transformer比较重,比较复杂,计算效率比较低。事实到底如何呢?

计算效率对比

上图列出了单层的self-attention / RNN / CNN 的计算效率。首先需要注意,上面列出的是 self-attention,不是Transformer的Block,因为Transformer Block里其实包含了好几层,而不是单层。先说self-attention,再说Transformer Block的计算量。

从上图来看,如果是 self-attention / CNN / RNN单层比较计算量的话,三者都包含一个平方项,区别主要是:self-attention 的平方项是句子长度,因为每一个单词都需要和任意一个单词发生关系来计算 attention,所以包含一个n的平方项。而RNN和CNN的平方项则是 embedding size。既然都包含平方项,如何比较三个模型单层的计算量呢?首先容易看出CNN计算量是大于RNN的,然后self attention和其他两者如何比较呢?可以这样考虑:如果句子平均长度n大于embedding size,那么意味着 self attention 的计算量要大于RNN和CNN;而如果反过来,就是说如果 embedding size 大于句子平均长度,那么显然 RNN和CNN的计算量要大于 self attention。回归实际,一般正常的句子长度平均起来也就几十个单词,而当前常用的 embedding size 从128到512都常见,所以在大多数任务中 self attention 的计算效率是要高于RNN和CNN的。

这里解释一下为什么只考虑Transformer中的 self attention 而不是整个Transformer。因为明显单个 Transformer Block 计算量大于单层RNN和CNN,就不用再比较了。

上面考虑的是三者单层的计算量,可以看出结论是:Transformer Block > CNN > RNN。如果是考虑不同的具体模型,会与模型的网络层深有很大关系,另外还有常见的 attention 操作,问题比较复杂就不具体讨论了。

上面只是理论分析,实际中三者的计算效率到底如何?给出一些三者计算效率对比的实验结论。

论文”Convolutional Sequence to Sequence Learning”比较了ConvS2S与RNN的计算效率,证明了与RNN相比,CNN明显速度具有优势,在训练和在线推理方面,CNN比RNN快9.3倍到21倍。论文”Dissecting Contextual Word Embeddings: Architecture and Representation”提到了Transformer和CNN训练速度比双向LSTM快3到5倍。论文”The Best of Both Worlds: Combining Recent Advances in Neural Machine Translation”给出了RNN / CNN / Transformer 速度对比实验,结论是 Transformer Base 速度最快;CNN速度次之,但是比 Transformer Base 慢了将近一倍;Transformer Big 速度再次,主要因为它的参数量最大,而吊在车尾最慢的是RNN结构。

总而言之,关于三者速度对比方面,目前的主流经验结论基本如上所述:Transformer Base 最快,CNN次之,再次 Transformer Big,最慢的是RNN。RNN比前两者慢了3倍到几十倍之间。

综合排名情况

以上介绍内容是从几个不同角度来对 RNN / CNN / Transformer 进行对比,综合这几个方面的实验数据,得出的结论是:单从任务任务综合效果方面来说,Transformer明显优于CNN,CNN略微优于RNN。速度方面Transformer和CNN明显占优,RNN在这方面劣势明显。这两者综合,给出的排序结果是 Transformer > CNN > RNN

从速度和效果折衷的角度来看,对于工业界实用化应用,在特征抽取器选择方面配置 Transformer base 是个较好的选择。

三者的合流:向Transformer靠拢

虽然,Transformer 的效果相对原生的RNN和CNN来说有较大的优势,但是研究人员并没有放弃RNN和CNN而是采用一种巧妙的改造方法,可以称作”寄居蟹”策略。Transformer Block 不是只有一个构件,而是由 multi-head attention/skip connection/Layer Norm/Feed forward netword 等几个构件组成的一个小系统,因此可以考虑将RNN和CNN塞到 Transformer Block 中,这就是寄居蟹策略的基本思路。

将RNN塞到Transformer Block中

将CNN塞到Transformer Block中

塞入的方法其实很简单,参考上面两张PPT,简而言之,大的方向就是把 self attention 模块用双向RNN或者CNN替换掉,Transformer Block 的其他构件依然健在。这只是说明一个大方向,具体策略可能有些差异,但是基本思想八九不离十。这种改造方法有奇效,能够极大提升RNN和CNN的效果。

RNN整容过程及效果

上图展示了对原生RNN不断进行改造,逐步加入Transformer的各个构件后的效果。从上图的逐步改造过程可以看出,原生RNN的效果在不断稳定提升,但是与Transformer相比,性能仍有差距。

CNN整容过程及效果

类似的,上图展示了对CNN进行不断改造的过程以及其对应的效果。同样地,性能也有不同幅度的提升,但是与Transformer相比性能存在一些差距。

这说明了Transformer之所以效果能够这么好,不仅仅是multi-head attention在发生作用,而是几乎所有构件都在共同发挥作用,是一个小小的系统工程。

从上面结果来看,改造后的CNN仍与Transformer性能有些差距,是否真的能够完全达到Transformer的性能呢?Lightweight convolution和Dynamic convolution给人们带来了曙光,在论文”Pay Less Attention With Lightweight and Dynamic Convolutions”里提出了上面两种方法,效果方面基本能够和Transformer真身相当,就是用Lightweight convolution和Dynamic convolutions替换掉Transformer中的Multi-head attention模块,其它构件复用了Transformer的东西,和原生CNN的最主要区别在于采用了Depth-wise separable CNN以及softmax-normalization等优化的CNN模型。

这也说明了RNN和CNN寄生到Transformer Block里的思路是没问题的(似乎是唯一出路),但是要想效果足够好,需要一些新型的RNN和CNN,以此来配合Transformer的其他构件,共同发挥作用。然而RNN并行计算能力差的这个天生缺陷,使得它即使塞到Transformer Block里仍然会整体拖慢Transformer的运行效率,所以猜测RNN这条路也走不通。

总结

进退维谷的RNN

为什么说RNN进退维谷?有几个原因。

首先,如果靠原生的RNN(包括LSTM,GRU以及引入Attention以及堆叠层次等改进方法),目前很多实验已经证明效果比起Transformer有较大差距,现在看来基本没有迎头赶上的可能,所以原生的RNN从效果来讲处于明显劣势。

其次,原生的RNN还有一个致命的问题:并行计算能力受限制太严重。想要大规模实用化应用目前看来希望渺茫。决定了RNN本身的根本特质是:T时刻隐层节点对前向输入及中间计算结果的序列依赖,因为它要线性序列手机前面的信息,这是RNN之所以是RNN的最主要特点。正是这个根本特质,使得RNN的并行计算能力想要获得根本解决解决基本陷入了一个两难的境地:要么仍然保持RNN序列依赖的根本特性,那么其并行能力基本无法有力发挥; 要么改变序列依赖关系,那么它就不能被称为RNN了。

一息尚存的CNN

CNN在14年左右刚出现时,跟RNN相比表现不算讨好,但使用发展的眼光看,未来的处境反过来比RNN还要好一些。造成这种奇怪的现象主要有两个原因:一个是因为CNN天生自带的高并行计算能力,这对于延长它的生命力发挥了很大的作用,这就决定了与Transformer相比并不存在无法克服的困难,所以仍然有希望;另一个原因是,早期的CNN做不好NLP的一个很大原因是网络深度做不起来,随着不断借鉴图像处理的的新型CNN模型的构造经验,以及一些深度网络的优化trick,CNN在NLP领域的深度深度逐步能做起来了。既然深度能做起来了,那么本来CNN做NLP天然的一个缺陷:无法有效捕获长距离特征的问题就得到了极大的缓解。目前看来靠堆深度或者结合Dilated CNN来一定程度上解决这个问题,虽然还不够好,但仍是那句话,希望尚在。

虽然希望尚在,但是目前也有很多实验证明了原生的CNN在很多方面仍然是比不过Transformer的,典型的还是长距离特征捕获能力方面,原生的CNN版本模型仍然极为显著地弱于RNN和Transformer,而这点在NLP界算是比较严重的缺陷。

之所以说CNN一息尚存,是因为将CNN塞入Transformer这个方案,对于篇章级别的NLP任务来说,跟采取self attention作为发动机的Transformer方案对比来说,是具有极大优势的领域,也是适合它的战场,这么说的原因下面会介绍。

稳操胜券的Transformer

之前已经说了,RNN和CNN的希望都是寄生在Transformer Block里,那么谁强谁弱就不用多说了吧。

Transformer作为一个新模型,并不是完美无缺的。它也有明显的缺点:首先,对于长输入的任务,典型的比如篇章级别的任务(例如文本摘要),因为任务的输入太长,Transformer会有巨大的计算复杂度,导致速度会急剧变慢。所以估计短期内这些领域仍是RNN或者长成Transformer模样的CNN的天下(其实目前他俩这块做的也不好),也是目前两者的希望所在,尤其是CNN模型,希望更大。除了这个缺点,Transformer整体结构确实显得复杂了一些,如何更深刻认识它的作用机理,然后进一步简化它,这也是一个好的探索方向。还有上面在做语义特征抽取能力比较时,结论是对于距离远与13的长距离特征,Transformer心梗性能弱于RNN,这一点有点出乎意料,因为Transformer通过self attention使得长特征直接发生关系,按理说距离不应该成为它的问题,但是效果仍然比如RNN,这背后的原因是什么?这仍是很有价值的一个探索点。