深度学习在NLP领域的发展
一、词向量历史
1.1 第一阶段:
Word embeddignd
- Word 2Vec
- Glove
通过无监督的语料,来学习到比较好的词向量,基于词向量来进行其他的下游任务,提高模型的泛化能力。
1.2 第二阶段:
RNN的改进和拓展(基于上下文,使得模型能对一个词表现多个意思)
- LSTM/GRU
- Seq2Seq
- Attention / Self-attention
1.3 第三阶段:
Contextual Word Embedding()
- ELMO
- OPENAI GPT
- BERT
二、词向量详细介绍
2.1 Word embedding
把词映射为 “ 语义 ”坐标系中的一个点,基于这个映射可以使语义相似的词相距较近。可以学习一些词对应关系。例如男性,女性词相关关系。
缺点:
由于一个词可能有多种语义。例如bank可以是,“银行”,也可以是“河堤”。所以,对于word embedding来说,不能基于上下文进行多语义判断。
2.2 RNN(上下文语义)
RNN中比较经典的例子是:seq2seq,它是由两个RNN组成,可以用于翻译,摘要,问答和对话系统。
如下图所示,为法语翻译成英语的例子。将法语通过encoder编码器(RNN)编码为context向量,获得法语的语义表示。然后用Decoder解码器(RNN)去将语义向量解码称为英文表示。
缺点:
1、监督数据量不足,难以学到复杂的上下文表示
解决方法:使用无监督的上下文词嵌入(ELMO,GPT,BERT)
三、词向量表示
3.1 One-Hot encoding
将词以词向量的方式表示,如下图所示,有四个词,将其进行one-hot 编码,编码为
第一个词为[1,0,0,0]
第二个词为[0,1,0,0]
第三个词为[0,0,1,0]
第四个词为[0,0,0,1]
特点:
高维(词越多,维数越高),稀疏(词分布较大,都在对角线上),正交(两个相邻词距离固定)
3.2 神经网络语言模型
给定一个句子 , 计算这个句子出现的概率。可以使用条件概率将其表示成句子中每个词词出现的概率,并将词出现概率累乘后即为句子出现概率。
该模型特点:
1、存在长距离依赖问题。
例如,我出生在法国,(巴拉巴拉*100个词),我会说一口流利的[mask],问[mask]是什么?
这里[mask]很大概率是“法语”,因为他出生在法国。但法国距离现在词位置非常远,神经网络语言很难去获得这个信息。
2、可以解决泛化能力较差,不能共享上下文的问题。
例如语料库中,出现较多“我要去北京”,而“我要去上海”相对较少。就会出现北京的权重比上海大。但是上海和北京权重应该都是类似的。通过神经网络语言模型可以使得,“我要去”后面跟“上海”和“北京”的权值差不多大。
3.3 word2Vec
如果两个词的上下文关系是相似的,则他们的语义也是相似的。即一个词的向量表示跟他周围的词相关。
如下图所示:训练过程中,你需要同时考虑了它左右的上下文,那么就可以使"written"带有语义信息了。通过这种操作,我们可以得到近义词,甚至cat和它的复数cats的向量极其相近。
Word2Vec有两种实现方式:
CBOW:给定上下文来预测输出词
假设我们现在的Corpus是这一个简单的只有四个单词的document:
{I drink coffee everyday}
我们选coffee作为中心词,window size设为2(仅选输入词前后各两个词和输入词进行组合)
也就是说,我们要根据单词"I","drink"和"everyday"来预测一个单词,并且我们希望这个单词是coffee。
Skip-Gram:通过输出词来预测上下文
上图中,w(t)就是中心词,也叫给定输入词。其中有一个隐藏层,它执行权重矩阵和输入向量w(t)之间的点积运算。隐藏层中不使用激活函数。现在,隐藏层中的点积运算结果被传递到输出层。输出层计算隐藏层输出向量和输出层权重矩阵之间的点积。然后用softmax激活函数来计算在给定上下文位置中,单词出现在w(t)上下文中的概率。
例如我们选定句子“The quick brown fox jumps over lazy dog”,设定我们的窗口大小为2(window_size=2),也就是说我们仅选输入词前后各两个词和输入词进行组合。下图中,蓝色代表input word,方框内代表位于窗口内的单词。
我们的模型将会从每对单词出现的次数中习得统计结果。例如,我们的神经网络可能会得到更多类似(“Soviet“,”Union“)这样的训练样本对,而对于(”Soviet“,”Sasquatch“)这样的组合却看到的很少。因此,当我们的模型完成训练后,给定一个单词”Soviet“作为输入,输出的结果中”Union“或者”Russia“要比”Sasquatch“被赋予更高的概率。
3.4 RNN
RNN具有“记忆”能力,在考虑t时刻的状态时,会参考t-1时刻的前序信息。公式及示意图如下;
RNN在执行过程中,需要进行反向传播,往回调整参数。但经过多层回传的问题,倘若回传的学习率<1,容易导致梯度消失的问题。倘若回传的学习率>1,容易导致梯度爆炸的问题。
LSTM可以解决梯度消失和梯度爆炸的问题。(即基于门的机制来避免梯度消失的问题)
GRU为在LSTM上的变体,把遗忘门和输入们合并成一个更新门。
对于RNN问题,可以将其用作序列标注(下图左),分类问题(下图右)
对于seq2seq模型,可以用作机器翻译,摘要,问题,对话等任务上。其使用两个RNN(encoder和decoder)进行训练。将前序句子转换成语义向量(encoder),并基于语义向量获得输出(decoder)
3.5 attention机制
attention机制,例如在任务中,翻译某个词时,现在位于位置,拥有比较粗糙的语义,则需要去前面获得一些对应的信息。使用softmax将前面词转换成[0~1]的概率,获得一个概率分布。加权累加后得到前序文本的向量context vector。context vector与很像,但为比更细化的内容。将其一起输入来进行预测,获得输出。
RNN缺陷问题:
1、顺序依赖,无法并行。
2、单向信息流问题,需要考虑整个句子。
普通的attention,如下图所示,需要考虑 "I" ,“ am”等其他单词,即需要一个外部的“驱动“,来进行。
self-attention为自驱动的,当编码第t个单词时,用当前状态去驱动“自己周围的内容”。
3.6 transformer结构
由多层的Encode-Decode堆叠而成。
对于每一次encoder和decoder,其结构如下:
Encoder中为self-attention和线性层组成;
Decoder中为self-attention,注意力层和线性层组成;
对于encoder层,其详细结构如下:
transformer结构如下:
假设句子只有thinking和machines两个词,首先对他们进行embedding,获得一个长度为四的词向量。接下来使用三个变换矩阵,,,分别把每个词变换成三个向量,,,,,。(*=)
获得向量后,我们要对其进行计算。(以Thinking词为例子)
1、计算和,的Score。(两个向量内积越大,代表两个向量越相似);
2、使用softmax将 score变成概率。
3、加权计算,计算类似。
其中:
为提取信息的向量;
为被检索的向量;
为词真正的语义向量;
如下为该方法的矩阵计算过程,以此计算所有的Q,K和V,并一步计算得到z:
3.7 multi-Heads多头attention
即由多个attention(Q、K和V)组成的模型。可以将其认为,每个heads解决一个任务的某一个问题。例如利用一组矩阵是用于解决“指代消解”,一组矩阵是用来关注”句子上下关系的“及一组矩阵是用来关注”国家首都等“对应关系的。即不同的head学到不同的语义关系。
传统的transformer是8个heads的。如下图所示:
根据计算得到z,但由于z信息比较多,需要用一个24*4的矩阵(每一个z为3位矩阵,8个z为24),将其压缩成一个四维的向量。
完整过程如下:transformer中每一个输入x有8个heads,每个head有对应的q,k,v。所以就有有8个q,k,v,获得8个z,并通过(24x3的矩阵)对其进行压缩,可以获得Z(四维矩阵)。
对于:
北京 到 上海 的机票。
上海 到 北京 的机票。
由于上海和北京在两个句子中代表的含义不同,分别代表始发点和目的地。
由此,transformer提供了位置编码,即每一个位置一个embedding。
但:
北京到上海的机票 vs 您好,我要一张北京到上海的机票。
对于“北京”一词,由于位置不一样,他们的编码肯定是不一样的。
由此,transformer又提供了相对位置编码,能较好的保证相对位置编码。
但bert或gpt使用的是比较简单的绝对位置编码。
在transformer 中decoder不能利用未来的信息。他利用一各掩码矩阵mask matrix,当预测第一个词时,只能看前1个,当预测第3个词时,可以看前三个。(对于mask matrix 中每一行)
四、上下文词嵌入(contextual word embedding)
问题:
1、由于word embedding无上下文。
2、并且,监督数据太少。
解决办法(contextual word embedding):
1、引入无监督模型。
2、考虑上下文的embedding。
4.1 ELMO
A: 你好,ELMO,词'stick'的词向量是什么?
ELMO:它有很多种表示,你要给我个句子,我才告诉你。
A:偶,好的。句子"Let's stick to improvisation in this skit"
ELMO:好的,在这个例子中,它的词向量为[-0.02,-0.16,0.12,-0.1,,,etc]
ELMO的思想就是:考虑上下文。
双向多次的LSTM的NNLM(神经网络语言模型)
ELMO问题:
1、contextual word embedding作为特征;
2、基于无监督学习,可能不适合某些特定任务。
OpenAI GPT改进
1、根据任务 fine-tuning(微调)。
2、使用transformer 代替 RNN/LSTM。
4.2 OPENAI GPT
只是用transformer 的decoder,没有用encoder的 transformer,
结构:
1、带mask的 self-attention
2、全连接层
训练语言模型是单句子的,对于多个句子,如何进行fine-tuning?
通过将两个句子强行拼接起来。使用start,extract来表示开始和结束,使用Delm表示分割符。
OpenAI GPT的问题:
1、单向的,即使用带mask的self-attention,在编码的时候只能看前面,不能看后面。
2、pretraning和fine-tunning不匹配。
解决:
使用BERT
1、使用marked LM(语言模型)
2、使用NSP multi-task learning (下一个句子预测)
3、使用encoder again
4.3 bert
1、将输入分成两段。
2、BPE编码
bert结构有
input(输入层):将输入分成两部分。以"[CLS]"开头,以"[SEP]" 作为分隔和结尾。
token embeddings(字向量):以细粒度的字为基准,获得词向量。
segment embeddings(段落表示):以"[SEP]" 左右来分段,左边为A句子,右边为B句子。
position Embeddings(位置表示):获得对应输入的位置信息。
1、解决单向信息流问题
使用masked ML,类似完形填空,随机[mask]掉15%的词,让bert来预测。
2、引入新任务解决pretraining和fine-tuning
bert以50%的概率抽取两个连贯的句子,也用50%的概率连续抽取两个句子,基于Next sentent prediction来学习两个句子之间的关系。
4.3.1 bert单个句子任务
例如情感分类,文本分类。输入是一个句子,进行编码,每个时刻都输出一个向量。拿[cls]的第一个词接上全连接层进行分类,获得分类结果。
bert任务还是预测一个词,[cls]是一个没有意义的词,它都是attention到其他有意义的词上,所以他的语义都是来自整个句子。所以这里说明他编码了整个句子的语义。
4.3.2 bert两个句子任务
4.3.3 bert问答任务
4.3.4 bert序列标注任务
5 bert代码及应用
预训练模型:
前四个为:英文模型;
最后一个:中文模型;
bert-large-ml-cased:多国语言;
uncased:不做大小写归一化,即大写小写同时存在。
cased:大写都归一化成小写了
fine-tuning
数据预训练:pretraining(准备数据)
数据预训练:pretraining(训练数据)
5.1 实战
1、高频常见问题(FAQ)回答机器人
解决方法:
1、相似计算(KNN),优点:简单,效果没意图分类好
bert提高10%
2、意图分类。
bert提高3%
5.2 注意事项
1、使用中文模型,不要使用多语言模型。
2、max_seq_length 可以小一点,提高效率。
3、内存不够,需要调整train_batch_size
4、有足够多的领域数据,可以尝试find tuning.