文章目录

  • Bert
    • 一、The Illustrated BERT
      • Example: Sentence Classification
      • Model Architecture
      • Model Inputs
      • Model Outputs
    • 二、Bert:一切过往,皆为序章
      • Bert语言模型任务一:Masked Language Model
      • BERT 语言模型任务二:Next Sentence Prediction
      • BERT的输出
      • Multi-Task Learning
      • Fine-Tuning
    • 参考

Bert

众所周知,谷歌开发的BERT,曾经被称为「地表最强」NLP模型。

而BERT,则与美国知名动画片「芝麻街」 (Sesame Street)里的虚拟人物同名。

一、The Illustrated BERT

There are a number of concepts one needs to be aware of to properly wrap one’s head around what BERT is. So let’s start by looking at ways you can use BERT before looking at the concepts involved in the model itself.

Example: Sentence Classification

使用 BERT 最直接的方法是用它来对单段文本进行分类。这个模型看起来像这样:

要训练这样的模型,我们主要训练分类器,在训练阶段对BERT模型进行微小地更改,这个训练过程称为微调

如果我们从监督学习的角度看待分类问题,我们需要一个带标签的数据集来训练这样的模型。对于这个垃圾邮件分类器而言,标记的数据集将是电子邮件列表和标签(“垃圾邮件”或“非垃圾邮件”)。

Model Architecture

现在我们已经有了一个关于如何使用Bert的例子,让我们仔细看看它是如何工作的

Bert基本上经过训练的Transformer Encoder

Bert Base和Bert Large都有大量的Encoder层(本文称之为Transformer Blocks)——Base版本有12个Transformer Blocks、Large版本有24个Transformer Blocks。相比于最初的Transformer,Bert中的前馈神经网络分别有768和1024个hidden unit,以及更多的attention heads(分别有12个和16个attention heads)

Model Inputs

第一个input token是一个特殊的[CLS] token,这里的[CLS]代表了分类

与Transformer的Encoder一样,Bert将一系列单词作为输入,这些作为输入的单词不断地向上流动,每一层都使用了Self-Attention,并通过前馈神经网络传递结果,然后将其传递给下一个Encoder

到目前为止,Bert在架构方面和Transformer完全相同

Model Outputs

每个位置输出一个大小为hidden_size的向量(在Bert Base中为768),对于上面的句子分类,我们只关注第一个位置的输出

Bert输出的第一个位置的向量可以用作我们的分类器的输入

二、Bert:一切过往,皆为序章

BERT 全称为 Bidirectional Encoder Representation from Transformer,是 Google 以无监督的方式利用大量无标注文本「炼成」的语言模型,其架构为 Transformer 中的 Encoder(BERT=Encoder of Transformer)

Bert 是传统语言模型的一种变形,而语言模型(Language Model, LM)做的事情就是在给定一些词汇的前提下, 去估计下一个词汇出现的概率分布

为什么要训练一个LM?因为有种种好处:

  • 好处1:无监督数据无限大,不像ImageNet还要找人标注数据,要训练LM 的话网络上所有文本都是你潜在的资料集
  • 好处2:厉害的LM 能够学会语法结构、解读语义甚至指代消解。透过特征撷取或是fine-tuning 能更有效率地训练下游任务并提升其表现
  • 好处3:减少处理不同NLP 任务所需的architecture engineering 成本

以往为了解决不同的NLP任务,我们会为该任务设计一个最适合的神经网络架构并做训练。不同的NLP任务通常需要不同的模型,如果能有一个能直接处理各式NLP任务的通用架构该有多好?Bert就是其中一个将此概念付诸于实践的例子

Bert 论文的作者们使用Transfomer Encoder、大量文本以及两个预训练目标,事先训练好一个可以套用到多个NLP 任务的Bert 模型,再以此为基础fine tune 多个下游任务。

这就是近来NLP 领域非常流行的两阶段迁移学习:

  • 先以LM Pretraining 的方式预先训练出一个对自然语言有一定「理解」的通用模型
  • 再将该模型拿来做特征撷取或是fine tune 下游的(监督式)任务

以往的预训练模型的结构会受到单向语言模型的限制(从左到右或者从右到左)的限制,因而也限制了模型的表征能力,是其只能获取单方向的上下文信息。而Bert利用Masked Language Model进行预训练并且采用双向Transformer组件(单向的Transformer一般被称为Transformer Decoder,其中每一个token只会attend到目前往左的token,而双向的Transformer则被称为Transformer Encoder,其每一个token都会attend到所有的token)来构建整个模型,因此最终能生成融合左右上下文信息的深层双向语言表示

上面这个示意图最重要的概念是预训练步骤跟fine-tuning 步骤所用的BERT 是一模一样的。当你学会使用Bert 就能用同个架构训练多种NLP 任务,大大减少自己设计模型的architecture engineering 成本

坏消息是,天下没有白吃的午餐。

要训练好一个有1.1 亿参数的12 层BERT-BASE得用16 个TPU chips跑上整整4 天,24 层的BERT-LARGE则有3.4 亿个参数,得用64 个TPU chips训练。喔对,别忘了多次实验得把这些成本乘上几倍

好消息是,Bert 作者们有开源了训练好的模型,只要使用TensorFlow或pytorch将已训练好的Bert 载入,就能省去预训练步骤的所有昂贵成本

Google在预训练Bert时让它同时进行两个任务:

  1. 完形填空,学术点的说法是 Masked Language Model
  2. 判断第 2 个句子在原始本文中是否跟第 1 个句子相接(Next Sentence Prediction

Bert语言模型任务一:Masked Language Model

在Bert中,Masked Language Model构建了语言模型,简单来说,就是随机遮盖或替换一句话里面的任意字或词,然后让模型通过上下文预测那一个被遮盖或替换的部分,之后做loss的时候也只计算被遮盖部分的loss。实际操作如下:

  1. 随机把一句话中 15% 的 token(字或词)替换成以下内容:

    • 这些 token 有 80% 的几率被替换成 [MASK],例如 my dog is hairy→my dog is [MASK]
    • 有 10% 的几率被替换成任意一个其它的 token,例如 my dog is hairy→my dog is apple
    • 有 10% 的几率原封不动,例如 my dog is hairy→my dog is hairy
  2. 之后让模型预测和还原被遮盖掉或替换掉的部分,计算损失的时候,只计算在第 1 步里被随机遮盖或替换的部分,其余部分不做损失,其余部分无论输出什么东西,都无所谓

这样做的好处是,BERT 并不知道 [MASK] 替换的是哪一个词,而且任何一个词都有可能是被替换掉的,比如它看到的 apple 可能是被替换的词。这样强迫模型在编码当前时刻词的时候不能太依赖当前的词,而要考虑它的上下文,甚至根据上下文进行 “纠错”。比如上面的例子中,模型在编码 apple 时,根据上下文 my dog is,应该把 apple 编码成 hairy 的语义而不是 apple 的语义

在Bert的Masked Language Model任务中,token分3种情况做mask,分别的作用是什么?

在Bert的Masked Language Model训练任务中,会对语料中15%的词进行mask,在这15%被mask的词中:

80%的token被替换为 [MASK]。意义:在不泄露label的情况下,通过被mask的单词的上下文,预测该单词,训练模型和词向量。问题:下游任务中不会出现 [MASK],导致预训练和微调不一致(这里很好解释:预训练的目标会令产生的语言表征对[MASK]敏感,但是却对其他token不敏感)

10% 的 token会被替换为随机的 token。意义:减弱了预训练和微调不一致给模型带来的影响。同时让模型知道,当单词不是[MASK]标记时,仍然需要输出,就迫使模型尽量在每一个token(即使该词不是mask)上都学习基于上下文的表示,这也是解决一词多义的关键。问题:模型可能会认为要预测的词永远不会是该位置原本的词。

10% 的 tokens 会保持不变但需要被预测:意义:让模型知道要预测的词有可能是该位置原本的词,而不是永远都是随机单词。

该策略使Bert不再只对[MASK]敏感,而是对所有的token都敏感,以致能抽取出任何token的表征信息。如果没有mask,该网络事先知道它需要预测什么,因此它可以很容地学习权值

BERT 语言模型任务二:Next Sentence Prediction

由于Bert是一个预训练模型,其必须要适应各种各样的自然语言任务,因此模型所输入的序列必须有能力包含一句话*(文本情感分类,序列标注任务)或者两句话以上(文本摘要,自然语言推断,问答任务)*。而Masked Language Model任务倾向于抽取token层次的表征,因此不能直接获取句子层次的表征。为了是模型能够有能力理解句子间的关系,Bert使用了Next Sentence Prediction任务来预训练,简单来说就是预测两个句子是否连在一起

我们首先拿到属于上下文的一对句子,也就是两个句子,之后我们要在这两个句子中加一些特殊的 token:[CLS]上一句话[SEP]下一句话[SEP]。也就是在句子开头加一个 [CLS],在两句话之间和句末加 [SEP],具体如下图所示:

可以看到,上图中的两句话明显是连续的。如果现在有这么一句话 [CLS]我的狗很可爱[SEP]企鹅不擅长飞行[SEP],可见这两句话就不是连续的。在实际训练中,我们会让这两种情况出现的数量为 1:1

具体做法:对于每一个训练样例,我们在语料库中挑选出句子A和句子B来组成,50%的时候句子B就是句子A的下一句,剩下50%的时候句子B是语料库中的随机句子

Token Embedding就是正常的词向量,即pytorch中的nn.Embedding()

Segment Embedding 的作用是用 embedding 的信息让模型分开上下句,我们给上句的 token 全 0,下句的 token 全 1,让模型得以判断上下句的起止位置,例如

[CLS]我的狗很可爱[SEP]企鹅不擅长飞行[SEP]

0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

Position Embedding 和 Transformer 中的不一样,不是三角函数,而是学习出来的

BERT的输出

Bert的特点:有多少个输入就有多少个对应的输出

C为分类token[CLS]对应最后一个Encoder的输出,Ti 则代表其他token对应最后一个Encoder的输出。对于一些token级别的任务*(如,序列标注和问答任务),就把Ti 输入到额外的输出层中进行预测;对于一些句子级别的任务(如,自然语言推断和情感分类任务)*,就把C输入到额外的输出层中,这里也就解释了为什么要在每一个token序列前都要插入特定的分类token[CLS]

Multi-Task Learning

把每一个训练样例输入到Bert中可以相应获得两个任务对应的loss,再把这两个loss加在一起就是整体的预训练loss。(也就是两个任务同时进行训练)

Input:
[CLS] calculus is a branch of math [SEP] panda is native to [MASK] central china [SEP]Targets: false, south
----------------------------------
Input:
[CLS] calculus is a [MASK] of math [SEP] it [MASK] developed by newton and leibniz [SEP]Targets: true, branch, was

可以明显地看出,这两个任务所需的数据其实都可以从无标签的文本数据中构建(自监督性质),比CV中需要人工标注的ImageNet数据集可简单多了

Fine-Tuning

Bert 的 Fine-Tuning 共分为 4 种类型

如果现在的任务是 classification,首先在输入句子的开头加一个代表分类的符号 [CLS],然后将该位置的 output,丢给 Linear Classifier,让其 predict 一个 class 即可。整个过程中 Linear Classifier 的参数是需要从头开始学习的,而 BERT 中的参数微调就可以了

这里使用第一个位置(即[CLS]位置)的output的原因:因为Bert内部是Transformer,而Transformer内部又是Self-Attention,所以[CLS]的output肯定含有整句话的完整信息,这是毋庸置疑的。但是Self-Attention向量中,自己和自己的值其实是占大头的,现在假设使用w1的output作分类,那么这个output中实际上会更加看重w1,而w1又是一个有实际意义的字或词,这样难免会影响到最终的结果。但是[CLS]是没有任何实际意义的,只是一个占位符而已,所以就算[CLS]的output中自己的值占大头也无所谓。当然我们也可以将所有词的output进行concat,作为最终的output

[CLS]对应的output被用来起到聚集整个序列表征信息的作用

如果现在的任务是将句子中各个字对应位置的output分别送入不同的Linear,预测出该字的标签,其实这本质上还是个分类问题,只不过是对每个字都要预测一个类别

如果现在的任务是 NLI(自然语言推理)。即给定一个前提,然后给出一个假设,模型要判断出这个假设是 正确、错误还是不知道。这本质上是一个三分类的问题,和 Case 1 差不多,对 [CLS] 的 output 进行预测即可

如果现在的任务是 QA(问答),举例来说,如上图,将一篇文章,和一个问题(这里的例子比较简单,答案一定会出现在文章中)送入模型中,模型会输出两个数 s,e,这两个数表示,这个问题的答案,落在文章的第 s 个词到第 e 个词。具体流程我们可以看下面这幅图

首先将问题和文章通过 [SEP] 分隔,送入 Bert 之后,得到上图中黄色的输出。此时我们还要训练两个 vector,即上图中橙色和蓝色的向量。首先将橙色和所有的黄色向量进行 dot product,然后通过 softmax,看哪一个输出的值最大,例如上图中 d2 对应的输出概率最大,那我们就认为 s=2

同样地,我们用蓝色的向量和所有黄色向量进行 dot product,最终预测得到 d3 的概率最大,因此 e=3。最终,答案就是 s=2,e=3

你可能会觉得这里面有个问题,假设最终的输出 s>e 怎么办,那不就矛盾了吗?其实在某些训练集里,有的问题就是没有答案的,因此此时的预测搞不好是对的,就是没有答案

Bert的优点:

  • 采用MLM对双向的Transformers进行预训练,以生成深层的双向语言表征
  • 预训练后,只需要添加一个额外的输出层进行fine-tune,就可以在各种各样的下游任务中取得state-of-the-art的表现。在这过程中并不需要对BERT进行任务特定的结构修改

参考

1、BERT知识点

2、BERT中,为什么已经有85%不被mask的单词,还需要在15%进行“mask策略”的单词中选取10%保持原词不变?

3、进击的Bert: NLP界的巨人之力与迁移学习

4、什么是BERT?

5、The Illustrated BERT, ELMo, and co. (How NLP Cracked Transfer Learning)

6、BERT 详解(附带 ELMo、GPT 介绍)

7、BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

Bert:一切过往,皆为序章相关推荐

  1. 2020总结:愿过往皆为序章,未来皆有可期

    2020 · 回顾告别 2020年是匆忙又坎坷的一年,突如其来的疫情,艰难的返程之路,接连不断的霉运,疲惫不堪的感情,生活好像突然变成了困难模式,充满了人民币玩家会员到期了的凄凉感. 年初从烟台回河北 ...

  2. 2021,一切过往皆为序章

    现在是北京时间 2021-01-09 10:07:59 ,回望上次写博客时间是 2017 年 3 月,至今有近 3 年没有写过博客. 这 3 年里,有得意也有失落.失落时,经历过 3 个月无业在家,找 ...

  3. 凡事过往 皆为序章 愿2020年所有美好 如期而至

    "成功的花,人们只惊羡它现时的明艳;而当初的芽,却浸透了奋斗的泪泉,洒满了牺牲的血雨."我们每个人都渴望成功,那么我们就应该在刚刚起步的时候, 用我们无悔的付出,去浇灌隔那刚刚萌芽 ...

  4. 2020 秋招总结:凡是过往,皆为序章

    点击我爱计算机视觉标星,更快获取CVML新技术 本文转载自AINLP.文末有近期CV招聘职位汇总. 作者:HardenHuang 研究方向:自然语言处理 知乎专栏:模型可解释性论文专栏 前言 文章更多 ...

  5. 所有过往、皆为序章:我的2021

    2021 生活 2021年,我用<道阻且长 行则将至>来总结和展望.2022年,我要说:所有过往.皆为序章. 2021年又波澜不惊的过去了,先简单回顾一下去年立的 flag,还是有得有失的 ...

  6. 凡是过往,皆为序章—写在2018年国基揭榜之时

    http://blog.sciencenet.cn/blog-699-1129950.html 2018年8月16日,2018年国家自然科学基金项目评审结果公布,得到资助者欢欣鼓舞,落败者安然伤神.以 ...

  7. 凡是过往,皆为序章;当下不负,未来展望【2021年终总结】

    Content (整个英文洋气洋气) I.[凡是过往,皆为序章] II.[当下不负] II.I 为什么从reader变成了writer(sharer) II.II 当下那点事 III.[未来展望] I ...

  8. 凡是过往,皆为序章。

    凡是过往,皆为序章 今天是元旦假期的最后一天,这三天我一直在想,21年的年终总结应该如何下笔.其实心里面想表达和记录的事情很多,可当真正坐在电脑前时,却发现没有头绪. 贵有恒,何必三更起五更眠.最无益 ...

  9. 凡是过往,皆为序章|Apache Doris 社区 2021 年终回顾

    时间转瞬即逝,2021 年已经进入倒计时. 感谢所有一直陪伴着 Apache Doris 的小伙伴们. 在过去一年,我们一起经历了 许多有意义的瞬间. 如果用几个关键词作为过去一年的总结 ,你心中的答 ...

最新文章

  1. 报错解决transmission: Error: Input/Output error和ls: reading directory '': Input/output error
  2. 【学习笔记】《数据挖掘:理论与算法》CH5 支持向量机
  3. 暴雪应该从《争霸艾泽拉斯》中吸取什么教训?
  4. BZOJ4543 POI2014 Hotel加强版 【长链剖分】【DP】*
  5. python 泰坦尼克号存活率分析
  6. django 不包括字段 序列化器_DRF比Django的认证和权限高在哪里
  7. 深入学习golang—channel
  8. SSL/TLS中的DH算法、DHE算法、 ECDHE算法介绍
  9. 深度学习 | 深度学习算法中英文对照表
  10. C++ 后台开发面试时一般考察什么?
  11. 项目管理工具——5W1H分析法
  12. Ubuntu16.04 与本地Win7共享文件夹
  13. 物品分类游戏html5,物品的用途分类教案
  14. Python小白的飞桨之旅
  15. ollvm编译出现的问题纪录
  16. idea中用rest风格发送delete,put请求报405(tomcat8)
  17. 制作CRM管理系统04(客户增加)
  18. java GUI SWING
  19. 2017年浙江工业大学大学生程序设计迎新赛热身赛-J-Forever97与寄信
  20. 【软考点点】软件开发模型

热门文章

  1. WeChatTweak-macOS 安装配置
  2. 复数类n次方原理以及C#代码实现
  3. 基于几何约束的传动机构设计
  4. HTML5+CSS大作业——个人简历设计(5页)
  5. AD18设置菜单为中文
  6. 爬虫实例:正则表达式爬取微博热搜榜
  7. 该网页无法正常运作 目前无法处理此请求HTTP ERROR 500
  8. python会计凭证_根据会计法律制度的规定,下列关于原始凭证的表述中,正确的是()。...
  9. CentOS 7添加硬盘扩展根目录空间
  10. linux ping 命令详解