《深度学习进阶:自然语言处理》第8章 Attention

《深度学习进阶:自然语言处理》啃书系列

  第2章 自然语言和单词的分布式表示
  第3章 word2vec
  第4章 word2vec的高速化
  第5章 RNN
  第6章 Gated RNN
  第7章 基于RNN生成文本
  第8章 Attention

《深度学习进阶:自然语言处理》第8章 Attention

  • 第8章 Attention
    • 8.1 Attention的结构
      • 8.1.1 seq2seq存在的问题
      • 8.1.2 编码器的改进
      • 8.1.3 解码器的改进①
      • 8.1.4 解码器的改进②
      • 8.1.5 解码器的改进③
    • 8.2 带Attention的seq2seq的实现
    • 8.3 Attention的评价
    • 8.4 关于Attention的其他话题
      • 8.4.1 双向RNN
      • 8.4.2 Attention层的使用方法
      • 8.4.3 seq2seq的深层化和skip connection
    • 8.5 Attention的应用
      • 8.5.1 GNMT
      • 8.5.2 Transformer
      • 8.5.3 NTM

第8章 Attention

上一章介绍了使用LSTM的seq2seq,但是这个结构存在一定的弊端:它将整个输入序列压缩成一个固定长度的隐藏状态向量,这个上下文向量包含了整个输入序列的信息,但是它的表示能力有限,意味着这种模型可能无法有效地处理长序列或复杂的语言结构。所以上一章也针对性地使用了“偷窥”的方法,将隐藏状态输入给解码器的每个时刻。这种做法是有效的,但效果有限。

为了克服这些限制,attention机制应运而生。attention机制允许模型在生成每个输出时,仅关注输入序列中与该输出相关的那些部分。这使得模型能够更好地处理长序列和复杂语言结构,并且能够自适应地处理输入序列中的变化。在attention机制下,每个输出都与输入序列的不同部分相关,因此模型可以在每个时间步上选择性地关注不同的输入信息。现在的seq2seq模型都采用了attention机制来提高其性能。

8.1 Attention的结构

注意力机制(attention mechanism,简称Attention)。基于Attention机制,seq2seq可以像我们人类一样,将“注意力”集中在必要的信息上。

8.1.1 seq2seq存在的问题

seq2seq中使用编码器对时序数据进行编码,然后将编码信息传递给解码器。此时,编码器的输出 h h h是固定长度的向量。实际上,这个“固定长度”存在很大问题。因为固定长度的向量意味着,无论输入语句的长度如何(无论多长),都会被转换为长度相同的向量。
在这里插入图片描述

图7-9

无论多长的文本,当前的编码器都会强行把信息转换为固定长度的向量,这样做早晚会遇到瓶颈。

8.1.2 编码器的改进

编码器将输入信息处理成隐藏状态向量 h h h,每个时刻都有对应的隐藏状态,可以拼接形成隐藏状态矩阵 h s hs hs,隐藏向量的个数与输入个数相同。如果我们将整个隐藏状态矩阵作为编码器的输出,这样就摆脱了编码器输出“只是一个固定长度的向量”的约束。

《深度学习进阶:自然语言处理》第8章 Attention_第1张图片

图8-2

上图结构可以抽象成下图,让我们关注编码器的输入和输出的对应关系。
《深度学习进阶:自然语言处理》第8章 Attention_第2张图片

图8-3

各个时刻的隐藏状态中包含了大量当前时刻的输入单词的信息。输入“猫”时的LSTM层的输出(隐藏状态)受此时输入的单词“猫”的影响最大。因此,可以认为这个隐藏状态向量蕴含许多“猫的成分”。按照这样的理解,编码器输出的 hs 矩阵就可以视为各个单词对应的向量集合。

因为编码器是从左向右处理的,所以严格来说,刚才的“猫”向量中含有“吾輩”“は”“猫”这3个单词的信息。考虑整体的平衡性,最好均衡地含有单词“猫”周围的信息。在这种情况下,从两个方向处理时序数据的双向RNN(或者双向LSTM)比较有效。

8.1.3 解码器的改进①

上一章的解码器只用了编码器的LSTM层的最后的隐藏状态。如果使用 h s hs hs,则只提取最后一行,再将其传递给解码器。下面我们改进解码器,以便能够使用全部 h s hs hs

上一章提到的“偷窥”技巧是将隐藏状态的最后一行输入给编码器的每个时刻,虽然有效,但是我们仔细想一想,解码器的每个时刻需要的信息肯定是不一样的。对于翻译来说,在将“吾輩は猫である”这句话翻译为英文时,肯定要用到诸如“吾輩 = I”“猫 = cat”这样的知识。也就是说,可以认为我们是专注于某个单词(或者单词集合),随时对这个单词进行转换的。但是偷窥技巧就做不到将输入单词与解码器的每个时刻对应。

在机器翻译的历史中,很多研究都利用“猫=cat”这样的单词对应关系的知识。这样的表示单词(或者词组)对应关系的信息称为对齐(alignment)。到目前为止,对齐主要是手工完成的,而我们将要介绍的Attention技术则成功地将对齐思想自动引入到了seq2seq中。这也是从“手工操作”到“机械自动化”的演变。

Attention机制能实现将编码器每个时刻关注的输入信息送到对应的编码器时刻中,完成输入和输出的对齐。
《深度学习进阶:自然语言处理》第8章 Attention_第3张图片

图8-6

我们在解码器中通过“某种计算”从隐藏状态矩阵 h s hs hs中提取每个时刻关注的信息。例如解码器的时刻1输出“I”,关注输入“吾輩”这个单词对于的隐藏状态,也就是 h s hs hs的第一行。所以“某种计算”在编码器的第一个时刻可以将 h s hs hs的第一行提取出来。

但是我们不能直接使用从隐藏状态矩阵选择目标单词向量的方式,这种方式是不能微分的。(插个眼,不是很理解原书中这个解释,理解了之后来补充。欢迎大家来答疑解惑,谢谢)。

个人理解,解码器每个时刻的输出与输入的单词并不是绝对一一对应的,翻译或别的场景下,输入可能对应输出的多个单词,或者是相反。例如将中文“给你”翻译为英文“Here you are”,中文词语与英文单词不是一一对应的。所以我们从隐藏状态矩阵抽取编码器每个时刻关注的信息,不应该一刀切就是抽取某个或某几个隐藏状态,而是应该给每个隐藏状态加上权重,然后求所有隐藏状态加权之后的和,作为编码器某个时刻的参考信息。这样也解决了反向传播时候的微分问题。
《深度学习进阶:自然语言处理》第8章 Attention_第4张图片

图8-8

8.1.4 解码器的改进②

上节中提到的权重 a a a肯定是需要从数据中自动学到的。

前面说到,编码器输出的隐藏状态矩阵相当于输入的每个单词的向量表示。而解码器每个时刻的输出也是输出的向量表示,
《深度学习进阶:自然语言处理》第8章 Attention_第5张图片

图8-12

我们比较编码器隐藏状态矩阵每个向量与解码器每个时刻的输出向量的相似度,使用这个相似度作为编码器隐藏状态矩阵每个向量的权重即可。向量的相似度可以使用向量的内积来计算,当然也有很多其他方法。求得相似度 s s s后,使用Softmax函数对 s s s进行正规化,形成最终的权重 a a a
《深度学习进阶:自然语言处理》第8章 Attention_第6张图片

图8-13、8-14合并

8.1.5 解码器的改进③

8.1.3节和8.1.4节的优化组合起来(具体代码实现请看原书,本文章重点关注原理而非实现),结果如下图:
《深度学习进阶:自然语言处理》第8章 Attention_第7张图片

图8-16

上下文向量 c c c就是解码器每个时刻的输出。

Attention Weight层关注编码器输出的各个单词向量 h s hs hs,并计算各个单词的权重 a a a;然后,Weight Sum层计算 a a a h s hs hs的加权和,并输出上下文向量 c c c。我们将进行这一系列计算的层称为Attention层。
《深度学习进阶:自然语言处理》第8章 Attention_第8张图片

图8-17

我们将这个Attention层放在编码器中LSTM层和Affine层的中间。
《深度学习进阶:自然语言处理》第8章 Attention_第9张图片

图8-18

我们把目光聚焦在于上一章编码器不同的位置上:上一章的编码器每个时刻的LSTM的输出隐藏状态经过全连接层后作为每个时刻的输出;增加Attention层后,LSTM的输出隐藏状态与Attention的输出上下文向量拼接后共同输入全连接层作为每个时刻的输出。

8.2 带Attention的seq2seq的实现

略。

8.3 Attention的评价

略。

8.4 关于Attention的其他话题

8.4.1 双向RNN

前面说到的RNN都是在预料上从左向右读取文本的。如果在两个方向上读取文本,整体信息的获取会更加平衡。下图为双向LSTM的示意:
《深度学习进阶:自然语言处理》第8章 Attention_第10张图片

图8-30

双向LSTM在之前的LSTM层上添加了一个反方向处理的LSTM层。然后,拼接各个时刻的两个LSTM层的隐藏状态,将
其作为最后的隐藏状态向量(除了拼接之外,也可以“求和”或者“取平均”等)。

8.4.2 Attention层的使用方法

除了上面介绍的将Attention层加在LSTM与全连接层之间的方式外,Attention还有很多其他的使用方式。
例如下图:
《深度学习进阶:自然语言处理》第8章 Attention_第11张图片

图8-32

上图中Attention层的输出(上下文向量)被连接到了下一时刻的LSTM层的输入处。通过这种结构,LSTM层得以使用上下文向量的信息。

8.4.3 seq2seq的深层化和skip connection

我们采用的Attention LSTM结构只使用了一层LSTM,实际上为了使seq2seq具有更强的表现力,可以加深LSTM层。
《深度学习进阶:自然语言处理》第8章 Attention_第12张图片

图8-33

另外,在加深层时使用到的另一个重要技巧是残差连接(skip connection,也称为 residual connection 或 shortcut)。所谓残差连接,就是指“跨层连接”。
《深度学习进阶:自然语言处理》第8章 Attention_第13张图片

图8-34

加法在反向传播时“按原样”传播梯度,所以残差连接中的梯度可以不受任何影响地传播到前一个层。这样一来,即便加深了
层,梯度也能正常传播,而不会发生梯度消失(或者梯度爆炸),学习可以顺利进行。

在时间方向上,RNN层的反向传播会出现梯度消失或梯度爆炸的问题。梯度消失可以通过LSTM、GRU等Gated RNN应对,梯度爆炸可以通过梯度裁剪应对。而对于深度方向上的梯度消失,这里介绍的残差连接很有效。

8.5 Attention的应用

Attention这一想法本身是通用的,不仅能使用在seq2seq上,在其他场景中也有很多可能性。

8.5.1 GNMT

略。

8.5.2 Transformer

RNN 需要基于上一个时刻的计算结果逐步进行计算,因此(基本)不可能在时间方向上并行计算 RNN。在使用了 GPU 的并行计算环境下进行深度学习时,这一点会成为很大的瓶颈。
为了去除RNN,人们做了很多研究,其中保护在“Attention is all you need”这篇论文中提出来的Transformer方法。如论文标题所示,Transformer不用RNN,而用Self-Attention进行处理。
Self-Attention 直译为“自己对自己的 Attention”,也就是说,这是以一个时序数据为对象的Attention,旨在观察一个时序数据中每个元素与其他元素的关系。
《深度学习进阶:自然语言处理》第8章 Attention_第14张图片

图8-37

左图是常规的Attention,右图是Self-Attention。Self-Attention 的两个输入中输入的是同一个时序数据。本书的啃书系列也快接近尾声,下一阶段计划学习Transformer,完成后将链接放置于此处。【此处预留链接】

Transformer的层结构:
《深度学习进阶:自然语言处理》第8章 Attention_第15张图片

图8-38

Transformer中用Attention代替了RNN,编码器和解码器两者都使用了Self-Attention。Feed Forward层表示前馈神经网络(在时间方向上独立的网络)。具体而言,使用具有一个隐藏层、激活函数为ReLU的全连接的神经网络。另外,图中的Nx表示灰色背景包围的元素被堆叠了N次。
图8-38显示的是简化了的Transformer,Skip Connection、Layer Normalization等技巧也会被用到。其他常见的技巧还有,(并行)使用多个Attention、编码时序数据的位置信息(Positional Encoding,位置编码)等。

8.5.3 NTM

略。

你可能感兴趣的:(深度学习,自然语言处理,人工智能,transformer,lstm)