序列模型——吴恩达深度学习课程笔记(五)

2020-07-20 12:03:21 浏览数 (1)

文章总览图

RNN模型

1,序列模型应用

输入或者输出中包含有序列数据的模型叫做序列模型。以循环神经网络RNN为基础建立的序列模型在自然语言处理,语音识别等领域中引起了巨大的变革。以下是一些序列模型的典型应用:

语音识别: 输入输出都为序列。

音乐生成: 输出为序列。

情感分析:输入为序列。

DNA序列分析:输入为序列。

机器翻译:输入输出都为序列。

视频行为识别:输入为序列。

命名实体识别:输入输出都为序列。

2,数学标记约定

在前面神经网络的数学书写中,我们遵守如下符号约定。不同节点node用下标来指定,不同样本sample用带小括号的上标来指定,不同层layer用带中括号的上标来指定,不同批次batch用带花括号的上标来指定。

在序列模型中,我们还要指定序列的位置position,我们约定用带尖括号的上标来指定。

3,序列模型优势

我们为什么要使用RNN这样的序列模型,而不是直接使用标准的全连接神经网络来解决输入或输出为序列数据的问题呢?

主要基于以下几点。

第一,全连接的神经网络不能够用一个模型适应输入或输出中不同的序列长度。例如,在不使用数据填充的技巧下,无法用同一个全连接模型架构对15个单词的长度的句子和150个单词长度的句子进行情感分析。但是RNN则能够自然地适应这种序列长度的变化。

第二,全连接神经网络不能够共享在序列不同位置学到的权重。这会导致参数过多的问题。而RNN则能够跨时间共享权重。

此外,以RNN为基础的序列模型通常还有时间平移非对称的特性,通常模型会更容易受到输入序列中较后位置的数据的影响。这一特性在时间序列预测等问题中通常是非常重要的,而全连接神经网络和卷积神经网络则不具有这样的特性。

4,序列模型类型

根据输入和输出的数量及输出生成方式,我们可以把序列模型分成以下一些类型。

(1)Many2One

例如情感分析。我们需要对序列数据进行正负判定或者打星操作。这种情况下,输入是一个序列,但输出是一个值。

(2)One2Many

例如音乐生成。输入一个音乐的类型或者空值,直接生成一段音乐序列或者音符序列。在这种情况下,输入是一个值,但输出是一个序列。

(3)Many2Many

例如序列标注。我们标注一个句子中每个词是否为实体名称。这时候,输入是一个序列,输出也是一个序列,并且它们的长度是一样的。

(4)Seq2Seq

例如机器翻译。这也是一种多对多的结构,但是输入和输出的长度却通常是不同的。我们通常会使用Encoder-Decoder架构来处理这种问题。即我们先用一个RNN网络作为编码器将输入序列压缩成一个向量,然后将压缩后的向量表示输入到一个作为解码器的RNN网络中产生输出。可以将Seq2Seq模型看成Many2One和One2Many的组合。

5,简单RNN

和一个普通神经网络相比,一个RNN神经网络单元的特点是会将上一个时间步的激活函数值传递给下一个时间步作为输入的一部分。在零时刻,我们要编造一个激活函数值传入RNN单元,通常会输入一个零向量。

一个基本RNN单元沿着时间步的前向传播计算可以写成如下形式。

可以简写成如下形式:

为了更新 RNN的参数,我们需要定义一个损失函数,并跨越时间进行反向传播,以计算损失函数相对RNN参数的梯度,并利用梯度下降法实现参数的更新。

6,LSTM结构

简单的RNN单元在处理长序列时,由于要穿越时间进行正向和反向传播,容易出现梯度消失和梯度爆炸的问题。其中梯度爆炸问题可以通过梯度裁剪clip gradient进行解决,但是梯度消失问题比较棘手,这使得基本的RNN难以解决长期依赖问题。

如下面的句子中,第一个句子主语是cat所以要用was,第二个主语是cats, 所以要用were,但由于中间还有很多单词,简单的RNN存在着梯度消失问题,久远的输入信息差异无法被记忆。

  • The cat, which already ate ...........,was full;
  • The cats, which already ate ...........,were full.

LSTM单元在基本的RNN单元基础上作了很大的改进,使得LSTM单元拥有了细胞状态,细胞状态取值负责记忆长期信息,而激活函数值负责记忆短期信息,这也是长短记忆模型(Long Short Term Memory)名字的来源。和基本的RNN相比,LSTM单元能够记住久远信息,解决了长期依赖问题,缓解了梯度消失,但计算量较大。

在LSTM单元中,细胞状态的取值由更新门和遗忘门来控制。在极端情况下,如果更新门一直取0,并且遗忘门一直取1,那么细胞状态将不会有改变,久远的信息将能够一直保持记忆并作用到输出中。

7,GRU结构

LSTM尽管非常强大而灵活,但是其计算代价较高。门控循环单元(Gated Recurrent Unit, GRU)提供了一种解决RNN梯度消失和长期依赖问题的低配版的方案。

和LSTM拥有长短记忆不同,GRU的细胞状态和激活函数值是保持一致的,也就是说它只有一个记忆。但是GRU的细胞状态可以通过更新门进行控制,当更新门取0时,GRU的细胞状态将不会更新,这使得GRU单元能够较好地解决梯度消失问题和长期依赖问题。

8,双向RNN

在语言的许多例子中,单词的含义不仅和它前面的单词有关,也和它后面的单词有关。前面介绍的从左到右单向扫描的循环神经网络不能够解决这种双向上下文依赖问题。

和单向RNN不同,双向的BRNN能够同时从过去和未来的序列中获得信息。它实际上是由普通的从左到右传播的单向的RNN和从右到左传播的单向RNN并联而成。

9,多层RNN

和普通的全连接神经网络相似,通过把上一层的激活函数值序列作为新的输入序列构造一个新的RNN层,RNN也可以有深层结构。不过由于已经存在着跨时间的连接,深层RNN的层数通常不会太大,层数为3或者5的多层RNN已经足够复杂。

词嵌入Embedding

1,词汇表征

为了让计算机能够处理语言这种非结构化数据,我们需要以某种方式将单词转化成数值矩阵。常用的两种词汇表征方式是onehot编码表征和Embedding嵌入表征。

onehot表征首先建立词汇表字典,每个词对应一个编号。然后用一个onehot向量表示一个词,onehot向量的长度和词汇表长度相同,其取值仅在该词对应编号处取1,其余位置都取零。

当我们需要明确输出某个确定的词时,例如在音乐生成,机器翻译,语音识别等问题中,我们通常会使用onehot表征。在这种表征下,每个词的编码具有唯一性和明确性,可以通过输出一个softmax向量来表示各个词出现的概率。

在另外一些情况下,例如情感分析,命名实体识别等问题中,我们通常采用Embedding表征会取得更好的效果。Embedding表征克服了onehot表征的稀疏性和不能反应语义的缺点,它将每个词表示成一个维度较小的浮点数向量,同时不同单词之间的余弦相似度可以衡量它们的语义相似度。

Embedding表征实际上是将每个单词映射成一个维度较低(相比于单词数量)空间的一个点(也对应一个向量),就好像把许多个单词作为一个一个的枣子镶嵌到一个面包中,所以叫做Embedding嵌入。

使用t-SNE算法可以将高维的Embedding词向量映射到2维空间,对词向量进行可视化,很明显我们可以看出相似的词总是聚集在一块儿。

2,获得Embedding词向量

那么如何获得Embedding词向量表征呢?一般有3种方法。第一种方法是用Word2Vec或Glove方法预训练词向量,这种方法一般要求关联的语料数据较多。第二种方法是载入预定义的词向量,可以载入别人使用网上大量的无标签的文本如维基百科等语料训练好的词向量,这种方法一般在问题关联的语料数据较少时使用,实际上是一种迁移学习。

前面两种方法的词向量本质上都是用Word2Vec或Glove方法得到的,利用语料中词汇之间的上下文关系就能够实现,不需要其它标签。第三种方法是利用问题标签end-to-end地训练词向量。在这种方法中,词向量随机初始化,在训练过程中通过梯度下降不断调整词向量的取值。这种方法既不需要预训练词向量,也不需要载入词向量,在语料数据较丰富时通常是首选。下面是一个在keras中使用end-to-end方式训练词向量的例子。

3,Word2Vec词向量

当我们要对一个词汇表学习一个词嵌入模型时,实际上是要学习一个词嵌入矩阵,当我们学习好了这样一个嵌入矩阵后,通过嵌入矩阵与对应词的onehot向量相乘,则可得到该单词的embedding向量。

Word2Vec是一种学习词嵌入矩阵非常流行的方法。它基于上下文相似的词具有相似的语义这一假设。

Word2Vec可以由两种方式来构建一个监督学习问题。第一种是CBOW,即通过上下文预测中间词。第二种是Skip-Gram,即通过中间词去预测上下文。

下面是一个Word2Vec模型训练词向量的网络结构。输入是一个onehot向量,如果是CBOW模型,则是上下文中多个词的onehot向量的平均。输入向量经过词嵌入矩阵的左乘得到对应的Embedding向量表示,也是模型的隐藏层。该Embedding向量再经过嵌入矩阵转置后的的左乘得到输出层,输出层的维度和输入层一样,实际上它的取值是输入对应的词向量和词典中各个词汇的词向量的点积。

为了进行标签预测,最终的输出层还要经过一个softmax激活函数。

上述方法从原理上讲已经可以用来学习词嵌入矩阵了,但是计算效率会像只蜗牛。主要瓶颈在于最后的softmax步骤,每一个样本都需要预测规模数以万计的词汇表中每个词的出现概率,计算量太大了。

有两种方法可以减少计算量,提高效率,第一个是层次化softmax,第二个是负采样方法。

层次化softmax的基本想法使用log(2,V)个二分类模型代替一个类别数量为V的softmax,从而极大地减少计算量。具体做法是引入一个二叉树,树的叶子结点数量为V,每个叶子结点表示一个单词,树的平均深度即为log(2,V),树在每一层的分叉方向的概率都由一个二分类模型来拟合。最终取某个单词值的概率为从根结点到达该单词对应叶子结点的路径中每一层分叉方向取值概率的乘积。

为了更加有效地降低计算量,通常会将词汇表构造成哈夫曼Huffman树。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。在这个情境下,每个词汇在训练语料中出现的频率即为对应叶子结点的权重。

创建哈夫曼树的方法如下描述。

代码语言:javascript复制
假设有n个结点,n个结点的权值分别为w1,w2,...,wn,构成的二叉树的集合为F={T1,T2,...,Tn},则可构造一棵含有n个叶子结点的哈夫曼树。
步骤如下:
(1)从F中选取两棵根结点权值最小的树作为左右子树构造一棵新的二叉树,其新的二叉树的权值为其左右子树根结点权值之和;
(2)从F中删除上一步选取的两棵二叉树,将新构造的树放到F中;
(3)重复(1)(2),直到F只含一棵树为止。

层次化softmax虽然有效,但比较复杂,负采样则是一种非常有效且非常简单的方法。负采样方法的基本想法是用一个简单的二分类问题来学习词嵌入矩阵。

定义一个新的学习问题:预测两个词之间是否是上下文-目标词对,如果是词对,则目标标签为1,否则为0。

对于每一个上下文单词,首先在其周围找一个目标词,这个目标词和上下文单词构成正样本对。同时在词汇表中随机选择k个单词,这k个单词和上下文单词构成负样本对,无论它是否在上下文单词的周围。随机选择k个单词和上下文单词构成负样本对的过程就叫做负采样。

那么在负采样的时候,如何确定某个单词的采样频率呢?一种方式是对每个单词等概率采样,这种方式的采样结果没有代表性。另一种方式是按照每个单词的词频为权重进行采样,这种采样方式会让一些常用词如a,the,I出现的次数过高。在实践中发现一种较为有效的平衡方式是按照单词词频的3/4次方为权重进行采样。

4,Glove词向量

GloVe(global vectors for word representation)词向量模型是另外一种计算词嵌入的方法,虽然使用不如Word2Vec普遍,但是这种模型更加简单。

Glove词向量的基本想法是用一个全局的词共现矩阵X来描述词和词之间的上下文关联性,然后基于此来计算词向量。词共现矩阵X的第i行第j列元素的取值Xij表示第i个词出现在第j个词上下文中的的次数。很显然词共现矩阵X具有对称性。

我们基于全局的词共现矩阵,可以定义模型的目标函数如下以学习词向量。

通过各种方式得到的词向量,我们是无法确保其每个分量都是我们能够理解的,因为对词向量整体都作一个正交变换,损失函数值是不变的。

5,词嵌入应用

下面介绍一些词嵌入的一些常见应用,如情感分类,命名实体识别,类比推理。

情感分类就是通过一段文本来判断这个文本中的内容是否喜欢其所讨论的内容。如电影评论正负分类,餐厅评论星级分类。

情感分类任务存在的一个问题就是只有很小的数据集,缺乏训练样本。但是通过使用预定义的词向量进行迁移学习,可以很容易地训练一个良好的情感分类模型。

命名实体识别是从句子中对名称实体进行识别定位。假如我们只有一个比较小的数据集,可能不包含durain(榴莲)和cultivator(培育家)这样的词汇,那么我们就很难从包含这两个词汇的句子中识别名字实体。

但是如果我们从网上的其他地方获取了一个学习好的词嵌入,它将告诉我们榴莲是一种水果,并且培育家和农民相似,那么我们就有可能从我们少量的训练集中,归纳出没有见过的词汇中的名字实体。

词嵌入还能够用来实现类比推理。通过不同词向量之间的相减计算,可以发现不同词之间的类比关系。

6,词嵌入偏见消除

以一些语料库中学习到的词嵌入向量,可能会存在一些性别、种族等偏见。当词向量的类比推理功能被用来作为相关的决策参考时,这种偏见是不能够忍受的。

在明确偏见的方向后,可以通过对词向量的调整消除词向量中的特定偏见。

语言模型

1,语言模型含义

对于某种特定的语言如中文或者英文,如果我们能够构建一个模型评估一个句子出现的概率,那么这个模型就是一个语言模型。用通俗的话说,语言模型能够判断某句话像不像人话。

利用条件概率公式,可以很容易将句子出现的概率展开。

为了计算右边的概率值,一种很简单的方法是引入马尔可夫假设。即当前这个词仅仅跟前面几个有限的词相关,因此也就不必追溯到最开始的那个词,这样便可以大幅缩减上述算式的长度。

然后我们可以得到 n-gram模型。当n = 2时,我们得到一个 bigram model。

下面的思路就很简单了,在给定的训练语料中,利用贝叶斯定理,将上述的条件概率值(因为一个句子出现的概率都转变为右边条件概率值相乘了)都统计计算出来即可。

2,RNN实现语言模型

下面阐述使用Many2Many的RNN结构实现语言模型的方法。我们的训练集是一个很大的文本语料库。首先需要做一些准备工作,建立词典将语料内容转化成onehot编码。我们的RNN结构的输入为转换成onehot编码的词汇序列,注意第一个输入为全零的向量,并且输入不包括最后一个结束符EOS。除第一个输出外,我们的RNN结构的输出为句子中每个位置出现词汇表中各个单词的条件概率的预测值。由于第一个输入为全零向量,第一个输出实际上就是第一个位置出现词汇表中各个单词的概率值的预测而非条件概率值的预测。

模型的损失函数设置为各个输出序列和真实序列之间的交叉熵损失。利用梯度下降法训练好模型后,输入任意一个句子序列,我们便可以将输出序列的各个条件概率结果相乘,从而得到句子出现的概率,即预测句子的可能性。

3,新序列采样

训练好了语言模型后,除了可以预测一句话是否像"人话"外,我们还可以用来生成一些像“人话”的词汇序列。我们采用的实际上是一个One2Many的结构,我们只要输入任意一个初始词汇,或者输入一个为全零向量的初始词汇,模型就可以blabla接着说一大堆话。这种功能可以称为自动文本生成或者新序列采样。从生成的序列中,我们能够观察到语言模型究竟学到了什么东西。

除了可以生成单词级的序列,我们也可以基于字符训练一个语言模型,生成字符级的序列。

根据softmax概率输出对词汇进行采样的时候,我们可以有不同的采样策略,第一种是随机采样,即按照softmax概率为权重对各个单词进行采样,第二种是贪婪采样,每次只取softmax概率向量中最大的那个单词。随机采样得到的输出序列引入了较多的随机性,可能会出现不太常见的组合,从而显得富有创造性。而贪婪采样方式得到的输出序列会相对容易预测,很像“人话“。

此外,我们还有第三种采样方式,即介于随机和贪婪采样之间的一种采样方式,我们可以通过引入一个softmax温度的变量,来控制随机性的大小。这种采样方式,可以叫做softmax温度采样

以下是引入softmax温度平衡随机性的代码示范。越高的温度对应着越高的随机性,当温度趋于0时相当于贪婪采样,温度取1时相当于随机采样,温度大于1时会比随机采样引入更大的随机性。

机器翻译

1,Encoder-Decoder结构

机器翻译使用的序列模型属于Seq2Seq模型,Seq2Seq模型采用了一种Encoder-Decoder的网络结构。Encoder-Decoder结构包含两部分,编码器Encoder和解码器Decoder。输入数据进入编码器得到一个新的压缩编码表示,然后将得到的压缩编码表示输入解码器网络,得到的输出和人工标注的输出作对比,并利用反向传播和梯度下降调整编码器和解码器的参数权重,从而对网络整体进行训练。

注意的是Encoder-Decoder的编码器和解码器可以是各种基本的网络类型,包括全连接网络,CNN和RNN。如果输入是图片,输出是一个描述图片的句子,那么编码器通常采用CNN,解码器采用RNN。这种模型叫做 Image to Sequence。

2,条件语言模型

机器翻译Seq2Seq模型的编码器是一个Many2One的结构,而解码器是一个One2Many的结构。实际上解码器翻译出句子的过程非常像我们前面对语言模型进行序列采样的过程。但是有些区别,我们的解码器的第一个激活端输入并不是零向量,而是编码器的输出,解码器要计算的是已知输入原文的的条件下各种译文的概率。因此,机器翻译的模型也被称之为条件语言模型。

2,Beam Search 集束搜索

除了建立条件语言模型评估各种译文相对原文的条件概率之外,机器翻译还有一个搜索问题需要解决。即在各种可能的翻译中找到一个答案使得这个条件概率的取值最大化。

一种想当然的简单的方案是贪心搜索,即每次都采样当前时间步输出的sofmax概率向量中取值最大的词。但是这种策略通常并不能够采集到整个句子条件概率最大的翻译结果,就好像下棋时每一步都只考虑当前步骤利益最大化,最终不见得能赢。

另一种方案是全局暴力搜索。即通过深度优先搜索或广度优先搜索遍历所有可能的翻译输出,并从中找到整个句子条件概率最大的翻译结果。这种方案听上去很稳妥,实际上会因为计算量过大难以实施。

折中权衡考虑搜索效果和搜索效率的算法就是集束搜索。这种算法在搜索路径上每一步都只保留当前结果最好(即各时间步输出单词对应条件概率的乘积最大)的B个(B为束宽参数)分支,然后在此基础上往前推进,直到遇到EOS结束,再从最终的B个完整句子中选择结果最好的那一个。

上述只是集束搜索的一个整体的思路,在实际应用中,还有一些地方需要做优化。一方面是为了避免一系列较小的数相乘造成数值下溢,我们会对优化目标取对数,化乘法为加法。

另一方面是进行长度归一化。根据现有的优化目标,由于连乘的各项条件概率取值总是小于1,模型会倾向于输出长度较短的翻译结果。通过引入长度归一化,可以调整这种倾向。

那么束宽参数B应该如何取值呢?在实践应用中,B常取10左右,在计算资源充裕的情况下,也可以取100或者1000等更大的值。为了评估束宽参数取值是否合理,我们也可以对模型的训练结果进行误差分析。

假设机器翻译算法得到了一个错误的翻译结果,我们便可以用这个翻译算法中的条件语言模型评估这个错误的翻译结果的条件概率,同时,我们也可以用它评估正确翻译结果的条件概率。如果正确结果的条件概率大于错误结果的条件概率,那么说明导致这个错误的原因是集束搜索束宽参数偏小,反之则说明导致这个错误的原因是我们的条件语言模型还不够准确。

通过对多个这样的错误例子进行误差分析,我们便可以确定我们的优化方向,是调整束宽参数,还是去优化我们的条件语言模型。

3,Bleu Score

Bleu 得分是一种机器翻译结果自动评价方法。Bleu的全称为 bilingual evaluation understudy,即双语互译质量评估辅助工具。Bleu的设计思想非常简单:机器翻译的结果越接近人工翻译的结果,则越好。

Bleu 得分的计算公式比较复杂。简单地说,Bleu得分是通过比较机器翻译结果中的 一元词组,二元词组,三元词组等多元词组和人工参考结果中对应词组的匹配度,并进行加权计算得出。以下是调用nltk工具包计算bleu得分的一个示范,其输出结果应当为1。

代码语言:javascript复制
from nltk.translate.bleu_score import sentence_bleu
reference = [['this', 'is', 'a', 'test'], ['this', 'is' 'test']]
candidate = ['this', 'is', 'a', 'test']
score = sentence_bleu(reference, candidate)
print(score)

4,Attention Model 注意力模型

使用前面的Seq2Seq模型去翻译较短的句子时,我们可以获得很好的效果。但是当句子长度增加时,例如将一个有一百多个单词的法语句子翻译成英语,那么翻译结果的bleu得分会降低很多。

这实际上非常容易理解,当句子很长时,我们的Seq2Seq模型仍然将句子编码压缩成一个较短的向量表示,这很有可能会有信息瓶颈,造成信息损失。此外,我们人类在翻译长句子的时候,通常是每次专注于其中一部分的翻译,一小句一小句地翻译最后再统筹一下,而不是像Seq2Seq模型那样一次读入全部原文,然后记住它们,最后一次翻译出全部译文。

Attention Model 通过将编码器输出的各个隐含状态加权成context并馈送到解码器作为输入,解决了信息瓶颈问题。在计算context时,参照了人类的注意力原理,给予不同时间步编码器的隐含状态不同的注意力权重,注意力权重最大处相当于原文对应的对齐点,从而像人类那样一部分一部分地翻译句子。

那么如何分配注意力权重呢?我们分配到各个编码器隐含状态的注意力权重之和应当为1。我们可以利用编码器的隐含状态和上一步的解码器状态作为输入,得到各个编码器隐含状态对应的score,然后对各个score应用softmax函数得到各个注意力权重,从而保证注意力权重之和为1。

在由编码器的隐含状态和解码器状态计算score时,我们可以有不同的计算方法。有一些方法会引入参数,另外一些方法不需要引入参数。引入参数的方法相当于嵌套了一个小的神经网络,参数需要和Seq2Seq模型的其他参数一起通过反向传播进行训练。

我们可以将Attention机制从Encoder-Decoder框架中剥离开来,以分析其本质思想。Attention的目的是从原始的大量信息中有选择地筛选出少量重要信息并聚焦到这些重要信息上,并忽略大多不重要的信息。

原始的大量信息我们可以称之为Source,Source由系列Value组成,每个Value本身可以是标量也可以是张量,这些Value有与之相关联的系列Key,这些Key也可以是Value本身,在上述Seq2Seq Attention的例子中即是如此。给定一个和我们需要聚焦到的信息有关的Query, 我们可以通过某种方式计算这个Query和Source的各个Key之间的关联度值,对这些关联度值进行类Softmax归一化得出注意力权重,然后将Source的各个Value基于注意力权重进行加权求和,从而得到信息的筛选结果,这个结果称之为Attention Value,在上述Seq2Seq Attention的例子中我们叫它context。

在分析了Attention的本质思想后,我们便可以将这种机制拓展应用到别的领域,只要我们可以定义Source和Target,Target的每个元素都可以作为一个Query。

以下是在图片描述和语音识别中应用Attention机制进行信息筛选和聚焦的例子。

在以上的例子中,我们的Attention机制相关的Source和Target都是不同的两组数据,但这不是必须的,我们的Attention机制也可以建立在Source和Target对应同一组数据的情况下,这称之为Self Attention。如果把机器翻译的译文作为这种Self Attention机制的Source和Target,那么我们可以让机器翻译的译文实现一种类似语法校准的功能。

更进一步,我们会发现引入Self Attention后模型会更容易捕获句子中长距离的相互依赖的关系。如果是RNN或者LSTM,对于远距离的相互依赖的特征,要经过若干时间步步骤以后才能将两者联系起来,而距离越远,有效捕获的可能性越小。但是Self Attention在计算过程中会直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,有效捕获的可能性大大增加。

==========end==========

0 人点赞