深入理解Transformer的笔记记录(精简版本)---- ELMO->GPT->BERT

1、ELMO

word embedding无法区分多义词的不同语义,其本质上是个静态的方式,所谓静态指的是训练好之后每个单词的表达就固定住了,以后使用的时候,不论新句子上下文单词是什么,这个单词的Word Embedding不会跟着上下文场景的变化而改变

ELMO根据当前上下文对Word Embedding动态调整的思路,事先用语言模型学好一个单词的Word Embedding,然后在我实际使用Word Embedding的时候,单词已经具备了特定的上下文了,这个时候可以根据上下文单词的语义去调整单词的Word Embedding表示。

1.1 ELMO采用了典型的两阶段过程:

(1) 第一个阶段是通过语言模型LSTM进行预训练

上图左端的前向双层LSTM代表正方向编码器,输入的是从左到右顺序的上文Context-before;

右端的逆向双层LSTM代表反方向编码器,输入的是从右到左的逆序的下文Context-after

同时,每个编码器的深度都是两层LSTM叠加

(2)第二个阶段是在做下游任务时,从预训练网络中提取对应单词的网络各层的Word Embedding(E1,E2,E3)作为新特征补充到下游任务中。

**双层双向LSTM:**虽然ELMO用双向LSTM来做encoding,但是这两个方向的LSTM其实是分开彼此独立训练的(一个从左向右预测,一个从右向左预测,在左边和右边的内部结构里,其本质还是单向),只是在最后在loss层做了个简单相加。 对于每个方向上的单词来说,在一个方向被encoding的时候始终是看不到它另一侧的单词的,既解决了see itself的问题,又充分用上了上下文的语义。

1.2 使用方法

使用这个网络结构利用大量语料做语言模型任务就能预先训练好这个网络,如果训练好这个网络后,再输入一个新句子,句子中每个单词都能得到对应的三个Embedding:

先将句子X作为预训练好的ELMO网络的输入

这样句子X中每个单词在ELMO网络中都能获得对应的三个Embedding

(1)第一个Embedding,是单词的Word Embedding

(2)第二个Embedding,是双层双向LSTM中第一层LSTM对应单词位置的Embedding,这层编码单词的句法信息更多一些

(3)第三个Embedding,是双层双向LSTM中第二层LSTM对应单词位置的Embedding,这层编码单词的语义信息更多一些。

之后给予这三个Embedding中的每一个Embedding一个权重a,这个权重可以学习得来。

根据各自权重累加求和,将三个Embedding整合成一个。

然后将整合后的这个Embedding作为X句在自己任务的那个网络结构中对应单词的输入,以此作为补充的新特征给下游任务使用。

可改进的地方

  • Transformer提取特征的能力是要远强于LSTM
  • ELMO采取双向拼接这种融合特征的能力可能比BERT一体化的融合特征方式弱

2、生成式的预训练之GPT:预训练(单向Transformer) + Fine-tuning

下图展示了GPT的预训练过程,其实和ELMO是类似的,主要不同在于两点:

首先,特征抽取器不是用的LSTM,而是用的Transformer,毕竟它的特征抽取能力要强于LSTM,这个选择很明显是很明智的;

其次,GPT的预训练虽然仍然是以语言模型作为目标任务,但是采用的是单向的语言模型,只采用单词的上文来进行单词预测,而抛开了下文。

什么是单向Transformer?

在正常的Transformer中,Encoder因为要编码整个句子,所以每个词都需要考虑上下文的关系。所以每个词在计算的过程中都是可以看到句子中所有的词的; 但是Decoder与Seq2Seq中的解码器类似,每个词都只能看到前面词的状态,所以是一个单向的Self-Attention结构。

而GPT使用的Transformer结构就是将Encoder中的Self-Attention替换成了Masked Self-Attention(所谓Masked,即遮蔽的意思),即句子中的每个词,都只能对包括自己在内的前面所有词进行Attention,从而每个位置的词看不到后面的词,这就是单向Transformer。

GPT在第二阶段的使用:

首先,对于不同的下游任务来说,网络结构要向GPT的网络结构看齐,把任务的网络结构改造成和GPT的网络结构是一样的

然后,在做下游任务的时候,任务的网络结构的参数初始化为预训练好的GPT网络结构的参数

再次,对网络参数进行Fine-tuning,使得这个网络更适合解决手头的问题

3、BERT:双向Transformer版的GPT

GPT是使用「单向的Transformer Decoder模块」构建的,而 BERT则是通过「双向的Transformer Encoder 模块」构建的

BERT综合了ELMO的双向优势与GPT的Transformer特征提取优势

  • 第一点是特征抽取器采用Transformer,把ELMO的特征抽取器换成Transformer,会得到BERT
  • 第二点是预训练的时候采用双向语言模型,把GPT的单项语言模型换成双向语言模型,就得到了BERT

预训练之后,针对下游每个不同的任务都会有一个任务模型,只是这些任务模型一开始全都初始化为预训练好的BERT模型,然后根据下游任务的特点针对性微调。

3.1 使用方法

BERT对输入、输出部分的处理:

BERT的输入部分是个线性序列,两个句子之间通过分隔符「SEP」分割,最前面是起始标识「CLS」,每个单词有三个embedding:

(1)单词embedding,这个就是我们之前一直提到的单词embedding,值得一提的是,有的单词会拆分成一组有限的公共子词单元,例如下图示例中'playing'被拆分成了'play'和'ing';

(2)句子embedding,用于区分两个句子,例如B是否是A的下文(对话场景,问答场景等);

(3)位置信息embedding,句子有前后顺序,组成句子的单词也有前后顺序,否则不通顺杂乱无章就是零散单词而非语句了,所以单词顺序是很重要的特征,要对位置信息进行编码.

把单词对应的三个embedding叠加(没错,直接相加),就形成了BERT的输入。

4、总结

  • ELMO采用双向LSTM结构,因为两个方向是彼此独立训练的,所以可以根据上下文预测中间词,尽管效果可能不是最佳
  • GPT由于采取了Transformer的单向结构,只能够看见当前以及之前的词,故只能根据上文预测下一个单词
  • BERT没有像GPT一样完全放弃下文信息,而是采用了双向的Transformer。第一个创新点,即Masked Language Model(MLM),所谓MLM是指在训练的时候随即从输入预料上mask掉一些单词,然后通过的上下文预测该单词。
  • 为了让BERT具备通过上下文做完形填空的能力,自然就得让BERT不知道中间待预测词的信息,所以就干脆不要告诉模型这个中间待预测词的信息好了。即在输入的句子中,挖掉一些需要预测的词,然后通过上下文来分析句子,最终使用其相应位置的输出来预测被挖掉的词

但是,直接将大量的词替换为<MASK>标签可能会造成一些问题,模型可能会认为只需要预测<MASK>相应的输出就行,其他位置的输出就无所谓。同时Fine-Tuning阶段的输入数据中并没有<MASK>标签,也有数据分布不同的问题。

为了减轻这样训练带来的不利影响,BERT采用了如下的方式:输入数据中随机选择15%的词用于预测,这15%的词中

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

这样一来就相当于告诉模型,我可能给你答案,也可能不给你答案,也可能给你错误的答案,有<MASK>的地方我会检查你的答案,没<MASK>的地方我也可能检查你的答案,所以<MASK>标签对你来说没有什么特殊意义,所以无论如何,你都要好好预测所有位置的输出。
第二个创新点,++"Next Sentence Prediction"++,其任务是判断句子B是否是句子A的下文,如果是的话输出'IsNext',否则输出'NotNext',这个关系保存在BERT输入表示图中的[CLS]符号中。

至于训练数据的生成方式是从平行语料中随机抽取的两句话:

其中50%是选择语料库中真正顺序相连的两个句子,符合IsNext关系

另外50%是第二个句子从语料库中随机选择出一个拼到第一个句子后面,它们的关系是NotNext

相当于我们要求模型除了做上述的Masked语言模型任务外,附带再做个句子关系预测,判断第二个句子是不是真的是第一个句子的后续句子。

之所以这么做,是考虑到很多NLP任务是句子关系判断任务,单词预测粒度的训练到不了句子关系这个层级,增加这个任务有助于下游句子关系判断任务。

可以看到,它的预训练是个多任务过程,即有上文提到的这两个训练目标:

一个Token级别或称为词级别,Token级别简言之就是完形填空,一个句子中间挖个词,让模型预测那个空的是哪个词,与传统语言模型相比,通过上下文来预测中间某个缺失的单词,是否比从左往右(或者从右往左)的单词预测来的更直观和容易呢

一个句子级别,即给两句句子,判断这两句是不是原文中的连在一起的互为上下文(句子级别的任务对于阅读理解,推理等任务提升较大)

相关推荐
Hejjon6 小时前
SpringBoot 整合 SQLite 数据库
笔记
西洼工作室8 小时前
【java 正则表达式 笔记】
java·笔记·正则表达式
初学者7.8 小时前
Webpack学习笔记(2)
笔记·学习·webpack
新手上路狂踩坑9 小时前
Android Studio的笔记--BusyBox相关
android·linux·笔记·android studio·busybox
stm 学习ing11 小时前
HDLBits训练3
c语言·经验分享·笔记·算法·fpga·eda·verilog hdl
尘觉11 小时前
算法的学习笔记—扑克牌顺子(牛客JZ61)
数据结构·笔记·学习·算法
bohu8312 小时前
sentinel学习笔记1-为什么需要服务降级
笔记·学习·sentinel·滑动窗口
初学者7.13 小时前
Webpack学习笔记(3)
笔记·学习·webpack
bohu8314 小时前
sentinel学习笔记5-资源指标数据统计
笔记·sentinel·statisticslot
璞~14 小时前
MQTT 课程概览 (学习笔记)02
笔记·学习