【李沐精读系列】BERT精读

论文:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

参考:BERT论文逐段精读、李沐精读系列、李宏毅版BERT讲解

一、介绍

        BERT(Bidirectional EncoderRepresentation Transformer,双向Transformer编码器)。与最近的语言表示模型(ELMo,GPT)不同,BERT的所有层旨在通过联合训练左右上下文的方式从未标注文本中预训练深层的双向表征

        BERT是基于EMLo和GPT(单向的Transformer编码器)的。但是又与它们俩不同,区别如下:

  • BERT:设计用来训练深的双向表示,使用没有标号的数据,再联合左右的上下文信息。因为这样的设计导致训练好的BERT只用加一个额外的输出层,就可以在很多NLP的任务(比如问答、语言推理)上面得到一个不错的结果,而且不需要对任务做很多特别的架构上的改动
  • GPT:单向Transformer编码器(用左边的上下文信息去预测未来),BERT同时使用了左侧和右侧的信息,它是双向的(Bidirectional)。
  • ELMO:一个基于RNN的架构,BERT用的是transformer,所以ELMo在用到一些下游任务的时候需要对架构做一点点调整,但是BERT相对比较简单,和GPT一样只需要改最上层就可以了。

        问:BERT实际上是做什么的呢?

其中,上图中的词是代表word,对于中文来说用字更为恰当。潮水是一个词,潮和水是字(character)。

二、导论

        自然语言任务包括两类:

  • 句子层面的任务(sentence-level):主要是用来建模句子之间的关系,比如说对句子的情绪识别或者两个句子之间的关系。
  • 词元层面的任务(token-level):包括实体命名的识别(对每个词识别是不是实体命名,比如说人名、街道名),这些任务需要输出一些细粒度的词元层面上的输出。

在使用预训练模型特征表示的时候,一般有两类策略:

  • 一个策略是基于特征的(feature-based):代表作是ELMo,对每一个下游的任务构造一个跟这个任务相关的神经网络,它使用的RNN的架构,然后将预训练好的这些表示(比如说词嵌入也好,别的东西也好)作为一个额外的特征和输入一起输入进模型中,希望这些特征已经有了比较好的表示,所以导致模型训练起来相对来说比较容易,这也是NLP中使用预训练模型最常用的做法(把学到的特征和输入一起放进去作为一个很好的特征表达)。
  • 另一个策略是基于微调的(fine-tuning):这里举的是GPT的例子,把预训练好的模型放在下游任务的时候不需要改变太多,只需要改动一点就可以了。这个模型预训练好的参数会在下游的数据上再进行微调(所有的权重再根据新的数据集进行微调)。

        这两种方法在预训练的过程中都使用的是同一个目标函数,它们使用的都是单向的语言模型学习通用的语言表征,限制了预训练表示的能力,尤其是对于fine-tuning方法。 主要的限制是标准语言模型是单向的(语言模型是从前面的词预测后面的词),这样在选架构的时候有一些局限性。例如,在OpenAI GPT中,作者使用从左到右的体系结构,其中每个token只能参加Transformer的自注意层中的先前token。 这样的限制对于句子级任务不是最理想的,并且在将基于fine-tuning的方法应用于token级任务(例如问题回答)时可能非常不利,在这种情况下,双向整合上下文至关重要。

        BERT通过使用“遮蔽语言模型”(MLM,Masked Language Model)预训练目标,减轻了先前提到的单向语言模型限制 。(MLM相当于完形填空,左右信息都要看)遮蔽语言模型从输入中随机屏遮蔽了某些token,目的是仅根据其上下文来预测被遮蔽的单词(原始词表对应的id)。 与从左到右的语言模型预训练不同,MLM使语言表征能够融合上下文,这使得我们能够预训练深层双向Transformer模型。 除了遮蔽语言模型外,我们还使用“下一个句子预测”(NSP,Next Sentence Prediction)任务来联合预训练文本对表示(NSP判断两个句子是否相邻,第二句是否是第一句的下一句)。

        本文的贡献有三点:

  • 证明了双向预训练对于语言表示的重要性。1)与GPT不同,它使用单向语言模型进行预训练,BERT使用遮蔽语言模型来实现预训练的深度双向表示。2)与ELMo不同,后者独立训练的从左到右和从右到左的网络,然后进行简单的浅层连接。(BERT在双向信息的应用上更好)
  • 预训练好的语言表征,不需要再去针对特定的任务精心设计模型结构。BERT是第一个基于fine-tuning的表示模型,可在一系列sentence-level和token-level任务上实现最先进的性能,其性能优于许多任务特定的体系结构。
  • BERT推动了11项NLP任务的发展。 可以在BERT上找到代码和经过预先训练的模型。

        最主要贡献是将这些发现进一步推广到深层双向体系结构,使的同样的预训练模型能够成功解决各种NLP任务

三、Related work
3.1 基于特征的无监督方法(EMLo)

        阐述了讲词嵌入、ELMo等工作。这里我结合了李宏毅的视频稍微展开讲讲ELMo模型。

        上图描述的就是单纯RNN的训练机制。但这是从左到右单向的RNN的。下图是双向的RNN。

        但是这样就出现了一个问题,同一个词汇由于正向RNN和反向RNN的词嵌入不一样,那我应该选择哪一个词嵌入呢?EMLo全都要!

3.2 无监督的微调方法(GPT)

        代表是GPT

3.3 监督数据中的迁移学习

        自然语言推理(Conneau et al.,2017)和机器翻译(McCann et al.,2017)有很多大型的有监督数据集,在这些数据集上预训练好语言模型,再迁移到别的NLP任务上,效果是非常好的。计算机视觉研究还证明了从大型预训练模型进行迁移学习的重要性,其中有效的方法是对通过ImageNet预训练的模型进行微调。

四、BERT
4.1 框架        

        BERT的框架只要包含两个步骤:预训练和微调。

  • 预训练是在无标签数据集上训练的
  • 微调使用的也是BERT模型,其权重初始化为预训练权重。所有权重在微调时都会参与训练,微调时使用有标签的数据
  • 每个下游任务都会创建一个新的BERT模型,来训练自己的任务。

其中,[CLS]是在每个输入示例前添加的特殊符号,[SEP]是特殊的分隔符标记(例如,分隔问题/答案)。

问:为什么[CLS]放在开头,不可以放在结尾嘛?

        bert内部transformer的self-attention特色是天涯若比邻,两个相邻的word和两个距离很远的word对self-attention来说是没有差别的。如果不考虑positional encoding的影响,把一个token放在句子的开头或者句子的结尾对bert来说基本上没有影响。

4.1.1 模型结构

        BERT的模型架构是多层双向Transformer编码器,基于Vaswani等人描述的原始实现。并且我们的Transformers实现几乎与原始实现相同。

        在这项工作中,我们将层(即,Transformer块)的数量表示为L,将隐藏层的大小表示为H,并将自注意力头的数量表示为A。我们主要报告两种模型尺寸的结果:

BERT_{BASE}(L=12,H=768,A=12,Total \, Parameters=110M)

BERT_{LARGE}(L=24,H=1024,A=16,Total\, Parameters=340M)

其中,L:transformer块的个数;H:隐藏层的大小;A:自注意力机制中多头的头的个数 。

怎样把超参数换算成可学习参数的大小?

模型中可学习参数主要来自两块。

  • 嵌入层:就是一个矩阵,输入是字典的大小(假设是30k),输出等于隐藏单元的个数(假设是H)
  • Transformer块分为两部分:
    • 自注意力子层:Q、K、V分别通过一个参数矩阵(W^Q,W^K,W^V)进行投影,参数矩阵维度是H×H(其实是多头,但是合起来还是原始维度大小。投影前后维度不变,所以矩阵大小必须是H×H)。投影之后输出的多头注意力还会经过一个矩阵W^Q将其映射回H维。所以自注意力层一共四个参数矩阵,可学习的参数量是4H^2
    • MLP层:有两层,输入输出分别是[H,4H]和[4H,H],所以每一层参数是4H^2,两层就是8H^2
  • 总参数应该是30000\cdot H+L\cdot 12H^2,带入base的参数大概就是1.1亿。

4.1.2 模型的输入输出

        为了可以处理多种任务,BERT输入可以是一个句子,也可以是句子对。在整个工作中,“句子”可以是一段连续的文本,而不仅仅真正语义上的一句话。BERT的输入是一个标记序列,可以是一个或两个句子。

  Transformer输入是一个句子对,编码器和解码器分别输入一个句子。而BERT只有编码器,要处理两个句子只能将其并为一个序列。
  BERT如果使用空格切词,一个词是一个token。BERT的训练数据量是非常大的,那么词表大小也会特别大,比如百万级别。那么根据上面的算法,模型的可学习参数基本都在词嵌入部分。
  WordPiece原理就是,一个词在数据集中出现的概率不大,那么就把它切开成子序列。如果子序列(很可能是词根)出现的概率很大的话,那么只保留这个子序列就行。这样就可以把比较长的词切成一些经常出现的片段。这样词表的大小相对来说比较小。

  BERT使用3w个词表的WordPiece embeddings。每个输入序列的第一个标记始终是一个特殊的分类标记([CLS],代表classification),BERT希望CLS对应的最终输出可以代表整个序列的信息。(自注意力可以同时看到所有词,所以CLS放在句首是没问题的,不一定非要在句尾)。

        句子对可以合在一起输入,但是为了做句子级别的任务,所以需要区分这两个句子,有两个办法:

  • 句尾加上特殊词[SEP]来分隔(表示separate)
  • 在词嵌入层用一个可学习的向量来表示每个token是属于句子A还是句子B。
  • 在下图中,画出了大概示意。我们用E表示输入embedding,用C\in \mathbb{R}^H来表示特殊token[CLS]的最终隐向量,用T_i\in \mathbb{R}^H来表示第i个输入token的最终隐向量。

        对于给定的token,它的输入表征是由token,segment,和 position embeddings相加构成的。这种结构的可视化效果如下。

        Transformer中位置信息是通过位置编码(cos函数)来得到的,而这里的位置信息和句子信息都是通过embedding学出来的。

4.2 BERT预训练(MLM+NSP)
4.2.1 MLM,Masked Language Model

        对于一个token序列,我们随机屏蔽了每个序列中15%的WordPiece token,将其替换为[MASK](CLS和SEP不做替换)。 这带来的一个问题是,微调时数据中是没有[MASK]的。预训练和微调时看到的数据有点不一样。为了缓解这种情况,我们并不总是用实际的[mask]标记替换“masked”词。
  如果某个token被选中masked,那么有80%的概率这个token真的被替换为[MASK];10%的概率将其替换为一个随机token(噪音),另外10%保持不变(真实数据,但是这个位置也要预测)。

问:BERT怎么填回被替换为[MASK]的词呢?

4.2.2 NSP,Next Sentence Prediction

        在QA和自然语言推理中都是句子对,如果让它学习一些句子层面的信息也不错,具体来说,一个输入序列里面有两个句子:a和b,有50的概率b在原文中间真的是在a的后面,还有50%的概率b就是随机从别的地方选取出来的句子,这就意味着有50%的样本是正例(两个句子是相邻的关系),50%的样本是负例(两个句子没有太大的关系),加入这个目标函数能够极大地提升在QA和自然语言推理的效果。

问:BERT怎么判断输入的两个句子是不是相接的关系?

根据Linear Binary Classifier来处理。

利用BERT的四个案例。

案例一:输入一个句子分类。

案例二:输入一个句子,给句子中的每个词进行分类。

案例三:根据输入的前提,判断假设是对的、错的还是无法判断。

案例四:给BERT读一篇文章,问它问题,希望它给出答案(问的问题一定可以在文章中找到)

        如果没有s,只有e那么就是此题无解。

4.3 BERT微调

问:BERT和一些基于编码器解码器的架构有什么不同?

  • transformer是编码器解码器架构
  • 因为把整个句子对都放在一起放进去了,所以自注意力能够在两端之间相互能够看到,但是在编码器解码器这个架构中,编码器一般是看不到解码器的东西的,所以BERT在这一块会更好一点,但是实际上也付出了一定的代价(不能像transformer一样能够做机器翻译)

在做下游任务的时候会根据任务设计任务相关的输入和输出,好处是模型其实不需要做大的改动,主要是怎么样把输入改成所要的那个句子对。

  • 如果真的有两个句子的话就是句子a和b
  • 如果只有一个句子的话,比如说要做一个句子的分类,b就没有了

然后根据下游的任务要求,要么是拿到第一个词元对应的输出做分类或者是拿到对应的词元的输出做所想要的输出,不管怎么样都是在最后加一个输出层,然后用一个softnax得到想要的标号。

五、结论

        BERT使用Transformer的编码器而不是解码器,好处是可以训练双向语言模型,在语言理解类的任务上表现比GPT更好,但缺点是,做生成类的任务不方便,比如机器翻译、摘要生成等等。只不过NLP领域,分类啊之类的语言理解任务多一些,所以大家更喜欢用BERT。(也就是BERT屠榜)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/436522.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JAVA 用二分法查找数组中是否存在某个值

二分法查找的概念 二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。首先,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成…

pinia报错does not provide an export named ‘hasInjectionContext

你们好,我是金金金。 场景 我这里是uniappvue3编写的一个小程序项目,在集成pinia过程当中遇到此问题,报错请求的模块 未提供 导出名hasInjectionContext(位于 pinia.mjs:6:10) 以下我项目当中vue和pinia的具体依赖版本…

selenium等待机制

selenium等待机制 影响元素加载的外部因素1.计算机的性能2.服务器的性能3.浏览器的性能4.网络因素 强制等待1.强制等待2.页面加载超时机制 隐性等待显性等待1.WebDriverWait类2.WebDriverWait类提供的方法untileuntile_not显性等待的语法格式 3.expected_conditions模块方法exp…

「Mybatis深入三」:高级查询-模糊查询

一、需求 根据username 模糊查询user 表 二、代码演示 1、方式1 数据库环境 CREATE DATABASE mybatis_db; USE mybatis_db; CREATE TABLE user (id INT(11) NOT NULL AUTO_INCREMENT,username VARCHAR(32) NOT NULL COMMENT 用户名称,birthday DATETIME DEFAULT NULL COMMEN…

Java开发从入门到精通(一):Java的基础语法进阶

Java大数据开发和安全开发 (一)Java注释符1.1 单行注释 //1.2 多行注释 /* */1.3 文档注释 /** */1.4 各种注释区别1.5 注释的特点1.5 注释的快捷键 (二)Java的字面量(三)Java的变量3.1 认识变量3.2 为什么…

【宏观经济】全国各地级市及上市公司“信息惠民国家试点”DID(2010-2024)

数据说明:信息惠民国家试点城市是,2014年6月23日,根据国家发改委网站发布的通知,国家发展改革委等12部门决定的,将全国80个城市列为信息惠民国家试点城市。推进信息惠民国家试点城市建设,有利于加快提升公共…

vue+Nodejs+Koa搭建前后端系统(九)-- 上传图片

web2.0的到来使网页世界正式进入了寒武纪,各式各样的多媒体资源屡见不鲜,上传资源变得刻不容缓! 前言 本文是在该系列的基础上,针对前后端代码的修改。 准备 HTTP上传图片时Content-Type值常见的有2种:application…

Django模型层(附带test环境)

Django模型层(附带test环境) 目录 Django模型层(附带test环境)开启测试环境数据的增加数据的删除修改数据查询数据查询所有数据去重查询排序查询统计剔除指定数据多表查询校验数据是否存在字段的筛选查询 开启测试环境 首先在app下找到tests.py文件并进入 MyDJ.settings要换成…

【QA-SYSTEMS】CANTATA-解决Jenkins中build Cantata报错

【更多软件使用问题请点击亿道电子官方网站查询】 1、 文档目标 解决Jenkins中build Cantata测试项目报找不到license server的错误。 2、 问题场景 在Jenkins中build Cantata测试项目,报错“Failed to figure out the license server correctly”。 3、软硬件环…

虚拟化相关面试题集锦(0)—— 引言

经常关注博主的朋友应该能够发现,我近期开始在虚拟化尤其是QEMU/KVM上下功夫。这是由于我个人非常看好这个方向,把它当作今后的学习和工作的战略目标,同时也是个人非常喜欢和感兴趣的课题。 笔者看好虚拟化的原因是当前云计算已经如日中天&a…

短视频矩阵系统----矩阵系统源码搭建(技术门槛?)

短视频矩阵是什么意思?短视频矩阵的含义可以理解为全方位的短视频账号,通过不同的账号实现全方位的品牌展示。实际上是指一个短视频账号,通过不同的链接实现品牌展示,在不同的粉丝流量账号中互相转发同一个品牌,在主账…

05 | 深入浅出索引(下)

在上一篇文章中,我和你介绍了 InnoDB 索引的数据结构模型,今天我们再继续聊聊跟 MySQL 索引有关的概念。 在开始这篇文章之前,我们先来看一下这个问题: 在下面这个表 T 中,如果我执行 select * from T where k betwe…

022—pandas 根据时间段转换为各小时的秒数

前言 本例中,有一些时间段数据,需要将这些时间段里的时间以小时为分组,将24个小时段中每个小时所占用的秒数计算出来。 需求: 以第一条数据为例,它所在两个小时,7点段占用24分钟15秒,8点段54…

大数据组件之Hadoop图文介绍

前言 在当今大数据时代,回顾技术发展历程,Hadoop作为一项具有里程碑意义的开源项目,在大数据存储和处理领域曾一度占据主导地位。诞生于2005年的Apache Hadoop,以其独特的分布式文件系统(HDFS)和高效的并行…

遗传算法理解与代码实战(一)- demo(python手写代码)

遗传算法(Genetic Algorithm, GA)是模拟自然界中生物进化的机制来搜索最优解的方法。遗传算法属于进化计算的一部分,它借鉴了达尔文的自然选择和孟德尔的遗传学原理。 1、算法背景 遗传算法的灵感来源于生物进化过程。在自然界中&#xff0…

string 的模拟实现

string 的相关介绍:C:string相关内容的简单介绍-CSDN博客 成员变量: private:char* _strsize_t _sizesize_t _capacity 构造函数 string类的构造函数不仅需要完成空间的开辟,还需要再开辟的过程中完成字符串的拷贝,它…

ThreadLocal在实际开发中如何使用?

在实际开发中,ThreadLocal 是一个非常有用的工具,用于解决多线程环境下数据隔离和线程上下文数据的问题。以下是一个关于 ThreadLocal 在实际开发中使用的详细讲解,包括其工作原理、应用场景和实战例子。 1. 工作原理 ThreadLocal 类…

Mybatis从入门到CRUD到分页到日志到Lombok到动态SQL再到缓存

Mybatis 入门 1.导入maven依赖 <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>x.x.x</version> </dependency>2.配置核心文件 <?xml version"1.0" encoding"U…

FISCO BCOS区块链平台上的智能合约压力测试指南

引言 在当今的分布式系统中&#xff0c;区块链技术因其去中心化、安全性和透明性而备受关注。随着区块链应用的不断扩展&#xff0c;对其性能和稳定性的要求也越来越高。因此&#xff0c;对区块链网络进行压力测试显得尤为重要。 目录 引言 1. 配置FISCO BCOS节点 2. 安装和…

Linux内核源码分析(强烈推荐收藏!)

一&#xff0c;前言 Linux内核是一个操作系统&#xff08;OS&#xff09;内核&#xff0c;本质上定义为类Unix。它用于不同的操作系统&#xff0c;主要是以不同的Linux发行版的形式。Linux内核是第一个真正完整且突出的免费和开源软件示例。Linux 内核是第一个真正完整且突出的…