# 第三周 序列模型和注意力机制（Sequence models & Attention mechanism）

## 3.1 基础模型（Basic Models）

### 机器翻译

用$$x^{< 1>}$$ 到$$x^{< 5>}$$表示输入句子的单词，用$$y^{< 1>}$$到$$y^{< 6>}$$表示输出句子的单词：

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/2d41c0090fd3d71e6f28eade62b7c97b.png)

首先，建立一个**RNN**编码网络（**encoder network**）（编号1），单元可以是**GRU**或**LSTM**。每次只向该网络中输入一个法语单词，将输入序列接收完毕后，这个**RNN**网络会输出一个向量来代表这个输入序列

之后建立一个解码网络（编号2），以编码网络的输出作为输入，之后它可以被训练为每次输出一个翻译后的单词，一直到它输出序列的结尾或者句子结尾标记

在给出足够的法语和英语文本的情况下，训练模型，通过输入一个法语句子来输出对应的英语翻译，这个模型将会非常有效。这个模型简单地用一个编码网络来对输入的法语句子进行编码，然后用一个解码网络来生成对应的英语翻译

### 图像描述

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/b9492d18803ebe3853e936098f08661c.png)

> 给出猫的图片，能自动地输出该图片的描述：一只猫坐在椅子上

通过输入图像来输出描述：

将图片输入到卷积神经网络中（一个预训练的**AlexNet**结构）（编号2），然后让其学习图片的编码，或者学习图片的一系列特征。去掉最后的**softmax**单元（编号3），这个预训练的**AlexNet**结构会输出4096维的特征向量，向量表示的就是这只猫的图片，这个预训练网络可以是图像的编码网络

接着把这个向量输入到**RNN**中（编号4），RNN要做的就是生成图像的描述，每次生成一个单词：输入一个描述输入的特征向量，然后让网络一个一个地输出单词序列

## 3.2 选择最可能的句子（Picking the most likely sentence）

**seq2seq**机器翻译模型和第一周所用的语言模型之间有很多相似的地方，但也有许多重要的区别：

可以把机器翻译想成是建立一个条件语言模型，能够估计句子的可能性

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/a8b8c64483ee84d57135829ab025da53.png)

绿色（编号2）表示**encoder**网络，紫色（编号3）表示**decoder**网络。不同在于语言模型总是以零向量（编号4）开始，而**encoder**网络会计算出一系列向量（编号2）来表示输入的句子，以这个向量作为输入，这叫做条件语言模型（**conditional language model**）

相比语言模型输出任意句子的概率，翻译模型会输出句子的英文翻译（编号5），这取决于输入的法语句子（编号6）。即估计一个英文翻译的概率，比如估计"**Jane is visiting Africa in September.**"翻译的概率，这句翻译是取决于法语句子，"**Jane visite I'Afrique en septembre.**"，这就是英语句子相对于输入的法语句子的可能性，是一个条件语言模型

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/fd97f885fe1e6e1a7c70bb965595210a.png)

> 模型将法语翻译成英文，通过输入的法语句子模型将会告诉你各种英文翻译所对应的可能性

$x$是法语句子"**Jane visite l'Afrique en septembre.**"，它将告诉你不同的英语翻译所对应的概率：从这个分布中进行取样得到$$P(y|x)$$，但不是从得到的分布中进行随机取样，而是要找到一个英语句子$$y$$（编号1），使得条件概率最大化：

$$
max\ P(y^{< 1>},y^{< 2>},\cdots,y^{< T\_y>}|x^{< 1>},x^{< 2>},\cdots,x^{< T\_x>})
$$

而解决这种问题最通用的算法就是束搜索(**Beam Search**)

为什么不用贪心搜索(**Greedy Search**)：

贪心搜索生成第一个词的分布以后，将会根据条件语言模型挑选出最有可能的第一个词进入机器翻译模型中，在挑选出第一个词之后将会继续挑选出最有可能的第二个词……这种算法就叫做贪心搜索，但是真正需要的是一次性挑选出整个单词序列，从$$y^{< 1>}$$、$$y^{< 2>}$$到$$y^{< T\_{y}>}$$来使得整体的概率最大化。所以贪心算法先挑出最好的第一个词，在这之后再挑最好的第二词，然后再挑第三个，这种方法并不管用

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/c50a0e8948bbdb9a1d23f2f8a768bf5c.png)

第一串（编号1）翻译明显比第二个（编号2）好，但如果贪心算法挑选出了"**Jane is**"作为前两个词，因为在英语中**going**更加常见，于是对于法语句子来说"**Jane is going**"相比"**Jane is visiting**"会有更高的概率作为法语的翻译，所以如果仅仅根据前两个词来估计第三个词的可能性，得到的更可能是**going**，最终得到一个欠佳的句子

当想得到单词序列$$y^{< 1>}$$、$$y^{< 2>}$$一直到最后一个词总体的概率时，一次仅仅挑选一个词并不是最佳的选择。如果字典中有10,000个单词，翻译有10个词，可能的组合就有10,000的10次方这么多，从这样大一个字典中来挑选单词，句子数量非常巨大，大大增加了运算成本，降低运算速度，不可能去计算每一种组合的可能性

所以最常用的办法就是用一个近似的搜索算法，它会尽力地将挑选出句子$$y$$使得条件概率最大化，尽管不能保证找到的$$y$$值一定可以使概率最大化

机器翻译模型和之前的语言模型一个主要的区别就是：相比之前的模型随机地生成句子，该模型是找到最有可能的翻译

## 3.3 集束搜索（Beam Search）

“**Jane visite l'Afrique en Septembre.**”翻译成英语"**Jane is visiting Africa in September**".，集束搜索算法首先做的就是挑选要输出的英语翻译中的第一个单词。这里列出了10,000个词的词汇表，忽略大小写，在集束搜索的第一步中用这个网络来评估第一个单词的概率值，给定输入序列$$x$$，即法语作为输入，第一个输出$$y$$的概率值是多少

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/8a22dfb5d3c0a4b5d2fdfa716dc3f3b2.png)

集束搜索会考虑多个选择，集束搜索算法会有一个参数**B**，叫做集束宽（**beam width**）。这个例子中集束宽设成3，意味着集束搜索一次会考虑3个可能结果，比如对第一个单词有不同选择的可能性，最后找到**in**、**jane**、**september**，是英语输出的第一个单词的最可能的三个选项，然后集束搜索算法会把结果存到计算机内存里以便后面尝试用这三个词。为了执行集束搜索的第一步，需要输入法语句子到编码网络，然后解码这个网络，**softmax**层会输出10,000个概率值，然后取前三个存起来，概率表示为：

$$
P(\hat y^{< 1>} | x)
$$

集束搜索算法的第二步：针对每个第一个单词考虑第二个单词是什么

![14a940ae2ea7932b7b7190eceb79f79e.png)](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/14a940ae2ea7932b7b7190eceb79f79e.png)

为了评估第二个词的概率值，把$$y^{< 1>}$$设为单词**in**（编号3），输出就是$$y^{< 2>}$$（编号5），有了这个连接（编号6），这个网络就可以用来评估：在给定法语句子和翻译结果的第一个单词**in**的情况下第二个单词的概率

在第二步更关心的是要找到最可能的第一个和第二个单词对，所以不仅仅是第二个单词有最大的概率，而是第一个、第二个单词对有最大的概率（编号7）。可以表示成第一个单词的概率（编号8）乘以第二个单词的概率（编号9）：

$$
P(\hat y^{< 1>},\hat y^{< 2>}|x)=P(\hat y^{< 1>} | x)\cdot P(\hat y^{< 2>}|x,\hat y^{< 1>})
$$

**jane**、**september**跟上面一样

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/507c9081ee77c686bb96a009248087fd.png)

注意，如果集束搜索找到了第一个和第二个单词对最可能的三个选择是“**in September**”或者“**jane is**”或者“**jane visits**”，就意味着去掉了**september**作为英语翻译结果的第一个单词的选择，第一个单词现在减少到了两个可能结果，但是集束宽是3，还是有$$y^{< 1>}$$，$$y^{< 2>}$$对的三个选择

接着，再预测第三个单词。分别以in september，jane is，jane visits为条件，计算每个词汇表单词作为预测第三个单词的概率。从中选择概率最大的3个作为第三个单词的预测值，得到：in september jane，jane is visiting，jane visits africa

![6a0b785dd54fcbc439bd82794eeefcf8.png)](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/6a0b785dd54fcbc439bd82794eeefcf8.png)

概率表示为：

$$
P(\hat y^{< 3>}|x,\hat y^{< 1>},\hat y^{< 2>})
$$

此时，得到的前三个单词的3种情况的概率为：

$$
P(\hat y^{< 1>},\hat y^{< 2>},\hat y^{< 3>}|x)=P(\hat y^{< 1>} | x)\cdot P(\hat y^{< 2>}|x,\hat y^{< 1>})\cdot P(\hat y^{< 3>}|x,\hat y^{< 1>},\hat y^{< 2>})
$$

以此类推，每次都取概率最大的三种预测。最后，选择概率最大的那一组作为最终的翻译语句：

**Jane is visiting Africa in September.**

如果参数B=1，则就等同于greedy search。实际应用中，可以根据不同的需要设置B为不同的值。一般B越大，机器翻译越准确，但同时也会增加计算复杂度

## 3.4 改进集束搜索（Refinements to Beam Search）

长度归一化（**Length normalization**）是对束搜索算法稍作调整的一种方式，使之得到更好的结果

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/725eec5b76123bf45c9495e1231b6584.png)

**束搜索**就是最大化概率$$P(y^{< 1 >}\ldots y^{< T\_{y}>}|X)$$，表示成:

$$
P(y^{< 1>}|X)P(y^{<  2 >}|X,y^{<  1 >})P(y^{<  3 >}|X,y^{<  1 >},y^{<  2>})\cdots P(y^{<  T\_{y} >}|X,y^{< 1 >},y^{< 2 >}\ldots y^{<  T\_{y} - 1 >})
$$

即乘积概率（**the product probabilities**）：

$$
arg\ max\prod\_{t=1}^{T\_y} P(\hat y^{<  t>}|x,\hat y^{< 1>},\cdots,\hat y^{< t-1>})
$$

这些概率值通常都远小于1，会造成**数值下溢**（**numerical underflow**），即数值太小了，导致电脑的浮点表示不能精确地储存

因此在实践中,不会最大化这个乘积，而是取$$log$$值：

$$
arg\ max \sum\_{t=1}^{T\_y}\log P(\hat y^{< t>}|x,\hat y^{< 1>},\cdots,\hat y^{< t-1>})
$$

会得到一个数值上更稳定的算法，不容易出现数值的舍入误差（**rounding errors**）或者说数值下溢（**numerical underflow**）

参照原来的目标函数（**this original objective**），如果有一个很长的句子，那么这个句子的概率会很低，因为乘了很多项小于1的数字来估计句子的概率，就会得到一个更小的概率值，所以可能不自然地倾向于简短的翻译结果，因为短句子的概率是由更少数量的小于1的数字乘积得到的，所以乘积不会那么小。概率的$$log$$值也有同样的问题

解决：可以把它归一化，通过除以翻译结果的单词数量。即取每个单词的概率对数值的平均，这样很明显地减少了对输出长的结果的惩罚：

$$
arg\ max\ \frac{1}{T\_y}\sum\_{t=1}^{T\_y}\log P(\hat y^{<  t>}|x,\hat y^{< 1>},\cdots,\hat y^{< t-1>})
$$

在实践中，会用一个更柔和的方法（**a softer approach**），在$$T\_{y}$$上加上指数$$\alpha$$：

$$
arg\ max\ \frac{1}{T\_y^{\alpha}}\sum\_{t=1}^{T\_y}\log P(\hat y^{<  t>}|x,\hat y^{< 1>},\cdots,\hat y^{< t-1>})
$$

$\alpha$可以等于0.7。如果$$\alpha$$等于1，就相当于完全用长度来归一化，如果$$\alpha$$等于0，$$T\_{y}$$的0次幂就是1，就相当于完全没有归一化，$$\alpha$$就是算法另一个超参数（**hyper parameter**）

总结一下如何运行束搜索算法：

当运行束搜索时，会看到很多长度分别等于1、2、3...的句子等等，针对这些所有的可能的输出句子，取概率最大的几个句子，然后对这些句子计算目标函数$$arg\ max\ \frac{1}{T\_y^{\alpha}}\sum\_{t=1}^{T\_y}\log P(\hat y^{< t>}|x,\hat y^{< 1>},\cdots,\hat y^{< t-1>})$$，最后从经过评估的这些句子中挑选出在归一化的$$log$$ 概率目标函数上得分最高的一个，也叫作**归一化的对数似然目标函数**（**a normalized log likelihood objective**）

如何选择束宽**B：**

![96e50aec6e1d7287e5bac70a0c4d92f4.png)](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/96e50aec6e1d7287e5bac70a0c4d92f4.png)

* **B**越大，考虑的选择越多，找到的句子可能越好，但是算法的计算代价越大，因为要把很多的可能选择保存起来，内存占用增大
* 如果用小的束宽**B**，结果会没那么好，因为在算法运行中，保存的选择更少，但是算法运行的更快，内存占用也小

在产品中，经常可以看到把束宽设到10，当B很大的时候，性能提高会越来越少。对于很多应用来说，从束宽1，也就是贪心算法，到束宽为3、到10，会看到一个很大的改善。但是当束宽从1000增加到3000时，效果就没那么明显

相对广度优先搜索（**BFS, Breadth First Search algorithms**），深度优先搜索（**DFS, Depth First Search**）这些精确的搜索算法（**exact search algorithms**），束搜索运行的更快，但是不能保证一定能找到argmax的准确的最大值

## 3.5 集束搜索的误差分析（Error analysis in beam search）

束搜索算法是一种**近似搜索算法**（**an approximate search algorithm**），也被称作**启发式搜索算法**（**a heuristic search algorithm**），它不总是输出可能性最大的句子，它仅记录着**B**为前3或者10或是100种可能

人工标记为$$y^\*$$。束搜索算法翻译结果标记为$$\hat y$$，是一个十分糟糕的翻译，改变了句子的原意：

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/748283d682db5be4855e61b90e96c427.png)

模型有两个主要部分，一个是神经网络模型，或说是序列到序列模型（**sequence to sequence model**），称作是**RNN**模型，另一部分是束搜索算法，以某个集束宽度**B**运行

**RNN**(**循环神经网络**)实际上是个编码器和解码器（**the encoder and the decoder**），它会计算$$P(y|x)$$。如对于句子：**Jane visits Africa in September**，将**Jane visits Africa**填入这里（上图编号1），忽略字母的大小写，后面也是一样，计算得到$$P(y^\*|x)$$，$$P(\hat y|x)$$ 同样如此，然后比较一下这两个值哪个更大

![1bc0b442db9d5a1aa19dfe9a477a3c3e.png)](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/1bc0b442db9d5a1aa19dfe9a477a3c3e.png)

* 若$$P(y^*|x)$$ 大于$$P(\hat y|x)$$，可束搜索算法却选择了$$\hat y$$ ， 因此能够得出束搜索算法实际上不能给出使$$P(y|x)$$最大化的$$y$$值，因为束搜索算法的任务就是寻找一个$$y$$的值来使这项更大，但是它却选择了$$\hat y$$，而$$y^*$$实际上能得到更大的值。因此这种情况下束搜索算法出错
* 若$$P(y^*|x)$$小于或等于$$P(\hat y|x)$$，$$y^*$$ 是比 $$\hat y$$更好的翻译结果，不过根据RNN模型的结果，$$P(y^*)$$ 是小于$$P(\hat y)$$的，即相比于$$\hat y$$，$$y^*$$成为输出的可能更小。因此在这种情况下是**RNN**模型出了问题

以上都忽略了长度归一化（**length normalizations**）的细节，如果用了某种长度归一化，那么要比较长度归一化后的最优化目标函数值

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/2689876529562b7d9a79bf868e7cbad7.png)

误差分析过程：

1. 先遍历开发集，找出算法产生的错误
2. 假如$$P(y^*|x)$$的值为2 x 10$$^{-10}$$，而$$P(\hat y|x)$$的值为 1 x10$$^{-10}$$，得知束搜索算法实际上选择了比$$y^*$$可能性更低的$$\hat y$$，则束搜索算法出错，缩写为**B**
3. 接着继续遍历第二个错误，若对于第二个例子是**RNN**模型出现了问题，用缩写**R**来代表**RNN**
4. 接着遍历更多的例子，有时是束搜索算法出现了问题，有时是模型出现了问题，等等
5. 执行误差分析，得出束搜索算法和**RNN**模型出错的比例是多少。对开发集中每一个错误例子，即算法输出了比人工翻译更差的结果的情况，尝试确定是搜索算法出了问题，还是生成目标函数(束搜索算法使之最大化)的**RNN**模型出了问题。找到这两个部分中哪个是产生更多错误的原因
6. 只有当发现是束搜索算法造成了大部分错误时，才值得花费努力**增大集束宽度B**；如果发现是**RNN**模型出了更多错，那么可以进行更深层次的分析，来决定是需要**增加正则化**还是**获取更多的训练数据**，抑或是尝试一个**不同的网络结构**

## 3.6 Bleu 得分（选修）（Bleu Score (optional)）

机器翻译（**machine translation**）的一大难题是一个法语句子可以有多种英文翻译而且都同样很好，常见的解决办法是通过一个**BLEU**得分（**the BLEU score**）的东西来解决，BLEU得分是一个有用的单一实数评估指标，用于评估生成文本的算法，判断输出的结果是否与人工写出的参考文本的含义相似

一般有多个人工翻译：

![5e854a803e36991a6e0dd4e33ecab930.png)](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/5e854a803e36991a6e0dd4e33ecab930.png)

BLEU得分做的就是给定一个机器生成的翻译，它能够自动地计算一个分数来衡量机器翻译的好坏。只要机器生成的翻译与任何一个人工翻译的结果足够接近，那么它就会得到一个高的BLEU分数。**BLEU**代表**bilingual evaluation understudy**(双语评估替补)。且这些人工翻译的参考会包含在开发集或是测试集中

假设机器翻译 (**MT**)的输出是：**the the the the the the the，**&#x662F;一个十分糟糕的翻译。衡量机器翻译输出质量的方法之一是**观察输出结果的每一个词，看其是否出现在参考中**，这被称做是机器翻译的精确度（**a precision of the machine translation output**）。这个情况下，机器翻译输出了七个单词并且这七个词中的每一个都出现在了参考1或是参考2，因此输出的精确度就是7/7，分母为机器翻译单词数目，分子为相应单词是否出现在参考翻译中。但是，这种方法很不科学，并不可取

改良后的精确度评估方法（**the modified precision measure**）：**把每一个单词的记分上限定为它在参考句子中出现的最多次数**。在参考1中，单词**the**出现了两次，在参考2中，单词**the**只出现了一次。单词**the**的得分上限为2。输出句子的得分为2/7，分母是7个词中单词**the**总共出现的次数，分子是单词**the**出现的计数，在达到**上限**时截断计数

上述都只是关注单独的单词，在**BLEU**得分中，另外一种更科学的打分方法是**bleu score on bigrams（二元词组）**，bigram的意思就是相邻的两个单词

定义**截取计数**（**the clipped count**），也就是**Count\_clip：**&#x7ED9;算法设置得分上限，上限值为二元词组出现在参考1**或**2中的最大次数

假定机器翻译输出了稍微好一点的翻译，对MT output进行分解，得到的bigrams及其出现在MT output中的次数count为：

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/0bc25316900ccd1d4dd25a35ec7c45c4.png)

相应的bigrams precision为4/6也就是2/3，为二元词组改良后的精确度

将改良后的一元词组精确度定义为$$P\_1$$，$$P$$代表的是精确度。下标1的意思是一元词组，即考虑单独的词，$$P\_n$$ 定义为$$n$$元词组精确度，用**n-gram**替代掉一元词组。即机器翻译输出中的$$n$$元词组的**countclip**之和除以$$n$$元词组的出现次数之和

![](https://github.com/fengdu78/deeplearning_ai_books/raw/master/images/7f48951acf8ca7c7b63f6c4c455ada18.png)

如果机器翻译输出与参考1或是参考2完全一致，那么所有的$$P\_1$$、$$P\_2$$等等的值，都会等于1.0

最终的BLEU得分：

将得到的$$P\_1$$，$$P\_2$$， $$P\_3$$...$$P\_n$$ 相加再取平均值

BLEU得分被定义为：

$$
p=exp (\frac{1}{n}\sum\limits\_{i=1}^{n}{P\_i})
$$

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/0f9646d825a0c254376e094b48523ed3.png)

然后用BP（“简短惩罚”brevity penalty） 的惩罚因子（the BP penalty）来调整。它能够惩罚输出了太短翻译结果的翻译系统：

$$
p=BP\cdot exp(\frac1n\sum\_{i=1}^np\_i)
$$

BLEU得分被用来评估许多生成文本的系统（systems that generate text），比如说机器翻译系统（machine translation systems），图像描述系统（image captioning systems）。不过它并没有用于语音识别（speech recognition）。因为在语音识别当中，通常只有一个答案

## 3.7 注意力模型直观理解（Attention Model Intuition）

给定一个很长的法语句子，在神经网络中，绿色的编码器要做的就是读整个句子，然后记忆整个句子，再在感知机中传递。紫色的神经网络，即解码网络（**the decoder network**）将生成英文翻译

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/59279ff91bb69a94280e6735eba8ab99.png)

对于短句子效果非常好，会有一个相对高的**Bleu**分（**Bleu score**），但是对于长句子而言，比如说大于30或者40词的句子，它的表现就会变差。**Bleu**评分随着单词数量变化，短的句子会难以翻译，因为很难得到所有词。对于长的句子，效果也不好，因为在神经网络中，记忆非常长句子是非常困难的。

而注意力模型翻译得很像人类，一次翻译句子的一部分。且机器翻译系统只会翻译句子的一部分，不会有一个巨大的下倾（**huge dip**），这个下倾衡量了神经网络记忆一个长句子的能力

对于句子里的每五个单词，使用双向的**RNN**（**a bidirectional RNN**），使用另一个**RNN**生成英文翻译：

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/3dcdd58eaa544a09e67eb892f8c732bf.png)

S^{< t>}$由原语句附近单元共同决定，**注意力权重（attention weights）**$$\alpha^{< t,t'>}$$ 表示尝试生成第$$t$$个英文词时应该花多少注意力在第$$t'$$个法语词上面。直到最终生成$$< EOS>$$。离得越近，**注意力权重**越大，相当于当前的注意力区域有个滑动窗。$$c$$表示编码器激活函数在注意力权重加权后的结果，将$$c$$输入到解码器用来生成翻译语句， 同时上一个时间步输出的翻译结果也加入

## 3.8 注意力模型（Attention Model）

注意力模型让一个神经网络只注意到一部分的输入句子。当它在生成句子的时候，更像人类翻译

假定有一个输入句子，并使用双向的**RNN**，或者双向的**GRU**或者双向的**LSTM**，去计算每个词的特征：

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/1e6b86a4e3690b4a0c6b8146ffa2f791.png)

用$$a^{< t{'}>}$$表示时间步$$t$$上的特征向量。用$$t{'}$$来索引法语句子里面的词，由于是双向RNN，每个$$a^{< t{'}>}$$：

$$
a^{< t{'}>}=(a^{\rightarrow < t{'}>},a^{\leftarrow < t{'}>})
$$

注意力权重用$$\alpha$$表示，C是各个RNN神经元经过注意力权重得到的参数值。例如$$\alpha^{< 1,t{'}>}$$表示机器翻译的第一个单词“jane”对应的第$$t{'}$$个RNN神经元，$$C^{< 1>}$$表示机器翻译第一个单词“jane”对应的解码网络输入参数。满足：

$$
\sum\_{t{'}}\alpha^{< 1,t{'}>}=1
$$

$$
C^{< 1>}=\sum\_{t{'}}\alpha^{< 1,t{'}>}\cdot a^{< t{'}>}
$$

用状态$$S$$表示生成翻译。$$\alpha^{< t,t{'}>}$$是输出$$\hat y^{< t>}$$在$$t{'}$$时对RNN单元花在$$a^{< t{ '}>}$$上的注意力权重因子。即在$$t$$处生成输出词应该花多少注意力在第$$t{'}$$个输入词上面

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/b22dff4a3b1a4ea8c1ab201446e98889.png)

为了让$$\alpha^{< t,t{'}>}$$之和为1，利用softamx思想，引入参数$$e^{< t,t{'}>}$$，使得：

$$
a^{< t,t'>} = \frac{\text{exp}(e^{< t,t'>})}{\sum^{T\_x}\_{t'=1} \text{exp}(e^{< t,t'>})}
$$

只要求出$$e^{< t,t{'}>}$$，就能得到$$\alpha^{< t,t{'}>}$$

如何求出$$e^{< t,t{'}>}$$：

建立一个简单的神经网络

![](https://baozou.gitbooks.io/neural-networks-and-deep-learning/content/assets/504import.png)

输入$$s^{< t-1>}$$，即神经网络在上个时间步的状态和$$a^{< t{'}>}$$，训练一个很小的神经网络，利用反向传播算法、梯度下降算法迭代优化，学到一个正确的函数$$e^{< t,t{'}>}$$ 和$$\alpha^{< t,t{'}>}$$

缺点：计算量较大，$$T\_x$$个输入单词和$$T\_y$$个输出单词的注意力参数的总数是$$T\_x\times T\_y$$，但是在机器翻译的应用上，输入和输出的句子一般不会太长，消耗还是可以接受

注意力模型在图像捕捉方面也有应用。比如图片加标题（**image captioning**），即看一张图，写下这张图的标题

Attention model还能处理日期标准化的问题（**the date normalization problem**）：

![](https://github.com/fengdu78/deeplearning_ai_books/raw/master/images/fa6769127cd98ea0058f600449833a21.png)

训练一个神经网络，输入任何形式的日期，生成标准化的日期形式

还有可视化的注意力权重（**the visualizations of the attention weights**）。颜色越白表示注意力权重越大，颜色越深表示权重越小。输出语句单词与其输入语句单词对应位置的注意力权重较大，即对角线附近

## 3.9 语音识别（Speech recognition）

输入音频片段$$x$$（**an audio clip,x**），生成文本$$y$$：

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/8da3e9cf049139a8e4a78503bd72e7fd.png)

音频片段横轴是时间。麦克风的作用是测量出微小的气压变化，而气压随着时间而变化。音频数据的常见预处理步骤就是运行这个原始的音频片段，然后生成一个声谱图（**a spectrogram**），横轴是时间，纵轴是声音的频率（**frequencies**），图中不同的颜色显示了声波能量的大小（**the amount of energy**），也就是在不同的时间和频率上这些声音有多大

在**end-to-end**模型中，可以构建一个系统，通过向系统中输入音频片段（**audio clip**），然后直接输出音频的文本（**a transcript**）。这种方法要用一个很大的数据集，需要上千上万个小时的语音素材

如何建立一个语音识别系统：

在输入音频的不同时间帧上，用一个注意力模型来输出文本描述，如"**the quick brown fox**"

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/4130b85a0694549f02bdf60f7c47a3d7.png)

另一种方法是**CTC**损失函数（**CTC cost**），即**Connectionist Temporal Classification**

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/8f409fc3980b0be00dca49bf4fac2659.png)

输入$$x$$和输出$$y$$的数量都是一样，这里只是一个简单的单向**RNN**结构，在实际中有可能是双向的**LSTM、GRU**结构，并且通常是很深的模型

在语音识别中，通常输入的时间步数量（**the number of input time steps**）要比输出的时间步的数量（**the number of output time steps**）多出很多。如一段10秒的音频，并且特征（**features**）是100赫兹的，即每秒有100个样本，于是这段10秒的音频片段就会有1000个输入

算法思想如下：

把输出相应字符重复并加入空白（blank），形如：

$$
ttt \_ h\_eee\_ \_ \_ \sqcup\_ \_ \_ qqq\_ \_ \cdots
$$

下划线”\_“表示空白，“$$\sqcup$$“表示两个单词之间的空字符

CTC损失函数的一个基本规则是没有被空白符”\_“分割的重复字符将被折叠到一起，即表示一个字符。**the**和**quick**之间有一个空格符，这段序列折叠成"the &#x71;**"**

## 3.10 触发字检测（Trigger Word Detection）

触发字系统的例子如下：

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/28443f8b28afa63adb6cf89ce19c4f6d.png)

对于这样的**RNN**结构，要做的就是计算出一个音频片段（an audio clip）的声谱图特征（spectrogram features），得到特征向量$$x^{< 1>}$$, $$x^{< 2>}$$, $$x^{< 3>}$$..，然后把它放到**RNN**中，最后定义目标标签$$y$$

![](https://raw.githubusercontent.com/fengdu78/deeplearning_ai_books/master/images/f2da69f9fa6462c8e591e79db452f6c1.png)

假如音频片段中的这一点是某人刚刚说完一个触发字，比如"**Alexa**"，那么在这一点之前，可以在训练集中把目标标签都设为0，在这个点之后把目标标签设为1。假如在一段时间之后，触发字又被说了一次，那么就可以再次在这个点之后把目标标签设为1

不过该算法一个明显的缺点：它构建了一个很不平衡的训练集（**a very imbalanced training set**），0的数量比1多太多

解决方法：在输出变回0之前，多次输出1，或说在固定的一段时间内输出多个1，就稍微提高了1与0的比例，即在音频片段中，触发字刚被说完之后，就把多个目标标签设为1

![](https://baozou.gitbooks.io/neural-networks-and-deep-learning/content/assets/506import.png)
