DeepLearning.ai学习笔记(五)序列模型 -- week2 序列模型和注意力机制

2022-05-11 16:34:21 浏览数 (1)

一、基础模型

假设要翻译下面这句话:

"简将要在9月访问中国"

正确的翻译结果应该是:

"Jane is visiting China in September"

在这个例子中输入数据是10个中文汉字,输出为6个英文单词,T_xT_y 数量不一致,这就需要用到序列到序列的RNN模型。​

类似的例子还有看图说话:

只需要将encoder部分用一个CNN模型替换就可以了,比如AlexNet,就可以得到“一只(可爱的)猫躺在楼梯上”

二、选择最优句子

下面将之前学习的语言模型和机器翻译模型做一个对比, P为概率

下图是语言模型,可以用在自动生成文章或者预测文字之类的应用中,即根据前一个字输出下一个字。

下图是机器翻译模型,可以看到后半部分(紫色)其实就是语言模型,吴大大称之为“条件语言模型”,即在语言模型之前有一个条件,也就是被翻译的句子。

用数学公式表示就是:

P(y^{<1>},…,y^{<T_y>}|x^{<1>},…,x^{<T_x>})

但是我们知道翻译是有很多种方式的,同一句话可以翻译成很多不同的句子,那么我们如何判断那一个句子是最好的呢?

还是翻译上面那句话,有如下几种翻译结果:

  • "Jane is visiting China in September."
  • "Jane is going to visit China in September."
  • "In September, Jane will visit China"
  • "Jane's Chinese friend welcomed her in September."
  • ....

与语言模型不同的是,机器模型在输出部分不再使用softmax随机分布的形式进行取样,因为很容易得到一 个不准确的翻译,取而代之的是使用Beam Search做最优化的选择。这个方法会在后下一小节介绍,在此之前先介绍一下贪婪搜索(Greedy Search)及其弊端,这样才能更好地了解Beam Search的优点。

得到最好的翻译结果,转换成数学公式就是argmax P(y^{<1>},…,y^{<T_y>}|x^{<1>},…,x^{<T_x>}) 那么贪婪搜索是什么呢?

通俗解释就是每次输出的那个都必须是最好的。还是以翻译那句话为例。

现在假设通过贪婪搜索已经确定最好的翻译的前两个单词是:"Jane is "

然后因为"going"这个单词出现频率较高和其它原因,所以根据贪婪算法得出此时第三个单词的最好结果是"going"。

所以根据贪婪算法最后的翻译结果可能是下图中的第二个句子,但是第一句可能会更好(不服气的话,我们就假设第一句更好hhhh)。

所以贪婪搜索的缺点是局部最优并不代表全局最优,就好像五黑,一队都是很牛逼的,但是各个都太优秀,就显得没那么优秀了,而另一队虽然说不是每个都是最优秀,但是凑在一起就是能carry全场。

更形象的理解可能就是贪婪搜索更加短视,看的不长远,而且也更加耗时。假设字典中共有10000个单词,如果使用贪婪搜索,那么可能的组合有10000^{10}种,所以还是挺恐怖的2333~~

三、定向搜索(Beam Search)

Beam Search是贪婪搜索的加强版,首先它需要设置beam width,下面设置为3。(如果设置为1,就是贪婪搜索)

步骤一

如下图示,因为beam width=3,所以根据输入的需要翻译的句子选出3个y^{<1>} 最可能的输出值,即选出P(y^{<1>|x})最大的前3个值。假设分别是"in","jane","september"。

步骤二

以"in"为例进行说明,其他同理。 如下图示,在给定被翻译句子x 和确定 y^{<1>} ="in" 的条件下,下一个输出值的条件概率是P(y^{<2>}|x,"in") 。此时需要从10000种可能中找出条件概率最高的前3个。

又由公式P(y^{<1>},y^{<2>}|x)=P(y^{<1>}|x)P(y^{<2>}|x,y^{<1>}) ,我们此时已经得到了给定输入数据,前两个输出值的输出概率比较大的组合了。

另外2个单词也做同样的计算。

此时我们得到了9组P(y^{<1>},y^{<2>}|x) ,此时我们再从这9组中选出概率值最高的前3个。如下图示,假设是这3个:

  • "in september"
  • "jane is"
  • "jane visits"

步骤3:

继续步骤2的过程,根据P(y^{<3>}|x,y^{<1>},y^{<2>}) 选出P(y^{<1>},y^{<2>},y^{<3>}|x) 最大的前3个组合。

后面重复上述步骤得出结果。

总结一下上面的步骤就是:

  • 第一步: 经过encoder以后,decoder给出最有可能的三个开头词依次为“in”, "jane", "september" --- P(y^{<1>}|x)
  • 第二步: 经过将第一步得到的值输入到第二步中,最有可能的三个个翻译为“in september”, "jane is", "jane visits" ---P(y^{<2>}|x,y^{<1>}) (这里,september开头的句子由于概率没有其他的可能性大,已经失去了作为开头词资格)
  • 第三步: 继续这个过程... ---- P(y^{<3>}|x,y^{<1>},y^{<2>})

四、改进定向搜索

因为P(y^{<1>},….,P(y^{T_y})|x)=P(y^{<1>}|x)P(y^{<2>}|x,y^{<1>})…P(y^{<T_y>}|x,y^{<1>},…y^{<{T_y-1}>}) 所以要满足argmax P(y^{<1>},….,P(y^{T_y})|x) ,也就等同于要满足argmax prod_{t=1}^{T_y}P(y^{<t>}|x,y^{<1>},…y^{<{t-1}>}) 但是上面的公式存在一个问题,因为概率都是小于1的,累乘之后会越来越小,可能小到计算机无法精确存储,所以可以将其转变成log形式(因为log是单调递增的,所以对最终结果不会有影响),其公式如下:

argmax sum_{t=1}^{T_y}logP(y^{<t>}|x,y^{<1>},…y^{<{t-1}>})

But!!!上述公式仍然存在bug,观察可以知道,概率值都是小于1的,那么log之后都是负数,所以为了使得最后的值最大,那么只要保证翻译的句子越短,那么值就越大,所以如果使用这个公式,那么最后翻译的句子通常都是比较短的句子,这显然不行。

所以我们可以通过归一化的方式来纠正,即保证平均到每个单词都能得到最大值。其公式如下:

argmax frac{1}{T_y}sum_{t=1}^{T_y}logP(y^{<t>}|x,y^{<1>},…y^{<{t-1}>})

通过归一化的确能很好的解决上述问题,但是在实际运用中,会额外添加一个参数α ,其大小介于0和1之间,公式如下:

argmax frac{1}{T_y^α}sum_{t=1}^{T_y}logP(y^{<t>}|x,y^{<1>},…y^{<{t-1}>})

五、定向搜索的误差分析

静下心来仔细想想beam search,我们会发现其实它是近似搜索,也就是说可能使用这种方法最终得到的结果并不是最好的。当然也有可能是因为使用的RNN模型有缺陷导致结果不是最好的。

所以我们如何判断误差是出在哪个地方呢? ​ 还是以翻译这句话为例:“简在9月访问中国”。

假设按照人类的习惯翻译成英文是“Jane visits China in September.”,该结果用 y^* 表示。

假设通过算法得出的翻译结果是:“Jane visited China in September.”,该结果用hat{y} 表示。 ​ 要判断误差出在哪,只需要比较P(y^*|x)P(hat{y}|x) 的大小即可。

下面分两种情况讨论:

1.P(y^*|x)>P(hat{y}|x) 上面的不等式的含义是beam search最后选出的结果不如人类,也就是beam search并没有选出最好的结果,所以问题出在beam search。

2.P(y^*|x)≤P(hat{y}|x) 上面不等式表示beam search最后选出的结果要比人类的更好,也就是说beam search已经选出了最好的结果,但是模型对各个组合的预测概率值并不符合人类的预期,所以这个锅需要模型背。

上面已经介绍了误差分析的方式,但时仅凭一次误差分析就判定谁该背锅肯定也不行,所以还需要进行多次误差分析多次。

如下图示已经进行了多次的误差分析,每次分析之后都判定了锅该谁背,最后计算出beam search和模型背锅的比例,根据比例作出相应的调整。

例如如果beam search更高,可以相应调整beam width。 如果模型背锅比例更高,那么可以考虑增加正则化,增加数据等操作。

六、Bleu得分(选修)

主要介绍了如何给机器翻译结果打分,因为是选修内容。。。so。。。emm

七、注意力模型直观理解

1.为什么要用注意力模型

​之前介绍的RNN翻译模型存在一个很明显的问题就是机器翻译的翻译过程是首先将所有需要翻译的句子输入到Encoder中,之后再通过Decoder输出翻译语句。如下图示机器算法将法语翻译成英语的模型。

机器翻译与人类的翻译过程不太相同。因为人类翻译一般是逐句翻译,或者是讲一段很长的句子分解开来进行翻译。

所以上述模型的翻译结果的Bleu评分与被翻译句子的长短有很大关系,句子较短时,模型可能无法捕捉到关键信息,所以翻译结果不是很高;但是当句子过长时,模型又抓不到重点等原因使得结果也不是很高。 ​

​而如果机器能像人一样逐句或者每次将注意力只集中在一小部分进行翻译,那么翻译结果将不受句子长度的影响。下图中的绿色线即为使用了注意力模型后的翻译句子得分。

2.模型介绍

​ 下图展示了普通的翻译模型双向RNN结构,该结构可根据输入x^{<t>} 直接得到输出y^{<t>}

注意力模型在此基础上做进一步处理。

为避免误解,使用另一个符号s 来表示节点。

如下图示,根据下面一层的双向RNN计算结果可得到节点s^{<1>} 与其他节点权重α^{<1,1>},α^{<1,2>},… ,通过这些权重可以知道该节点与其他节点的相关联程度,从而可以达到将注意力集中到部分区域的效果。 ​

​其他节点同理。整个注意力模型结构如下图示。

八、注意力模型

特别要区分a (字母a)a (alpha)。前者表示特征节点,后者表示注意力权重。

1.参数介绍

​如下图示,注意力模型采用双向RNN结构,所以每个节点有两个值,用(overrightarrow{a}^{<t'>},overleftarrow{a}^{<t'>} )表示,为了使公式更简化,令a^{<t'>}=(overrightarrow{a}^{<t'>},overleftarrow{a}^{<t'>}) 。其中t' 表示输入数据的索引。

上一节已经介绍了注意力权重α^{<t,t'>} ,以第一个节点为例,它的权重值可以用α^{<1,t'>} 表示,且所有权重值满足sum{α^{<1,t'>}}=1

所有权重与对应节点的线性之和用c^{<t'>} 表示(为方便书写,用c 表示),c表示context,即上下文变量。

还是以第一个节点为例,c的计算公式如下:

c^{<1>}=sum_{t'}α^{<1,t'>}a^{<t'>}

2.注意力权值计算公式

alpha^{<t,t'>}=frac{exp(e^{<t,t'>})}{sum_{t''=1}^{T_x}{exp(e^{t,t''})}}上面公式中的e^{<t,t'>} 计算图如下:

其中s^{<t-1>} 表示上一个状态的值,a^{<t'>} 表示第t'个特征节点。

视频中吴大大并没有很详细的介绍上面的网络,只是一笔带过,说反向传播和梯度下降会自动学习,emmm。。。那就这样吧。

结合下图可以独自参考一下上面的公式是什么意思。

3.舶来品

下面的笔记是《大数据文摘》的笔记,感觉他写的清楚一些。

如图所示,这是一个双向的rnn,并且在普通rnn的基础上增加attention层,将阶段性的输入部分转化为输出,这样的方式也更符合人类的翻译过程。

让我们拿出细节部分仔细的理解一下,首先是attention层,也就是下图中context^{<t>} ,每一个attention单元接受 三个单词的输入所以也称作语境单元(context),α 是每单个输入词在语境单元中占得权重。对每一个语境单元t 来说,因为α 是通过softmax决定的,所以sum_{i=1}^{T_x}α^{t,i}=1 。这里决定终每一个单词占得语境权重仍然是通过一 个小型的神经网络来进行计算并且后得到的。

输出的context^{<t>} 进入到下一层Post LSTM 这一步就和之前学习过的那样子,将前一步的输出与这一步经过重重分析的输入综合到一起产生这一步的输出。

让我们评估一下attention model: 由于结构的复杂,计算量与时间比普通的语言模型要多和慢许多。不过对于机 器翻译来说,由于每一句话并不会特别特比特的长,所以有的时候稍微慢一点也不是完全无法接受:p

一个很重要attention model的应用就是语音识别,人通过麦克风输入一句话让机器来翻译输入的内容,让我们来 看一下是如何实现的

九、语音辨识

一般语音识别过程是如下图示的,即首相将原音频(黑白的,纵轴表示振幅)转化成纵轴为频率的音谱图,并且通过人工预先设定的音素(phonemes)再来识别。

而引入注意力机制后的模型就表现优秀得多了

CTC(connectionist temporal classification)是之前较为常用的方法。

具体原理如下:

假设每秒音频可以提取出100个特征值,那么假设10秒的音频就有1000个特征值,那么输出值也有1000个,但是说出的话并没有这么多啊,那该怎么处理呢?

方法很简单,只需要把“_”进行压缩即可,注意需要将 "_"和空额区分开来,因为空格也是占一个字符的。

十、触发字检测

假设下图式训练集中的一段音频,其中包含了两次唤醒词

搭建一个attention model,在听到唤醒词之前一直输出的是0,在听到唤醒词以后输出1,但因为一个唤醒词会持 续半秒左右所以我们也不仅仅只输出一次1,而是将输出的1持续一段时间,通过这样的方式训练出的rnn就可以很 有效的检测到唤醒词了。

0 人点赞