seq2seq模型与注意力机制

seq2seq模型与注意力机制解析

Posted by Jinliang on July 19, 2019

1. seq2seq模型

seq2seq模型,从表面意思了解,就是序列到序列的模型,即输入为序列,输出也为序列。

我们常见的机器翻译图像描述就是显著的代表,我们首先简单了解一下这两个任务。

  • 机器翻译

    机器翻译任务中,我们将网络分为编码网络与解码网络。

    编码网络是一个RNN结构,可以使GRU,或者是LSTM,它接收输入序列,然后输出一个向量代表输入序列:

    image-20190717174754834

    然后是解码网络,它以编码网络的输出作为输入,每次输出一个翻译后的单词,然后将当前的输出作为下一次的输入,直至输出序列结尾或句子结尾标记。

  • 图像描述

    图像描述指的是输入我图像,输出为对当前图像的描述,即文本。

    我们使用之前学习的CNN 网络学习图片的特征,例如AlexNet,将最后一层的softmax去掉,输出为4096维的向量,我们可以把这部分作为编码网络

    解码网络与机器翻译中的很像,使用RNN结构,每次输出一个单词。

第1小节提及到的机器翻译模型语言模型很相似,将机器翻译模型的编码网络删除,那么两个模型几乎一样的。只不过加上编码网络后,机器翻译模型的最开始的输入不是0,而是RNN学习到的特征向量;语言模型最开始的输入却是0。因此,机器翻译模型相比于语言模型,相当于增加了一个条件(编码网络学习到的特征),我们可以称机器翻译模型为条件语言模型

当我们使用上述模型进行机器翻译时,我们不能从得到的分布中随机采样,我们的目的是找到一个句子,使其概率最大化。其中一种方法就是贪心策略:在生成第一个词的时候,我们选择所有词中概率最大的,然后挑选第2个词,仍然选择概率最大的,知道最后。

但是贪心策略得到的往往不是概率最大的,或者说往往不是句子的总概率最大的。我们最常用的方法是近似的搜索算法,他不能保证找到的y是全局最优的,但是它尽可能使得到的y概率最大化。


集束搜索就是这样的一种方法。

集束搜索有一个超参数,叫做集束宽度,当集束宽度为3时,代表每个RNN单元,我们选择总概率值最大的3个作为输出。

我们学习一下集束搜索的详细过程。

在编码网络执行过后,我们会得到一个特征向量,对于解码网络的第一个RNN单元,如下所示:

image-20190717194927368

蓝色的为第1个解码网络RNN单元,这个单元会输出n个词的分布(n为词汇表的大小),我们从n中选择最大的3个概率所对应的单词,作为下一个RNN单元的输入。

在解码网络的第2个RNN单元中,由于我们有3个输入,所以我们得到$3\times n$种概率分布(注意,此时的概率分布不仅仅是当前RNN单元的概率输出,而是考虑到编码网络与解码网络第1个RNN单元的输出),即$P(\hat y^{<1>},\hat y^{<2>}\mid x)$,我们在$3\times n$种概率分布中选择最大的3个作为下一个RNN单元的输出。

解码网络的第3个RNN单元所做的工作与第2个RNN单元工作一致,每次仅保存3个概率最大的输出。

我们可以发现,集束宽度为1时,就退化成了贪心策略。

在上述最基本的集束搜索之上,我们可以做一些改进:

  • ​ 解决数值不准确的问题

    我们需要求的结果用公式表达为:

    \[\arg \max_y \Pi_{t=1}^{T_y}p(y^{<t>}\mid x,y^{<1>},\ldots,y^{<t-1>})\tag{2-1}\]

​ 公式2-1就是概率乘积,由于每个概率都是远远小于1的,许多概率的乘积会导致数值下溢(数值太小,电脑 的浮点不能精确的存储),我们可以使用一个trick解决这个问题,就是log函数,log函数是严格单调递增的, 所以最大化$P(y\mid x)$与最大化$\log P(y\mid x)$的效果是一样的。

​ 使用log后的公式如下:

​ \(\arg \max_y \sum_{t=1}^{T_y}\log p(y^{<t>}\mid x,y^{<1>},\ldots,y^{<t-1>})\tag{2-2}\)

  • 解决倾向于简短翻译的缺点

    观察公式2-1、2-2,我们可以发现,因为每个概率的值大小都远小于1(使用log函数后,变为远小于0),因此越长的句子概率值越小,使得模型倾向于选择较短的句子。

    为了解决这个问题,我们可以对其使用归一化,通过除以每个句子中单词的数量,取每个单词概率对数值的平均,这样减少了对输出长的结果的惩罚。

    相比于除以每个句子的单词数量,我们有个更柔和的方法,我们加入一个超参数:

    \[\arg \max_y\frac{1}{T_y^\alpha} \sum_{t=1}^{T_y}\log p(y^{<t>}\mid x,y^{<1>},\ldots,y^{<t-1>})\tag{2-3}\]

​ 其中$\alpha$可以等于0.7,如果等于0,那么相当于没有进行归一化。

​ 通过公式2-3,也称作归一化的对数似然目标函数,通过其选择得分最高的句子。

  • 集束宽度B的大小

    如果B很大,会得到更好的结果,但是算法运行的慢、占用内存大、计算量大;

    如果B很小,效果没有那么好,但是算法运行的快,占用内存小,计算量小。

    我们可以取B为3,但是在实践中,略微有些小,取B为10是一个不错的选择,但也不是绝对的,针对不同的应用,需要不同的B。

    有一点特性我们要注意到,就是B从1到3再到10,我们会看到很大的改善;但是B从1000到3000,改善就很小了。

    在搜索算法中,有DFS/BFS等,集束搜索与他们不同,集束搜索拥有更快的搜索效果,但是不保证能找到精确的最大值。


集束搜索是一种近似搜索方法,也被称作启发式搜索方法,但是当我们模型的效果不如预期那么好时,我们怎样定位是集束搜索的问题还是RNN网络的问题呢?

这就需要我们之前提到的误差分析,我们现在学习一下关于集束搜索的误差分析。

我们的机器模型有神经网络模型(seq2seq模型)和集束搜索算法组成,当我们的机器翻译模型达不到预期模型时,我们应该定位是RNN神经网络的原因,还是集束搜索算法的原因。

具体的做法是,我们需要比较$P(y^* \mid x)$与$P(\hat y \mid x)$的大小关系:

  • $P(y^* \mid x) >P(\hat y \mid x)$

    这种情况下,RNN模型能够给出正确的“评分”,但是集束搜索算法没有搜索到正确的答案,因此,属于集束搜索算法出错了,我们可以通过增大集束宽度的方法提高集束算法的准确度。

  • $P(y^* \mid x) \leq P(\hat y \mid x)$

    这种情况下,对于$y^*$的评分低于$\hat y$,说明RNN模型除了问题,我们可以进行更深层次的分析,来看是过拟合还是欠拟合,进而选择不同的方案。

3. 注意力模型

注意力模型或者说注意力这种思想是深度学习最重要的思想之一,我们对其进行了解并学习。

上面讲的机器翻译模型有个缺点,即对于长的句子效果不好,因为在神经网络中,记忆非常长的的句子是非常困难的。注意力模型会模拟人类的翻译方式,每次翻译句子的一部分。

注意力模型起源于机器翻译,但是被推广到其他领域,属于非常开创性的思想。

image-20190718203745980

如上图所示,这是一个双向RNN网络,我们可以理解为机器翻译中的编码器,它读入原始句子的每个单词,然后生成每个单词对应的特征向量$\hat y^{}$。注意,此处的编码网络与之前的编码网络不通,之前的编码网络输出全部的特征向量作为解码网络的$a$,但是在这里,每个单词都会生成一个特征向量。

接下来是注意力模型的核心部分:

image-20190718204128081

上图的下半部分就是我们提到的双向RNN网络,用于编码,生成每个单词的特征向量。

上面的网络就是解码网络,我们以翻译后句子中的其中一个单词为例,在t时刻我们的输入包含以下内容:

  • RNN上一单元的$S^{}$
  • RNN上一单元的输出$\hat y^{}$
  • 从编码器获得的注意力特征向量$\sum _{t’=1}\alpha ^{<t,t’>}a^{<t’>}$($\alpha ^{<t,t’>}$代表求解t个单词时,采纳每个输入单词特征$a^{<t’>}$的多少)

那么注意力参数$\alpha$是怎样计算的呢?

\[\alpha^{<t,t'>}=\frac{e^{e^{<t,t'>}}}{\sum_{t'=1}^{T_x}e^{e^{<t,t'>}}}\tag{3-1}\]

通过公式3-1我们可以看到,这样生成的注意力参数和为1,但是$e^{<t,t’>}$怎样求解呢?

image-20190718210016399

如上图所示,通过一个小型的神经网络,以上一RNN单元的隐藏层$S^{}$与编码网络中当前单词的输出$a^{<t'>}$为输入,经过标准的神经网络,得到$e^{<t,t'>}$的值。

注意力模型的缺点就是时间复杂度为$O(n^3)$。

4. 语音识别与触发字检测

在之前,语音识别系统靠音位来构建,也就是人工设计的基本单元。但是在现在,已经被end-to-end方法所取代,我们可以直接向系统输入音频片段,直接输出文本。

image-20190718221245071

我们可以使用学习过的注意力模型。

还有一种办法是使用CTC损失函数做语音识别:

image-20190718222838768

网络如上图所示,我们使用RNN,输入x和输出y的数量是一样的,通常语音识别的输入时间步数量比输出时间步数量多得多,例如上述模型的输出为:ttt_h_eee__q_,。CTC损失函数的一个基本规则是将空白符之间的重复的字符折叠起来,这样我们得到的输出会短很多。


触发字检测系统,关于触发字检测系统,目前出发发展阶段,还没有一个广泛的定义。

我们来学习一个常见的模型:

image-20190718223703409

如下图所示,我们输入音频片段,然后得到特征向量,再将特征向量放入RNN中,判断当前的单词是什么。如果当前的单词时触发字,我们就将其标记为1;反之为0。这样的标签方案对于RNN是可行的,并且效果还不错。

但是存在一个问题,就是我们的训练集不平衡,1很少,0很多。一个简单粗暴的方法是在输出1时,我们令其附近的单词标记也为1,这样稍微提高了1的比例。