所以,我们希望有一种词向量可以在不同的语境中对词语有不同的表示。
RNNLM模型就是训练一个神经网络,给了前一个词,输出下一个词,训练语料也就是我们日常接触到的新闻、小说、游记等预料。
仔细想一下,在h这个向量中,不仅包含了上一个时刻的向量,同时也包含了当前时刻的输入,那么得到的这个向量是不是就把上下文的信息考虑进来了呢?如果这时候我们取这个h向量的内容,得到的是不是就是包含了当前语境的变量呢。
顺着这个思路,就有了TagLM这篇论文,论文的作者和emlo的作者相同,所以这篇文章也可以算是preElmo。
在语言模型的训练是利用现有的数据来进行训练,相当于已经先天就是带有标签的数据。在针对NER的任务时,先用RNN提前训练好一组词向量。wordembedding的词向量做一个拼接,作为NER的输入。
下面描述一些模型的训练细节
图中的左下方是先对词进行一个char级别的cnn保证不会出现很多的OOV情况,之后和token的embedding做一个拼接,之后经过一层双向的rnn。
红框部分就是将当前得到的向量和lm得到的向量做一个拼接的操作,LM训练的方法也很简单,就是用了一个双向的RNN,最后将这个输出做一个 拼接
看一下当年的论文结果,实体识别的准确率上达到了最好。因为在最开始部分加了charCNN,所以很多人名也可以被准确的识别出来。
在这篇文章之后,很多人开始做类似的尝试。Cove借鉴了LM的思想,用NMT得到的向量,来代替LM的向量,从而改善了效果。但是这种方法未能证明比LM效果要好,因为一般来说,NMT本身就是比LM还要难做的东西,得到向量编码不一定就会比lm准确。
说完了上面两篇,开始讲本文的主题之一:EMLo,Elmo相对之前的模型,有两点改进:1、加入上下文信息,不在像之前固定的窗口大小,这样可以保证得到的向量是有上下文信息的;2、增加模型的神深度,并且保证将每一层得到的向量都用于预测。
训练方法还是用双向的LSTM
在模型的输入阶段还是使用了characterCNN保证不会出现很多的OOV,最后在输出阶段,将正向和反向的权证保证相同。目前函数也是最大似然。
EMLo的另外一个创新点就是根据不同的下游任务,选择不同的embedding的权重,这里它考虑了所有隐层和最后输出层的表示,通过不同权重,加权求和得到最终的输出。
γ表示训练出的LM向量的权重,s表示每一层的权重的分配。
在具体的使用中,首先通过LM得到每个词的embedding,之后冻结embeeding的词向量,可以将它和输入拼接,也可以和隐藏层拼接,这个结合具体的任务。在训练中还需要注意使用dropout和regularization的使用。
在NER任务上,和之前的模型有了明显的提升。
同时,在多个nlp任务上,都有明显的提升。证明了,迁移学习在nlp任务中有很好的应用。
和Glove相比,EMLo模型中,同一个词在不同的语言环境中编码是不同的,但是Glove却只能有一种embedding的内容。
对模型进行更细粒度的分析发现,两层lstm的第一层 更多的是get'到编码的语法信息,第二层一般是get到词义的信息。在词性标注任务中,只使用第一层的准确率是97.3%,要好于使用第二层的,反之在相近词分析的任务中,第二层的F1值是高于第一层。
Transformer
在讲transformer之前,先回顾一下,句子的表示方法。对于一个长度不定的句子来说,一般有几种方法:在得到词向量之后,通过求和、或者求平均的方法,来表示整个句子;另外的方法是采用CNN或者RNN的方法对句子进行编码,最终得到句子的输出。
对于一个句子来说,最常用的编码方法就是RNN。输入每个词的向量,将当前词的向量和上下文信息做融合,最终得到一个向量,算作是对整个句子进行表征。这样的逻辑应该是很符合大家的认知的。
但是这种序列的结构,是很不方便进行并行训练的,只能按照序列的顺序进行训练;同时这种模型没有考虑词和词之间的一个关联性,两个词词义相近或者相反,在模型中,并没有表示出来。
另外一种常用的模型就是CNN,CNN采用多个卷积核,把这个词旁边的信息和这个词关联起来进行处理,这样就把词语之间的关系关联了起来,同时还可以方便的实现并行;但是这样的处理方式只能提取到局部的信息,不能提取整个句子的相关性,如果句子的长度很长,就需要很多层,才能 提取出整个句子的表示;
近些年来,常用的一种思想就是attention机制。attention在NMT中有着广泛的应用,提取出句子中多个关键词语表达的含义,降低最后一个词对整个句子的影响。
既然attention这么牛逼,我是否可以直接通过一个attention把句子中关键的词选择出来,而不再经过RNN编码,再选择。
举一个在NMT中的例子,当我在翻译深度这个词时,首先会初始化一个Z0,这个Z0会和输入的隐层做一个内积操作,从而得到一组权重,最后用这一组权重和隐含层的向量加权和,来作为深度这个词的向量,整个的过程就是使用attention机制进行翻译。在这个例子中,key和value是相同的。
抽象化之后如下图,其中,key的维度和query的维度必须相同,因为两者要做内积,必须保证维度相同。
如果有多个query,那么query就会变成一个矩阵了,处理的思想还是相同的。还是Q和K做一个softmax之后和V作为加权和这样就得到attention矩阵了
以上就是encoder和decoder之间使用的attention,通过这种方式,表征出输出的向量。那么如何做self-attention呢
self-attetnion就是自己对自己做attetion,选择出最重要的词或者句子。比如说,在获取a这个字母的向量时,会先将a的向量和其他所有的词进行内积操作,得到的权证和这个词的向量相乘,加和之后得到向量,作为a在上下文中的向量。经过这样处理之后,不仅得到了结合上下文的词的编码,还实现了可并行化处理的功能。
Transformer的主要思想就是这个思路,这个结构还是建立在encoder和decoder的基础上,首先在encoder部分,做了两次self-attention。然后看decoder部分,decoer部分在做self-attention的时候,只能对已经输出的词做attention,不能对还没有输出的词做attention,所以还没有输出的词语需要用mask来遮盖住。这样经过两次self-attention再经过一次encoder和decoder的attention的操作,经过softmax得到最终的输出。
具体来说,输入端部分就是这种结构。
decoder部分和encoder类似,只是在后面的字符上会用mask作为遮挡,从而避免作弊的嫌疑。
在transformer中更重要的一个处理是引入了multi-head机制,说白了就是利用多个卷积核来提取不同的特征。这一点在图像的处理中经常使用。
如下图所示,不同的卷积核是可以提取到不同的特征的,但是无法确定哪个特征是最重要的。
同时self-attention是可以帮助我们决定哪个特征是重要的
将两者结合一下就是multi-head的attetnion
论文中transformer的结构图
论文中多头attetnion
这里有个细节就是scaled-dot attention,为什么要加一个scaled,试想,如果当一个句子的长度很长,那么就会导致这个向量在经过softmax之后,就会让这个分布很尖,就会导致梯度很小,这么深的模型,梯度这么小,很容易训练不下去。所以除以key的维度。
在encoder部分,还有一个残差连接和layer normalization,前者是想保留一些特征,让这些特征直接进入到下一层,不用经过feed forward network 之后 经过一层normalization
为了保存序列信息,加入了position embedding,
在多头attention的使用上,self-attention中q=k=v ,在encoder-decoder中k=v,但是q和k是不相等的。
BERT是在transformer的基础上,加入了双向的结构,在多个任务上取得了惊人的效果。
BERT的思想就是用transformer替代了lstm
BERT的改进之一就是使用了mask LM
ELMo中采用的是双向的lstm,但是前向和后向是分开考虑,只是在最后做了一个拼接,我能不能在最开始编码的时候,就把这两个放在一起考虑呢,答案是肯定的。加入mask就是想让模型通过对左右词的判断,最终输出被mask的词,这样可以提升模型的训练效果,这个15%的比例,是经过试验效果决定的,太大太小都会影响训练的效果。
三种模型的对比,GPT使用了transformer进行编码,但是只采用了单向的,ELMo虽然使用了双向的,但是使用lstm进行编码,效果肯定没有selfattention好。
BERT的另一个改进的地方就是加入下一个句子的预测,建模句子与句子之间的关系。训练的方法就是将一些文章中的下一句替换掉,这样标签的话就是是否是下一句。从而在建模的时候,可以把句子与句子之间的关系也表示出来。
整理一下,整个模型的input就是这个样子:segment embedding 会把一些词形的变化分开,比如加ing ed 这种形式。