课程向:深度学习与人类语言处理 ——李宏毅,2020 (P19)

BERT and its family:Introduction and Fine-tune

李宏毅老师2020新课深度学习与人类语言处理课程主页:
http://speech.ee.ntu.edu.tw/~tlkagk/courses_DLHLP20.html
视频链接地址:
https://www.bilibili.com/video/BV1RE411g7rQ
图片均截自课程PPT、且已得到李宏毅老师的许可:)



前言

上篇中(P18)我们对经典伟大的语言模型进行了概述总结

而在本篇中,我们将继续讲解以 BERT 为代表的语言模型,进行介绍以及模型的微调,文章将从三个方面讲解:
1 What is pre-train model (P19)
2 How to fine-tune (P19)
3 How to pre-train (P20)

过去,在NLP领域通常是一个任务一个模型,但今天已经逐渐迈向希望模型先了解普遍的语言,再去解各式各样的NLP任务

I Pre-train & Fine-tune

在这里插入图片描述

今天在NLP领域一个常见的方法是,根据大量无标注的文字资料来训练一个模型,希望这个模型能读懂文字,这个读懂我们接下来就会讲,这个训练过程就叫Pre-train预训练。接下来针对想要机器解的任务再收集少量的对应的有标注训练资料去Fine-tune微调刚刚预训练的模型,然后就可以让机器去解各式各样的任务。

例如,就上图而言,有三个任务要解,这三个任务只需要把原来的模型进行稍稍地修改并用有限的对应任务的训练资料来微调,期待模型可以得到很好的结果。这个其实也很接近人类学习语言的过程,比如要测试你的英文水平,如雅思托福,有各式各样的题型,但是你学习英文的方法并不是通过不断地做题来学到的。而是类似上图在阅读大量英文资料后,了解每一个词汇的作用,语法等,接下来再做一些考古题针对性学习就可以通过某个语言能力的鉴定。

讲到Pre-train Model,最知名的就是BERT。

II What is pre-train model

在这里插入图片描述

2.1 Word2vec & Glove

那在BERT之前,其实就已经有Pre-train Model了,它做的就是给输入的每一个token输出一个embedding vector表示,这个vector应该包含了这个token的语义,意思相近的token应该有相似的embedding,且embedding的某些维度应该是代表某些特定的语义。

像这样的预训练模型,在没有ELMO、BERT之前,就是像上图一样。输入一个token就输出一个embedding就结束了,那怎么实现呢?有很多种方法,举例来说,可以建一个表,这个表里面存的就是每个token都有一个向量对应。

但像过去这样的预训练模型,最大的问题就是,同一个token都有相同的embedding,像这样的模型是不考虑每个token的上下文的,同样的token无论上下文如何都有一样的embedding。这样的著名经典模型有Word2vec、Glove,不再细讲。

2.2 FastText

在这里插入图片描述

2.2.1 English

除了 Word2vec、Glove之外,还有什么样的技术呢?如果你今天考虑的是英文,那token就不能是词汇了,因为英文的词汇实在是太多了,且有未登录词的问题,就是说如果给模型一个它从没见过的词,它将无法做embedding。所以怎么办呢?

输入将改成字母的序列,输出就是这个词的向量。期待模型可以通过读英文词汇的各个字母就可以判断没有见过的词汇。有代表性的模型就是鼎鼎大名的FastText。

2.2.2 Chinese

在这里插入图片描述
那如果是中文呢?对于中文,还有更特别的解法,在中文里面,部首也是跟语义有关的,如水字旁就是与水有关,木字旁就与植物有关。因此,对于中文,每一个词汇就像是一个图画,那我们能不能把中文的字的Image,如上图”信“,丢到CNN里,期待CNN可以学会它看到人字旁看到言就知道人言为信,输出信对应的embedding。这个不见得能做到 人言为信 这么高端的理解。但至少还能学习到部首偏旁等。

2.3 Defect

在这里插入图片描述
至此,上述就是过去常用的预训练模型,但是像这样的模型,它不会考虑每个token的上下文的。如上图,”养只狗“的狗和”单身狗“的狗都是狗,它们的embedding也就是一样的,但是我们知道这两只狗的狗是有着不同意思的。

那过去还没有ELMO这一套之前,有人会想说,也许我们就给不同意思的狗就当作不同token来看,通过加下标表示不同的狗。但这样的想法又会有问题,这两个狗虽然有语义不同,但也是有一定相关的。

2.4 Contextualized Word Embedding

在这里插入图片描述
所以后来就有了 Contextualized Word Embedding 与上下文有关的词嵌入,如ELMO、BERT等等就是Contextualized Word Embedding。

Contextualized Word Embedding与过去的 Word Embedding、Glove、FastText不同的地方就是,过去的这些模型都是吃一个token就要吐出一个embedding。而Contextualized 都是吃一整个句子,再给每一个token一个embedding,虽然这也是给每个token一个embedding,但它是在看过整个句子即上下文后才给出embedding。

2.4.1 Structure

那像这样的与上下文有关的embedding应该长什么样子呢?其实你只需要找到模型的输入可以token sequence,输出是每个token对应的vector就可以了,就像是seq2seq里面的Encoder这样的东西。
在这里插入图片描述
而这样的模型往往都非常的深,有很多层,网络的架构可以用LSTM(ELMO)、Self-attention layers(BERT)或者Tree-based model(文法树,今天并没有非常的流行)

2.4.2 Trend

在这里插入图片描述

2.4.2.1 Bigger

如上图,像这样的模型越来越大,而除了让模型越来越大的研究方向外,就是让模型越来越小,如下图
在这里插入图片描述

2.4.2.2 Smaller

既然BERT非常大,另一个研究方向就是让BERT变得更小。如上图所示,其中最有名的便是ALBERT,且模型结构几乎与BERT一样,原来BERT12、24层都是不一样的参数,而ALBERT12、24层都是一样的参数,且模型效果甚至优于BERT。

那怎么让模型变小呢?
在这里插入图片描述

2.4.2.2 Architecture

上述的四种方法都可以实现让模型变小,而这些都在机器学习课程中讲过,如果你想直到哪些模型都用了哪些技术,你可以使用上图下面的链接进行参考查询。

除了用一些神经网络压缩方法让模型结构变小,可不可以通过直接修改网络结构来减少参数呢?
在这里插入图片描述
近年来,在神经网络结构上也有一些突破,如上图的这些模型,这些模型设计的初衷都是为了让预训练模型可以读非常长的sequence,如一本书的长度。

举例来说,像BERT这样的模型一次只能读512个token,但Transformer-XL可以让模型读跨segment的sequence,跨段阅读,具体怎么实现请参考文献。而Reformer和Longformer都是想要减少self-attention带来的运算量,O(n^2),n是token sequence的长度,同样具体怎么实现请参考文献。

III How to fine-tune

3.1 Overview

在这里插入图片描述
在有一个预训练模型之后,我们希望可以在预训练模型上面再叠一些具体的NLP任务的任务层,就可以用在具体特定的NLP任务上。那我们该怎么改造这个预训练模型,即怎么改造这个输入为token sequence,输出为对应token的vector的预训练模型,使得它可以使用在任意的NLP任务上?

3.2 Input

在这里插入图片描述
首先,先看输入部分,对于输入部分,预训练模型本身不需要修改,对于一个句子没有什么特殊处理,但对于多个句子需要每个句子之间加“[SEP]”分隔符后再输入给预训练模型。

而什么时候模型需要同时输入多个句子呢?举例来说,如QA问题,要将问题和文章一起输入给模型、又如NLI自然语言推理问题,要将前提和假设一起输入给模型。

3.3 Output

输入的部分处理我们已经讲完了,而输出的部分一共有四个可能,接下来我们将把输出部分的四个可能一个一个看下去。

3.3.1 one class

在这里插入图片描述
输入:one sentence
输出:one class

如上图,对于模型输入一整个句子,输出一个类别的问题。
在原始BERT论文中解法如上图绿色框框,同样是读入所有的token sequence,并在开头加一个特殊符号“[CLS]”表示分类符号,通过"[CLS]"得到的embedding再输入给一个线性分类器里,输出类别。
另外一个做法是不加“[CLS]”特殊符号了,就是把所有token的embedding sequence都丢到一个可以处理sequence的模型中,如RNN、LSTM等,输出一个类别。

3.3.2 class for each token

在这里插入图片描述

3.3.2 class for each token

输入:one sentence
输出:class for each token

如上图,对于模型输入一整个句子,输出每个token的类别的任务。
我们只需要一个模型,它可以把整个句子中每个token经过预训练模型得到的embedding sequence当作输入,接下来对每一个embedding进行输出类别,它可以是LSTM。

3.3.3 copy from input

在这里插入图片描述
输入:document
输出:two number

如上图,第三个任务是解类似QA问题,而且是Extraction-based Question Answering,如SQuAD,给模型读一篇文章,并提出一个问题,希望模型能正确的得到答案,且答案是原文中的一部分。而对于模型而言,它只需要输出两个数字s和e表示起始索引和终止索引,其索引内的token sequence就是正确答案,那该怎么实现呢?在这里举一个BERT的例子。如下图。
在这里插入图片描述
解法:将问题和文章中间加"[SEP]",开头加"[CLS]"输入给BERT,此时我们得到了每一个对应位置的embedding,另外,再从头训练两个向量 橙蓝,其维度和 黄色embedding是一样的,然后将橙色的向量与文章的embedding做dot-product点积运算得到每一个文章内的词汇的scalar,再将其softmax后得到对应分数,找出其中分数最高的,如上图的d2,此时s就等于2。同理,蓝色的向量与橙色的向量运算过程一样,得到e等于多少。至此,答案就是 d s 至 d e d_s至d_e dsde

在训练的时候,橙蓝向量从头训练,BERT微调就好。

此时,会有这样的问题,假设s和e矛盾了,比如s=3,e=2,这不是没有答案了吗?对,此时模型就是输出此题无解,在SQuAD2.0中是有无解的问题的。

3.3.4 general sequence

在这里插入图片描述

3.3.4.1 v1

输入:sentence
输出:sentence

最后一个任务就是怎么让预训练模型处理seq2seq问题呢,也就是怎么把预训练模型接入seq2seq模型里面呢?最简单的做法就是把预训练模型当作seq2seq中的Encoder,具体任务模型就是Decoder。但这样的坏处就是这个具体任务模型没有被事先预训练到,一般而言具体任务的有标注数据会很少很少,我们期待这个具体任务的模型越小越好,希望这个具体任务模型大多数参数都是经过预训练的,但上述这种Encoder-Decoder方法显然不能预训练具体任务模型的。
在这里插入图片描述

3.3.4.1 v2

其实,对于seq2seq问题,还有另外一种使用预训练模型的方法。

现在 w 1 , w 2 w_1,w_2 w1,w2是输入的sequence,接下来,输入一个特别的符号"[SEP]",它会输出一个embedding,将这个embedding再丢到具体训练任务模型中,然后输出产生想要输出的sequence的第一个token。接下来,再把这个token丢到预训练模型中,再产生embedding,把这个embedding同样输入到具体训练任务模型中生成第二个token,依次生成,直至具体训练任务输出"[EOS]"。


以上讲的都是怎么在预训练模型上加上什么东西,让它能够解决各式各样的具体问题。
接下来,假如我们有一些具体训练任务的有标注数据,我们该怎么微调预训练模型呢?

3.4 Fine-tune

3.4.1 Methods

在这里插入图片描述

根据具体训练任务的有标注数据进行微调预训练模型有两种方法,

第一种做法是,预训练模型训练完后就固定住了,变成了一个Feature Extractor特征提取器,对输入的token sequence,输出一堆的embedding表示,再将这些embedding丢到具体任务模型中,我们只微调具体任务模型的参数。

第二种做法是,我们把预训练模型与具体任务模型接在一起,微调模型时既会微调预训练模型,也会微调具体训练任务模型。如果直接训练这种组合起来的巨大模型,往往会过拟合,但是预训练模型的大部分已经预训练过了,只有很小部分的参数是由具体训练任务改变。在文献上,第二种方法往往优于第一种方法。

3.4.2 Adaptor

在这里插入图片描述
但是如果我们现在采取的是第二种方法,Fine-tune整个巨大的模型,会遇到什么样的问题呢?你可能会遇到这样的问题,如上图所示。

我们有三个具体的NLP任务,如果我们仅仅使用同一个预训练模型+具体任务模型的方式,经过每一个具体任务数据Fine-tune整个模型后,同一个预训练模型因不同训练数据的微调会得到三种有区别的预训练模型,如上图的Model就应该一个变蓝色、一个变绿色、一个变灰色的。那每一个任务都需要存一个新的这样的预训练模型,而预训练模型往往都是非常的巨大,这样是非常不切实际的。

所以就有了Adaptor,我们能不能对于不同的训练任务只调预训练模型的一部分就好。我们在预训练模型中加入一些layers,这些layers就叫Adaptor,它只是模型的一小部分参数而已。我们在根据不同训练任务微调模型时,只需调Adaptor的部分即可。因此,对于不同任务,我们只需要存不同的Adaptor参数和共同的一个预训练模型参数即可,这样的参数量就要比每一个任务都存一个预训练模型的参数量远远小得多。
在这里插入图片描述
Adaptor结构如上图,以供参考,其实Adaptor方法有很多,怎样才能得到最好的Adaptor结构设计呢?这也是一个值得研究的问题。(小细节,上图文献中是Adapter,而不是Adaptor)

3.5 Weighted Features

在这里插入图片描述
目前为止,我们都是让训练模型输入token sequence,经过很多个layer层(12、24)后得到每个token的embedding,再把这个embedding丢到具体任务里去。其实还有另外一种做法,其实预训练模型中每一层学到的东西是不一样的,所以有个做法是把不同层的输出进行加权求和得到embedding,而其中的权重参数都是跟着具体任务训练得到的。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿芒Aris

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值