notebook notebook
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)

学习笔记

啦啦啦,向太阳~
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)
  • 深度学习

    • Posts

    • PyTorch 入门

    • 鱼书进阶-自然语言处理

    • 深度学习-李宏毅

      • Regression
      • 神经网络训练不起来怎么办
      • CNN
      • Self-Attention
      • 各式各样的 Attention
      • Pointer Network
      • 图神经网络
      • Transformer
      • 生成对抗网络 GAN
      • Self Supervised Learning
      • BERT and its family
        • 1. What is pre-train model?
          • 1.1 Pre-train Model 的历史
          • 1.2 Contextualized Word Embedding
          • 1.3 Bigger Model
          • 1.4 Smaller Model
        • 2. How to fine-tune?
          • 2.1 NLP tasks
          • 2.2 How to fine-tune
          • 2.3 Adaptor
          • 2.4 Weighted Features
        • 3. Why Pre-train Models?
        • 4. How to Pre-train?
          • 4.1 Pre-training by Translation
          • 4.2 Self-supervised Learning
          • 4.3 Predict Next Token
          • 4.4 Predict Next Token - Bidirectional
          • 4.5 Masking Input
          • 4.6 Span Boundary Objective(SBO)
          • 4.7 XLNet
          • 4.8 MASS / BART
          • 4.9 UniLM
          • 4.10 ELECTRA
          • 4.11 Sentence Level
          • 4.12 NSP -> SOP
          • 4.13 T5
          • 4.14 Others
        • 5. Multilingual BERT
      • Data Efficient & Parameter-Efficient Tuning
      • Auto-Encoder
      • 机器学习的可解释性
      • Adversarial Attack
      • Domain Adaptation
      • 强化学习
      • 神经网络压缩
      • Life Long Learning
      • Meta Learning
      • ChatGPT 是怎样炼成的
    • 李宏毅-2017版

    • 李宏毅-2019版

    • 预训练语言模型-邵浩2021版

    • 王树森

  • 机器学习

  • 知识图谱

  • AI
  • 深度学习
  • 深度学习-李宏毅
yubin
2022-09-10
目录

BERT and its family

# 1. What is pre-train model?

# 1.1 Pre-train Model 的历史

以前,Pre-train Model 想要做的是:Represent each token by a embedding vector. 如下图所示:

image-20220910092744562

以前所做的往往是 simply a table look-up,也就是静态查表,这有一个问题:The token with the same type has the same embedding.

上面所说的技术就有知名的 Word2vec [Mikolov,er al., NIPS’13]、Glove [Pennington, et al., EMNLP’14]。

除此之外还有什么技术呢?

如果你考虑的是英文,如果将 English word 作为 token 的话,英文单词实在太多了,这样静态查表总会有找不到的词汇。也许我们可以把 model 改成将英文 character 作为 input,输出就是一个 vector,这就是 FastText 做的:

image-20220910093518145

如果考虑中文,那每一个中文其实也可以看做一个 image,然后丢到 CNN 里从而输出对应的 vector,这也许也是可以的:

image-20220910093735265

上面所说的技术不会考虑到 context,比如同一个“狗”出现在“圈养狗”和“单身狗”中意思不是一样的。

# 1.2 Contextualized Word Embedding

image-20220910094424787
  • Tree-based model 好像没有特别强,所以目前也用的不多。

# 1.3 Bigger Model

1365470-20211026224307862-217905674

# 1.4 Smaller Model

image-20220910095704359
  • 这里面很出名的是 ALBERT

这些让 BERT 变小的技术是 Network Compression。

还有一些在这些模型的 Network Architecture 上也有很多的突破:

image-20220910095915587
  • Transformer-XL 解决了 BERT 一次只能读 512 个 token 的问题
  • Reformer 和 Longformer 是为了减少 self-attention 过程中的运算复杂度

# 2. How to fine-tune?

# 2.1 NLP tasks

可以根据 input 和 output 的类型进行一个分类:

image-20220910100216657

# 2.1.1 Input

对于 multiple sentences 的情况,假如有两种不同类型的 sentence,可以在两者之间加一个特殊分隔符 [SEP]:

image-20220910100807708

然后把它们丢到 model 里面就可以了。

# 2.1.2 Output

output 有多个类型,我们逐一看一下。

# 1)one class

一种做法如下图所示:

image-20220910101027092
  • 输入的时候加一个特别的 token:[CLS],pretrain 的时候就要告诉 model 当看到 [CLS] 就要产生一个与整个句子有关的 Embedding
  • 然后把这个与整个句子有关的 Embedding 丢到一个 task specific model 中得到一个 class,这个 model 什么样要看任务有多复杂,但很多情况下直接是一个 linear transform 就可以了,或者多叠几层 linear transform。

还有另外一种做法是将整个句子的 Embedding 都进行处理得到一个 class:

image-20220910101447795
# 2)class for each token

这种就是对每个 token 都给一个 class,做法如下图:

image-20220910101645179
  • 这里的 task specific model 可以是一个 LSTM,也可以是其他的。
# 3)copy from input

完全从 input 做 copy,这种类型的任务也没有很多,其中最经典的就是 Extraction-based QA,这个任务是:

image-20220910101915337

原始的 BERT 的 paper 里提供了这种任务的解决方法,可以参考论文。

# 4)general sequence

按照 seq2seq model 的设计,可以这样做:

image-20220910102404705

但问题是,作为 decoder 的 task specific model 是完全没有 pretrain 过的,所以这样做也许不是最好的。

来看第二种版本:

image-20220910102738639
  • 这种做法就是输入 input sequence 后再输入一个 [SEP],这时 Model 会输出与 [SEP] 相对应的 Embedding Vector,把这个 vector 输入到 task specific model 得到输出 ,然后接着把 当做 input 得到 ,一直如此直到得到 <EOS>。

# 2.2 How to fine-tune

假设你有一些 task specific data,该怎样去 fine-tune 呢?这里有两种做法。

第一种做法,固定住 pre-trained model 从而变成一个 feature extractor,然后我们只 fine-tune 那些 task specific 的部分:

image-20220910103323315

第二种做法,把 pre-trained model 和 task-specific model 合在一起 fine-tune,当成一个巨大的 model 来解这个 down-stream task:

image-20220910103554759

在以前,巨大 model 在 train 时很容易 overfitting,但第二种做法由于只有 task-specific 的 param 是随机初始化的,pre-trained model 的 param 并不是随机初始化的,所以也许这种方式并没有那么容易 overfitting。在一些文献中指出,第二种做法的 performance 往往比第一种要好一些。

# 2.3 Adaptor

刚刚讲的第二种 fine-tune 方法有一个问题,对每一个 task specific 进行 fine-tune 后,pretrained model 会变得不一样:

image-20220910105412511

这样每个任务都需要存一个新的 model,而这些 model 往往非常巨大,所以这可能行不通的,因此有了 Adaptor 的概念。也就是说,我们能不能只能调 pretrained model 的一部分就好了,于是我们在 pretrained model 里面加了一个很小的 layer,这些 layer 就叫做 Adaptor,下图用 Apt 来简称。这样 fine-tune 时只调整 Pretrained Model 的 Adaptor 部分,这样存储时就只需要存一份 pretrained model 的主体部分,从而减小存储压力:

image-20220910105923387

这边举一个使用 Adaptor 的例子,当然还有很多其他做法:

image-20220910110135189
  • pretrain 的时候是没有 Adaptor 的,而是在准备 fine-tune 时才加入并只调整 Adaptor 的参数。

这个例子的表现结果如下:

image-20220910110516588
  • Accuracy delta 中的 0 代表当我们 fine-tune 整个 model 时的 performance
  • 蓝色这条线表示越往右边微调参数越多

# 2.4 Weighted Features

我们之前是把 input sequence 后扔进整个 model 后,拿到最后的 Embedding 输给 down-stream task layer 中。但还有一种做法,因为每一层他所抽取的资讯是不一样的,所以一种做法是把不同层的 feature 给 weighted sum 起来得到一个新的 embedding,这个 embedding vector 同时综合了多层抽取的资讯,然后再把它丢到 down-stream 中:

image-20220910111338745

这里的 、 该设为多少呢?它们可以被视为 task specific layer 的参数的一部分从而一起 learn 出来。

# 3. Why Pre-train Models?

GLUE 是检测一个模型了解人类语言的能力:

image-20220910135932970
  • 黑色的这条线表示人类理解这个数据集的能力,可以看到后面提出的 pretrain model 都至少可以在这个 corpus 上超越人类的 performance 了。

有很多 paper 讨论了为什么 pretrain model 是有效的,这里选其中一篇来讲解。这里选了 arxiv 上 1908.05620 这一篇,分析其中的两个结果

image-20220910140557668
  • 虚线代表没有 pretrain 的 model,实线代表有 pretrain 的 model,它们的 model 大小是一样的。
  • 可以看到,有 pretrain 的 model 在 training 时 training loss 下降的非常快。

那只看 training loss 是不是有可能是因为 pretrain model 会 overfitting 呢?它在面对新的数据时 generalize 的能力如何呢?我们来看下图:

image-20220910161032304
  • 可以看到,fine-tuning BERT 所处在的 local minima 是一个盆地,而左图是一个峡谷。一般来说,local minima 处在盆地时的泛化能力是要比处在峡谷时要强的。

# 4. How to Pre-train?

这章讲如何得到 pre-train 的模型。

我们希望什么样的 pre-train 的 model 呢?我们希望它能把 token sequence 吃进去,然后把每个 token 变成一个 embedding vector,而且希望这些 embedding vector 是 contextulize 的,即考虑上下文的。

# 4.1 Pre-training by Translation

像这种抽取 contextulize 的 embedding 的方法最早是 CoVe 这篇 paper,它是通过 translation 而不是现在常用的 unsupervised learning 的方法得到的这个 model:

image-20220911105537473
  • 把这个 model 当作是 translation 的 Encoder,最终训练好 Encoder 和 Decoder,这里的 Encoder 就是我们 pretrain 好的 contextulize word embedding 的 model。

这篇 paper 选择 translation 也是有合理性的,因为他会把input sequence 里面的资讯都如实呈现到输出里面,而像 summarize 之类的任务就不行。但这种方式的问题是收集大量的 pair data 作为 training data 是很困难的,于是就有了之后的 unsupervised 的方法,现在也常称为 self-supervised 方法。

# 4.2 Self-supervised Learning

Self-supervised Learning 是 Yann LeCun 在 Twitter 上提出的,其基本概念如下:

image-20220911110848667

# 4.3 Predict Next Token

给这个 model 一个 得到 representation ,然后用 来预测下一个 token 。怎样从 预测 呢,如下图:

image-20220911111325008

这样就用从 预测 这个任务来训练 model:

image-20220911111557442

注意,在训练时不可以让 model 一次把 同时读进去,然后让他预测 ,否则 model 可能直接把下一个 token 给输出出去,从而学不到什么东西。

以上所讲的 Predict Next Token 任务是最早的 unsupervised pretrain 技术,这样得到的 model 就是一个 language model(LM)。

这个 model 可以使用 LSTM,也可以使用 Self-attention。使用 LSTM 的 language model 有 ELMo、ULMFiT 等,使用 Self-attention 的有 GPT、Megatron、Turing NLG 等。

使用 Self-Attention 作为 model 来做 predict next token 时,注意要给 self-attention 加一个 constraint,不能让它看到后面的,比如 位置只能 attend 到 和 ,而不能 attend 到 及 ,从而防止它看到它不该看的以后的答案:

image-20220911112705093

# 4.4 Predict Next Token - Bidirectional

刚刚讲的最终得到的 contextualize representation 只考通过 predict next token 得到的,而且是只考虑了 left context,并没有考虑 right context。

ELMo 就是同时考虑了 left context 和 right context 用来得到一个 token 的 contextualize representation:

image-20220912225943109
  • 它有一个由左向右的 LSTM,看 去预测 ;又有一个由右向左的 LSTM,看 来预测 。
  • 然后 ELMo 把正向的 LSTM 和逆向的 LSTM 输出的 vector 给 concatenate 起来,当作代表 的 contextualize representation。

所以说 ELMo 通过两个方向的 LSTM 来考虑了一个 token 的 left context 和 right context。但这样还不够,因为 machine 在看 left context 进行 encoding 时没有看到 right context,即两次 encoding 的过程都只是看到句子的一半而非全部,两个 LSTM 得到的 vector 是没有交互的。

# 4.5 Masking Input

BERT 弥补了刚刚讲的 ELMo 的 encoding 过程没有左右 context 交互的问题,而且 BERT 做的也不再是 predict next token,而是 masking input:

image-20220912231915822
  • BERT 对 input sequence 的一些 token 给 masking 掉,对 masking 的部分有随机两种做法:一种是替换成一个 special token [MASK],一种是随机 sample 一个 token 替换到这里。
  • 然后用所 masking 掉的部分输出的 vector 来预测 masking 掉的是哪个 token。

BERT 用的 Model 是 Transformer Encoder 堆叠起来的。

其实考古一下的话,Word2Vec 的 CBOW 模型的 training 过程就与 BERT 很像,只不过 BERT 内部结构更加复杂,所考虑的东西也更多了。

原始 BERT 中要 masking 掉哪些位置是随机决定的,但这不一定很好。具体改进的做法有:

image-20220912231915822
  • 上面的 WWM 是 masking 掉一整词,防止出现要预测“黑 [MASK] 江”这种简单的任务;
  • 下面是指讲 entity 先识别出来,然后 masking 掉 entity,这么做的就是 ERNIE。

还有一种 masking 的方法叫做 SpanBert,它就是一次 masking 掉很长的一个范围,原来的 BERT 只是每次随机选一个 token 来 masking 掉。SpanBert 每次盖住多长是有一个几率分布:

image-20220912233424453

这篇 paper 也对比多不同类型的 masking 方法的效果:

image-20220912233711412
  • Geometric Spans 就是 SpanBert 提出的 masking 方法。

# 4.6 Span Boundary Objective(SBO)

SpanBert 同时提出了一个新的预训练方法:Span Boundary Objective(SBO)。做法如下:

image-20220912233424453
  • 先 masking 一个范围,同时有一个 SBO 的 model,它把这个所 masking 部分的左右两边的 token 吃进去,同时给 SBO model 一个数字 2,这个数字表示要预测所 masking 掉 span 里的第 2 个 token

这个训练方法也许看上去匪夷所思,其实这种设计所期待的是:一个 span 的左右两边的 token 可以包含它内部整个 span 的资讯。为什么这样呢?以后讲到 coreference 时会有用处。

# 4.7 XLNet

“XL” 指的是 Transformer-XL,具体是什么可以参考 paper。

以往的 predict next token 是根据 left context 去 predict 下一个 token,而 XLNet 是把 input sequence 里面的 token 给随机打乱,比如下图中的下面部分:

image-20220913084531392
  • 下面就是把“深度学习”打乱成“习度学深”,然后让 model 根据“习度”去预测“学”。

另外,原始 BERT 是根据整个句子的资讯加上 mask 掉的 [MASK] 本身去预测 mask 掉的 token,如下图的上面部分所示。而 XLNet 是只根据 sentence 的一部分而非全部来预测,而且到底是根据哪些部分是随机决定的,还有一个特别的是它不会给 model 看到 mask 的部分(但也会给它 positional information),如下图的下面部分所示:

image-20220913085318325

其实 XLNet 为了实现上面所说的,在架构上也做了很多改变,具体可参考原 paper。

# 4.8 MASS / BART

其实 BERT 本身有点不善言辞,也就是说它不太适合 generation 的任务。而我们想把它用于 sequence-to-sequence,就要让它具有产生句子的能力,也就是”Given paritial sequence, predict the next token“。但 BERT 的训练任务却是从来没有只看 partial sequence 来 predict。

下面我们的讨论只局限于 autoregressive model 的情况下,即根据前面的 sequence 来产生下一个 token,由左向右地产生,而不讨论 non-autoregressive 的情况。

BERT 本质是一个 encoder,不太适合 seq2seq 的任务,所以我们可以直接 pretain 一个 seq2seq 的 model:

image-20220913091212560

但要注意,我们要对 input 的做某种程度的破坏,否则这个 seq2seq model 学不到什么东西。怎么来对 input 进行破坏呢,这里有两篇 paper 来探讨这个事情:

  • MAsked Sequence to Sequence pre-training (MASS)
  • Bidirectional and Auto-Regressive Transformers (BART)

那么他俩做的是什么事呢?MASS 的想法与 BERT 很像,就是随机把一些地方 mask 掉,实际上原始 MASS 的 paper 只要求能 reconstruct 一开始 mask 掉的部分就可以了:

image-20220913091815205.png

在 BART 里面还提出了各式各样的方法,比如 delete 掉一个 token、做 permutation、做 rotation(即改变起始位置)、做 Text Infilling(随机插一个 [MASK] 来误导 model):

image-20220913092204603

BART 做了这么方法,结果表明:

  • Permutation / Rotation do not perform well.
  • Text Infilling is consistenly good.

# 4.9 UniLM

UniLM 同时是 Encoder 和 Decoder,同时还是一个 seq2seq 的 model:

image-20220913092618180

UniLM 不像之前 encoder 和 decoder 拆开,而是只有一个 model 来做三种类型 pretrain:

image-20220913125600417
  • 既当作 BERT 一样训练,又当作 GPT 来训练,还当成一个 seq2seq 来训练。

# 4.10 ELECTRA

ELECTRA 做的是先将一个 sentence 中的某个 token 给 replace 掉,然后让 model 来判断每个输入的 token 是否有被 replace,比如我们将“the chef cooked the meal”中的 “cooked” 给 replace 成 “ate”:

image-20220913130327366

但问题来了,怎么把一个词 replace 后可以语法上没有错但语义会怪怪的呢?因为太离谱的 replace 很容易就会被发现从而使 model 学不到什么东西。做法就是加一个 small BERT 来产生用来 replace 的 token:

image-20220913130652447

注意,因为下面的这个 small BERT 不是要效果很好,希望它预测后有点错误。而且这不是一个 GAN。

神奇的是,ELECTRA 训练的效果还很好:

image-20220913131002607
  • 横轴是所需的计算量,纵轴是在 GLUE 上的得分

# 4.11 Sentence Level

有时候我们希望的不是给一个 token 一个 embedding,而是给一个 sentence 一个 embedding,也就是用一个 global embedding 来表示整个 input 的 token sequence。

基于“You shall know a sentence by the conpany it keeps” 的想法,有一个叫做 Skip Thought 的想法:有一个 seq2seq 的 model,encoder 读入一个 sentence 变成一个 vector,然后 decoder 用这个 vector 来预测输入 sentence 的下一个 sentence:

image-20220913131739146

这样如果两个句子所接的下一句很像,那这两个 sentence 的 embedding 也应该很相近。

但我们说过,如果让 model 去生成东西的话,运算量就往往比较大,于是有了一个进阶版:Quick Thought:

image-20220913132033136

这个方法是说,有两个 encoder,吃进去两个 sentence,得到两个 vector,如果两个 sentence 是相邻的话,那得到的两个 vector 越相近越好,反之则越远越好。从而避开了做”生成“这个事情。

# 4.12 NSP -> SOP

原始 BERT 的 pretrain 中有一个任务是 NSP,指的是给 BERT 随便两个 sentence,通过 [CLS] 的输出来让 BERT 告诉我们这两句是否具有上下句关系:

image-20220913132901812

后来 RoBERTa 等模型发现说 NSP 没什么用,于是墙倒众人推,很多人都说 NSP 没什么用。于是有了 SOP(Sentence order prediction)任务,就是对给的两个相邻但可能颠倒前后顺序的 sentence,model 要告诉我们给的第一句是否是给的第二句的在语义上的前一句,是就回答 Yes,不是就回答 None。这个方法用在了 ALBERT 上。

之所以 SOP 比 NSP 有用,也许是因为 NSP 这个任务本身很简单,而 SOP 相比较来说更难一些。

# 4.13 T5

讲了这么多 pretrain 的方法,哪种最好呢?Google 就展现了自己雄厚的财力,把当时几乎所有 pretrain 的方法都做了一遍,发表了 T5 这篇 paper,它长达五十几页。

image-20220913133753191
  • paper 叫做 T5,用的训练数据集叫做 C4。命名大师!

# 4.14 Others

除了刚刚提到的 ERNIE,还有另外一个同名的 ERNIE:

image-20220913135117986

另外,还有一种语音版的 BERT,即 Audio BERT:

image-20220913135227152

# 5. Multilingual BERT

编辑 (opens new window)
上次更新: 2022/10/03, 13:55:17
Self Supervised Learning
Data Efficient & Parameter-Efficient Tuning

← Self Supervised Learning Data Efficient & Parameter-Efficient Tuning→

最近更新
01
Deep Reinforcement Learning
10-03
02
误删数据后怎么办
04-06
03
MySQL 一主多从
03-22
更多文章>
Theme by Vdoing | Copyright © 2021-2024 yubincloud | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×