数学符号

在命名实体识别中,对于一个句子,也就是一个单词序列,以NLP - 图1代表第i个样本的输入序列中第t个单词的取值,以NLP - 图2表示第i个样本输出序列中第t个元素的取值。NLP - 图3分别表示输入序列与输出序列的长度。
image.png
表示一个句子里的单词通常使用词向量。首先构造一个单词表,通常单词表的长度在10000以上。然后,我们使用词向量来表示句子中的每一个单词。单词出现的那个维度取1,其他全部取0。若句子中出现的单词不在单词表中,则用UNK去取代。
image.png

循环神经网络

依据上文所述的例子,或许我们可以使用一个普通的神经网络,以一个词向量序列作为输入,一个实现命名实体识别的输出序列作为输出。但这个模型有两个问题:1、在不同的应用场景中,输入、输出序列的长度并不确定。2、一个普通的神经网络并不共享从文本的不同位置学到的特征。
image.png
所谓循环神经网络,就是对词向量都会有一个负责读取输入的隐藏层,同时给出输出结果。比如对第一个输入的单词,隐藏层会立即给出预测的结果,然后把结果通过激活函数输送到下一轮循环中。下一轮循环再读取下一个单词,继续输出。每一个时间步完成独立的操作。每一个时间步的参数都是共享的。管理着从NLP - 图7到隐藏层连接的一系列参数写为Wax,每一步都由相同的参数表示。隐藏层之间水平的联系由参数Waa决定,同时每一个时间步都是同样的。输出参数由Wya决定,同理也都是共用的。这个模型也有一个缺点,那就是它只会用之前的信息做出预测,也就是系统不会基于NLP - 图8等对NLP - 图9做出预测。
image.png
循环神经网络的前向传播公式如下:
NLP - 图11
激活函数g通常我们会选取tanh(ReLU)函数,输出函数g可以选取sigmoid函数。
RNN的前向传播如图所示:
image.png
RNN采用的损失函数为交叉熵损失函数,总损失函数为每一项损失函数之和:
NLP - 图13
通过时间反向传播:
image.png

不同类型的循环神经网络

先前我们提到的循环神经网络实际上是多对多类型。但假如我们进行不同的任务,比如说情感分析,那么模型就需要进行改动,变成多对一结构。再或者,如果需要完成一个音乐生成的任务,那么我们就需要一对多模型。
image.pngimage.png
此外,多对多模型也可有其他表现形式,例如一个翻译程序,那么输出语言的长度可能与输入语言的长度不一致。这个网络有两个不同的组成部分:解码器用于读取输入语句,解码器用于输出目标语句。
image.pngimage.png

语言模型和序列生成

语言模型就是为了说明某个特定的句子出现的概率是多少。比方说如下两个句子,虽然读音相似,但一个好的语言模型应该能够判断出用户的意图为第二个语句的概率明显更大。
image.png
要通过RNN训练一个语言模型,第一步是为训练集中每一条语句记录(语音)进行tokenize,也就是构建词向量。
image.png
对于第一个单词,在输入后通过神经网络,再通过softmax层,会计算得出该单词是字典中每一个单词的概率。同时,该估计值会继续作为下一轮循环的输入,以此类推。这就是为什么NLP - 图21的原因。
image.png

对新序列采样

在对每一个输出(即经过softmax层输出的每个单词序列的概率)进行np.random.choice命令后,就完成了采样。实际上采样就是把经过softmax层输出的NLP - 图23,即概率,转变为具体选择的单词。这个单词就可以作为下一次循环的输入。当采样所得的输出值为EOS或达到所设定的时间步时,就代表输入停止。当读到未知单词时,可以进行拒绝,也可以从词典中随机取出一个词,再进行循环。
除了基于词汇的词典,还可以选择基于字母的语言模型,各有利弊。基于字母的训练模型通常成本较为高昂。
image.png

GRU

GRU的引入是为了解决梯度消失的问题。前面已经提到过,第t次循环经过激活函数的输出为:
NLP - 图25
因此,一个RNN单元进行的就是这样的运算:
image.png
对一个句子“The cat,which ate already,was full.”来说,由于cat与was离得太远了,因此由于梯度消失问题,模型很难把cat与was联系起来。由此我们引入一个记忆细胞c,让它记住cat是单数还是复数,以便确定之后用was还是were。NLP - 图27实际上就是输出了NLP - 图28的激活值。NLP - 图29值每次都要计算一遍,而使用sigmoid激活函数的NLP - 图30函数决定了决定到底要不要更新c值。如图中所示,在遇见cat值时,第一次将NLP - 图31置1,之后的每一个单词,NLP - 图32输出的都是0,由于NLP - 图33,因此不更新,直到遇到was,NLP - 图34输出1,更新NLP - 图35,这样就把两者联系了起来。
image.png
在完整的GRU中,还要加上一个新的门NLP - 图37,用于计算c跟前一项有多少关联性。
image.png

LSTM

LSTM的新特性是使用NLP - 图39完全替代了NLP - 图40,并且引入了NLP - 图41遗忘门,NLP - 图42输出门,同样也使用sigmoid函数。而且NLP - 图43的更新函数同时涉及到NLP - 图44更新门以及NLP - 图45遗忘门。
image.png
image.png
GRU相比LSTM是一个简单得多的模型,运算速度也可以更快,LSTM的功能则更加强大,因此到底使用GRU还是LSTM还是看具体情况。

双向RNN

单向RNN的劣势之前已经讨论过了。双向RNN顾名思义,不仅包含先前向前循环的操作,还可以反向循环。现在我们加上一个反向循环层,这样就和原先正向循环的网络构成了一个无环图,如图所示。这样对于一个单词序列,正向计算会从NLP - 图48开始逐个计算,反向则从NLP - 图49反向逐次计算。最后,通过激活函数在正向与反向分别计算出的值得到最终结果。
image.png
双向RNN也有它的缺点:必须要给定一个输入完的单词序列才可开始计算。这样,在语音识别中,用户也必须要说完一句话之后系统才能给出结果,这可能就会在一定程度上影响体验。但是,带LSTM单元的双向RNN是目前使用最广泛的,也应该成为NLP的首选方案。

深层RNN

RNN也可以有很多层。每层单元的计算公式如下:
NLP - 图51
RNN不像卷积网络那样有很多隐含层,一般来说,三四层可能就足够了。
image.png

词嵌入

在先前的例子中我们使用词向量来表示一个单词序列,这种方法把每个词孤立起来,因此对相关词的泛化能力不强。模型无法感知两个单词之间的关系,因为任意两个词向量之间的内积都是0。
image.png
由此我们想到,可能给每个单词打上标签可能会更好。自此,词向量不再是只有一维取值为1,其他维度均为0的向量。相反,现在每个维度代表该词取不同类别的概率。比如说man与woman两个单词,在gender类别上的取值就很大,分别为-1与1。
image.png
这样一来,每一个单词就可以依据向量嵌在一个多维的空间中。在这个空间中靠的近的单词可以被认为是具有相同特征。这就是词嵌入这一术语的由来。
image.png

使用词嵌入

如下图中的例子,依照之前词嵌入以及命名实体识别的技术,可以训练出一个模型,识别出Sally Johnson是一个人,而且是一个种植水果的农民。假如把apple farmer替换成durian cultivator,且你的字典中也没有这两个单词,词嵌入的技术仍然可以猜测到Robert Lin是一个人名。
词嵌入可以先从学习一个非常大的文本集开始(使用网上训练好的词嵌入模型),然后将其迁移至只有少量标注训练集的任务中。这样的好处是可以用低维的词向量替换原先巨大的词向量,这样就可以更加紧凑。最后,在新的任务中训练模型时,可以选择要不要用新的数据微调词嵌入(前提是第二步的词向量维度很大)。这实际上就是一个迁移学习的过程。
image.png

词嵌入特性

词嵌入可不可以推导出两个单词之间的联系,如已知man与woman相对,那么king与哪个单词相对?答案是可以的。只需将两者的词向量相减,我们就可以看到两个结果只有在gender维度值为-2,其他都约等于0。因此,由于两者之差相等,我们可以推导出king与queen也是相反的。
image.png
刚才我们在已知man,woman,king的情况下找到queen向量的过程其实可以直观地用图表示。其实整个过程为了使下面这个等式成立,也就是在寻找一个点,能与前三个点构成一个平行四边形。所以归纳成算法就是找到一个点,使最底下的函数取最小值。这个函数被称为Consine相似度函数。
image.png
image.png

嵌入矩阵

词嵌入可以通过嵌入矩阵来实现。矩阵的长为字典长度,每一列表示该单词在不同类别上的取值。我门再构建一个普通词向量,除了该单词所在的维度其他均为0,那么使用该矩阵与词向量相乘后,就得到了该单词的词嵌入信息。但在实际使用过程中,不会真的拿矩阵去与向量相乘,因为这样的操作很费时间,与向量相乘只是一个直观的表示。编程时,只需取出矩阵其中一列即可。
image.png

学习词嵌入

那么,如何通过神经网络预测句子呢?对于一个单词序列,我们需要将每一个单词的词向量乘以嵌入矩阵得到嵌入向量。随后将所有单词的嵌入向量输入至神经网络的输入层中,经过隐藏层再通过softmax输出最后的结果。得到的结果也是一个词向量,也就预测了空格中到底应该填什么单词。也可以设置一个历史窗口,隔几个单词预测下一个单词。
image.png
相似地,也可以通过给出空格前面的几个单词与后几个单词,或只有后几个单词,或附近的词来预测应该填入的词。
image.png

Word2Vec

其实刚才我们学习第这个模型就被称作skip-gram模型。
image.png
但这个模型存在一些问题。softmax的输出为
NLP - 图64
一个首要的问题就是计算速度问题。每次想要计算该概率,都要对词典中所有项求和。解决方法可以是带有分类器的softmax等。分类器是一个二叉树,但它通常不是平衡的,一些少见的单词可能会在很深的地方。
文本采样可能会遇到一些麻烦。因为在一篇文章中,a、the、and这些词出现的频率太高了,这些词很容易产生影响。但是我们通常希望预测的是一些不那么不那么常用的单词,比如durian,那么就需要采用不同的策略来平衡常见的词以及不那么常见的词。
image.png

负采样

skip-gram模型带来的问题是计算速度太慢,在负采样中,生成数据的方式是选择一个上下文词,即context,在选择一个target word,及打算匹配的目标。若该样本为正样本,则取1,若为负则取0。我们要做的就是将与context有关的文本标签打上1,字典中的其他词,即负样本,打上0。k值,即学习的样本数量一般取5-20为佳,对于更大的数据集,k可以取2-5。
image.png
由于target的取值为1或0,而模型的目标是判断一词target值为1的概率,因此我们采用sigmoid函数估计概率。公式如下:
NLP - 图67
所以,我们要做的事就是输入一个context词,与嵌入矩阵相乘后得到嵌入向量,随后输入神经网络。得到的输出为词典大小维度,每个都经过logistic回归得出。在这些输出中,我们可以查找一个单词比如juice,然后获取它的target值。但是在训练的过程中并不会每次都训练10000多个神经元,而是只训练其中的k+1(1个正样本,k个负样本)个。所以,不同于skip-gram计算一个10000维softmax分类器,而是把它转变为10000个二分类问题,较为容易计算。
负样本采样的最佳实践:
image.png
**

GloVe(global vectors for word representation)

GloVe的含义即为用词表示的全局向量。它将我们之前使用的context对应target的模型进一步明确化。NLP - 图69所表达的含义是j作为context word时i出现的次数。因此,j就对应c,i就对应t。不难看出,NLP - 图70,存在一种对应关系。
模型可以由这一函数式引入,NLP - 图71可以类比NLP - 图72,我们的目的就是使该式最小。
image.png
但在实际使用中,还需在前面加一项权重值NLP - 图74,它的用途一方面是当NLP - 图75取0时取0,还可以减弱高频词this,is,of,a的权重。相反,对于频度很低的词,比如说durian,就可以适当提高该项的权重。同时,在这个模型中,NLP - 图76是对称的。所以,往往在训练开始时,会同时初始化NLP - 图77的值执行梯度下降。由于两者是对称的,因此最后的e值可以直接取两者的平均,而不是像之前那样,NLP - 图78负责不同的功能。
image.png

情绪分类

情绪分类的任务实际上就是输入一个单词序列,对情感进行分级。
前序步骤与前文中的模型相同,对于一个单词序列,获取每个单词的嵌入向量。随后,可以将这些嵌入向量输入一个均值计算单元,取一个均值。这样会得到一个与嵌入向量相同维度的特征向量,随后输入softmax分类器中,最后输出几个情感可能结果的概率值。这种模型的原理是把所有单词的意思平均起来,但是这也会引入一些缺陷:不考虑词序。
比如说下图中的例子,虽然这是一条差评,但good出现了很多次,采用这种算法很有可能会识别为一条积极的评价。
image.png
为了解决这个问题,我们可以引入RNN。这一模型实际上就是之前提到过的many-to-one网络模型。
image.png

词嵌入除偏

机器学习训练的模型可能会像人一样,对选择产生“偏见”。比方说,模型会倾向于选择男性而不是女性。比方说对于babysitter一词模型认为其与女性的关系更为密切,即babysitter与grandmother之间的距离(相似度)相比与grandfather之间更小(相似度更大)。那么我们通过它画出一条中轴线,使用等距化方法,使grandmother、grandfather两者与中轴线等距,这样一来就可以解决偏见问题。其他类似问题也可以通过这种方法解决。
image.png

序列模型

序列模型的一个应用实例是语言的翻译,输入一个句子,即单词序列,经过编码器与解码器后,会输出目标语种的翻译。此外,卷积网络AlexNet输出的是一个描述该照片的一个信息序列,若我们把它作为输入,同样经过一系列操作后就可以生成有关图片的文字描述。
image.pngimage.png

选择最可能的句子

先前我们构建的模型(语言模型 Language Model)能够估计句子的可能性,也可以用于生成新的句子。而翻译模型包含encoder网络以及decoder网络,其中decoder网络与之前的语言模型看起来十分相似。两者的不同之处在于语言模型总是以零向量开始,而encoder网络会计算出一系列向量来表示输入句子。有了这个输入句子,decoder网络就可以以这个句子开始,而不是以零向量开始。所以,这个模型也叫”conditional language model”。因为它输出的是条件概率,即翻译出来的目标文字基于原始文字上的概率。
image.png
所以,一个模型可以多个翻译版本,且会给出对应不同翻译版本的概率大小。我们要做的就是找到条件概率最大的句子y。不使用贪心算法的原因很简单,考虑全局与序列问题。
image.png

集束搜索(Beam Search)

贪心算法的方法是对于一个输入序列,输出序列中的每个NLP - 图87都选择最优解。这种算法输出时不会考虑之前或之后输出的单词。因此我们改进的算法引入了一个参数B,称为集数宽,那么在考虑输出时就不会只考虑单个输出,而是一次考虑B个。
在下面的例子中,B=3。假设模型选择出了最可能作为第一个字的三个解,将它们储存在内存中。得到了三个最可能的选择后,集束算法会根据每个单词考虑第二个单词是什么。评估第二个单词的值时,会将第一个单词(in)输入至RNN的下一次循环中,然后输出NLP - 图88。因此,输出下一个单词时参考的是条件概率NLP - 图89。由于我们考虑的是一个序列,因此输出两个单词的序列条件概率为:
NLP - 图90
每一步预测都会选择B个最可能的值,那么下一步可选择的值就有B*10000种可能性,按照以上的公式再次取出前三个可能性最大的值。同时,为了做出预测,每一步都会复制三个同样的网络进行评估。
image.png
image.png

改进集束搜索

集束搜索可以通过长度归一化进行进一步优化。集束搜索的目标得到使图中概率最大化的解:
image.png
由于这个式子可以展开变成很多条件概率的解,因此计算机实际要做的不断计算许多远小于1的浮点数的乘积。因此它有可能会造成数值下溢的问题。所以在实际使用中,我们会倾向于使用log值进行运算。
image.png
还有个问题,由于这两个模型会将许多小于1的项相乘,序列越长概率越小,因此它会倾向于选择较短的句子。所以,我们需要做一个归一化,取每个单词概率对数值的平均。
image.png
如何选择B值?太大会影响性能,太小影响结果。所以最好的做法是从1开始,不断尝试各种取值。集束搜索与DFS,BFS不同,集束搜索运行得更快,但并不保证得出精确的最大值。

集束搜索误差分析

当你的模型翻译时出现了错误,究竟是集束搜索出现了问题,还是RNN出现了问题?通过比较NLP - 图96NLP - 图97的大小,就可以做出判断。
image.png若前者大,那么就是集束搜索的问题。若后者大,那么就是RNN的问题。
可以对验证集进行统计,然后选择改进搜索算法或者网络。
image.png

注意力模型

在传统的encoder-decoder网络中,对于短的句子有着非常好的表现效果,但是句子越长,Bleu得分就会越低。因此,我们引入注意力模型来改善这一问题。
image.png
我们需要额外构建一个RNN网络。在输出第一个翻译的单词前,我们需要计算序列中每一个单词对于第一个单词的权重。比方说,第二第三个单词对第一个单词的权重就比较大,越往后单词的权重就越小。随后,我们把这些权重信息输入新构建的神经网络,在执行计算后输出具体翻译的单词。通过这种方法,在翻译每个单词时,模型都会注意待翻译单词附近的单词。
image.png
对于一个双向RNN,设NLP - 图102,我们引入一个新的RNN来生成最终结果。对于每一个单词,在输入新的RNN前都要计算权重值,所有单词对一个单词的权重值之和为1。权重NLP - 图103NLP - 图104之积的总和输入到NLP - 图105中,输出结果,以此类推。这个新的神经网络与标准RNN结构类似,都是一次输出一个单词的翻译结果。
image.png
注意力权重的计算公式如下。它使用了softmax,这是为了确保所有权重加起来和为1。NLP - 图107的学习需要借助神经网络。
image.png