深度学习 NLP-Transformer and variant (TF and 魔改s)

1. 写在前面开胃菜

这一部分主要阐述,写这篇文章的动机,所以是开胃菜。

1. 所谓“魔改”

实际工业界里,很难在论文中找到 模型+数据 都直接符合需求的NLP model。如果要在某类task上开始一轮新的工作,最好在相似的任务上“魔改”操作。

2. why and how

总的来说,新的paper经过学术界同行监督,总是会有新的进步,比如:

  • 1.模型效果、提高可解释性
  • 2.加速推理、减少参数量
  • 3.更好地提取数据特征
  • 4.泛化地在领域内的任务中应用

如何去做呢?

  • 1.以史为鉴:关注task发展史,看前辈如何踩坑避障
  • 2.关注SOTA:了解最新的架构设计和应用
  • 3.总结:听专家总结,梳理自己的知识体系

3. 正文预告

15-16年,RNN架构非常火爆。直到现在,我个人首选的sequence tagging任务model依然是bi-lstm+crf。无他,效果稳定,模型简单。
然而,尽管后续LSTM、GRU、SRU都算作是RNN的衍生物,但统统都不能解决推理时间过长的问题(上线的痛,懂的自然懂!)。因为语言模型处理输入:序列,天然的要求前后依赖。输入就是那么长,每个time step会顺序地做计算,并行化:“不存在的”!

RNN架构先天不足:难以并行化处理序列输入,因为后一个time step总是依赖于前一个time step的输出作为输入

而Transformer,本身在架构设计上就是奔着并行化的目标去的。如果读者了解过CNN中卷积、池化的概念,应该就可以顺畅理解:尽管二维数据比一维序列更加复杂,但在感受野并行处理的情况下,完美利用GPU,速度飞快。

深度学习 NLP-Transformer and variant (TF and 魔改s)_第1张图片
(扯远了,为什么Transformer处理序列数据也够快,会重新开新文章说的~)

“天下苦Transformer久矣”(这是万能必备句式,划重点)!

今天这篇文章,会总结式的记录几个基于Transformer魔改的新架构,全是“当前浪”献上的满满厚爱!

2. 正文主食

1. 速览Transformer

what’s Transformer?

一言以蔽之:seq2seq model with self-attention

深度学习 NLP-Transformer and variant (TF and 魔改s)_第2张图片
Transformer的核心在最右侧的两张图中,分别是被框起来的 encoder和decoder部分。

从左向右、从下向上的看:

1. encoder

  • 1.首先实际序列中的每个 c h a r i char_i chari,通过一个固定size的映射矩阵,转换为某个固定维度的embedding向量 x i x_i xi

  • 2.向量 x i x_i xi经过一个矩阵变化得到 a i = W x i a_i=Wx_i ai=Wxi,而 a i a_i ai再加上每个 c h a r i char_i chari的位置向量 e i e_i ei就可以得到对encoder不断循环部分的输入了

  • 3.红色的self-attention网络:
    深度学习 NLP-Transformer and variant (TF and 魔改s)_第3张图片

  • 通过 [ q i k i v i ] − 1 = [ W q W k W v ] − 1 ( a i + e i ) [q_i k_i v_i]^{-1} = [W_q W_k W_v]^{-1}(a_i + e_i) [qikivi]1=[WqWkWv]1(ai+ei)的运算将输入序列中的每个 c h a r i char_i chari,转换为三种描述,分别是: q u e r y i , k e y i , v a l u e i query_i,key_i,value_i queryi,keyi,valuei

  • 通过每两个位置的char间的query和key两两比较,度量出一个相关程度 α 1 , j \alpha_{1,j} α1,j,然后 通过softmax得到 α ^ 1 , j \hat \alpha_{1,j} α^1,j。即从全局视野考察,最后确定输出其他位置的输入和1号位的相关程度。

  • 最后以 α ^ 1 , j \hat \alpha_{1,j} α^1,j为权重,将对应位置的 v a l u e i value_i valuei做weighted sum,就可以得到self-attention的输出 b i b_i bi,类似的所有位置都经过上述过程。

  • 4.add: 普通的add; Norm: layer Norm,而不是batch Norm

  • 5.蓝色的 前馈神经网络:Fully connected network

2. decoder

而decoder,又多增加了一个 交叉注意力机制(右下角masked multi-head self-attention的输出中,最终只有Q接到了上层)

  • 而mask则是在文本向量化过程中,由于文本长度小于Fix_length的Padding部分,在Padding部分对应index的score设为-inf。最后的效果就是使得经过softmax之后,Padding部分给予的attention权重为近似0
  • 这种类似的操作在Decoder部分也使用了,目的是为了Decoder只关注早于当前输出位置的部分。

2. Sandwich Transformers

1. 动机

可能单纯为了想得到一个效果更好的transformer。self-attention特征提取能力比较强,而网络偏底层的部分,恰好是特征较为集中的地方。所以,“不如多叠几层self-attention试试看?”。

2. 做法

“reorder” the sub-layer module,调整self-attention和fully connected层的顺序。
可以看到s层:self-attention层向左靠拢,聚集在一起了;与之对应f层:fully connected layer靠右聚集;中间部分则不变化。

深度学习 NLP-Transformer and variant (TF and 魔改s)_第4张图片

3. 实验

深度学习 NLP-Transformer and variant (TF and 魔改s)_第5张图片

4. 结论

深度学习 NLP-Transformer and variant (TF and 魔改s)_第6张图片

  • 不需要更多参数、内存;简单底层多叠的self-attention,中间正常结构,top多叠fully connected layer,此时表现会比baseline要好。

3. Universal Transformer

1.动机

Transformer在翻译、句法分析上表现很好;而一旦测试序列长于训练数据,因为没见过相对应position embedding 就没有办法了。而且从理论上说transformer不是图灵完备的,不能做重复某些字符串之类的工作(很难理解)。
所以universal transformer想要改进其表现,使用新颖高效的时间并行循环方式将标准 Transformer 扩展为计算通用(图灵完备)模型,从而可在更广泛的任务中产生更强的结果。

2.做法

深度学习 NLP-Transformer and variant (TF and 魔改s)_第7张图片

  • universal transformer将模型建立在 Transformer 的并行结构上,以保持其快速的训练速度。
  • 使用用单一的时间并行循环的变换函的多次应用代替了 Transformer 中不同变换函数的固定堆叠(即,相同的学习转换函数在多个处理步骤中被并行应用于所有符号,其中每个time step的输出馈入到下一个time step中)。
  • 关键在于,RNN 逐个符号(从左到右)处理序列,而 Universal Transformer 同时处理所有符号(像 Transformer 一样),随后使用self-attention机制在可变数量的情况下并行地对每个符号的解释进行细化。 这种时间并行循环机制比 RNN 中使用的顺序循环更快,也使得 Universal Transformer 比标准前馈 Transformer 更强大。

3. 大白话

  • transformer的self-attention如果叠六层,虽然每一层结构一致,但是其实权重是不一样的。而universal transformer则是借助RNN的时间权重共享思路,让同一个网络重复的在纵向时间轴上计算多次。
  • Universal Transformer 不像 RNN 那样,每次输入一个字符的embedding来进行时间循环,而是并行地使用多个self-attention 循环重复地修改句子中每一个符号的embedding表示。
  • 而且Universal Transformer使用自适应计算时间机制(adaptive computation time,ACT),使模型动态调整句子中每个位置的embedding表示在时间上迭代的次数。到达迭代次数后,下一轮直接进行复制即可。

4. 用图说话

  • 下图中的postion代表了输入句子中的每个字,而每个字向量都纵向的向上输入到 所有的self-attention中,即每个self-attention仍然会获取到全局视野。
  • 而每个self-attention中 不同位置会经过多少个time step是由ACT决定的,即多个time-step后有的self-attention网络权重可能就不会再更新了,会保持不变。
    深度学习 NLP-Transformer and variant (TF and 魔改s)_第8张图片

4. Residual Shuffle Exchange Network

1. 结论

在这里插入图片描述

  • 参数少
  • 速度快
  • 用exchange、shuffle来取代self-attention,获取到远处的信息

2. 做法

深度学习 NLP-Transformer and variant (TF and 魔改s)_第9张图片

  1. 如何shuffle?
  • perfect shuffle:就好像洗牌,每两层switch unit就会把把输入的数据,从中间拆成两份(a1a2a3,b1b2b3),然后像洗牌一样再叠成新的序列(a1b1a2b2a3b3)。

深度学习 NLP-Transformer and variant (TF and 魔改s)_第10张图片
2. detail of Switch Unit
深度学习 NLP-Transformer and variant (TF and 魔改s)_第11张图片
输入的两个元素,如图分别进入上下两条通路:

  • 上面的通路,做的是一些非线性转换

而u则像是一个forget gate,决定:1. 非线性变换信息 2. 交换过的信息有,分别有多少会被传递至下一组unit中

  • 下面的通路,做一个 swapHalf ,看起来就像是“洗牌”

( [ a b ] , [ c d ] ) = [ [ a d ] , [ c b ] ] \left(\left[\begin{array}{l} a \\ b \end{array}\right],\left[\begin{array}{l} c \\ d \end{array}\right]\right)=\left[\left[\begin{array}{l} a \\ d \end{array}\right],\left[\begin{array}{l} c \\ b \end{array}\right]\right] ([ab],[cd])=[[ad],[cb]]

  1. butterfly network
    深度学习 NLP-Transformer and variant (TF and 魔改s)_第12张图片
    实际中使用的是右图,即对称的butterfly network

  2. 新文章的改进结构

简化了switch unit的计算。
深度学习 NLP-Transformer and variant (TF and 魔改s)_第13张图片

  1. 小的缺点
    深度学习 NLP-Transformer and variant (TF and 魔改s)_第14张图片
    如果输入8个字,那么只需要 l o g 2 8 = 3 log_2{8}=3 log28=3层就可以 完成完全的位置交换。那整个结构就只需要 n l o g n nlogn nlogn就可以完全模拟self-attention结果了。
    然而缺点是 序列长度必须要向上对齐到 2 n 2^n 2n

3. 参数量对比

  • 跟所需要的参数量相比,他的性能已经很好
  • 在同样的GPU Memory下,可以处理更长的序列;相同长度序列下,需要的时间却更短
    深度学习 NLP-Transformer and variant (TF and 魔改s)_第15张图片

深度学习 NLP-Transformer and variant (TF and 魔改s)_第16张图片

5. Bert

BERT: bidirectional encoder representations from transformers
深度学习 NLP-Transformer and variant (TF and 魔改s)_第17张图片
从全称中就已经可以明确得到指示:bert 就是把transformer中的decoder部分拿出来,通过预训练得到一组真正有效的embedding表示。

深度学习 NLP-Transformer and variant (TF and 魔改s)_第18张图片

1. masked LM

  • 让bert做完形填空
    mask掉一些字符,根据对应位置的字向量输出,后接简单线性多分类器进行预测。

  • 因为分类器能力很弱,所以要分类正确,那么字向量要足够的好
    深度学习 NLP-Transformer and variant (TF and 魔改s)_第19张图片

2. NSP:next sentence predication

预测两个句子是否有上下文的关系

  • nsp训练一个分类器:预测两个句子是否应该接在一起

bert 的内部是transformer——“天涯若比邻”,所以cls安置在句子的开头还是结尾完全是没有差别的

深度学习 NLP-Transformer and variant (TF and 魔改s)_第20张图片

6. ALBERT

1. 动机

降低参数消耗

2. 做法

  • bert vs albert: “a light bert”
  • 简化版bert: 每一层的weight都是share同一组参数的
    深度学习 NLP-Transformer and variant (TF and 魔改s)_第21张图片
  1. reduce embedding矩阵
    使用(id, embedding)维度的矩阵,来编码每一个字。实际输入某个字时,网络使用id查询对应的embedding。而这里可以通过矩阵乘法,“时间换空间” 的将embedding的维度降低。
    深度学习 NLP-Transformer and variant (TF and 魔改s)_第22张图片
  2. 多层self-attention layer共享参数
    深度学习 NLP-Transformer and variant (TF and 魔改s)_第23张图片
    参考albert的网络结构和参数信息,看到确认到因为albert是多层参数共享的,所以参数量不会随着层数增加而变化,只随着hidden size改变而变化。

3. pretrain

ALBERT:预训练的task在NSP中有所差异

  • 如果AB是合法的句子顺序,那么BA则作为反例输入训练集。
    深度学习 NLP-Transformer and variant (TF and 魔改s)_第24张图片
  • BERT的NSP任务实际上是一个二分类,训练数据的正样本是通过采样同一个文档中的两个连续的句子,而负样本是通过采用两个不同的文档的句子。

NSP(Next Sentence Prediction):下一句预测, 正样本=上下相邻的2个句子,负样本=随机2个句子

  • 在ALBERT中,为了只保留一致性任务去除主题识别的影响,提出了一个新的任务 sentence-order prediction(SOP)。

SOP (Sentence ):句子顺序预测,正样本=正常顺序的2个相邻句子,负样本=调换顺序的2个相邻句子

对于NLI自然语言推理任务。研究发现NSP任务效果并不好,主要原因是因为其任务过于简单。

NSP其实包含了两个子任务,主题预测与关系一致性预测,但是主题预测相比于关系一致性预测简单太多了。

因为只要模型发现两个句子的主题不一样就行了,而SOP预测任务能够让模型学习到更多的信息。SOP因为是在同一个文档中选的,其只关注句子的顺序并没有主题方面的影响。

7. Reformer

1. multi-head

google对attention机制的完善。就是把Q,K,V通过参数矩阵映射一下,然后再做Attention,把这个过程重复做h次,结果拼接起来就行了,可谓“大道至简”。PS:这个应该在transfomer里讲的,忘记了。
深度学习 NLP-Transformer and variant (TF and 魔改s)_第25张图片
深度学习 NLP-Transformer and variant (TF and 魔改s)_第26张图片

2. 改进

  • 可逆神经网络,将只需要存储一层的激活结果即可,N的因素消失了。
  • 分块计算前馈全连接层,节省内存。
  • 采用局部敏感哈希技术,近似计算注意力,将时空开销从O(L2)变为O(L)。

1. Locality Sensitive Hashing Attention

reformer 针对长输入序列做改进:LSH attention

因为self-attention内部QKV运算的空间复杂度是 n 2 n^2 n2,attention score的结果矩阵会迅速增大,但是其实并非所有的score都是重要的。

一个 query 和其他的所有的token的计算 attention score主要是取决于高相似度的几个tokens之间,那么就针对这里做改进。

两个新概念:

  1. Shared-QK Transformer

在标准Transformer中,Q,K,V是由激活结果A分别通过三个线性层映射得到。
  但是这里引入了LSH attention,我们需要Q和K是相同的(备注:其实这里让Q和K相同并不是LSH必须,LSH只需要让Q、K变成单位向量即可,因为要在单位球面上进行相似查找,本文让Q和K一样只是为了方便批处理,加速计算),让Q和K通过相同的线性映射即可实现该目的。
  我们称这样的模型为shared-QK Transformer,实验结果表明共享Q、K并没有影响Transformer的表现效果。

  1. LSH attention

正如上面介绍的,我们每一次只计算一个qi和K的结果,但是我们需要和K中的每一个元素都计算吗?其实不是,我们只需要关心与qi相近的keys即可,K中的每一个元素从宏观上理解就是一个word。假设K的长度为64K,也就是有64K个tokens,我们只需要考虑其中的32或者64个最近的keys,那效率将大大提升。如何得到这最近的keys呢?利用Locality sensitive hashing就可以实现,它的基本思路就是距离相近的向量能够很大概率hash到一个桶内,而相距较远的向量hash到一个桶内的概率极低。

深度学习 NLP-Transformer and variant (TF and 魔改s)_第27张图片
使用hash函数的分桶策略,要求attend之后靠近在一起的几个query-key score分在一个bucket中,然后在bucket内部进行self-attention。

  1. hash function:

h ( x ) = argmax ⁡ [ x R ; − x R ] h(x)=\operatorname{argmax}[x R ;-x R] h(x)=argmax[xR;xR]

其中:x是 d k d_k dk维度的query or key,R是 [ d k , b 2 ] \left[d_{k}, \frac{b}{2}\right] [dk,2b]大小的变换矩阵,而b是目标bucket的数量。

  1. 说明

右边图中,黑点代表在self-attention后softmax中占主导地位的score

  • a:属于普通encoder的图,因为decoder中 q 3 q_3 q3不能向前attend到 k 6 k_6 k6上去;而且可以明显看到黑点分布很稀疏,集中在几组token之间
  • b:将key-query hash到相同bucket后,对输入先bucket排序,同个bucket内按照token 的 position排序
  • c:b中蓝色、绿色区域 key-query的分布不均衡。为了减小bucket中q和k不均衡的问题,文章提出了保证通过令 k j = q j ∣ q j ∣ k_{j}=\frac{q_{j}}{\left|q_{j}\right|} kj=qjqj从而使得 h ( k j ) = h ( q j ) h\left(k_{j}\right)=h\left(q_{j}\right) h(kj)=h(qj) , 即使用了share-QK attention,得到图c。因为Q=K,此时就能保证对角线都是attend to的,而且q和k在bucket中的个数一样。同时因为同一个bucket中保证相似,所以同一个bucket都用小黑点高亮了。
- 我们注意到对角线的点为空心,这是因为我们虽然在正常实现上,我们的q会attend to本身位置的value.
- 但是在share-QK的实现下,如果attend to本身,会导致其值特别大,其他的值特别小,经过softmax之后,其他都是0,就自己本身是1。
- 所以为了避免这种情况,我们q不会去attend 自身位置的值,除非只有自己本身可以attend to(例如图3/4的 q1 )
  • d: 极端情况,不同bucket中数量分布不均衡。此时在操作c的基础上进行chunk操作:对于bucket中的每个query,都可以attend to自己以及前一个bucket 中相同hash 值的key。如左边图的最后一行所表示,但每个输入字不对自己进行attention
  1. 多轮LSH attention:

单个hash函数,总不可避免的会出现个别相近的items却被分到不同的桶里,多轮hash并行执行就可以避免。

  1. 总结下,过程就是:
  • 首先我们令输入序列的queries = keys
  • 然后我们对其做LSH bucketing,得到每个query和key都在各自的bucket中(不同颜色表示)
  • 我们跟根据bucket对query进行排序,同个bucket中,按照query原本的position进行排序。
  • 在之后我们对于每个排序后的新序列,进行chunk 拆分
  • 最后我们对于每个query只管制自己以及自己之前的chunk,对于这些候选集中相同bucket的key进行attend

假设输入字是1024维度,现在每个bucket size变成32,复杂度由n方变为nlogn

2. Reversible Layer

出发点:做误差反传时,每一层的权重、输出都要在内存中做记录,这其实占据了很大的空间。这里reversible layer要说的是,只要记住最后一层layer的信息,来回推前面层的信息就够了。

“时间换空间”

在RevNet中,首先将输入 x x xcopy为两个部分 x 1 x_1 x1 x 2 x_2 x2然后通过不同residual functions: F ( ⋅ ) F(\cdot) F() G ( ⋅ ) G(\cdot) G()得到输出 y 1 y_1 y1 y 2 y_2 y2

y 1 = x 1 + F ( x 2 ) y 2 = x 2 + G ( y 1 ) \begin{array}{l} y_{1}=x_{1}+F\left(x_{2}\right) \\ y_{2}=x_{2}+G\left(y_{1}\right) \end{array} y1=x1+F(x2)y2=x2+G(y1)

而反向计算时:
x 2 = y 2 − G ( y 1 ) x 1 = y 1 − F ( x 2 ) \begin{array}{l} x_{2}=y_{2}-G\left(y_{1}\right) \\ x_{1}=y_{1}-F\left(x_{2}\right) \end{array} x2=y2G(y1)x1=y1F(x2)

深度学习 NLP-Transformer and variant (TF and 魔改s)_第28张图片

F是fully connected的输出,而g是Reversible layer的输出。通过如上的操作,并行的存了两份值,然后就可以相互作差、作和计算出前一层的输出。

声明:文章主体框架来自“李宏毅-深度学习”2020网络课程,文字、图片部分包含了个人理解、讲授内容和网络博客。欢迎交流,时间仓促,请联系我!

你可能感兴趣的:(深度炼丹十八式-NLP,Transformer,self-attention,bert,自然语言处理,深度学习)