Day 29 BERT

BERT 全名为 Bidirectional Encoder Representations From Transformers,翻译成中文其实就是双向 Transformer 的 Encoder。那麽,BERT 可以拿来做什麽?我们又为何会提到他呢?

PS:接下来介绍的图片教材来源皆为台大李宏毅教授的 BERT 教学,有兴趣的话可以去听详细内容,相信一定能有所收获。

BERT 在做什麽?

我们刚才说了,BERT 的架构是 Transformer 的 Encoder。还记得 Encoder 做的事情吗?就是将我们 input 的序列资料转换成向量,之後再由 Decoder 读取该向量的资讯後产生 output 。

因此, BERT 在做的事情就是透过一层又一层的 Self-Attention layer 去关注、学习每一个输入的向量後,输出另一串向量。而我们便能够从输出的向量中取需要的部份,丢进其他模型或者分类器中来完成自己想要做的任务(这一阶段我们称呼为 Fine-Tuning(微调))。

BERT 的强大之处

我们为什麽会提到 BERT 呢?这里就必须先提一下过去我们在处理自然语言处理(NLP)任务时所会面临的困境:

  1. 训练数据不好取得。
    假设今天我们想要做翻译任务,我们花了千辛万苦的收集了大约十万篇文章;每篇文章起码1000字以上。我们想要用该资料集对模型进行训练却很有可能训练不起来。因为要同时理解A、B两种不同语言的语意并将双方的知识对应在一起本来就是一件超级困难的事情。只凭十万笔资料就想学会2种语言并融会贯通根本是痴人说梦。

  2. 缺乏通用架构
    假设我们真的克服了训练数据的问题并且成功的设计出了一个将A语言翻译成B语言的模型,其结构通常也是专门为了完成该任务来进行设计的。不同的自然语言任务通常需要不同的模型,而重新设计一个模型并进行测试是非常累人的。

BERT 的强大之处就在於它的训练资料可以直接从无标记文本中直接取得!它的预训练资料包含了大量来自 Wikipedia(25亿字)、 BooksCorpus(8亿字) 等未经标签的文本资料。运用的方式很简单,就是让它去预测下一个字就行了!就像是我们在日常生活中看过、写过越多文章,对於一个语言的知识累积就会越来越深一样。而当模型已经具备了很多语言的知识、常识後,训练起来是不是就容易多了呢?

正因如此, BERT的架构还只需要先训练好一个之後,就可以套用到其他自然语言任务中!并且在众多自然语言处理的任务中都有良好的表现。
(因为它已经学会一种语言了,我们自然能将它套用在不同的任务中,不过还是需要视任务情况对後续进行微调啦)

使用步骤


BERT 的使用分为两大步骤: Pre-training(预训练) 与 Fine-Tuning(微调)。
在 Pre-training 阶段,BERT 会接收大量文本资料,然後以非监督式学习的方式开始训练模型。然後当我们的模型对自然语言理解到一定程度後,我们就可以进入 Fine-Tuning 阶段了。

在 Fine-Tuning 阶段,我们会针对不同的任务,使用有标签的资料对模型进行训练、微调。像是把文本进行切分、层数选择、调整学习率...等。

训练方式

在 Pre-training(预训练)阶段,BERT主要使用2种方法进行训练,分别是:

  • 遮罩语言模型 (Masked LM)
  • 下一句预测 (Next Sentence Prediction)


首先是 Masked language model,简称为 Mask LM。输入的辞汇中有15%的机率被替换成 [Mask] 的 token,而 BERT 要做的便是填回被盖住的辞汇。(其实就是克漏字啦)

将挖空部份的embedding丢进一个线性的多分类器中,并要求这个线性的分类器去预测这个被挖空的辞汇

例如图中的范例,首先我们照常将输入通过 BERT 後,我们会将[MASK]位置的输出丢进一个线性的多分类器内,然後要求这个线性的分类器去预测被遮住的辞汇『退了』二字才行。

PS:一般在做 BERT 中文训练时,用"字"来训练可能比用"词"训练更为恰当。因为中文的"字"是有限的,但"词"的组合却是成千上万。


再来是下一句预测 (Next Sentence Prediction),其实就是让 BERT 去预测下一个句子接在上一个句子後面是否合理。例如图中的句子,一个是"醒醒吧",另一个是"你没有妹妹",我们会希望 BERT 也能准确的预测说这两个句子是接在一起的。

而为了让BERT预测两个句子是否相接,我们还必须引入一些特殊的符号:[SEP]是用来告诉BERT这次句子的交界处;而[CLS]则是放在句子起始处,用来告诉BERT接下来在这个位置要做分类,并将该位置的输出放进一个线性的二元分类器,再由该分类器输出这两个句子是否相接的结果。

PS:另外由於 Encoder 内部采用 Self-Attention 的关系,[CLS]不管是放在头还是尾其实是影响不大的。

BERT 的用法

BERT 的原论文有提出4种不同的 BERT 应用情境:

首先是第一种:句子分类判断。例如情绪分析,或是文章分类...等。
作法是将想要分类的句子输入 BERT 後,开头的地方再加一个代表分类的符号[CLS]。接下来再将该符号位置的输出丢给一个线性分类器,并由这个线性分类器去预测这个句子类别,而训练时我们只要微调 BERT 并训练分类器即可。


第二个任务是将句子中每个词的分类:输入一个句子,而句子里的每一个辞汇都要决定属於哪一个类别,例如 slot-filling。

而 BERT 的作法就是先输入一个句子,再将每个辞汇的输出都丢入线性分类器里面,让他去决定这个辞汇的所属类别。


第三种用法则是判断句子关系:输入2个句子 然後输出一个类别。例如 natural language inference(自然语言推理),要机器学会推论一句话,就是先给机器一个前提与架设,然後要机器根据前提与假设去推论对错,或者不知道。

如图中所示,先输入2个句子,然後在句子的起始处与相接处放入特殊符号[SEP],再将开头处的输出丢给线性分类器去判断 True/False 或者 unknown。


最後则是文章问答提取最佳解:大致上就是输入一篇文章,提出问题後再找出解答。

例如图中的问题,我们给定了文章 D 与问题 Q ,那我们有一个 QA model,而这个 QA model 就是输入一篇文章跟一个问题,然後输出2个整数 s 跟 e;而 s 与 e 代表现在答案落在文章的第 s 个辞汇~第 e 个辞汇中。假设图片中第一个答案为 gravity,而他是这篇文章中第17个字,则输出 s=17,e=17 答案就是 gravity。那这个问题套用到 BERT 要怎麽做呢?

  1. 首先将问题输入进去,然後给个分隔符号[SEP],再将文章输入进去。
  2. 接着,同时让模型学习两个向量(一橘一蓝),这2个向量的维度与黄色相同。
  3. 橘色的向量跟文章产出的向量做dot product(内积),会算出一个纯量(scalar)
  4. 将纯量通过 Softmax 後,每一个文章的辞汇都会得到一个分数
  5. 接下来看哪一个词汇得到的分数最高,例如图中最高分的辞汇是第二个,即 s = 2


而红色的向量决定了 s 是多少,那蓝色的向量则决定了 e 是多少。
同样的方法,将蓝色的向量与黄色的向量做内积,然後再透过Softmax 看谁算出的分数最高,例如图中第三个词汇算出来的词汇最高,则 e = 3。
那 s=2、e=3 就代表答案为文章的第2,第3个字,也就是"d2d3"。

那假设今天输出的是 s=3、e=2 的话就互相矛盾,则模型会输出此题无解。而橘色的向量跟蓝色的向量其实都是学出来的(与昨天介绍的 Self-Attention 内的 Query 、 Key 、 Value 一样),因此在训练的时候需要给机器很多的问题、文章跟答案坐落的地点来让机器去进行学习才行。


<<:  Day 29 - State Monad IV

>>:  DAY29 欸你Git来Hub一下

【额外分享】超深度铁人赛後自我审视

本文同步刊於 Medium 目录 前言 铁人赛 系列文提到的项目 比赛结束之後 区块链 近期规划 未...

【PHP Telegram Bot】Day26 - 入群欢迎机器人(2):设定欢迎讯息

如果欢迎讯息写死在程序里,临时想换还要把程序打开来改,改完还要测试,不如就直接让它能在群组里设定吧...

[Day 28]从零开始学习 JS 的连续-30 Days---BOM-浏览器物件模型(下)

BOM ( Browser Object Model ) 浏览器物件模型 BOM 核心是 windo...

DAY20 MongoDB Oplog 玩坏它

DAY20 MongoDB Oplog 玩坏它 把手弄脏,亲眼於本机见证节点同步跟不上 本篇的目的就...

Day8-安装Kind要在docker之後

从上一章了解各种K8s的特点,在这章将会教学如何安装Kind。 由於其利用docker的特性,会比使...