本文转载自微信官方账号AI NLP

NLP

自然语言处理是信息时代最重要的技术之一。理解复杂语言也是人工智能的重要组成部分。自从谷歌在2018年10月底宣布bert在11个nlp任务中的卓越表以来,BERT已经成为最杰出的NLP。本文为大家分析一下伯特。

自然语言处理的常见任务有:中文分词、句法分析、自动文摘、问答系统、文本分类、回指消解、情感分析等。

我们将从one-hot、单词嵌入、rnn、seq2seq和transformer这几个构成我们理解bert的基础的方面一步步来接近bert。

单词嵌入

首先,我们需要对文本进行编码,使其成为计算机可读的语言。编码时,我们期望句子在词与词之间保持相似的线条,词的向量表示是机器学习和深度学习的基础。

单词嵌入的一个基本思想是,我们把一个单词映射到语义空之间的一个点,把一个单词映射到低维稠密空之间的一个点。这种映射使得语义相似的词在语义空之间的距离很近。如果这两个词之间的关系不是很密切,那么在语义上,

如上图,英语和西班牙语在语义空之间映射,语义相同的数字分布在语义空之间的相同位置

在空句之间的结构中,我们期望获得较低级别的关系,例如:

VKing - VQueen = VMan-VWomenVParis - VFrance = VBerlin -VGerman

国王和王后的关系应该和男人和女人的关系大致相同,所以他们通过矩阵运算来维持这种关系

巴黎和法国的关系应该和柏林和德国的关系大致相同,所以他们通过矩阵运算来维持这种关系

简单回顾一下单词嵌入,对于自然语言处理,我们输入离散符号,对于神经网络,它处理向量或矩阵。所以第一步,我们需要把一个单词编码成一个向量。最简单的方式就是表达一热。如下图所示:

单向编码

通常我们的话很多,只显示了会议出现的地方,所以必然会有一些问题

高维的表示稀疏性正交性(任意两个词的距离都是1,除了自己和自己,这样就带来一个问题,猫和狗距离是1,猫和石头距离也是1,但我们理解上猫和狗距离应该更近一些)

两个词在意义上无法正确表达,所以我们希望低维相似度更近,语义相似的词更近,语义相似的词更远。

解决方法是单词enbedding,这是一种具有密集维度的表示。

神经网络语言模型

我们都知道单词2vec,手套。其实早在神经网络语言模型中就出现了。早就有了一个词向量。语言模型是自然语言处理的基本任务。给定一个包含k个单词的句子w,我们需要计算这个句子的概率。使用分解成条件概率积的形式。条件概率的计算。

统计n-gram、词频统计等传统方法,出现多的概率较高,出现少的概率较低。

不能常时依赖上下文,如:他出生在法国,他可以讲一口流利的(__),我们希望法语的概率比英语、汉语的概率要高。n-gram记住只能前面有限几个词,若参数比较多,它根本学不到这复杂关系,这是传统语言模型比较大的一个问题。这个可以通过后面的rnn、lstm解决,我们这里先不讨论。第二个问题就是泛化能力的问题,泛化能力,或者说不能共享上下文的信息,我要去(__)玩, 北京、上海应该是一样的,因为都是中国的一个城市,概率应该相等或相近的,但是因为预料中北京很多,所以出现上海的概率很低。那神经网络语言模型就可以解决这样的问题。

神经网络语言模型架构如上所示:

将每个单词向量连接成一个句子矩阵。每一栏都是一个字。比如北京、上海、天津相对较近,面积大致相同,所以在预测时可以给出大致相同的概率,这不仅与预期的统计结果有关。单词可以通过矩阵乘法来提取,但是为了提取一个单词,我们必须进行矩阵运算,效率相对较低,所以更成熟的框架提供了一种查表的方法,效率更高。

因为语境环境很相似,他们会分享相似的语境,让我去的概率会更高。这也是神经网络语言模型的一个好处。我们通过神经网络语言模型得到一个词向量。当然,我们也可以使用其他任务来获取词向量,比如句法分析,但是那些任务大多是监督学习,需要大量的标注信息。

语言模型无监督,数据采集不需要太多成本。

Word2vec不同于神经网络语言模型,后者使用分布式假设直接学习这个词向量。如果两个词的语境相似,那么它们的语义也相似。

Word2vec可以分为cbow和skip-gram。

我们可以通过word2vec或者手套从大量未标注的语料库中学习。我们可以学习更好的向量表示和单词之间的一些关系。比如男女关系,时间关系,学习了这种关系后,我们可以把它作为后续任务的特征,从而提高模型的泛化能力。

但同时也存在一些问题,如:

He deposited his money in this bank .His soldiers were arrayed along the river bank . word embeding 有个问题就是我们的词通常有很多语义的,比如bank是银行还是河岸,具体的意思要取决与上下文,如果我们强行用一个向量来表示语义的话,只能把这两种语义都编码在这个向量里,但实际一个句子中,一个词只有一个语义,那么这种编码是有问题的。RNN/LSTM/GRU

那么这个上下文的语义就可以由RNN/LSTM/GRU来解决,与普通的深度学习不同,RNN是一个序列模型,它有一定的记忆单元,可以记住之前的历史信息,因此可以对一些与这个上下文相关的语义进行建模。RNN的记忆单元可以记住当前单词之前的信息。

RR可以解决。理论上,我们希望学习一段长久的关系。但是由于梯度消失的问题,长期依赖并不能很好的训练。

事实上,lstm可以解决RNN依赖梯度长期消失的问题。

seq2seq

对于翻译,我们不能要求英语的第一个单词必须对应法语的第一个单词,也不能要求同样的长度。对于这样一个rnn,这个问题是无法解决的。我们用两个RNNs拼接成seq2seq。

我们可以用两段RNN组成seq2seq模型从而可以来做翻译,摘要、问答和对话系统。

比如经典的翻译例子就是法语到英语的翻译,由编码器编码到语义空,由解码器根据语义空解码翻译成英语句子。

编码器把要翻译的句子映射到整个语义空,解码器按照语义空,一个一个翻译,但句子长度有时会被截断。一个问题是我们需要一个固定长度的上下文向量来编码所有的语义,这非常困难,不可能记住每一个细节。用一个向量很难记住整个语义。

这时候我们引入了注意机制。

可以理解为,上下文只记住一个粗略提取的信息,一种方法是做内积,内积大的话会比较关注。这里可以理解为一种提取方法。在提取相关内容时,会用具体的ecoder位置进行计算,得到更详细的内容。

注意做内积。变大变近很重要。后续关注和transformer都是对seq2seq的改进,可以解决embbeing这个词没有上下文的问题。

有了关注机制,我们取得了很大的成绩,但还是有问题。

顺序依赖,如下图所示:t依赖t-1,t-1依赖t-2,这是串行的,很难并行计算,连续依赖通常比较慢,无法并行:

The animal didn’t cross the street because it was too tired.The animal didn’t cross the street because it was too narrow. 存在单向信息流的问题,只看前文,我们很难猜测it指代的具体内容,编码的时候我们要看整个句子的上下文,只看前面或者只看后面是不行的。 RNN的两个问题: 1、顺序依赖,t依赖t-1时刻。 2、单向信息流(如例子中指代信息,不能确定) 3、需要一些比较多的监督数据,对于数据获取成本很高的任务,就比较困难,在实际中很难学到复杂的上下文关系Contextual Word Embedding

为了解决RNN问题,引入了上下文词嵌入。

contextual word embedding:无监督的上下文的表示,这种无监督的学习是考虑上下文的,比如ELMo、OpenAI GPT、BERT都是上下文相关的词的表示方法。

注意力需要两句话,但我们往往只有一句话,需要自我关注。在提取信息和编码时,自我关注是自我驱动的。自我关注关注的是有关单词前后的整个语境。

自我关注原本是变压器的一部分。变压器是如何解决这个问题的?

变压器:

本质上也是编码器和解码器的过程。刚开始,六个编码器,六个解码器叠放在一起。如果是LSTM,通常很难进行深度训练,也不能很好地进行比较

每层的结构都是一样的。我们取出一层进行解析。每一层都有自我关注和前馈。解码器和普通注意力输入来自编码器。和seq-2seq一样,我翻译一个单词的时候会考虑编码器的输出做一个普通的注意。

给定下图所示例子中的思维和机器两个词,首先通过单词嵌入变成一个向量,然后通过自我注意变成一个向量。这里,sefl-注意考虑上下文。然后连接到全连接层。在计算z1的时候,我不得不依靠x1,x2,x3的整个序列来计算z1。z2也是如此。当我计算r1时,只要有z1,我就可以计算r1。只要有z2,就能算出r2。这个差别很大,我可以并行计算。

让我们来看看自我关注是如何计算的

假设只有两个字,映射成长度只有四个的向量。然后,使用三个变换矩阵wqwkwv将每个向量变换成三个向量q1k1v1q2k2v2,再乘以映射向量。

向量可以在获得后进行编码。考虑到上下文,如上所述,bank同时具有多种语义,所以在对这个词进行编码时要考虑其他词。具体计算是q1k1做内积q2k2做内积得到分数,内积越大说明差不多,softmax会变成概率。关注概率为0.88的思考,关注概率为0.12的macheins这个词

可以计算z1,Z1 = 0.88v1+0.12z2。

z2的计算类似,

q表示为了给自己编码而查询其他词,K表示被查询,V表示这个词的真实语义,经过转换成为包含上下文的真实信息。普通注意可以理解为自我注意的特例。

普通注意力的比较:

其实有多个头,也就是多个注意力,都是通过训练学会的。不同的关注点关注不同的信息,这是指上下关系的分辨率。原纸有八个头,每个注意力得到一个三维矩阵。

8个3维拼接成24维,太多信息24 *4后压缩成4维。

位置代码:

北京 到 上海 的机票上海 到 北京 的机票

自我关注不考虑位置关系。在北京,两句话初始映射是一样的。因为上下文相同,qkv也一样,最后的向量也一样。在这样的句子里,注意的向量是一样的。其实不一样,一个是出发城市,一个是到达城市。

介绍位置编码、绝对位置编码和每个位置一个嵌入

每个位置嵌入一个,同一句话,多一个字会不一样,编码也会不一样

北京到上海的机票 vs 你好,我要北京到上海的机票

Tranformer的原始论文使用相对位置编码,而bert open gpt使用简单的绝对位置编码:

你可以试试伯特。改变相对位置是否更好:

变压器中编码器的完整结构,加上剩余连接和分层形式

解码器添加普通注意力,最后一分钟输出会被输入

变压器的解码器不能使用未知信息,即单向信息流问题。

变压器解决了这个问题:

可以并行计算,训练很深入。后来,开放的gpt可以到达12层伯特的16层和24层

单向信息流的问题:编码器的时候至少要考虑前后信息,这样才能达到很好的效果。

Transformer解决了常见的单词嵌入没有上下文的问题,但是要解决这个问题,需要大量的标注信息样本。

如何解决变压器的问题,介绍了elmo

Elmo:无监督的基于上下文的学习。

语言模型的预测逐一进行;

双向lstm,每个向量2n,是一种特征提取方法,考虑到上下文,编码后是固定的。

Elmo:把上下文看作一个特征,但是无监督的语料库与我们真实的语料库不同,不一定满足我们特定的任务,是一个双向的特征提取。

Openai gpt有所改进。也是transformer学习的语言模型,不固定。通过任务微调,使用transfomer代替elmo的lstm。

Openai gpt其实缺少编码器的变压器。当然,编码器和解码器之间并没有什么讲究。

OpenAI gpt可以进行微调,但有些特殊任务与预处理输入不同。单句和两句不一致的问题很难解决,解码器只能看到前面的信息。

伯特

伯特在这些方面做了改进:

Masked LMNSP Multi-task LearningEncoder again

伯特为什么更好?

单向信息流的问题 ,只能看前面,不能看后面,其实预料里有后面的信息,只是训练语言模型任务特殊要求只能看后面的信息,这是最大的一个问题。其次是pretrain 和finetuning 几个句子不匹配

伯特的输入是两句话,分隔符sep和cls表示开头。对于两个输入句子,使用位置编码。据此,片段嵌入可以知道单词属于哪个句子,使得学习更加容易。可以清楚的知道第一句话需要编码什么信息,第二句话可以编码什么信息。

单向信息流的问题,换一个任务来处理这个问题

单向信息流问题:mask ml有点类似完形填充空,根据上下文信息猜测信息,计算最大概率,随机扔掉15%的单词给bert做预测,考虑前后双向信息,如何造两句话?

-抽取连续句子1的正样本的概率为50%

50%概率抽随机句子 负样本 0

这样学习两个句子之间的关系,可以预测句子之间的关系,这在一些问答场景中非常重要。

微调:

对于单个句子的任务,我们取第一个cls向量,用一些完全连通的层连接起来,做一个分类。标记的数据微调参数还包括一个完全连接的参数。为什么选择第一种?

伯特的任务是预测单词。预测的时候会参考其他词。比如吃本身就是吃的语义,显然不可能直接按照吃来分类。cls没有太多其他词的语义,所以它的语义完全来自整句话的其他语义,编码整句话的语义。用就可以了。当然,所有的结果都可以拼接后再做预测。

注意:

使用中文模型,不要使用多语言模型max_seq_length 可以小一点,提高效率内存不够,需要调整 train_batch_size有足够多的领域数据,可以尝试 Pretraining

bert的实际应用相对简单,但深入细节并推荐简单的演示示例:

https://www.jianshu.com/p/3d0bb34c488a

1.《bert 从 one-hot 到 BERT,带你一步步理解 BERT》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《bert 从 one-hot 到 BERT,带你一步步理解 BERT》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/junshi/1757330.html