从论文理解BERT模型

BERT模型出自该论文:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

在论文中,作者对BERT的名称做出这样的解释——Bidirectional Encoder Representations from Transformers. 那么顾名思义,BERT可能是由来自Transformer模型中的双向Encoder编码器并组成。事实上,确实是这样的。

BERT采取的运行模式

与Transformer直接用数据进行训练不同的是,BERT模型采用了预训练(Pre-training)和微调(Fine-tuning)的方式。

论文中简单介绍了三种一般预训练语言表示:

  • Unsupervised Feature-based Approaches
    (基于无监督特征的方法)
  • Unsupervised Fine-tuning Approaches
    (无监督微调方法)
  • Transfer Learning from Supervised Data
    (从监督数据迁移学习)

监督和无监督是机器学习中的一个概念,如果数据集中是带有Label标签的那么则称为监督;如果不带任何标签则是无监督。

BERT采取的是第二种无监督微调方法。
具体方法是将整体的模型先在大量无标签的文本数据中进行训练,得到预训练模型。
之后针对下游任务(downstream task),此时由于每个任务都是不同的(比如:单句分类、问答任务…),再进行有监督的数据训练,从而进行参数的微调。

这样做的优点是,很少有参数需要从头训练。节省时间的同时也提高了准确率。

原文:
The advantage of these approaches is that few parameters need to be learned from scratch. At least partly due to this advantage, OpenAI GPT achieved previously state-of-the-art results on many sentencelevel tasks from the GLUE benchmark.

F1

BERT模型

BERT模型主要分为三个部分:(这里根据的是BERT的代码实现,在论文中没有提及)

  • Embedding
  • Encoder
  • Pooler(应该是可选的,在论文中没找到…)

其中,Encoder部分正如作者说的一样,同Attention is all you need这篇文章中的Encoder部分完全相同,不过采用了很多个Encoder进行堆叠。

BERT

Embedding

从模型图中看出,词嵌入的数据不那么简单,是三个embedding的相加:

  1. WordPiece Embeddings
  2. Segment Embeddings
  3. Position Embeddings
    Embedding

WordPiece

由于BERT的设计是用来处理各种下游任务的,在输入上(token sequence)需要能够明确表示每个句子(sentence)。不过,这里的sentence不同于自然语言中的句子,不单单是一句话。由于支持了上下文长序列,这里的sentence可以是多条句子的组合,也可以是文章中的一段或几段。

但是!前面不是提过需要预训练大量的数据吗?也就是意味着token sequence中有着海量的词,由于下文相关的其他embedding是进行学习的,如果这样,那就会导致整个模型要学习的参数大部分集中在数据预处理部分,这显然是不利的。因而需要提出全新的分词方法。

WordPiece将单词划分成一组有限的公共集合(词汇表),其中最小的token并不是单个英文词本身,而是更细粒度的切分。这个词汇表的限制大小为30000,所以只是尽可能添加最常用的单词和子单词。但是这个词汇表这样就可以表示出所有的词了吗?它是如何做到的?

词汇表中包含的元素有以下几种:

  • 单词本身
    整个单词足够常见,会直接出现在词典中。
  • 被切分的子单词(单词开头)和独立单词
    切分:按照一定规则对单个单词进行切分,并加以开头与否的区分。比如:tradition被划分为 tra、##di、##tion三个token。(##表示非完整单词,而是某个单词的非开头部分)
  • 被切分的子单词(以##开头)
  • 单个字符

那这种方法为什么可以表示出每个单词呢?

具体的切分规则如下:

  1. 分词器对整个单词进行检测,是否在词汇表中。
  2. 如果没有,尝试将单词分解为词汇表中包含的尽可能多的子单词。
  3. 最后将单词分解为单个字符。

这样下来,几乎可以表示每一个单词。
值得一提的是,词汇表中没有NLP中常用的标记符<UNK>等,对于词汇表中没有的词,将其分解为子单词,利用子单词生成嵌入向量,就可以获得原始单词的近似向量。
当然,论文提到了几个新的token。
<CLS>:作为每个sentense的开始,通常标识着分类任务,如果不是分类任务可以去掉。
<SEP>:作为sentense内部的分隔符。

Segment

这里就是分割的意思,表明token是来自哪一个句子的。

Position

token在句子中的位置。
不同于Transformer中的正弦函数表示,而这里的Position是一个固定值。
另外,Transformer中这个编码是通过手动构造矩阵获得的,而BERT中是通过学习获得的。

Pre-training

BERT的名称中第一个字母的含义就是Bidirectional,那么肯定是在双向上做了一些改动的。

既然BERT不采用传统从左到右或者从右到左的模型来训练,是不是意味着每一个数据可以看到它前方和后方的数据,这样不就可以轻松通过直接间接的方式来预测目标单词了吗?那在这样透明的环境中用什么方法去训练呢?

论文中提及的方式是完形填空(Cloze task)类的方法。

训练方式

  • Masked LM(MLM
  • Next Sentence Prediction (NSP)

MLM

将输入单词(input token)按照一定比例,随机进行隐藏(masked),将选中的单词替换成特殊的token [MASK]。随后处理后的序列送入模型,将最后得到的隐藏层向量(其实就是输出结果)经过softmax后与词汇表进行对比。

这样其实就进行了一个完形填空方式的预测单词任务。
论文中使用的比例是15%。

当然,仅仅这么做是不够的。

如果这么做,预训练部分和微调部分其实是不匹配的。因为[MASK]在微调的过程中是不出现的。为了解决这个问题,论文作者用了以下的办法:

  1. 还是按比例选择token,比例为15%。
  2. 如果选中了token:
    • 80%概率 用[MASK]进行替代。
    • 10%概率 在词汇表中选择一个随机的token。
    • 10%概率 保留原token。

可以看到论文中对此做出的例子解释:
在这里插入图片描述

个人认为,随机替换的目的是为了抑制过拟合。并且作者在论文中提到,这样的随机替换只占到了所有内容的1.5%,并不会对模型的语言理解能力造成较大的影响。

NSP

当BERT运用在QA问题和语义推断上的问题时,就需要理解两个句子之间的关系。
而已有的MLM并不能获取句子与句子之间的关系,所以采用NSP进行预训练。

具体做法如下:
对于每一个训练样例,在语料库中挑出句子A和B来组成。

  • 50%的时候,挑选连贯的句子即B就是A的下一句(标注为IsNext)
  • 50%的时候,句子B为语料库中的随机句子(标注为NotNext)

由于[CLS]是每个句子的开头,所以[CLS]中学习了句子与句子之间的关系,在Figure1中是C。这样就解决了句子层次间的问题。

Fine-tuning

微调任务是直接的,因为Transformer中的自注意机制允许BERT对许多下游任务进行建模,无论这些任务设计单个文本还是文本对,只需要通过更改适当的输入和输出。

这是论文中给出的在不同下游任务的说明。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值