⑴ BERT关系抽取之R-BERT模型
前期知识准备 :RNN, CNN, BERT, SemEval-2010 Task 8数据集, F1值
关系分类是一个重要的NLP任务,其主要目标是提取出实体之间的关系。最先进的关系分类方法主要是基于CNN或RNN。最近,预训练BERT模型在许多NLP的分类和序列标注任务中都获得了非常好的结果。关系分类不同于其他NLP任务的主要原因是它既依赖于句子的信息,又依赖于两个目标实体的信息。在本文中,我们提出了一个用来解决关系分类任务的模型,它既利用了预训练的BERT语言模型,又结合来自目标实体的信息。我们定位目标实体并通过预训练结构传递信息,同时还结合了两个实体的相关编码。在SemEval-2010 Task 8任务上,相比目前的最优模型我们的方法获得了有效的提升。简桐搜
R-BERT的预训练完全采用BERT模型,输入句子为单句,因此不需要添加[SEP]。其输出分为三部分,分别是[CLS]隐含状态向量和两个实体的隐含状态向量。作者认为第一部分可以保存句子的语义内容,后两个部分可以保存两个实体的信息。
其中,i ,j分别为第一个实体的首、尾字符位置;k,m分别为第二个实体的首、尾字符位置。神经网络中,权重系数和偏置系数均共享,即 W0 = W1 = W2,b0 = b1 = b2。
该数据集包含9类语义关系和一个Other类别,规定某关系如果不属于9类语义关系中的一种,则其属于Other类别。9类关系分别是:Cause-Effect、Component-Whole、Content-Container、Entity-Destination、Entity-Origin、Instrument-Angency、Member-Collection、Message-Topic和Proct-Procer。数据集中共有10717个句子,8000个句子为训练集,2717个句子为测试集,每个句子包含e1和e2两个名词以及与该句子相关的关系类型。需要注意的是,关系是有向的,即关系(e1, e2)和关系(e2, e1)不同。
作者还在相同的数据集上比较了其他多种模型,其中包括:SVM、RNN、MVRNN、CNN+Softmax、FCM、CR-CNN、Attention CNN、Att-Pooling-CNN和Entity Attention Bi-LSTM,以F1值作为评测标准,其结果如下:
可见,R-BERT的F1值达到了89.25,相比于其他方法有着明显的优势。
为了探究BERT模型之外的部分对最后识别结果的影响,作者分别进行了如下额外实验,并得到结论:
(1)去除了实体前后的标识符,这种做法会使模型的F1值从89.25%降到87.98%,说明了标识符可以帮助提供实体信息。
(2)在BERT输出层仅使用[CLS]句子向量而不利用实体向量,这样会使得模型F1值从89.25%降到87.99%,说轮正明主动明确实体信息对模型是有帮助的。
想办法给模型明确实体的位置对于关系抽取问题精度的提升是有拦历帮助的。
https://zhuanlan.hu.com/p/78445887
https://blog.csdn.net/qq_36426650/article/details/96629835
⑵ BERT详解(附带ELMo、GPT 介绍)
首先我会详细阐述 BERT 原理,然后简单介绍一下 ELMO 以及 GPT
BERT 全称为 B idirectional E ncoder R epresentation from T ransformer,是 Google 以 无监督的方式利用大量无标注文本 “炼成”的语言模型,其架构为 Transformer 中的 Encoder(BERT=Encoder of Transformer)
我在 Transformer 详解 中已经详细的解释了所有 Transformer 的相关概念,这里就不再赘述
以往为了解决不同的 NLP 任务,我们会为该任务设计一个最合适的神经网络架构并做训练,以下是一些简单的例子
不同的 NLP 任务通常需要不同的模型,而设计这些模型并测试其 performance 是非常耗成本的(人力,时间,计算资源)改扒哗。如果有一个能 直接处理各式 NLP 任务的通用架构 该有多好?
随着时代演进,不少人很自然地有了这样子的想法,而 BERT 就是其中一个将此概念付诸实践的例子
Google 在预训练 BERT 时让它同时进行两个任务:
1. 漏字填空
2. 下个句子预测
对正常人来说,要完成这两个任务非常简单。只要稍微看一下前后文就知道完形填空任务中 [MASK] 里应该填 退了 ;而 醒醒吧 后面接 你没有妹妹 也十分合理(?)
接下来我会分别详细介绍论文中这两个任务的设计细节
在 BERT 中,Masked LM(核行Masked Language Model)构建了语言模型,简单来说,就是 随机遮盖或替换 一句话里面的任意字或词,然后让模型通过上下文预测那一个被遮盖或替换的部分,之后 做 Loss 的时候也只计算被遮盖部分的 Loss ,这其实是一个很容易理解的任务,实际操作如下:
这样做的好处是,BERT 并不知道 [MASK] 替换的是哪一个词,而且 任何一个词都有可能是被替换掉的,比如它看到的 apple 可能是被替换的词 。这样强迫模型在编码当前时刻词的时候 不能太依赖当前的词 ,而要考虑它的上下文,甚至根据上下文进行 "纠错"。比如上面的例子中,模型在编码 apple 时,根据上下文 my dog is,应该 把 apple 编码成 hairy 的语义而不是 apple 的语义
我们首先拿到属于上下文的一对句子,也就是两个句子,之后我们要在这两个句子中加一些特殊的 token: [CLS]上一句话[SEP]下一句话[SEP] 。也就是在句子开头加一个 [CLS] ,在两句话之间和句末加 [SEP] ,具体地如下图所示
可以看到,上图中的两句话明显是连续的。如果现在有这么一句话 [CLS] 我的狗很可爱 [SEP] 企鹅不擅长飞行 [SEP] ,可见这两句话就 不是连续的 。在实际训练中,我们会让这两种情况出现的数量为** 1:1**
Token Embedding 就是正常的词向量,即 PyTorch 中的 nn.Embedding()
Segment Embedding 的作用是用 embedding 的信息让模型 分开上下句 ,我们给上句的 token 全 0,下句的此含 token 全 1,让模型得以判断上下句的起止位置,例如
Position Embedding 和 Transformer 中的不一样,不是三角函数,而是 学习出来的
BERT 预训练阶段实际上是将上述两个任务结合起来,同时进行,然后将所有的 Loss 相加,例如
BERT 的 Fine-Tuning 共分为 4 种类型,以下内容、图片均来自台大李宏毅老师 Machine Learning 课程 (以下内容 图在上,解释在下)
为什么要用CLS?
这里李宏毅老师有一点没讲到,就是为什么要用第一个位置,即 [CLS] 位置的 output。这里我看了网上的一些博客,结合自己的理解解释一下。因为 BERT 内部是 Transformer,而 Transformer 内部又是 Self-Attention, 所以 [CLS] 的 output 里面肯定含有整句话的完整信息 ,这是毋庸置疑的。但是 Self-Attention 向量中,自己和自己的值其实是占大头的,现在假设使用 的 output 做分类,那么这个 output 中实际上会更加看重 ,而 又是一个有实际意义的字或词,这样难免会影响到最终的结果。但是 [CLS] 是没有任何实际意义的,只是一个占位符而已,所以就算 [CLS] 的 output 中自己的值占大头也无所谓。当然你 也可以将所有词的 output 进行 concat,作为最终的 output
首先将问题和文章通过 [SEP] 分隔,送入 BERT 之后,得到上图中黄色的输出。此时我们还要训练两个 vector,即上图中橙色和黄色的向量。首先将橙色和所有的黄色向量进行 dot proct,然后通过 softmax,看哪一个输出的值最大,例如上图中 对应的输出概率最大,那我们就认为 s=2
同样地,我们用蓝色的向量和所有黄色向量进行 dot proct,最终预测得 的概率最大,因此 e=3。最终,答案就是 s=2,e=3
你可能会觉得这里面有个问题,假设最终的输出 s>e 怎么办,那不就矛盾了吗?其实在某些训练集里,有的问题就是没有答案的,因此此时的预测搞不好是对的,就是没有答案
以上就是 BERT 的详细介绍,参考以下文章
ELMo是Embedding from language Model的缩写,它通过无监督的方式对语言模型进行预训练来学习单词表示
这篇论文的想法其实非常简单,但是效果却很好。它的思路是用 深度的双向 Language Model 在大量未标注数据上训练语言模型 ,如下图所示
在实际任务中,对于输入的句子,我们使用上面的语言模型来处理它,得到输出向量,因此这可以看作是一种 特征提取 。但是 ELMo 与普通的 Word2Vec 或 GloVe 不同,ELMo 得到的 Embedding 是 有上下文信息 的
具体来说,给定一个长度为 N 的句子,假设为 ,语言模型会计算给定 的条件下出现 的概率:
传统的 N-gram 模型 不能考虑很长的历史 ,因此现在的主流是使用 多层双向 LSTM 。在时刻 ,LSTM 的第 层会输出一个隐状态 ,其中 , 是 LSTM 的层数。最上层是 ,对它进行 softmax 之后得到输出词的概率
类似的,我们可以用 一个反向 来计算概率:
通过这个 LSTM,我们可以得到 。我们的损失函数是这两个 LSTM 的 加和 :
这两个 LSTM 有各自的参数 和 ,而 Word Embedding 参数 和 Softmax 参数 是共享的
为了用于下游(DownStream)的特定任务,我们会把不同层的隐状态组合起来,具体组合的参数是根据不同的特定任务学习出来的,公式如下:
GPT 得到的语言模型参数不是固定的,它会根据特定的任务进行调整(通常是微调),这样的到的句子表示能更好的适配特定任务。它的思想也很简单,使用 单向 Transformer 学习一个语言模型 ,对句子进行无监督的 Embedding,然后 根据具体任务对 Transformer 的参数进行微调 。GPT 与 ELMo 有两个主要的区别:
这里解释一下上面提到的 单向 Transformer 。在 Transformer 的文章中,提到了 Encoder 与 Decoder 使用的 Transformer Block 是不同的。在 Decoder Block 中,使用了 Masked Self-Attention ,即句子中的每个词都只能对 包括自己在内的前面所有词进行 Attention ,这就是单向 Transformer。GPT 使用的 Transformer 结构就是将 Encoder 中的 Self-Attention 替换成了 Masked Self-Attention ,具体结构如下图所示
训练的过程也非常简单,就是将 n 个词的词嵌入 ( ) 加上位置嵌入 ( ),然后输入到 Transformer 中,n 个输出分别预测该位置的下一个词
这里的位置编码没有使用传统 Transformer 固定编码的方式,而是动态学习的
Pretraining 之后,我们还需要针对特定任务进行 Fine-Tuning。假设监督数据集合 的输入 是一个词序列 ,输出是一个分类的标签 ,比如情感分类任务
我们把 输入 Transformer 模型,得到最上层最后一个时刻的输出 ,将其通过我们新增的一个 Softmax 层(参数为 )进行分类,最后用 CrossEntropyLoss 计算损失,从而根据标准数据调整 Transformer 的参数以及 Softmax 的参数 。这等价于最大似然估计:
正常来说,我们应该调整参数使得 最大,但是 为了提高训练速度和模型的泛化能力 ,我们使用 Multi-Task Learning,同时让它最大似然 和
这里使用的 还是之前语言模型的损失(似然),但是使用的数据不是前面无监督的数据 ,而是使用当前任务的数据 ,而且只使用其中的 ,而不需要标签
针对不同任务,需要简单修改下输入数据的格式,例如对于相似度计算或问答,输入是两个序列,为了能够使用 GPT,我们需要一些特殊的技巧把两个输入序列变成一个输入序列
ELMo 和 GPT 最大的问题就是 传统的语言模型是单向的 —— 我们根据之前的历史来预测当前词。但是我们不能利用后面的信息。比如句子 The animal didn’t cross the street because it was too tired 。我们在编码 it 的语义的时候需要同时利用前后的信息,因为在这个句子中, it 可能指代 animal 也可能指代 street 。根据 tired ,我们推断它指代的是 animal 。但是如果把 tired 改成 wide ,那么 it 就是指代 street 了。传统的语言模型,都 只能利用单方向的信息 。比如前向的 RNN,在编码 it 的时候它看到了 animal 和 street ,但是它还没有看到 tired ,因此它不能确定 it 到底指代什么。如果是后向的 RNN,在编码的时候它看到了 tired ,但是它还根本没看到 animal ,因此它也不能知道指代的是 animal 。 Transformer 的 Self-Attention 理论上是可以同时关注到这两个词的,但是根据前面的介绍,为了使用 Transformer 学习语言模型,必须 用 Mask 来让它看不到未来的信息 ,所以它也不能解决这个问题的
根据上文内容预测下一个可能跟随的单词,就是常说的自左向右的语言模型任务,或者反过来也行,就是根据下文预测前面的单词,这种类型的LM被称为自回归语言模型。(GPT,ELMO)GPT 就是典型的自回归语言模型。ELMO尽管看上去利用了上文,也利用了下文,但是本质上仍然是自回归LM,这个跟模型具体怎么实现有关系。ELMO是做了两个方向(从左到右以及从右到左两个方向的语言模型),但是是分别有两个方向的自回归LM,然后把LSTM的两个方向的隐节点状态拼接到一起,来体现双向语言模型这个事情的。所以其实是两个自回归语言模型的拼接,本质上仍然是自回归语言模型。
自回归语言模型有优点有缺点,缺点是只能利用上文或者下文的信息,不能同时利用上文和下文的信息,当然,貌似ELMO这种双向都做,然后拼接看上去能够解决这个问题,因为融合模式过于简单,所以效果其实并不是太好。它的优点,其实跟下游NLP任务有关,比如生成类NLP任务,比如文本摘要,机器翻译等,在实际生成内容的时候,就是从左向右的, 自回归语言模型天然匹配这个过程 。而Bert这种DAE模式,在生成类NLP任务中,就面临训练过程和应用过程不一致的问题,导致 生成类的NLP任务到目前为止都做不太好 。
自回归语言模型只能根据上文预测下一个单词,或者反过来,只能根据下文预测前面一个单词。相比而言,Bert通过 在输入X中随机Mask掉一部分单词 ,然后预训练过程的主要任务之一是根据上下文单词来预测这些被Mask掉的单词,如果你对Denoising Autoencoder比较熟悉的话,会看出,这确实是典型的DAE的思路。那些被Mask掉的单词就是在输入侧加入的所谓噪音。类似Bert这种预训练模式,被称为DAE LM。
这种DAE LM的优缺点正好和自回归LM反过来,它能比较自然地融入双向语言模型,同时看到被预测单词的上文和下文,这是好处。缺点是啥呢? 主要在输入侧引入[Mask]标记,导致预训练阶段和Fine-tuning阶段不一致的问题 ,因为Fine-tuning阶段是看不到[Mask]标记的。DAE吗,就要引入噪音,[Mask] 标记就是引入噪音的手段,这个正常。
XLNet的出发点就是:能否 融合自回归LM和DAE LM两者的优点 。就是说如果站在自回归LM的角度,如何引入和双向语言模型等价的效果;如果站在DAE LM的角度看,它本身是融入双向语言模型的,如何抛掉表面的那个[Mask]标记,让预训练和Fine-tuning保持一致。当然,XLNet还讲到了一个Bert被Mask单词之间相互独立的问题。
⑶ BERT预训练模型
n-gram语言模型:根据前面n个词预测当前词,它的缺点是,一般只能取1-2,n越大计算成本越高,这就使得它关注的信息是非常局限的。
预训练语言模型:wordvec\glove\fasttext。wordvec是根据周围词预测当前词或当前词预测周围词,相比于n-gram,它关注了下文,但它仍然是关注局部信息。glove通过构建词频共现矩阵来训练词向量,将全局信息融入到词向量中。fasttext仍然是局部的,只是他分词是基于subword,对于oov词相对友好。三者共同的缺点是,无法解决一词多义问题。
高级语言模型:elmo\GPT,elmo采用1层静态向量+2层单向LSTM提取特征,并且能够解决一词多义,elmo是一个双向语言模型,但实际上是两个单向语言模型(方向相反)的拼接,这种融合特征的隐搭能力比 BERT 一体化融合特征方式弱。GPT采用Transformer的decoder单元提取特征,同样也可以解决一词多义问题,但GPT是单向的。所以,对上下文信息的融合,二者能力还不够。
bert是双向语言模型,句子没有shift_mask操作,所以是完整的上下文环境,证实了双向语言模型对文本特征表示的重要性。bert同时证实了预训练模型能够简化很多繁重任务的网络结构,在11个nlp任务上都有显着提升。
bert采用Transformer的encoder单元提取特征,encoder中包含几个重要的机制:self-attention、muti-head attention、position encoding。
bert分为bert_base和bert_large大小两个模型,bert_base采用了12个encoder单元,768维隐藏层,12个attention。bert_base采用了24个encoder单元,1024维隐藏层,16个attention。
input:单句或句对组合,有[cls]作为句子开头的标记,[sep]作为句子分隔和结束的标记。
token embedding:对于英文采用WordPiece embeddings,也就是一个单词会被拆成词根词缀的,比如图中的playing被拆灶扰拿成了play和ing两个token;对于中文,就是单子拆分。
segment embedding:相邻句子采用不同的标志分隔,形如111111111100000011111100000。
position embedding:在transformer中,单词之间是没有先后顺序的,而语言本身是有序的,所以采用采用正余弦函数来计算每个单词的先后顺序,这种方式有点勉强,算是折中方式。
前面讲到elmo也是双向语言模型,它是采用bi-LSTM来提取特征,如下:
比如一句话:‘北京是中国的首都’,在LSTM中从左往右,预测‘中国’的时候只能看到‘北京’,从右往左,预测‘中国’的时候只能看到‘首都’,然后将两个lstm的输出做拼接来达到上下文信息融合的目的李旦。其实是没有完全做到双向,只是以结构的改变来接近双向语言模型。真正的双向是预测‘中国’的时候,需要同时看到‘北京’和‘首都’。由此,mask LM产生了。
mask LM的原理是将‘中国’遮盖住,同时用‘北京’和‘首都’来预测‘中国’。‘北京’和‘首都’联系起来语言模型很容易联想到就是‘中国’啦。这个思想和wordvec的CBOW模型如出一辙,就是用周围词预测当前词,只是这个思想放在厉害的transformer中,便能大显其能。
BERT的mask方式:在选择mask的15%的词当中,80%情况下使用mask掉这个词,10%情况下采用一个任意词替换,剩余10%情况下保持原词汇不变。这样mask的优点是什么?
1)被随机选择15%的词当中以10%的概率用任意词替换去预测正确的词,相当于文本纠错任务,为BERT模型赋予了一定的文本纠错能力;
2)被随机选择15%的词当中以10%的概率保持不变,缓解了finetune时候与预训练时候输入不匹配的问题(预训练时候输入句子当中有mask,而finetune时候输入是完整无缺的句子,即为输入不匹配问题)。
在Mask LM任务中,模型学到了词与词之间的关系,而NSP任务是要模型学到句子与句子之间的关系,比如问答、推理等。它将训练语料分为两类,一是将50%语料构建成正常语序的句子对,比如A-B句子对,B就是A的实际下一个句子,并做标记为isnext;二是将50%语料构建成非正常语序句子对,B是来自语料库的随机句子,并做标记为notnext。然后通过对句子对的关系做分类,预测B到底是不是A句子的下一个句子,使模型具有句子级别的识别能力。
微调的目的在于我们的任务与bert预训练任务是不一致的,但是bert是非常好的语言模型,他具备提取词法和句法的强大能力。将bert嵌入到我们的网络结构中,能够简化在语言模型方面的复杂结构。只需要将输入做成和bert适配的格式就行,而在bert后面接上全连接、CNN等简单模型进行训练,就能够使训练得到一个比较好的效果。
GPT 和 BERT 都采用Transformer,Transformer 是encoder-decoder 结构,GPT 的单向语言模型采用 decoder 部分,decoder 的部分见到的都是不完整的句子;BERT 的双向语言模型则采用 encoder 部分,采用了完整句子。他俩最主要的区别在于BERT是双向语言模型,更适合文本分类等任务,GPT是单向语言模型,更适合生成式任务。
1)低层网络捕捉了短语级别的结构信息
2)表层信息特征在底层网络(3,4),句法信息特征在中间层网络(6~9),语义信息特征在高层网络。(9~12)
3)主谓一致表现在中间层网络(8,9)
1)ROBERTA
•静态mask->动态mask:在bert中每一个epoch被mask的是相同的词,而ROBERTA在每一个epoch结束,重新随机15%的词,使不同的词被mask。
•去除句对NSP任务,输入连续多个句子:在bert中最长是512个token,输入单句或者句对不容易把512个token占满,ROBERTA输入更多句子占满512个坑位。
•训练使用更多数据 更大batch size 更长时间
2)ALBERT
•减少参数:词表 V 到隐层 H 的中间,插入一个小维度 E,即一个VxH的embedding变成两个VxE, ExH的两个fc。
•共享所有层的参数:Attention 和 FFN,在bert中每一层的Attention 和 FFN的参数是不一样的。
•SOP 替换 NSP:负样本换成了同一篇文章中的两个逆序的句子,bert中是A-->B和A-->随机,ALBERT中是A-->B,B-->A。
•BERT对MASK 15% 的词来预测。ALBERT 预测的是 n-gram 片段,包含更完整的语义信息。
•训练数据长度:90%取512,BERT90% 128
•对应BERT large:H:1024 ->4096 L:24->12 窄而深->宽而浅
⑷ 预训练模型综述--Albert,xlnet,bert,word2vec
Albert,xlnet,bert,word2vec
通过预训练模型实现迁移学习,迁移学习本质上是在一个数据集上训练模型,然后对该模型进行调整,以在不同的数据集上执行不同拿或的自然语言处理功能。
1. word2vec
线性模型 :
很神奇的地方,从而也说明高维空间映射的词向量可以很好体现真实世界中token之间的关系。如:king-man = queen-woman
负采样 :
由于训练词向量模型的目标不是为了得到一个多么精准的语言模型,而是为了获得它的副产物——词向量。所以要做到的不是在几万几十万个token中艰难厅敏伍计算softmax获得最优的那个词(就是预测的对于给定词的下一词),而只需能做到在几个词中找到对的那个词就行,这几个词包括一个正例(即直接给定的下一词),和随机产生的噪声词(采样抽取的几个负例),就是说训练一个sigmoid二分类器,只要模型能够从中找出正确的词就认为完成任务。
这种负采样思想也应用到之后的BERT里,只不过从word-level变成sentence-level,这样能获取句子间关联关系。
缺点是上下文无关(static):
因而为了让句子有一个整体含义(context),大家会在下游具体的NLP任务中基与词向量的序列做encoding操作。
下面是一个比较表格,模型不细讲了,预测目标这里的next word下一个词,是所有传统语言模型都做的事——寻找下一个词填什么。
BERT模型进一步增加词向量模型泛化能力,充分描述字符级、词级、句子级甚至句间关系特征。
真正的双向encoding:
Masked LM,类似完形填空,尽管仍旧看到所有位置信息,但需要预测的词已被特殊符号代替,可以放心双向encoding。
Transformer做encoder实现上下文相关(context):
使用transformer而不是bi-LSTM做encoder,可以有更深的层数、具有更好并行性。并且线性的Transformer比lstm更易免受mask标记影响,只需要通过self-attention减小mask标记权重即可,而lstm类似黑盒模扮或型,很难确定其内部对于mask标记的处理方式。
提升至句子级别:
学习句子/句对关系表示,句子级负采样。首先给定的一个句子,下一句子正例(正确词),随机采样一句负例(随机采样词),句子级上来做二分类(即判断句子是当前句子的下一句还是噪声),类似word2vec的单词级负采样。
二、BERT细则
这里主要介绍BERT的三个亮点Masked LM、transformer、sentence-level。
1. Masked Language Model
原本叫cloze test,是完形填空的意思。
随机mask语料中15%的token,然后将masked token 位置输出的最终隐层向量送入softmax,来预测masked token。
这样输入一个句子,每次只预测句子中大概15%的词,所以BERT训练很慢。。。(但是google设备NB。。)
而对于盖住词的特殊标记,在下游NLP任务中不存在。因此,为了和后续任务保持一致,作者按一定的比例在需要预测的词位置上输入原词或者输入某个随机的词。如:my dog is hairy
2. Transformer —— attention is all you need
Transformer模型是2018年5月提出的,可以替代传统RNN和CNN的一种新的架构,用来实现机器翻译,论文名称是attention is all you need。无论是RNN还是CNN,在处理NLP任务时都有缺陷。CNN是其先天的卷积操作不很适合序列化的文本,RNN是其没有并行化,很容易超出内存限制(比如50tokens长度的句子就会占据很大的内存)。
下面左图是transformer模型一个结构,分成左边Nx框框的encoder和右边Nx框框的decoder,相较于RNN+attention常见的encoder-decoder之间的attention(上边的一个橙色框),还多出encoder和decoder内部的self-attention(下边的两个橙色框)。每个attention都有multi-head特征。最后,通过position encoding加入没考虑过的位置信息。
下面从multi-head attention,self-attention, position encoding几个角度介绍。
multi-head attention:
将一个词的vector切分成h个维度,求attention相似度时每个h维度计算。由于单词映射在高维空间作为向量形式,每一维空间都可以学到不同的特征,相邻空间所学结果更相似,相较于全体空间放到一起对应更加合理。比如对于vector-size=512的词向量,取h=8,每64个空间做一个attention,学到结果更细化。
self-attention:
每个词位的词都可以无视方向和距离,有机会直接和句子中的每个词encoding。比如上面右图这个句子,每个单词和同句其他单词之间都有一条边作为联系,边的颜色越深表明联系越强,而一般意义模糊的词语所连的边都比较深。比如:law,application,missing,opinion。。。
position encoding:
因为transformer既没有RNN的recurrence也没有CNN的convolution,但序列顺序信息很重要,比如你欠我100万明天要还和我欠你100万明天要还的含义截然不同。。。
transformer计算token的位置信息这里使用正弦波↓,类似模拟信号传播周期性变化。这样的循环函数可以一定程度上增加模型的泛化能力。
但BERT直接训练一个position embedding来保留位置信息,每个位置随机初始化一个向量,加入模型训练,最后就得到一个包含位置信息的embedding(简单粗暴。。),最后这个position embedding和word embedding的结合方式上,BERT选择直接相加。
3. sentence-level representation
在很多任务中,仅仅靠encoding是不足以完成任务的(这个只是学到了一堆token级的特征),还需要捕捉一些句子级的模式,来完成SLI、QA、dialogue等需要句子表示、句间交互与匹配的任务。对此,BERT又引入了另一个极其重要却又极其轻量级的任务,来试图把这种模式也学习到。
句子级负采样
句子级别的连续性预测任务,即预测输入BERT的两端文本是否为连续的文本。训练的时候,输入模型的第二个片段会以50%的概率从全部文本中随机选取,剩下50%的概率选取第一个片段的后续的文本。 即首先给定的一个句子(相当于word2vec中给定context),它下一个句子即为正例(相当于word2vec中的正确词),随机采样一个句子作为负例(相当于word2vec中随机采样的词),然后在该sentence-level上来做二分类(即判断句子是当前句子的下一句还是噪声)。
句子级表示
BERT是一个句子级别的语言模型,不像ELMo模型在与下游具体NLP任务拼接时需要每层加上权重做全局池化,BERT可以直接获得一整个句子的唯一向量表示。它在每个input前面加一个特殊的记号[CLS],然后让Transformer对[CLS]进行深度encoding,由于Transformer是可以无视空间和距离的把全局信息encoding进每个位置的,而[CLS]的最高隐层作为句子/句对的表示直接跟softmax的输出层连接,因此其作为梯度反向传播路径上的“关卡”,可以学到整个input的上层特征。
segment embedding
对于句对来说,EA和EB分别代表左句子和右句子;对于句子来说,只有EA。这个EA和EB也是随模型训练出来的。
如下图所示,最终输入结果会变成下面3个embedding拼接的表示。
首先,XLNet 是一个类似 BERT 的模型,而不是完全不同的模型。但这是一个非常有前途和潜力的。总之,XLNet是一种通用的自回归预训练方法。
那么什么是自回归(AR)语言模型?
AR语言模型是一种使用上下文词来预测下一个词的模型。但是在这里,上下文单词被限制在两个方向,前向或后向。
AR 语言模型的优势是擅长生成式自然语言处理任务。 因为在生成上下文时,通常是前向的。AR 语言模型很自然地适用于此类 NLP 任务。
但AR语言模型有一些缺点,它只能使用前向上下文或后向上下文,这意味着它不能同时使用前向和后向上下文。
自回归语言模型有优点有缺点,缺点是只能利用上文或者下文的信息,不能同时利用上文和下文的信息,当然,貌似ELMO这种双向都做,然后拼接看上去能够解决这个问题,因为融合模式过于简单,所以效果其实并不是太好。它的优点,其实跟下游NLP任务有关,比如生成类NLP任务,比如文本摘要,机器翻译等,在实际生成内容的时候,就是从左向右的,自回归语言模型天然匹配这个过程。而Bert这种DAE模式,在生成类NLP任务中,就面临训练过程和应用过程不一致的问题,导致生成类的NLP任务到目前为止都做不太好。
与 AR 语言模型不同,BERT 被归类为自动编码器(AE)语言模型。
AE 语言模型旨在从损坏的输入重建原始数据。
损坏的输入意味着我们在预训练阶段用 [MASK] 替换原始词 into 。目标是预测 into 得到原始句子。
AE 语言模型的优势是,它可以从向前和向后的方向看到上下文。
但 AE 语言模型也有其缺点。它在预训练中使用 [MASK] ,但这种人为的符号在调优时在真实数据中并不存在,会导致预训练-调优的差异。[MASK] 的另一个缺点是它假设预测(掩蔽的)词 在给定未屏蔽的 词 的情况下彼此独立。例如,我们有一句话“它表明住房危机已经变成银行危机”。我们掩蔽“银行业”和“危机”。在这里注意,我们知道掩蔽的“银行业”和“危机”包含彼此的隐含关系。但 AE 模型试图预测“银行业”给予未掩蔽的 词,并预测“危机”分别给出未掩蔽的 词。它忽略了“银行业”与“危机”之间的关系。换句话说,它假设预测(掩蔽)的标记彼此独立。但是我们知道模型应该学习预测(掩蔽)词之间的这种相关性来预测其中一个词。
作者想要强调的是,XLNet 提出了一种让 AR 语言模型从双向上下文中学习的新方法,以避免 MASK 方法在 AE 语言模型中带来的缺点。
XLNet的出发点就是:能否融合自回归LM和DAE LM两者的优点。就是说如果站在自回归LM的角度,如何引入和双向语言模型等价的效果;如果站在DAE LM的角度看,它本身是融入双向语言模型的,如何抛掉表面的那个[Mask]标记,让预训练和Fine-tuning保持一致。当然,XLNet还讲到了一个Bert被Mask单词之间相互独立的问题,我相信这个不太重要,原因后面会说。当然,我认为这点不重要的事情,纯粹是个人观点,出错难免,看看就完了,不用较真。
AR 语言模型只能向前或向后使用上下文,那么如何让它从双向上下文中学习呢?
语言模型包括两个阶段,即预训练阶段和调优阶段。XLNet 专注于预训练阶段。在预训练阶段,它提出了一个名为排列语言建模的新目标。我们可以从这个名称知道基本思想,它使用排列。
这里我们举一个例子来解释。序列的次序是 [x1, x2, x3, x4] 。这种序列的所有排列如下。
因此对于这 4 个词的([图片上传失败...(image-c7a4e0-1570519576567)]
)句子,有 24([图片上传失败...(image-d738b7-1570519576567)]
)个排列。
情景是我们想要预测 x3 。因此在 24 个排列中有 4 种模式,分别 x3 位于第 1 位,第 2 位,第 3 位,第 4 位。
当然,上面讲的仍然是基本思想。难点其实在于具体怎么做才能实现上述思想。首先,需要强调一点,尽管上面讲的是把句子X的单词排列组合后,再随机抽取例子作为输入,但是,实际上你是不能这么做的,因为Fine-tuning阶段你不可能也去排列组合原始输入。所以,就必须让预训练阶段的输入部分,看上去仍然是x1,x2,x3,x4这个输入顺序,但是可以在Transformer部分做些工作,来达成我们希望的目标。具体而言,XLNet采取了Attention掩码的机制,你可以理解为,当前的输入句子是X,要预测的单词Ti是第i个单词,前面1到i-1个单词,在输入部分观察,并没发生变化,该是谁还是谁。但是在Transformer内部,通过Attention掩码,从X的输入单词里面,也就是Ti的上文和下文单词中,随机选择i-1个,放到Ti的上文位置中,把其它单词的输入通过Attention掩码隐藏掉,于是就能够达成我们期望的目标(当然这个所谓放到Ti的上文位置,只是一种形象的说法,其实在内部,就是通过Attention Mask,把其它没有被选到的单词Mask掉,不让它们在预测单词Ti的时候发生作用,如此而已。看着就类似于把这些被选中的单词放到了上文Context_before的位置了)。具体实现的时候,XLNet是用“双流自注意力模型”实现的,细节可以参考论文,但是基本思想就如上所述,双流自注意力机制只是实现这个思想的具体方式,理论上,你可以想出其它具体实现方式来实现这个基本思想,也能达成让Ti看到下文单词的目标。
上面说的Attention掩码,我估计你还是没了解它的意思,我再用例子解释一下。Attention Mask的机制,核心就是说,尽管当前输入看上去仍然是x1->x2->x3->x4,但是我们已经改成随机排列组合的另外一个顺序x3->x2->x4->x1了,如果用这个例子用来从左到右训练LM,意味着当预测x2的时候,它只能看到上文x3;当预测x4的时候,只能看到上文x3和x2,以此类推……这样,比如对于x2来说,就看到了下文x3了。这种在输入侧维持表面的X句子单词顺序,但是其实在Transformer内部,看到的已经是被重新排列组合后的顺序,是通过Attention掩码来实现的。如上图所示,输入看上去仍然是x1,x2,x3,x4,可以通过不同的掩码矩阵,让当前单词Xi只能看到被排列组合后的顺序x3->x2->x4->x1中自己前面的单词。这样就在内部改成了被预测单词同时看到上下文单词,但是输入侧看上去仍然维持原先的单词顺序了。关键要看明白上图右侧那个掩码矩阵,我相信很多人刚开始没看明白,因为我刚开始也没看明白,因为没有标出掩码矩阵的单词坐标,它的坐标是1-2-3-4,就是表面那个X的单词顺序,通过掩码矩阵,就能改成你想要的排列组合,并让当前单词看到它该看到的所谓上文,其实是掺杂了上文和下文的内容。这是attention mask来实现排列组合的背后的意思。
ALBERT相比于BERT的改进
ALBERT也是采用和BERT一样的Transformer的encoder结果,激活函数使用的也是GELU,在讲解下面的内容前,我们规定几个参数,词的embedding我们设置为E,encoder的层数我们设置为L,hidden size即encoder的输出值的维度我们设置为H,前馈神经网络的节点数设置为4H,attention的head个数设置为H/64。
在ALBERT中主要有三个改进方向。
1、对Embedding因式分解(Factorized embedding parameterization)
在BERT中,词embedding与encoder输出的embedding维度是一样的都是768。但是ALBERT认为,词级别的embedding是没有上下文依赖的表述,而隐藏层的输出值不仅包括了词本生的意思还包括一些上下文信息,理论上来说隐藏层的表述包含的信息应该更多一些,因此应该让H>>E,所以ALBERT的词向量的维度是小于encoder输出值维度的。
在NLP任务中,通常词典都会很大,embedding matrix的大小是E×V,如果和BERT一样让H=E,那么embedding matrix的参数量会很大,并且反向传播的过程中,更新的内容也比较稀疏。
结合上述说的两个点,ALBERT采用了一种因式分解的方法来降低参数量。首先把one-hot向量映射到一个低维度的空间,大小为E,然后再映射到一个高维度的空间,说白了就是先经过一个维度很低的embedding matrix,然后再经过一个高维度matrix把维度变到隐藏层的空间内,从而把参数量从O(V×H) O(V×H)O(V×H)降低到了O(V×E+E×H) O(V×E+E×H)O(V×E+E×H),当E<<H时参数量减少的很明显。
下图是E选择不同值的一个实验结果,尴尬的是,在不采用参数共享优化方案时E设置为768效果反而好一些,在采用了参数共享优化方案时E取128效果更好一些。
2、跨层的参数共享(Cross-layer parameter sharing)
在ALBERT还提出了一种参数共享的方法,Transformer中共享参数有多种方案,只共享全连接层,只共享attention层,ALBERT结合了上述两种方案,全连接层与attention层都进行参数共享,也就是说共享encoder内的所有参数,同样量级下的Transformer采用该方案后实际上效果是有下降的,但是参数量减少了很多,训练速度也提升了很多。
下图是BERT与ALBERT的一个对比,以base为例,BERT的参数是108M,而ALBERT仅有12M,但是效果的确相比BERT降低了两个点。由于其速度快的原因,我们再以BERT xlarge为参照标准其参数是1280M,假设其训练速度是1,ALBERT的xxlarge版本的训练速度是其1.2倍,并且参数也才223M,评判标准的平均值也达到了最高的88.7
除了上述说了训练速度快之外,ALBERT每一层的输出的embedding相比于BERT来说震荡幅度更小一些。下图是不同的层的输出值的L2距离与cosine相似度,可见参数共享其实是有稳定网络参数的作用的。
3、句间连贯(Inter-sentence coherence loss)
BERT的NSP任务实际上是一个二分类,训练数据的正样本是通过采样同一个文档中的两个连续的句子,而负样本是通过采用两个不同的文档的句子。该任务主要是希望能提高下游任务的效果,例如NLI自然语言推理任务。但是后续的研究发现该任务效果并不好,主要原因是因为其任务过于简单。NSP其实包含了两个子任务,主题预测与关系一致性预测,但是主题预测相比于关系一致性预测简单太多了,并且在MLM任务中其实也有类型的效果。
这里提一下为啥包含了主题预测,因为正样本是在同一个文档中选取的,负样本是在不同的文档选取的,假如我们有2个文档,一个是娱乐相关的,一个是新中国成立70周年相关的,那么负样本选择的内容就是不同的主题,而正样都在娱乐文档中选择的话预测出来的主题就是娱乐,在新中国成立70周年的文档中选择的话就是后者这个主题了。
在ALBERT中,为了只保留一致性任务去除主题识别的影响,提出了一个新的任务 sentence-order prediction(SOP),SOP的正样本和NSP的获取方式是一样的,负样本把正样本的顺序反转即可。SOP因为实在同一个文档中选的,其只关注句子的顺序并没有主题方面的影响。并且SOP能解决NSP的任务,但是NSP并不能解决SOP的任务,该任务的添加给最终的结果提升了一个点。
4、移除dropout
除了上面提到的三个主要优化点,ALBERT的作者还发现一个很有意思的点,ALBERT在训练了100w步之后,模型依旧没有过拟合,于是乎作者果断移除了dropout,没想到对下游任务的效果竟然有一定的提升。这也是业界第一次发现dropout对大规模的预训练模型会造成负面影响。
参考链接:
彻底搞懂BERT
什么是 XLNet,为何它会超越 BERT?
XLNet:运行机制及和Bert的异同比较
一文揭开ALBERT的神秘面纱
不懂word2vec,还敢说自己是做NLP?
⑸ RoBERTa 和 ALBERT
BERT 模型是 2018 年提出的,并在很多自然语言处理任务有前所未有的提升。因此 2019 年就有很多工作是围绕着 BERT 展开的,其中出现了两个 BERT 的改进版模型,RoBERTa 和 ALBERT。RoBERTa 在更大的数据集和最优的参数中训练 BERT,使 BERT 的性能再次提升;ALBERT 主要是对 BERT 进行压缩,通过共享所有层的参数以及 Embedding 分解减少 BERT 的参数量。
本文主要介绍 BERT 的两种改进模型 RoBERTa 和 ALBERT,关于 BERT 模型可以参考之前的文章 《彻底理解 Google BERT 模型》 ,首先总体看一下 RoBERTa 和 ALBERT 的一些特点。
RoBERTa:
ALBERT:
RoBERTa 主要试验了 BERT 中的一些训练设置 (例如 NSP Loss 是否有意义,batch 的大小等),并找出最好的设置,然后再更大的数据集上训练 BERT。
原来的 BERT 只使用了 16G 的数据集,而 RoBERTa 在更大的数据集上训练 BERT,使用了 160G 的语料:
BERT 在训练的过程中采用了 NSP Loss,原本用意是为了让模型能够更好地捕捉到文本的语义,给定两段语句 X = [x1, x2, ..., xN] 和 Y = [y1, y2, ...., yM],BERT 中的 NSP 任务需要预测 Y 是不是 出现在 X 的后面。
但是 NSP Loss 受到不少桥帆文章的质疑 ,例如 XLNet,RoBERTa 采用了一个哗消带实验验证 NSP Loss 的实用性。实验中采用了四种组合:
Segment-Pair + NSP: 这个是原来 BERT 的训练方法,使用 NSP Loss,输入的两段文字 X 和 Y 可以包含多个句子,但是 X + Y 的长度要小于 512。
Sentence-Pair + NSP: 与上一个基本类似,也使用 NSP Loss,但是输入的两段文字 X 和 Y 都分别是一个句子,因此一个输入包含的 token 通常比 Segment-Pair 少,所以要增大 batch,使总的 token 数量和 Sentence-Pair 差不多。
Full-Sentences: 不使用 NSP,直接从一个或者多个文档中采样多个句子,直到总长度到达 512。当采样到一个文档末尾时,会在序列中添加一个文档分隔符 token,然后再从下一个文档采样。
Doc-Sentences: 与 Full-Sentences 类似,不使用 NSP,但是只能从一个文档中采样句子,所以输入的长度可能会少于 512。Doc-Sentences 也需要动态调整 batch 大小,使其包含的 token 数量和 Full-Sentences 差不多。
上图是实验结果,最上面的两行是使用 NSP 的,可以看到使用 Segment-Pair (多个句子) 要好于 Sentence-Pair (单个句子),实验结果显示使用单个句子会使 BERT 在下游任务的性能下降,主要原因可能是使用单个句子导致模型不能很好地学习长期的依赖关系。
中间两行是不使用 NSP Loss 的结果,可以看到两种方式都是比使用 NSP 效果要好的,这说明了 NSP Loss 实际上没什么作用,因此在 RoBERTa 中丢弃了 NSP Loss。
原始的 BERT 在乱芦训练之前就把数据 Mask 了,然后在整个训练过程中都是保持数据不变的,称为 Static Mask。即同一个句子在整个训练过程中,Mask 掉的单词都是一样的。
RoBERTa 使用了一种 Dynamic Mask 的策略,将整个数据集复制 10 次,然后在 10 个数据集上都 Mask 一次,也就是每一个句子都会有 10 种 Mask 结果。使用 10 个数据集训练 BERT。
下图是实验结果,可以看到使用 Dynamic Mask 的结果会比原来的 Static Mask 稍微好一点,所以 RoBERTa 也使用了 Dynamic Mask。
之前的一些关于神经网络翻译的研究显示了使用一个大的 batch 并相应地增大学习率,可以加速优化并且提升性能。RoBERTa 也对 batch 大小进行了实验,原始的 BERT 使用的 batch = 256,训练步数为 1M,这与 batch = 2K,训练步数 125K 的计算量是一样的,与 batch = 8K 和训练步数为 31K 也是一样的。下图是使用不同 batch 的实验结果,不同 batch 学习率是不同的,可以看到使用 batch = 2K 时的效果最好。
BERT 的预训练模型参数量很多,训练时候的时间也比较久。ALBERT 是一个对 BERT 进行压缩后的模型,降低了 BERT 的参数量,减少了训练所需的时间。
注意 ALBERT 只是减少 BERT 的参数量,而不减少其计算量。ALBERT 能减少训练时间,这是因为减少了参数之后可以降低分布式训练时候的通讯量;ALBERT 不能减少 inference 的时间,因为 inference 的时候经过的 Transformer 计算量和 BERT 还是一样的。
下面介绍 ALBERT 的一些优化方法。
这是对 Embedding 进行分解,从而减少参数。在 BERT 中,Embedding 的维度和 Transformer 隐藏层维度是一样的,都是 H。假设词库的大小为 V,则单词的 Embedding 矩阵参数量就有 VH,如果词库很大,则参数量会很多。
因此,ALBERT 使用了一种基于 Factorized 的方法,不是直接把单词的 one-hot 矩阵映射到 H 维的向量,而是先映射到一个低维空间 (E 维),再映射到 H 维的空间,这个过程类似于做了一次矩阵分解。
这个是参数共享机制,即所有 Transformer 层共享一套参数,Transformer 包括 Multi-Head Attention 的参数和 Feed-Forward 的参数。针对不同部分的参数,ALBERT 采用了四种方式实验。
all-shared: 共享所有的 Transformer 参数。
shared-attention: 只共享 Transformer 中 Multi-Head Attention 的参数。
shared-FFN: 只共享 Transformer 中 Feed-Forward 的参数。
not-shared: 不共享参数。
上图显示了不同共享方式模型的参数量,可以看到共享所有参数之后的模型要远远小于不共享参数的模型。当 E = 768 时,not-shared 的参数量其实就是 BERT-base 的参数量,等于 108M,而共享所有参数后,模型的参数量变为 31M。
通过共享参数可以有效地减少模型的参数量,另外共享参数还可以帮助模型稳定网络中的参数。作者对比了 ALBERT 和 BERT 每一层 Transformer 的输入和输出的 L2 距离,发现 ALBERT 的效果更加平滑,如下图所示。
如 RoBERTa 结果显示的,NSP Loss 对于模型并没有什么用处,因此 ALBERT 也对 NSP 进行了一些思考。
ALBERT 认为 BERT 中使用的 NSP 任务过于简单了,因为 NSP 的反例是随机采样得到的,这些反例的句子通常属于不同的主题,例如前面的句子是来自体育新闻,而后面的句子来自于娱乐新闻。因此 BERT 在进行 NSP 任务时,通常是不需要真正学习句子之间的语义以及顺序的,只需要判断它们的主题类型。
ALBERT 将 NSP 替换成了 SOP (sentence order prediction),预测两个句子是否被交换了顺序。即输入的两个句子是来自同一文档的连续句子,并随机对这两个句子的顺序进行调换,让模型预测句子是否被调换过。这样可以让模型更好地学习句子语义信息和相互关系。
RoBERTa 更像是一个经过仔细调参后得到的 BERT 模型,并且使用了更大的数据集进行训练。
ALBERT 对 BERT 的参数量进行了压缩,并且能够减少分布式训练的开销。但是 ALBERT 并不能减少需要的计算量,因此模型在 inference 时的速度没有提升。
RoBERTa: A Robustly Optimized BERT Pretraining Approach
ALBERT: A LITE BERT FOR SELF-SUPERVISED LEARNING OF LANGUAGE REPRESENTATIONS
⑹ 理解Bert
离开深度学习瞎折腾了一段时间后,我终于又回来了。
于是赶紧回顾了下18年之后NLP的发展,基本就是将迁移学习更广泛的用于消岁NLP领域,以及把17年年底的《Attention is all you need》里的思想给发扬光大了,ELMO弥补了传统word2vec多义词表示的不足,GPT使用更强大的特征提取器Transformer取代LSTM,Bert使用双竖如向Transformer进一步改进了GPT成为这两年发展的集大成者。
从Bert模型所带来的NLP界里程碑式的影响和所取得的成就来看,无疑Bert将会是未来两三年NLP应用发展的基石,于是有必要仔细的看看其模型的结构,数据是如何流动的,训练的和测试的。
不得不说现在的学习环境相对几年前好太多了,本文主要参考了以下几篇文章,然后加了点自己的理解:
Dissecting BERT Part 1: The Encoder
The Illustrated Transformer
Dissecting BERT Appendix: The Decoder
它的总体框架同lstm时代的MNT或者是attention is all you need中的 transformer 一样的 encoder-decoder 结构:
我们先来介绍一下Encoder部分。
为了理解这个架构,我们使用一个简单的具体的例子,来看一下 输入 的数据是怎么通过 encoder 一步一步变化让后到 输出 的。
bert的词嵌入由三个嵌入token embedding、segment embedding,和position embedding叠加而成。
这个过程跟以往的RNNs没什么区别,比如给定一个句子余桥启:
第一步是先将其标记化:
然后是数字化,将每个标记映射到语料词汇表中的唯一整数编号:
接下来就是得到序列中每个词的词嵌入,也就是将整数映射到一个 维的向量,这个向量是模型在训练时学习的,你可以将其视为一个查表的过程,这些向量的元素作为模型的参数,像其他权重一样通过反向传播进行了优化。
在论文中是使用WordPiece tokenization 来将英文单词转换成768( )维的向量,转化的过程类似这样:
把每个词的向量放到一起,就得到了一个 句子长度x向量维度 ( ) 尺寸的矩阵 Z :
说明一点,我们通常使用 填充 的方式来让输入序列具有相同的长度,比如通过添加"<pad>" 标记来增加某些序列的长度,还是前面的例子,填充后可能变为:
如果设定 设定为9,那我们就把句子从5填充到了9。
但是,上面的embedding并没有包含词的位置信息。于是,我们的目标是能够根据词在句子中的位置适当调整这个向量,使它带上位置信息。
作者选择的方法是使用预定的(非学习的)正余弦函数将 之间的数字加到前面的embedding中,即通过正余弦函数将位置表示为彼此的线性组合,从而实现网络学习中标记位置之间的相对关系。在Token embedding 获得的矩阵 的基础上加上位置矩阵 。
数学上,用 表示序列中标记的位置,用 表示token embedding特征向量中的位置:
具体来说,对于给定的句子 ,其位置嵌入矩阵为:
作者解释说,使用这种确定性方法的结果和学习位置表示(就像我们对词嵌入那样)的结果差不多,因此这样反而会有一些优势:
因此,添加了位置信息之后的矩阵是:
它是第一个encoder块的输入,尺寸是
共有N个编码器块连接在一起直到生成编码器的输出,特定的块负责查找输入表示之间的关系并将编码在其输出中。
直观地,通过这些块的迭代过程将帮助神经网络捕获输入序列中的词之间的更加复杂的关系,你可以把它理解成一个整体用来捕捉输入序列的语义。
encoder中使用Transformer的多头注意力机制,这意味着它将计算 份不同权重矩阵的自注意力,然后将结果连接在一起。
这些并行注意力计算的结果称之为Head,我们用下标 来表示一个特定的head和相关的权重矩阵。
如上图所示,一旦计算了所有head,它们将被连接起来,得到一个尺寸为 的矩阵,然后将它乘以一个尺寸为 的权重矩阵 进行线性变换,就得到了一个尺寸为 的最终结果,用数学公式表示就是:
其中的 通过 乘以相应权重矩阵 获得,我们通过一个简单的例子来可视化的看一下这个过程。
这图描绘了输入标记通过 token embedding 和 positional encoding ,再输入到Encoder:
接下来,我们再来看下Encoder中的操作过程,先看一下单头的self-attention:
上图描绘了一个Head的 是怎么来的,其中的 的尺寸是 , 因为Q和K需要计算相似性,所以维度应当是相同的, 的尺寸是 , 的维度可以相同也可以不同,在论文中 .
所谓的自注意力,就是 与 的点积进行 的缩放之后通过softmax获得一个概率权重,然后用这些权重分别乘以各自的 即可:
为了加深理解,我们选择其中一个头,通过图形继续可视化的看一下这个变化过程:
然后计算self-attention,
多头的话就是同时有多个上述计算过程在进行:
假设我们有8个Head,那么我们就获得8个 :
但是,显然前馈层只需要一个矩阵 ,怎么处理呢?类似多卷积核的处理,把这8个矩阵连起来,乘以一个权重矩阵 压缩到一个矩阵。
为了有一个更加全面直观的认识,我们把上面整个过程放到一个图里,
显然,第二个encoder块是不需要embedding过程的,只要把第一个encoder块的输出作为输入即可。
经过上面的介绍,你应该对这个过程已经有了足够的了解,但是,为什么可以利用向量点积来计算注意力概率呢?
于是让我们进一步深入来了解其中的原理。
这个结构体系的关键在于:
也就是每个词的q向量与每个词的k向量的点积,套用点积公式:
这意味着 和 的方向越相似,长度越大,点积就越大。词与此之间关联越大,对于理解这个词时得到的关注越大,跟我们的本意是相同的。
我们再看一下最开头的结构示意图,每个encoder块在Multi-Head Attention之后经过一个 Add & Norm层才进入下一个块。于是我们来看一下这一层做了些什么。
Add 实际就是一个残差连接,将输出加上输入,这个在每一块的self-attenton以及FFN之后都会有,然后跟随一个Layer Norm 。
Norm 是一个Layer Normlization,将 正则化,就是把它缩放到一个均值为0方差为1的域里。因为
不过一般在这一层之前,就会有一个dropout层。
每个encoder块都由 mulit-head atteion add & Norm feed forword network add & Norm 这样一个过程,下面来介绍一下这个Feed-Forward Network。
这是一个全连接层,包含两个线性变化和一个非线性函数(实际一般就是ReLu),
对于输入的 (尺寸为 ) ,通过权重矩阵 (尺寸为 )和偏置 线性变换到隐藏层 (尺寸为 ) ,然后**ReLu **激活 ,记下来再用权重矩阵 (尺寸为 ) 和偏置 的线性变换到输出层(尺寸为 ) ,表示成数学公式就是:
在最后一个encoder块输出之后连接到decoder。
Decoder和Encoder的结构是类似的,但是因为可视信息的不同,又有所差别。
Transformer解决的是翻译的问题,将一个句子翻译成另一种语言,我们希望模型能够捕捉到输入句子中词之间的关系,并且将输入句子中包含的信息与每一步已翻译的内容结合起来。继续上面的例子,我们的目标是把一个句子从英文翻译为西班牙文,这是我们获得的序列标记:
我们同之前一样来看看输入到输出数据是如何流动的。
这是我们的解码器的输入标记:
然后这是解码器的期望输出:
但是,这里存在一个问题,比如输入这边我们已经看到了'como' 的后面是'estas', 然后再用它来预测'estas' ,这显然是不合理的,因为模型在测试的时候是看不到后面的词的。
因此,我们需要修改注意力层,防止模型可以看到预测词右边的信息,与此同时,它能利用已经预测的词,即左边的信息。
继续上面的例子,我们将输入标记转换成矩阵的形式,并添加位置信息:
和encoder一样,decoder块的输出也将是大小为 的矩阵,在逐行线性变换+softmax激活后,将生成一个举证,其中每行的最大元素表示下一个单词。也就是说,分配"<SS>" 的行负责预测“Hola”, 分配"Hola"的行负责预测"," ...以此类推。比如,为了预测"estas", 我们将允许该行直接和下图中绿色区域互动,而不能和红色区域互动:
但是,在我们使用多头注意力机制的时候,所有的行都会产生交互,因此需要在输入的时候添加遮罩,这个遮罩会在注意力计算之后进行:
这是 self-attention 的计算结果:
然后我们在此基础上添加遮掩,就是把矩阵上三角的位置全部设置为 :
于是,在进行softmax激活之后,矩阵就变成了:
恰好达到了我们的要求,那些需要在训练时忽略的右侧的词的注意力全部变成了0。
当将这个注意力矩阵与 相乘时,预测的词就是模型可以访问元素右边的元素。注意,这里的多头注意力输出将是 维的,因为它的序列长度是 。
这个就是 Decoder 从 target序列 的输入,并经过 Masked Multi-Head Attention 的一个变化得到了 ,decoder的还有一部分输入来自于源语句经过 Encoder 的最终输出 (尺寸是 )。
接下来,就是与encoder一样的 Multi-Head Attention Add and Layer Norm -> FFN 的过程。
只不过,现在的 来自于 ,而 来自于 :
计算每个query相对于key的注意力之后,得到的是一个 的矩阵, 继续咱们的例子,比如注意力矩阵为:
如上图所见,这个注意力是当前Decoder输入与Encoder输出的每个词之间的注意力,咱们用这个矩阵再乘以 ,就得到了一个 的矩阵,每一行代表了源语句相对于当前输入词汇的特征:
h个Head连接起来,尺寸变为 ,它通过 的权重矩阵 线性变换到一个 的输出。
这在多个Decoder之后,最后输出的矩阵通过乘以权重矩阵 ( ) 进行线性变换,变换之后再对每一行的向量softmax, 其中选择值最大位置对应词表索引的词就是预测的词。
损失的话只需要用预测的每个词向量与真实的词的one-hot词表示计算交叉熵即可。
⑺ 1080ti微调12层bert要多久
看你所谓的训练是指重头预训练一个bert,还是用bert做漏瞎微调。前者别想了,后者视数据量而定,一般几十分钟吧。
影驰GTX 1080Ti名人堂显卡延续了经典的白色装甲设计,采用全新的Lumin X RGB炫彩技术,除了中亩明央名人堂LOGO部分,外接供电和视频接口均添加了RGB元素,玩家可使用影驰最新魔盘实现1680万色的多彩调节。此外还有HOF Armor+金属强化背板,HOF Panel液晶显示屏。
同时,还采用“TriMax”散热器,在HOF系列成熟的散热体系上再次优化,采用三枚9CM大风扇,能够带来强大的散热效能。
GTX 1080Ti名人堂有限量版和高频版,同样采用GP-102核心,流处理器个数为迅搜告3584个。
基础频率和提升频率分别达到了1645MHz和1759MHz(高频版是基础频率为1569MHz,提升频率为1683MHz),同时使用的11GB高速显存,在显存频率是11210MHz(高频版11010MHz)。
总结如下:
影驰GTX 1080Ti名人堂限量版沿用10系名人堂的皇冠造型,更添加了许多RGB元素。12层至臻纯白PCB设计,高强度铝合金HOF Armor+背板,用料豪华。
⑻ Bert技术
google在2018年10月底公布BERT在11项nlp任务中的卓越表现,NLP任务的两个衡量指标上全面超越人类,并且还在11种不同NLP测试中创出最佳成绩,包括将GLUE基准推至80.4%(绝对改进7.6%),MultiNLI准确度达到86.7% (绝对改进率5.6%)等,此后,BERT(Bidirectional Encoder Representation from Transformers)就成为NLP领域大火、整个ML界略有耳闻的模型。
BERT的出现,彻底改变了预训练产生词向量和下游具体NLP任务的关系,提出龙骨级的训练词向量概念。
词向量,就是用一个向量的形式表示一个词。
(1)one-hot编码:词的符号化。
(2)词的分布式表示:词的语义由其上下文决定。以(CBOW)为例,如果有一个句子“the cat sits one the mat”,在训练的时候,将“the cat sits one the”作为输入,预测出最后一个词是“mat”。分布式表示的较大优点在于它具有非常强大的表征能力,比如n维向量每维k个值,可以表征k的n次方个概念。
其中,词嵌入就是分布式表示的一种:基于神经网络的分布表示一般派亩称为词向量、词嵌入( word embedding)或分布式表示( distributed representation)。核心依然是上下文的表示以及上下文与目标词之间的关系的建模。本质:词向量是训练神经网络迅羡信时候的隐藏层参数或者说矩阵。
两种训练模式:CBOW (Continuous Bag-of-Words Model)和Skip-gram (Continuous Skip-gram Model)
NLP任务分成两部分,一是预训练产生词向量,二是对词向量操作实现特定功能。而词向量模型是一个工具,可以把抽象存在的文字转换成可以进行数学公式操作的向量,而对这些向量的操作,才是NLP真正要做的任务。从word2vec到ELMo到BERT,做的其实主要是把下游具体NLP任务的活逐渐移到预训练产生词向量上。
(1)word2vec:上下文概率的一种表示,但无法对一词多义进行建模
(2)ELMo:用的是一个双向的LSTM语言模型,由一个前向和一个后向语言模型构成,目标函数就是取这两个方向语言模型的最大似然。
在预训练好这个语言模型之后,ELMo就是根据下面的公式来用作词表示,其实就是把这个双向语言模型的每一中间层进行一个求和。最简单的也可以使用最高层的表示来作为ELMo。
然后在进行有监督的NLP任务时,可以将ELMo直接当做特征拼接到具体任务模型的词向量输入或者是模型的最高层表示上。总结一下,不像传统的词向量,每一个词只对应一个词向量,ELMo利用预训练好的双向语言模型,然后根据具体输入从该语言模型中可以得到上下文依赖的当前词表示(对于不同上下文的同一个词的表示是不一样的),再当成特征加入到具体的NLP有监督模型里。
(3)bert
word2vec——>ELMo:
结果:上下文无关的static向量变成上下文相关的dynamic向量,比如苹果在不同语境vector不同。
操作:encoder操作转移到预训练产生词向量过程实现。
ELMo——>BERT:
结果:训练出的word-level向量变成sentence-level的向量,下游具体NLP任务调用更方便,修正了ELMo模型的潜在问题。
操作:使用句子级负采样获得句子表示/句对关系,Transformer模型代替LSTM提升亩轮表达和时间上的效率,masked LM解决“自己看到自己”的问题。
(1)bert模型证明了双向预训练对于语言表示的重要性。与采用单向语言模型进行预训练的模型不同,BERT使用masked language models 进行预训练的深层双向表示。
(2)经过预训练的模型表示解决了许多为特定任务而设计架构的需要。BERT是第一个基于微调的表示模型,它在一系列句子级和词级别的任务上实现了最先进的性能,优于许多具有特定任务架构的系统。
bert架构由两步实现:预训练和模型微调;在预训练阶段,基于无标注数据通过多轮预训练任务完成。在微调阶段,bert模型由预训练的参数进行初始化,然后由待下游的任务数据进行参数微调。
bert模型是多层双向transformer编码器。将层的数量(Transformer blocks)表示为L,隐藏的大小表示为H,而self-attention heads 为A。在所有的情况下,我们将feed-forward/filter大小设置为4H,即H=768时,为3072, H=1024时,为4096.
bert的两种格式:
BERTBASE : L=12, H=768, A=12, Total Parameter=110M,
BERTLARGE : L=24, H=1024, A=16, Total Parameters=340M
为了使用bert可以应对各式各样的下游任务,bert的输入为token序列,它可以表示一个句子或句子对(比如对话)。使用该方案,输入可以是任意跨度的相邻文本,即一个token序列可以是单个句子,也可以是多个句子。
具体地说,bert使用30000个词的词级别的embeddings。每个序列的起始token是[CLS]。句子对被打包在一个序列中,用两种方式区别句子。方法一,使用特殊token[SEP];方法二,在每个标记中添加一个学习过的嵌入,表示它是属于句子A还是句子B。
两个无监督任务对BERT进行训练。
任务一:Masked LM语言模型。
为了训练双向表示模型,随机按百分比的方式(一般选15%)屏蔽输入序列中的部分词,然后预测那些屏蔽词。在这种情况下,屏蔽词的最终隐向量经softmax运算后输出。有点类似于中文的完形填空。
虽然如些操作可以获得一个双向的预训练模型,但这在预训练和微调之间创建了一个不匹配,因为在微调过程中从来没有见过[MASK]词。为了减轻这一点,我们并不总是用实际的[MASK]词替换被屏蔽的词。相反,生成随机选择15%的词进行预测,例如在句子 my dog is hairy 选择了 hairy。接着执行下面的过程:
数据生成器不会总是用[MASK] 替换所选单词,而是执行以下操作:
80%的时间,将单词替换为[MASK]词。例如 my dog is hairy -> my dog is [MASK]
10%的时间, 用一个随机词替换这个词, 例如 my dog is hairy -> my dog is apple
10%的时间, 保持单词不变,例如 my dog is hairy -> my dog is hairy。
每一轮使用交叉熵损失来预测原始词。
任务二:下一句的预测;
许多重要的下游任务,如问答(QA)和自然语言推理(NLI),都基于理解两个文本句之间的关系,而语言建模并不能直接捕获到这两个文本句之间的关系。为了训练一个理解句子关系的模型,我们预训练了一个二分类的预测下一个句子的任务,该任务可以由任何单语语料库生成。
具体来说,在为每个训练前的例子选择句子A和B时,50%的时间B是A后面的实际下一个句子,50%的时间B是来自语料库的随机句子。例如:
Input =[CLS] the man went to [MASK] store [SEP],he bought a gallon [MASK] milk [SEP]
Label = IsNext
Input = [CLS] the man [MASK] to the store [SEP],penguin [MASK] are flight ##less birds [SEP]
Label = NotNext
我们完全随机选择NotNext 句子,最终预测模型在这个任务中达到97%-98%的准确率。
预训练数据:预训练过程很大程度上依赖现有语言模型的数据。从维基网络上抽取文本信息,忽略列表,表格和标题。对于预训练过程来说,使用文档级别的语料库而不是经过乱序后的句子级语料库来提取长的连续序列是很重要的。
对于序列级别分类任务,BERT微调很简单。BERT使用self-attention机制来统一两个过程。因为编码文本序列中,使用self-attention有效地包含了两上句子之间双向交叉的attention。
微调过程,就是对于每一个任务,简单地将特定的输入和输出接入bert,然后端到端地调节全部参数即可。在输入端,句子A和句子B类似于(1)语义句子对(2)假设前提(3)问答中的问句(4)文本分类或序列标记中文本。在输出端,token向量被传递给token级别任务的输出层,例如,序列标签,问答对的答案。[CLS]向量被传递给分类的输出层,用于分类或情感分析。
相对于预训练,微调要相对容易。大多数模型超参数与预训练相同,除了批的大小、学习率和训练轮数。
可以通过一个额外的输出层对预训练的BERT表示进行微调,以创建适用于各种任务的最先进模型,比如问答和语言推断,无需对特定与任务的架构进行实质性修改。
第一,如果NLP任务偏向在语言本身中就包含答案,而不特别依赖文本外的其它特征,往往应用Bert能够极大提升应用效果。
第二,Bert特别适合解决句子或者段落的匹配类任务。就是说,Bert特别适合用来解决判断句子关系类问题,这是相对单文本分类任务和序列标注等其它典型NLP任务来说的,很多实验结果表明了这一点。
第三,Bert的适用场景,与NLP任务对深层语义特征的需求程度有关。感觉越是需要深层语义特征的任务,越适合利用Bert来解决
第四,Bert比较适合解决输入长度不太长的NLP任务,而输入比较长的任务,典型的比如文档级别的任务,Bert解决起来可能就不太好。
【引用】:
bert论文:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
https://www.cnblogs.com/robert-dlut/p/8638283.html
https://blog.csdn.net/DarrenXf/article/details/89184225
https://www.cnblogs.com/xlturing/p/10824400.html
https://www.cnblogs.com/ylHe/p/10193166.html