【自然语言处理】Seq2Seq 讲解

有任何的书写错误、排版错误、概念错误等,希望大家包含指正。

Encoder-Decoder

Encoder-Decoder (编码器-解码器)模型是一种神经网络设计模式(框架),其架构示意图如图 1 1 1 所示。模型分为两部分:编码器和解码器。编码器将输入的文字、图像或者音视频编码为状态,该状态通常为一个固定长度的向量,解码器接收状态并解码输出。

在这里插入图片描述

图 1    Encoder-Decoder 模型架构示意图

在具体实现时,编码器和解码器通常使用循环神经网络,如 RNN、LSTM、GRU 等,有些情况也可以使用卷积神经网络,实现语言翻译、文档摘取、问答系统等功能。

单一的循环神经网络不能处理输入序列的长度与输出序列长度不一致的自然语言问题。Encoder-Decoder 框架的提出正是为了解决这一问题,它的编码器和解码器结构允许输入序列与输出序列长度不一致,这在很多自然语言任务上都非常有帮助。下面以一个简单的语言翻译场景为例,输入语句由 T T T 个单词组成,输出语句由 T ′ T' T 个单词组成,此时 Encoder-Decoder 模型架构如图 2 2 2 所示。

在这里插入图片描述

图 2    基于语言翻译的 Encoder-Decoder 模型架构

2 2 2 可以看作由一个语句生成另一个语句的通用处理模型。假设这个语句对为 < X , Y > \left< X, Y \right> X,Y,目标是给定输入语句 X X X,期待通过 Encoder-Decoder 模型生成目标语句 Y Y Y X X X Y Y Y 可以是同一种语言,也可以是两种不同的语言。其中, X X X Y Y Y 分别由各自的单词序列构成:
X = ( x 1 , x 2 , … , x T ) Y = ( y 1 , y 2 , … , y T ′ ) X=(x_1,x_2,\dots, x_T) \\ Y = (y_1,y_2,\dots, y_{T'}) X=(x1,x2,,xT)Y=(y1,y2,,yT)

为了方便, x t x_t xt 既表示单词又表示单词嵌入, y t ′ y_{t'} yt 同理。

Encoder

Encoder,顾名思义就是对输人句子 X X X 进行编码,通过非线性变换将输入句子转化为中间语义表示 c c c
c = f ( x 1 , x 2 , … , x T ) c = f(x_1, x_2, \dots, x_T) c=f(x1,x2,,xT)
常⽤的编码器是循环神经⽹络,可以是一层,也可以是多层,甚至可以采用双向循环神经网络。可以认为,编码器将输入序列的部分信息保存在语义向量 c c c 中。

扫描二维码关注公众号,回复: 14657760 查看本文章

Decoder

解码器的任务是根据句子 X X X 的中间语义表示 c c c 和之前已经生成的历史信息 y 1 y_1 y1 y 2 y_2 y2 … … y t ′ − 1 y_{t'-1} yt1 来生成 t ′ t' t 时刻要生成的单词 y t ′ y_{t'} yt
y t ′ = g ( c , y 1 , y 2 , … , y t ′ − 1 ) y_{t'} = g(c, y_1, y_2,\dots, y_{t'-1}) yt=g(c,y1,y2,,yt1)
本质上, y t ′ y_{t'} yt 是根据以之前时刻的输出序列 y 1 y_1 y1 … \dots y t ′ − 1 y_{t'-1} yt1 和 中间语义表示 c c c 为条件的条件概率(即 P ( y t ′ ∣ y 1 , … , y t ′ − 1 , c ) P(y_{t'}\mid y_1,\dots, y_{t'-1}, c) P(yty1,,yt1,c))选择出来的。函数 g g g 对应条件概率 P ( y t ′ ∣ y 1 , … , y t ′ − 1 , c ) P(y_{t'}\mid y_1,\dots, y_{t'-1}, c) P(yty1,,yt1,c) 的具体计算,我们可以使用自定义的输出层和 softmax 运算来计算条件概率,例如,基于前一时刻的输出 y t ′ − 1 y_{t'-1} yt1 c c c 来计算当前时刻输出 y t ′ y_{t'} yt 的概率分布;对于解码器采用含有隐藏状态的循环神经网络,可能还会用到隐藏状态进行计算。随便举一个简单的计算方式,对于不含隐藏状态的条件概率,我们可以将 y t ′ − 1 y_{t'-1} yt1 c c c 映射到相同维度,对应元素相加的结果作为 softmax 的输入,softmax 输出的概率分布为 y t ′ y_{t'} yt 的条件概率分布。

另外,相比于编码器,解码器虽然也可以采用多层循环神经网络,但是不能使用双向结构。原因很明显,在预测阶段,解码器负责按时序输出结果,采用双向结构意味着解码器提前获取到了后面时刻的输出,这对于预测显然是没有意义的。

Encoder-Decoder 是个非常通用的计算框架,而编码器和解码器具体使用什么模型则由我们自己决定。常见的有 CNN、RNN、BiRNN、GRU、LSTM、Deep LSTM 等,而且变化组合非常多。Encoder-Decoder 模型的应用场景非常广泛,比如对于机器翻译来说 < X , Y > \left<X,Y\right> X,Y 就是对应不同语言的语句,其中 X X X 是英语语句, Y Y Y 就是对应的中文语句翻译;对于文本摘要来说, X X X 就是一篇文章, Y Y Y 就是对应的摘要;对于对话机器人来说, X X X 就是某人的一句话, Y Y Y 就是对话机器人的应答等。

Seq2Seq

Seq2Seq 模型是基于 Encoder-Decoder 框架生成的,其输入和输出都是序列。个人认为,Seq2Seq 模型更倾向于处理序列问题、更加具体,而 Encoder-Decoder 模型是一个框架,可以用于处理序列问题和非序列问题。在自然语言处理中,我们会认为Encoder-Decoder 模型就是Seq2Seq 模型,而且 Seq2Seq 也不特指具体方法,只要满足输入序列、输出序列的目的,都可以称为 Seq2Seq 模型。

首先要明确,训练阶段和预测(推理)阶段的 Seq2Seq 模型结构是一致的,不同的在于解码器部分的计算流程。图 3 3 3 采用了其中一种方式实现 Seq2Seq,对比在训练阶段和预测阶段将英语翻译成法语句对应流程的区别。

在这里插入图片描述

图 3    Seq2Seq 模型的训练流程(上)和预测流程(下)

在数据集中,我们可以在每个语句后附上特殊符号 <EOS>(end of sequence)以表示序列的终止。预测阶段和训练阶段的编码流程是一致的,编码器每个时刻的输入依次为英语语句中的单词、标点和特殊符号 <EOS>。编码器在最终时刻的隐藏状态作为编码器输入语句的表征或编码信息(hidden state)。预测阶段和训练阶段的解码流程是不同的。

训练阶段

训练阶段(如图 3 3 3 下),输入语句的表征只用于初始化解码器的第一个时刻的状态,解码器的输入为编码器输入语句对应的法语语句,每个时刻输入一个法语单词,也输出一个语法单词,期望的输出单词应该是输入单词的下一个单词,这与语言模型的训练思想是一致的。可见,即使解码器每个时刻的输出单词不是输入单词的下一个单词,也不影响下一个时刻的输入,这种根据标准答案来解码的方式称为强制教学(teacher forcing)。

当然,强制教学并不是必须的,训练时我们也可以采用类似于预测阶段的方式,即将前一个时刻的预测结果作为下一个时刻的输入。但是,在实践中人们发现,这样训练非常困难。因为没有任何的引导,一开始会完全是瞎预测,正所谓“一步错,步步错”,而且越错越离谱,这样会导致训练时的累积损失太大(误差爆炸),训练非常耗时。如果我们能够在每一步的预测时,让老师来指导一下,即提示一下上一个词的正确答案,解码器就可以快速步入正轨,训练过程也可以更快收敛。因此大家把这种方法称为 teacher forcing。可见,这种操作的目的就是为了使得训练过程更容易。

具体的损失函数。根据最大似然估计,我们可以最大化输出序列基于输入序列的条件概率
P ( y 1 , … , y T ′ ∣ x 1 , … , x T ) = ∏ t ′ = 1 T ′ P ( y t ′ ∣ y 1 , … , y t ′ − 1 , x 1 , … , x T ) = ∏ t ′ = 1 T ′ P ( y t ′ ∣ y 1 , … , y t ′ − 1 , c ) \begin{align} P(y_1,\dots, y_{T'} \mid x_1,\dots, x_T)& = \prod_{t'=1}^{T'}P(y_{t'}\mid y_1,\dots, y_{t'-1}, x_1, \dots, x_T) \notag\\ &=\prod_{t'=1}^{T'} P(y_{t'}\mid y_1,\dots, y_{t'-1}, c) \notag \end{align} P(y1,,yTx1,,xT)=t=1TP(yty1,,yt1,x1,,xT)=t=1TP(yty1,,yt1,c)
并得到该输出序列的损失
− log ⁡ P ( y 1 , … , y T ′ ∣ x 1 , … , x T ) = − ∑ t ′ = 1 T ′ log ⁡ P ( y t ′ ∣ y 1 , … , y t ′ − 1 , c ) -\log P(y_1, \dots, y_{T'}\mid x_1, \dots, x_T) = -\sum_{t'=1}^{T'} \log P(y_{t'}\mid y_1, \dots, y_{t'-1}, c) logP(y1,,yTx1,,xT)=t=1TlogP(yty1,,yt1,c)
在模型训练中,所有输出序列损失的均值通常作为需要最小化的损失函数。另外,关于条件概率的计算上面已经介绍过了。

预测阶段

预测阶段(如图 3 3 3 上),输入语句的表征不仅用于初始化解码器的第一个时刻的状态,而且在每个时刻都与前一个时刻的预测结果拼接后作为当前时刻的输入。另外,前一个时刻的状态也会传递到下一个时刻。我们希望解码器在各个时刻能正确依次输出翻译后的法语单词、标点和特殊符号 <EOS>。需要注意的是,解码器在最初时刻的输入用到了一个表示序列开始的特殊符号 <BOS>(beginning of sequence)。

有三种常用的预测方法:贪婪搜索、穷举搜索和束搜索。假设解码器的输出是⼀段文本序列,输出⽂本词典 Y \mathcal Y Y(包含特殊符号 <EOS>)的大小为 ∣ Y ∣ |\mathcal Y| Y,输出序列的最大长度为 T ′ T' T。所有可能的输出序列一共有 O ( ∣ Y ∣ T ′ ) O(|\mathcal Y|^{T'}) O(YT) 种。这些输出序列中所有特殊符号 后面的子序列将被舍弃。

贪婪搜索

贪婪搜索(greedy search)是一种简单的解决方案。对于输出序列任一时刻 t ′ t' t,我们从 ∣ Y ∣ |\mathcal Y| Y 个词中搜索出条件概率最大的词
Y t ′ = arg ⁡ max ⁡ y ∈ Y P ( y ∣ y 1 , … , y t ′ − 1 , c ) Y_{t'} = \arg \max_{y\in \mathcal Y} P(y\mid y_1,\dots, y_{t'-1}, c) Yt=argyYmaxP(yy1,,yt1,c)
作为输出。一旦搜索出号 <EOS> 符号,或者输出序列长度已经达到了最大长度 T ′ T' T,便完成输出。

在训练阶段我们提到基于输入序列生成输出序列的条件概率为 ∏ t ′ = 1 T ′ P ( y t ′ ∣ y 1 , … , y t ′ − 1 , c ) \prod\limits_{t'=1}^{T'}P(y_{t'}\mid y_1, \dots, y_{t'-1}, c) t=1TP(yty1,,yt1,c)。我们将该条件概率最大的输出序列称为最优输出序列。而贪婪搜索的主要问题是不能保证得到全局最优输出序列。

穷举搜索

如果目标是得到最优输出序列,我们可以考虑穷举搜索(exhaustive search):穷举所有可能的输出序列,输出条件概率最大的序列。

虽然穷举搜索可以得到最优输出序列,但它的计算开销 O ( ∣ y ∣ T ′ ) O(|\mathcal y|^{T'}) O(yT) 很容易过大。例如,当 ∣ Y ∣ = 10000 |\mathcal Y|=10000 Y=10000 T ’ = 10 T’= 10 T=10 时,我们将评估 1000 0 10 = 1 0 40 10000^{10} = 10^{40} 1000010=1040 个序列:这几乎不可能完成。而贪婪搜索的计算开销是 O ( ∣ Y ∣ T ′ ) O(|\mathcal Y|T') O(YT),通常显著小于穷举搜索的计算开销。例如,当 ∣ Y ∣ = 10000 |\mathcal Y|=10000 Y=10000 T ’ = 10 T’= 10 T=10 时,我们只需评估 10000 × 10 = 1 0 5 10000 \times 10=10^5 10000×10=105 个序列。

束搜索

束搜索(beam search)是对贪婪搜索的一个改进算法。它有一个束宽(beam size)超参数。我们将它设为 k k k。在第一个时刻,选取当前时刻条件概率最大的 k k k 个词,分别组成 k k k 个候选输出序列的首词。在之后的每个时刻,基于上个时刻的 k k k 个候选输出序列,从 k ∣ Y ∣ k|\mathcal Y| kY 个可能的输出序列中选取条件概率最大的 k k k 个,作为该时刻的候选输出序列。最终,我们从各个时刻的候选输出序列中筛选出包含特殊符号 的序列,并将它们中所有特殊符号后 面的子序列舍弃,得到最终候选输出序列的集合。

在这里插入图片描述

图 4    束搜索的过程。束宽为 2,输出序列最⼤⻓度为 3。候选输出序列有 A、C、AB、CE、ABD 和 CED

4 4 4 通过一个例子演示了束搜索的过程。假设输出序列的词典中只包含 5 5 5 个元素,即 Y = { A , B , C , D , E } \mathcal Y=\{A,B,C,D,E\} Y={ A,B,C,D,E},且其中一个为特殊符号 。设束搜索的束宽等于 2 2 2,输出序列最大长度为 3 3 3。在输出序列的第一个时刻,假设条件概率 P ( y 1 ∣ c ) P(y_1\mid c) P(y1c) 最大的两个词为 A A A C C C。我们在第二个时刻将对所有的 y 2 ∈ Y y_2\in \mathcal Y y2Y 都分别计算 P ( A , y 2 ∣ c ) = P ( A ∣ c ) P ( y 2 ∣ A , c ) P(A, y_2 \mid c)= P(A \mid c)P(y_2 \mid A,c) P(A,y2c)=P(Ac)P(y2A,c) P ( C , y 2 ∣ c ) = P ( C ∣ c ) P ( y 2 ∣ C , c ) P(C, y_2 \mid c) = P(C \mid c)P(y_2 \mid C,c) P(C,y2c)=P(Cc)P(y2C,c) ,并从计算出的 10 10 10 个条件概率中取最大的 2 2 2 个,假设为 P ( A , B ∣ c ) P(A,B\mid c) P(A,Bc) 和P ( C , E ∣ c ) (C,E \mid c) (C,Ec)。那么,我们在第三个时刻将对所有的 y 3 ∈ Y y_3 ∈\mathcal Y y3Y 都分别计算 P ( A , B , y 3 ∣ c ) = P ( A , B ∣ c ) P ( y 3 ∣ A , B , c ) P(A,B, y_3 \mid c)= P(A,B \mid c)P(y_3 \mid A,B,c) P(A,B,y3c)=P(A,Bc)P(y3A,B,c) P ( C , E , y 3 ∣ c ) = P ( C , E ∣ c ) P ( y 3 ∣ C , E , c ) P(C,E , y_3 \mid c) = P(C, E \mid c)P(y_3 \mid C, E, c) P(C,E,y3c)=P(C,Ec)P(y3C,E,c),并从计算出的 10 10 10 个条件概率中取最大的 2 2 2 个,假设为 P ( A , B , D ∣ c ) P(A,B,D\mid c) P(A,B,Dc) P ( C , E , D ∣ c ) P(C, E, D \mid c) P(C,E,Dc)。如此一来,我们得到六个候选输出序列:(1) A;(2) C;(3) A、B;(4) C、 E;(5) A、B、D 和 (6) C、E、D。这六个序列构成最终候选输出序列的集合。

在最终候选输出序列的集合中,我们取以下分数最高的序列作为输出序列:
1 L α log ⁡ P ( y 1 , … , y L ) = 1 L α ∑ t ′ = 1 L log ⁡ P ( y t ′ ∣ y 1 , … , y t ′ − 1 , c ) \frac{1}{L^{\alpha}}\log P(y_1, \dots, y_L) = \frac{1}{L^{\alpha}} \sum_{t'=1}^L \log P(y_{t'}\mid y_1, \dots, y_{t'-1}, c) Lα1logP(y1,,yL)=Lα1t=1LlogP(yty1,,yt1,c)
其中 L L L 为最终候选序列长度, α α α 一般可选为 0.75 0.75 0.75。分母上的 L α L^{\alpha} Lα 是为了惩罚较长序列在以上分数中较多的对数相加项。分析可知,束搜索的计算开销为 O ( k ∣ Y ∣ T ′ ) O(k |\mathcal Y| T') O(kYT)。这介于贪婪搜索和穷举搜索的计算开销之间。此外,贪婪搜索可看作是束宽为 1 1 1 的束搜索。束搜索通过灵活的束宽 k k k 来权衡计算开销和搜索质量。

BLEU

对于机器翻译进行人工评价是非常耗时且昂贵的,为此提出了一种快速、便宜且语言独立的自动机器翻译评价方法,即 BLEU 指标。它和人工评价高度相关,并且每次运行的边际成本很低。

仅简单介绍基础用法。

定义 p n p_n pn 是预测序列的所有 n-gram 精度,那么 BLEU 的计算公式为
exp ⁡ ( min ⁡ ( 0 ,    1 − l e n l a b e l l e n p r e d ) ) ∏ n = 1 p n 1 / 2 n \exp\left(\min \left( 0, \; 1-\frac{ {\rm len}_{\rm label}}{ {\rm len}_{\rm pred}} \right) \right)\prod_{n=1} p_n^{1/2^n} exp(min(0,1lenpredlenlabel))n=1pn1/2n
BLEU 值越大,表明预测序列越好,模型越优质。

通过例子理解。假设真实的标签序列为 l a b e l = ( A , B , C , D , E , F ) {\rm label} = (A, B, C, D, E, F) label=(A,B,C,D,E,F),预测出的标签序列为 p r e d = ( A , B , B , C , D ) {\rm pred} = (A, B, B, C, D) pred=(A,B,B,C,D)

p 1 p_1 p1 的计算方式为,逐个查看预测序列中的每个元素是否出现在真实序列中。 p r e d 1 = A {\rm pred_1}=A pred1=A l a b e l \rm label label 序列中出现过,匹配成功; p r e d 2 {\rm pred_2} pred2 p r e d 3 \rm pred_3 pred3 均为 B B B,但是在 l a b e l \rm label label B B B 只出现了一次,所以仅匹配成功一次; p r e d 4 \rm pred_4 pred4 p r e d 5 \rm pred_5 pred5 也都匹配成功。可见,匹配的总次数为 5 5 5,其中成功的次数为 4 4 4,因此 p 1 = 4 / 5 p_1=4/5 p1=4/5

p 2 p_2 p2 的计算方式为,预测序列中的相邻两个元素作为一组,与真实序列进行匹配。 ( p r e d 1 , p r e d 2 ) = ( A , B ) {\rm (pred_1,pred_2)}=(A,B) (pred1,pred2)=(A,B) ( l a b e l 1 , l a b e l 2 ) = ( A , B ) ({\rm label_1,label_2})=(A,B) (label1,label2)=(A,B) 匹配成功; l a b e l \rm label label 中没有出现过 ( p r e d 2 , p r e d 3 ) = ( B , B ) {\rm (pred_2,pred_3)}=(B,B) (pred2,pred3)=(B,B),匹配失败; ( p r e d 3 , p r e d 4 ) = ( l a b e l 2 , l a b e l 3 ) = ( B , C ) {\rm (pred_3,pred_4)} = {\rm (label_2,label_3)} =(B,C) (pred3,pred4)=(label2,label3)=(B,C) ( p r e d 4 , p r e d 5 ) = ( l a b e l 3 , l a b e l 4 ) = ( C , D ) {\rm (pred_4,pred_5)} = {\rm (label_3,label_4)} =(C,D) (pred4,pred5)=(label3,label4)=(C,D),均匹配成功。可见,匹配的总次数为 4 4 4,其中成功的次数为 3 3 3,因此 p 2 = 3 / 4 p_2=3/4 p2=3/4

类似地,可以得到 p 3 = 1 / 3 p_3=1/3 p3=1/3 p 4 = p 5 = ⋯ = 0 p_4=p_5 = \dots = 0 p4=p5==0

BLEU 公式中的 l e n l a b e l l e n p r e d \frac{ {\rm len}_{\rm label}}{ {\rm len}_{\rm pred}} lenpredlenlabel 部分是用于惩罚过短的预测。直观上,预测序列越短,与真实序列的匹配成功的可能性就越大。极端地,预测序列只有一个元素,将很容易与真实序列中的元素匹配,但其实这种匹配对于正确翻译语句来说贡献很小,所以需要对其施加惩罚。需要注意,因为连乘运算前的系数均不大于 1 1 1,所以惩罚越严重系数越接近 0 0 0

BLEU 公式中的 p n 1 / 2 n p_n^{1/2^n} pn1/2n 部分表明长匹配应该具有高权重。直观上,单个元素与真实序列匹配成功并不值得过多的关注,但是多个元素组成的长子语句与真实序列匹配成功有着重要的意义,因此对于长匹配,我们应该给予更高的权重。 p n p_n pn 的指数为 1 / 2 n 1/2^n 1/2n,对一个概率值开 2 n 2^n 2n 根会使结果变大,且 n n n 越大,放大效果越明显,以此赋予长匹配高权重。

REF

[1]《动手学深度学习》阿斯顿·张、李沐等著

[2]《深入浅出 Embedding》吴茂贵、王红星著

[3] Cho K, Van Merriënboer B, Gulcehre C, et al. Learning phrase representations using RNN encoder-decoder for statistical machine translation[J]. arXiv preprint arXiv:1406.1078, 2014.

[4] Sutskever I, Vinyals O, Le Q V. Sequence to sequence learning with neural networks[J]. Advances in neural information processing systems, 2014, 27.

[5] Seq2Seq李沐 - bilibili

[6] CS224n笔记 - 知乎

[7] Encoder-Decoder - CSDN博客

[8] 机器翻译自动评价之BLEU详解 - 知乎

猜你喜欢

转载自blog.csdn.net/weixin_46221946/article/details/128786412