MENU

Seq2seq and Attention

October 20, 2023 • Read: 167 • Deep Learning阅读设置

Seq2seq and Attention

Learn from these blog:

Seq2seq

1 什么是Seq2seq

Seq2seq,全称为sequence to sequence,即序列到序列,是序列到序列任务的统称。

序列到序列任务,简单地说,有2种具有某种对应关系的相互对应的序列,一个序列根绝这种对应关系得到与之对应的另一个序列的任务就是Seq2seq任务。
例如,最典型的Seq2seq任务:翻译任务,以中英翻译为例-中文句子和与其含义相同的英文句子相互对应,一个中文句子根据中英文语言之间的对应关系,得到与之对应的含义相同的英文句子。

序列到序列任务可以理解为,一种用来学习2种序列之间对应关系,以实现从一种序列转换到对应的另一种序列的任务。
翻译任务中,实际上学习的对应关系是一种语言与另一种语言之间的映射关系。

序列到序列任务中的2种序列可以是任何2种具有某种映射关系的序列,这个任务主要解决的问题就是得到2种序列之间的映射关系。

2 Seq2seq基础-如何思考用机器解决seq2seq任务

以翻译任务为例。

形式上,该任务有一个输入序列$ x_1, x_2, ..., x_m $,和一个对应的输出序列$ y_1, y_2, ..., y_n $,而该任务是要根据输入序列,找到最有可能的与之对应的目标序列。

因此,形式上目标序列就是最大化条件概率:
2023-10-24T13:24:09.png

为什么是概率形式:理解为与输入序列对应的序列有很多,即是不确定的,目标序列在形式上是其中概率最大的。简单的理解就是输入序列与输出序列之间不是一种一一对应、唯一确定的关系。

人类做的翻译任务,就是根据$ x $,翻译出最可能的$ y $,就对应于该公式:
2023-10-24T13:26:32.png

机器做该翻译任务,是根据$ x $,和经过训练得到的针对翻译任务的模型的参数集合$ \theta $,翻译出最可能的$ y $,对应于该公式:
2023-10-24T13:29:49.png

$ \theta $理解为训练后的能做翻译任务的模型。

2023-10-24T13:30:30.png

由此可得,为了定义一个机器翻译系统,我们需要回答以下3个问题:

  • 建模modeling:$ p(y|x, \theta) $的模型是什么样的?
    回答该问题等同于设计出一个能做该任务的模型,$ \theta $为该模型种带的参数。
  • 学习learning:如何找到$ \theta $?
    回答该问题等同于设计出该模型对应的损失函数。
    模型根据损失函数训练,使得自己从一个能做该任务进化到会做该任务。
  • 推理inference:如何找到最好的y?
    由于模型输出的是$ p(y|x, \theta) $,回答该问题等同于设计一个策略根据模型的输出得到目标序列,即2023-10-24T13:34:31.png

回答了以上三个问题,一个机器翻译系统就定义好了。
由此也可以看到,模型往往是一个系统中的一大部分,并不等同于一个系统,往往还有推理(可以理解为对模型输出的解码)这么个部分。

3 Seq2seq基础-Seq2seq的典型模型框架:Encoder-Decoder框架

2023-10-24T13:36:53.png
Encoder-decoderseq2seq任务的标准建模范式。这个框架由两部分组成:

  • Encoder: 接收source序列,并且生成对应的表示。
  • Decoder: 使用source表示,生成target序列。

4 Seq2seq基础-Seq2seq的模型:条件语言模型

回答$ p(y|x, \theta) $是什么样的模型,对应建模问题。

语言模型是估计tokens序列$ y = (y_1, y_2, ..., y_n) $的概率$ p(y) $,是序列$ y $的无条件概率。
语言模型可以理解为做的任务是在没有任何条件下得到序列$ y $。

Seq2seq模型是在给定条件序列$ x $下,估计序列$ y $的概率$ p(y|x) $,换句话说序列$ y $是基于序列& x &得到的,因此是序列$ y $的条件概率。
Seq2seq模型类似于语言模型,只是多了一个给定条件:序列$ x $。
因此根据语言模型,seq2seq任务可以被建模为条件语言模型:
2023-10-24T13:42:59.png

注意,条件语言建模不仅可以用来解决seq2seq任务,一般来说,条件语言建模中的$ x $可以是tokens序列外的其他东西。例如,在图像字幕捕获任务中,$ x $就是一个图像,而$ y $是该图像的描述。

条件语言模型与语言模型唯一的区别是$ x $的存在,因此条件语言建模和训练与语言模型类似,具体地:

  • 将source和之前生成的tokens喂入网络;
  • 通过decoder得到对应的上下文向量表示;
  • 根据该表示,预测下一个token的概率分布。

通常以一种简单的方式根据一个向量表示来得到一个token的概率分布:用一个线性层后接softmax作为分类部分。

  • 线性层用于将$ d $维向量表示转换为对应于token预测的$ |V| $维的向量表示;
  • softmax操作用于将表示预测的向量表示中的标量转换为概率值,即一个向量的每个维度的值都为0到1之间的值,并且所有维度的值之和为1。
    2023-10-24T13:48:58.png

5 最简单的模型:2个RNNs分别作为Encoder和Decoder

2023-10-24T13:49:59.png

Encoder RNN接收source,整个Encoder RNN的最后一个(隐层)状态作为source的表示,用于初始化Decoder RNN。

这个模型有不同的改进版,例如,encoder和decoder可以有好几层,不同层学习到的信息不同,这样学习到的表示包含的信息更丰富。

6 训练:交叉熵损失

类似于语言模型,seq2seq模型是训练来根据之前的预测tokens和给定的$ x $,来预测下一个token。

因此,训练就要使模型在预测每个token,即在每一步,最大化其分配给正确token的概率(最大概率为1)。

损失函数推理过程如下:
2023-10-24T13:55:07.png

7 推理:贪婪解码Greedy Decoding和束搜索Beam Search

到目前为止,已经有了一个能做好根据序列$ x $预测可能的(即还无法完全确定为一个的)对应序列$ y $的模型,即模型能够完成$ p(y|x, \theta) $,但目标是得到与$ x $最匹配的那个$ y $。因此,该部分对应实现2023-10-24T14:02:58.png

2023-10-24T14:03:32.png

需要注意的是,条件概率公式的计算:$ P(A|B) = P(AB)P(B) $,也就是说:
2023-10-24T14:04:38.png

模型能做的是预测每一步所有可能的tokens的概率,要确定目标$ y^' $就要从$ |V|^n $个可能中确定,在实际中是不可行的。因此,只能确定一个近似解。

根据模型的特定:只能预测每一步所有可能的tokens的概率,有两种确定近似解的策略:

  • 贪婪解码:每一步选择概率最大的token。
    这是最直接和简单的方式,它可能是很好的一个基线,但存在一个问题:当前步最可能的token不一定是那个组成到当前步为止的最可能的序列的token,即
    2023-10-24T14:08:02.png
  • 束搜索:追踪几个最可能的假设。
    贪婪解码是按照贪婪策略直接确定一个假设为目标$ y^' $。
    而束搜索是每一步在当前假设的基础上,保留几个最可能的假设,如图,通常beam size设置为4到10,beam size越大,计算效率越低,并且往往句子质量也会越差。
    2023-10-24T14:10:26.png
    2023-10-24T14:10:44.png
    2023-10-24T14:11:05.png
    2023-10-24T14:11:31.png
    2023-10-24T14:12:04.png
    2023-10-24T14:12:39.png

Attention

1 引入注意力的原因:固定的Encoder表示

Encoder产生的固定的source表示是次优的(suboptimal):

  • 对于encoder,将source的所有信息压缩为一个向量,一定程度上限制了source的长度。
    因为,如果source太长,encoder将所有信息压缩为一个向量,很可能会“忘掉”某些信息。
  • 对于decoder,生成token的每一步都是基于表示source的相同不变的表示,一定程度上限制了decoder生成token的性能。
    因为,生成token的每步与source中相关联的信息部分可能是不同的,每个生成步对应不同的source表示或许更有用。
    2023-10-24T14:17:55.png

2 注意力机制

注意力机制是神经网络的一部分,它能够使decoder中的每个生成步得到包含与自己最相关信息的代表source的表示。
换句话说,注意力机制使得encoder不再将source所有信息压缩为一个向量给所有decoder的生成步使用,而是encode出source中每个token的表示。

根据注意力机制的作用,decoder中每个生成步都有一个与之对应的source表示,因此每个生成步对应的source表示的生成需要每个生成步自己的信息与source中所有信息参与,这样每个生成步才能得到包含与自己最相关的信息的source表示,这也称为每个生成步的attention。
2023-10-24T14:21:52.png

decoder每个生成步对应的attention的计算步骤:
2023-10-24T14:22:13.png

attention的大体计算策略如下:
2023-10-24T14:22:49.png

3 注意力分数的计算方式

2023-10-24T14:25:13.png
注意力分数是计算attention的其中一个步骤,其计算方式并不是固定的,理论上可以应用任何你想用的函数来计算。
通常都会应用以下三种流行的、表现较好的计算注意力分数的方式:
2023-10-24T14:25:01.png

  • 点乘:最简单的方式,公式如下:
    2023-10-24T14:25:59.png
  • 双线性函数:用在Luong attention中,公式如下:
    2023-10-24T14:26:49.png
  • 多层感知机:用在Bahdanau attention中,公式如下:
    2023-10-24T14:27:20.png

双线性函数代码实现体现为:decoder的表示通过一个线性层引入一个权重矩阵,后再与encoder表示点乘。

多层感知机代码实现体现为:decoder的表示与encoder的表示求和,通过一个线性层引入一个权重矩阵,再套上tanh,最后再与一个权重矩阵点乘。

4 注意力机制模型:Bahdanau和Luong

1) Bahdanau Model (or Bahdanau Attention)
2023-10-24T14:30:12.png

  • encoder: 双向RNN,前向和后向
    source中每个token经过encoder后的表示等于对应前向和后向状态的拼接。
  • attention score(注意力分数的计算方式): 多层感知机。
    这里给出这种注意力分数的计算方式和示意图,与前面略有不同的是,这里代表decoder每步的表示与代表encoder各token的表示,有各自的线性层即各自的可训练权重,前面展示的是共有一个,但本质方式相同。
    2023-10-24T14:33:15.png
    2023-10-24T14:33:39.png
  • attention的应用: 用于decoder每2步之间
    对于decoder的第t步,首先用前一步生成的$ h_{t-1} $与encoder的各token表示生成attention,然后将$ h_{t-1} $、上一步生成的output及由$ h_{t-1} $生成的attention用于第t步token的生成,具体地:

    • $ h_{t-1} $作为输入到第t步的上一层的隐层状态;
    • attention和output拼接作为第t步的输入。
      2023-10-24T14:36:12.png

2) Luong Model (or Luong Attention)
2023-10-24T14:36:55.png

  • encoder: 单向RNN
  • attention score(注意力分数的计算方式): 双线性函数
    在原文中展示了前面提到的3种注意力分数的计算方式,其对应公式和代码分别如下:
    2023-10-24T14:38:41.png
    2023-10-24T14:38:55.png
  • attention的应用:用在decoder每步生成状态t和预测这步的output之间。
    对于decoder的第t步,首先利用上一步的$ h_{t-1} $和上一步的output得到当前步对应的$ h_t $,再将$ h_t $与encoder各token表示生成对应的attention,再将attention与$ h_t $进行拼接预测这一步的output,最后将这一步的$ h_t $和output传给下一步。

Transformer

Transformer是seq2seq任务建模的新范式:之前的模型在encoder和decoder中的处理是通过循环或卷积网络完成的,Transformer仅使用了注意力机制。
2023-10-24T14:42:54.png

Transformer的形象描述:
2023-10-24T14:43:29.png

在之前,要理解(得到对应表示)source中的一个token,必须先理解完这个token之前的所有token。这就对应之前的RNN Encoder工作的机制。
而在Transformer中的Encoder中,所有token都是同时与其他所有token交互。
并且Transformer的Decoder中,所有token也都是与之前token交互并与encoder的各token交互。

其他关于更多Transformer细节,查阅原blog:Sequence to Sequence (seq2seq) and Attention

Last Modified: October 24, 2023