1.1 为什么选择序列模型
这些序列模型都属于监督式学习,带有标签的(x,y)作为样本;
输入x和输出y不一定都是序列模型;
如果都是序列模型的话,模型长度不一定完全一致。
1.2 Notation
这句话包含9个单词,输出y即1*9向量,表示对应单词是否是人名的一部分,1表示是,0表示不是。
y = [1 1 0 1 1 0 0 0 0]
一些notation:X(i)<t>表示第i个输入的序列的第t个对应位置
对应的y(i)<t>
Tx(i)表示第i个输入的序列长度
对应的Ty(i)
通过建立一个包含10,000个单词的词汇库用one-hot表示x(i)。
NLP实际应用中的词汇库可达百万级的词汇量。
如果出现词汇表之外的单词,可以使用UNK或其他字符串来表示。
1.3 recurrent neural network model循环神经网络模型
使用标准神经网络处理存在两个问题:一是不同样本的输入序列长度和输出序列长度不一定相同,解决办法之一是设定一个最大序列长度,对每个输入输出序列补0并统一到最大长度,这样做实际效果不理想;第二个问题,也就是主要问题,这种标准神经网络无法共享序列不同x之间的特征,例如,某个x即“Harry”是人名成分,那么句子其它位置出现了“Harry”,也很可能也是人名。这是共享特征的结果,如同CNN网络特点一样。但是,上图所示的网络不具备共享特征的能力。值得一提的是,共享特征还有助于减少神经网络中的参数数量,一定程度上减小了模型的计算复杂度。例如上图所示的标准神经网络,假设每个x扩展到最大序列长度为100,且词汇表长度为10000,则输入层就已经包含了100 x 10000个神经元了,权重参数很多,运算量将是庞大的。
标准的神经网络不适合解决序列模型问题,而循环神经网络(RNN)是专门用来解决序列模型问题的。RNN模型结构见上图。序列模型从左到右依次传递。x到y hat之间是隐藏神经元。a会传入到第t+1个元素中,作为输入。
RNN正向传播:
参数w后接的第一个字母下标表示要获得什么类型的变量,第二个字母下标表示要乘以什么类型的变量。
g(·)表示激活函数,计算a的激活函数用tanh比较多。
计算y hat的激活函数如果是二分类问题可以用sigmoid函数,如果是多分类问题可以用sotfmax函数。
将前向传播简化表示:
也就是写法上把Waa和Wax合并成Wa。
以上所述的RNN为单向RNN,即按照从左到右顺序,单向进行,y hat只与左边元素有关,但有时也可能与右边元素有关,为了解决这个问题可以用双向RNN,简称BRNN,使y hat与左右元素都有关,以后介绍。
1.4 通过时间的反向传播
蓝色箭头是正向传播,红色箭头是反向传播。
单个元素的损失函数和所有元素的损失函数见上图。反向传播就是从右向左分别计算L(y hat, y)对参数Wa,ba,Wy,by的偏导数。一般可以通过框架如TensorFlow,PyTorch等自动求导。
这种从右向左的求导过程称为Backpropagation through time, 因为是逆时间从右向左,好像穿越时间了。
1.5 different types of RNNs不同类型的循环神经网络
one to one就是普通的神经网络;one to many一般是音乐生成,后面介绍;many to one可以是情感分类;Tx=Ty的many to many可以是上面识别人名的例子;Tx≠Ty可以是将法语翻译成英语,字数不一样,前一部分是输入的法语,是编码器encoder,后部分是输出的英语,是decoder。
1.6 语言模型和序列生成
语言模型是自然语言处理(NLP)中最基本和最重要的任务之一。使用RNN能够很好地建立需要的不同语言风格的语言模型。
什么是语言模型呢?上图是一个例子,在语音识别中,某句有两种翻译,很明显,第二句更有可能是正确的翻译,语言模型实际上会计算出这两句话各自的出现概率,选择概率大的语句作为正确的翻译。
如何使用RNN构建语言模型?首先,我们需要一个足够大的训练集,训练集由大量的单词语句语料库corpus构成,然后对corpus的每句话进行切分词(tokenize), 做法和第二节一样,建立vocabulary,对每个单词进行独热编码。
每句话结束末尾,需要加上 < EOS > 作为语句结束符。另外,若语句中有词汇表中没有的单词,用 < UNK > 表示。则上面这句话可表示为:The Egyptian < UNK > is a bread of cat. < EOS >
准备好训练集并对语料库进行切分词等处理之后,接下来构建相应的RNN模型。sotfmax输出层y hat<1>表示出现该语句第一个单词的概率,sotfmax输出层y hat<2>表示在第一个单词基础上出现第二个词的概率,即条件概率,以此类推,最后是出现的条件概率。
单个元素的sotfmax损失函数和该样本所有元素的损失函数见上图。
对语料库的每条语句进行RNN模型训练,最终得到的模型可以根据给出语句的前几个单词预测其余部分,将语句补充完整。
整个语句出现的概率等于语句中所有元素出现的条件概率乘积,如某个语句包含y<1>,y<2>,y<3>,则整个语句出现的概率为上图右下角。
1.7 Sampling novel sequences对新序列采样
利用训练好的RNN语言模型,可以进行新的序列采样,从而随机产生新的语句。首先,从第一个元素输出y hat<1>的sotfmax分布中用numpy(np.random.choice)随机选取一个word作为新语句的首单词。然后,y<1>作为x<2>,得到y hat<2>的sotfmax分布。从中选择概率最大的word作为y<2>,继续将y<2>作为x<3>,以此类推,直到产生结束符,则标志语句生成完毕。当然,也可以设定语句长度上限,达到上限即停止生成新的单词。最终,根据随机选择的首单词,RNN模型会生成一条新的语句。
如果不希望新的语句中包含 < UNK > 标志符,可以在每次产生 < UNK > 时重新采样,直到生成非 < UNK > 标志符为止。也可以直接忽略。
word level RNN是每次生成单个word,语句由多个words构成。另一种情况是character level RNN,即词汇表由单个英文字母或字符组成,如上图。
character level RNN与word level RNN不同的是,y hat由单个字符组成而不是word。训练集中的每句话都当成是由许多字符组成的。character level RNN的优点是能有效避免遇到词汇表中不存在的单词 < UNK > 。但是,character level RNN的缺点也很突出。由于是字符表征,每句话的字符数量很大,这种大的跨度不利于寻找语句前部分和后部分之间的依赖性。另外,character level RNN的在训练时的计算量也是庞大的。基于这些缺点,目前character level RNN的应用并不广泛,但是在特定应用下仍然有发展的趋势。
对新序列采样的一些结果:
1.8 带有神经网络的梯度消失
英语语句中可能存在跨度很大的依赖关系,即某个word可能与它距离较远的某个word具有强依赖关系,如上图的句子,was受cat影响,were受cats影响,它们之间跨越了很多单词。而一般的RNN模型每个元素受其周围附近的影响较大,难以建立跨度较大的依赖性。上面两句话的这种依赖关系,由于跨度很大,普通的RNN网络容易出现梯度消失,捕捉不到它们之间的依赖,造成语法错误。解决梯度消失的问题下几个视频会讲。
RNN也可能出现梯度爆炸的问题,即gradient过大,当出现NaN,就表示数值过大发生了溢出。常用的解决办法是设定一个阈值,一旦梯度最大值达到这个阈值,就对整个梯度向量进行尺度缩小,这种做法被称为gradient clipping梯度剪枝。
1.9 gated recurrent unit GRU单元
为了解决梯度消失问题,对上图单元进行修改,引入了记忆单元,构建GRU,如下图。
其中c=a, c=a。表示(更新)门(u表示update更新),记忆单元。当门=1时,代表更新;当门=0时,代表记忆,保留之前的模块的输出。因此,门可以保证RNN模型中跨度很大的依赖关系不受影响,消除梯度消失问题。
*是元素对应乘积,不是矩阵相乘。
c,c~,门都是相同的维度。
将上图黄色圈起来的三个式子抄到下一页,再做一些更改就是完整的GRU:
计算c与c的相近性。
1.10 长短期记忆long short term memory(LSTM)
LSTM比GRU更复杂一点,也更强大和灵活。LSTM用了三个门分别表示update gate,forget gate和output gate。
如果考虑c对三个门的影响,可加入peephole connection偷窥孔连接, 对LSTM的表达式进行修改。
1.11 bidirectional RNN双向神经网络
紫色是从左到右的传递信息,绿色是从右到左的传递信息,他们都是正向传播。所以如黄色箭头所示,y hat<2>可以考虑到以前、现在和未来的信息。
y hat的表达式见上图。
BRNN能够同时对序列进行双向处理,性能大大提高。但是计算量较大,且在处理实时语音时,需要等到完整的一句话结束时才能进行分析。
1.12 deep RNNs深层循环神经网络
Deep RNNs由多层RNN组成。用上标[l]表示层数,deep RNN中a[l]的表达式为
我们知道DNN层数可达100多层,而Deep RNNs一般没有那么多层,3层RNNs已经较复杂了。
另外一种Deep RNNs结构是每个输出层上还有一些垂直单元,如上图。