引言
从本系列博客开始,我们将来一起学习一下NLP领域的相关基础知识,NLP领域重要的模型是RNN,在此之前,先来了解一些符号的含义。
1.符号定义
(1)符号定义
假设建立一个能够自动识别句中人名位置的序列模型,它的输入序列是这样的:“Harry Potter and Herminoe Granger invented a new spell.”,(这些人名都是出自于J.K.Rowling笔下的系列小说Harry Potter)。输出y,使得输入的每个单词都对应一个输出值,同时这个能够表明输入的单词是否是人名的一部分。
注:这是一个命名实体识别问题,常用于搜索引擎,比如说索引过去24小时内所有新闻报道提及的人名,用这种方式就能够恰当地进行索引。命名实体识别系统可以用来查找不同类型的文本中的人名、公司名、时间、地点、国家名和货币名等等。
符号定义如下:
注意:在这个例子中Tx=Ty,但是在其他案例中不一定相等。
(2)序列表示
序列表示主要是对每个单词进行编码,从而得到序列的编码,我们采用one-hot编码方式。
Step1:定义词典;
Step2:索引每个单词在词典的位置;
Step3:编码单词,在编码向量中,向量中下标等于单词在词典中的位置的元素定义为1,其他下标的元素定义为0;
Step4:循环Step2-Step3,得到序列中所有单词的编码向量。
举个例子,如下为输入序列,假设词典有10000个单词,如下所示:
而Harry在词典中4075下标,因此该单词编码表示4075下标的位置为1,其他为0,得到编码向量,也称为独热向量。序列中其他位置的单词依次得到的内容如上。
注意:如果遇到了一个不在词表中的单词,那么就是创建一个新的标记,也就是一个叫做Unknow Word的伪造单词,用<UNK>作为标记,来表示不在词表中的单词,我们之后会讨论更多有关这个的内容。
2.循环神经网络模型
(1)标准神经网络的缺点
可以用标准神经网络学习序列模型,但是效果并不好,原因如下:
一、输入和输出数据在不同例子中长度不一定相同,不是所有的例子都有着同样输入长度或输出长度。即使每个句子都有最大长度,也许可以填充(padding)使每个输入语句都达到最大长度,但并不是一个好的表达方式。
二、网络结构并不共享从文本的不同位置上学到的特征。比如,神经网络已经学习到了在位置1出现的Harry可能是人名的一部分,那么如果Harry出现在其他位置,我们也希望能够自动识别其为人名的一部分的话。这就类似卷积网络,垂直卷积可以在图片中不同位置学习到相同的垂直特征,但普通的网络就不行。
三、假设词典是10000词,则编码向量是10,000维的one-hot向量,因此这会是十分庞大的输入层。如果总的输入大小是最大单词数乘以10,000,那么第一层的权重矩阵就会有着巨量的参数。但循环神经网络就没有上述问题。
(2)循环神经网络
上图即为一个循环神经网络的结构图,假设我们进行人名识别任务,即识别句子中的词是否是人名的一部分。任务流程为在第一个时间步,我们把第一个词x1输入到第一层,第一层预测出y1;在第二个时间步,我们把第二个词x2输入到第二层,同时第二层接受来自时间步1的信息,即第一层输出的激活值,结合这两部分,第二层预测出y2;持续这种模式输入,到最后一个时间步,输入x<Tx>和上一个时间步的激活值,预测出y<Ty>。所以在每一个时间步中,循环神经网络传递一个激活值到下一个时间步中用于计算,这就是RNN的核心思想。至于第一层接受的激活值a0,通常需要在0时刻构造一个。
注意:观察上图两个句子,在识别Teddy这个词的时候,Teddy Roosevelt是泰迪罗斯福,而Teddy bears是泰迪熊,根据RNN的结构,Teddy的识别过程只能接受来自前一个时间步的激活值,也就是网络只能学习到Teddy及以前的句子信息,而以后的句子内容无法学习,也就难以识别Teddy究竟是不是人名的一部分。要解决这个问题,我们需要用到双向循环神经网络BRNN,这里先不阐述。
上图所示即为RNN的前向传播流程图,在第一层中,接受a0激活值和第一个词向量x1,公式如下:
其中g1()=tanh(),g2()=softmax(),权重矩阵有下标aa、ax和ya,第一位表示计算数据类型,比如a表示计算数据类型为a类型,即激活值,y表示计算数据类型为y类型,即输出值。第二位表示参与运算的数据类型,比如aa表示计算激活值a时权重矩阵需要和上一时间步的激活值a进行运算,ax表示计算激活值a时权重矩阵需要和词向量x进行运算。
更一般的有:
为了更加简洁的描述问题和公式,我们做如下公式记号:
上面两个式子中,下式[]和权重矩阵部分的乘积表示为上式。
把两个权重矩阵合并为一个表示,如上式所示。
上面这两个式子,将上式用下式代替。有了上述符号简化,我们可以改写前向传播的公式:
同理,下式也可以改写:
3.通过时间的反向传播
当前向传播的流程结束后,需要计算损失,然后进行反向传播,由于RNN的反向传播和时间步有关(每一层均是一个时间步的计算流程),因此反向传播更像通过时光机穿越到过去进行计算,于是RNN的反向传播又叫通过时间反向传播。下面让我来看看具体的流程:
首先定义模型的损失函数,模型的损失函数为交叉熵损失函数:
需要把每一时间步的损失都计算出来,最后加在一起得到总损失L。而反向传播的流程如下:
红色箭头所示的方向即为反向传播的方向,通过下图导数的相关参数,按照反向传播的方向传递参数信息,即可进行梯度的计算。
如图上所示,列了一些梯度计算的有关公式,这是一个时间步(一层)的梯度计算。当然目前所讨论的RNN基于输入序列的长度和输出序列的长度一致,下面介绍一些其他RNN的结构。
4.不同类型的循环神经网络
目前常见的RNN结构有4种:一对一、一对多、多对一、多对多,除去注意力机制,多对多结构也分为两种(编号4和编号5)。下面我来一一举例说明这些结构的应用:
一对一(编号1):这个并不重要,给定输入x,输出y,如果去掉初始激活值a0,这就是标准的神经网络。
一对多(编号2):音乐生成,比如给定想要生成的音乐风格(可能是一个整数),然后每一层依次输出一些值并把值输入给下层进行合并,最终输出一个曲子,可以理解为每一层生成一个音符,但是音符又不能独立,下一层输出的音符要依靠上一层的音符从而确保曲子的连贯性。
多对一(编号3):类似评价类或者情感分类问题,给定一段文本,要求输出一个评价或者语句的情感。比如“These is nothing to like in this movie.”(“这部电影没什么还看的。”),所以输入x就是一个序列,而输出y可能是从1到5的一个数字(代表电影是1星,2星,3星,4星还是5星),或者是0或1(这代表正面评价和负面评价)。
多对多(编号4):这个例子就是上文提到的人名识别任务案例,对于输入序列的每一个词都需要输出是否是人名的一部分。
多对多(编号5):机器翻译,输入序列和输出序列长度不一致。比如输入英语,翻译成汉语,那么每个词依次输入到网络中,输入部分构成编码器(x输入的结构)。而网络读取所有的词后,解码器(y输出的结构)依次输出要求翻译的结果。