论⽂解读:Bert原理深⼊浅出
Bert ⾃ Google 于 2018 年发表⾄今,⼀直给⼈们带来惊喜,期间也陆陆续续因为Bert出现的原因多了不少新的岗位,甚⾄公司 JD 上都明确表明必须懂 Bert。
它在 11 项⾃然语⾔处理任务中均表现出惊⼈的成绩:包括将 GLUE 基准推⾄ 80.4%(绝对改进率7.6%),MultiNLI 精度达到 86.7%(绝对改进 5.6%)和 SQuAD v1.1 问题回答测试 F1 到93.2。
res.png
⾕歌团队的 Thang Luong 直接定义:BERT 模型开启了 NLP 的新时代!
Bert 能有这么好的效果,深⼊其原理本⾝,⼜究竟好在哪⾥?
Bert是什么?
BERT,全称是 Bidirectional Encoder Representation from Transformers,基于语义理解的深度双向预训练Transformer。
要理解 Bert,5 个关键词帮你理解其思想,分别是 Pre-training、Deep、Bidirectional、Transformer、Language Understanding。
Deep
Bert 与 Transformer 不同,Bert 的神经⽹络层更深,意味着它能更准确表达语义的理解,提取更多特征。
Bidirectional
BERT 被设计成⼀个深度双向模型,使得神经⽹络更有效地从第⼀层本⾝⼀直到最后⼀层捕获来⾃⽬标词的左右上下⽂的信息。
传统上,我们要么训练语⾔模型预测句⼦中的下⼀个单词( GPT 中使⽤的从右到左的上下⽂),要么训练语⾔模型预测从左到右的上下⽂。这使得我们的模型容易由于信息丢失⽽产⽣错误。
Transformer
Bert 是基于 Tranformer 的深度双向语⾔表征模型,也就是利⽤ Transformer 结构构造了⼀个多层双向的Encoder ⽹络。它的特点之⼀就是所有层都联合上下⽂语境进⾏预训练。
Bert 的⽬标是⽣成预训练语⾔模型,所以只需要 Encoder 机制。Transformer 的 Encoder 是⼀次性读取整个⽂本序列,⽽不是从左到右或者从右到左按顺序读取。
Pre-training
pre-training 的意思是,作者认为,确实存在通⽤的语⾔模型,先⽤⼤量数据预训练⼀个通⽤模型,然后再微调模型,使其适⽤于下游任务。为了区别于针对语⾔⽣成的 Language Model,作者给通⽤的语⾔模型,取了⼀个名字,叫语⾔表征模型 Language Representation Model。
深度学习就是表征学习,⼤多只在预训练表征微调的基础上加⼀个线性分类器作为输出就可以完成下游任务。
Language Understanding
Bert 是⼀个语⾔表征模型,能实现语⾔表征⽬标训练,通过深度双向 Transformer 模型达到语义理解的⽬的。
整合以上特点,我们就可以很直观的理解 Bert,Bert 是⼀个⽤ Transformer 作为特征抽取器的深度双向预训练语⾔理解模型。Bert 就是⼀个预训练模型,利⽤双向 Transformer,通过⼤量数据训练⼀个语⾔表征模型,这是⼀个通⽤模型,通过对其微调来适⽤下游任务,包括分类,回归,机器翻译,问答系统等等任务。
深⼊理解Bert⼯作原理
bert.png
Bert 的模型结构如图左边第⼀个,Bert 采⽤了 Transformer Encoder,也就是每时每刻的Attention 计算都能够得到全部时刻的输⼊。
OpenAI GPT 采⽤ Transformer 的 Decoder,每个时刻的 Attention 计算只能依赖于该时刻前的所有时刻的输⼊,因为 OpenAI GPT 是单向语⾔模型。
ELMO 则采⽤的是 LSTM,这个模型虽然可以学习到前后语义,但是输出依赖于前⾯的输⼊,决定了 EMLO 的⽹络层数不会太多,会造成⼤量耗时,这就决定了 ELMO 提取的特征有限。
redditBert的输⼊有什么不同
Bert 的输⼊相较其它模型,采⽤了三个 Embedding 相加的⽅式,通过加⼊ Token Embeddings,Segment Embeddings,Position Embeddings 三个向量,以此达到预训练和预测下⼀句的⽬的。
input.png
如上图,Bert 的输⼊ Input 是两个句⼦:"my dog is cute","he likes playing"。⾸先会在第⼀句开头加上特殊Token [CLS] ⽤于标记句⼦开始,⽤ [SEP] 标记句⼦结束。
然后对每个 Token 进⾏ 3 个 Embedding,词的 Embedding (Token Embeddings),位置Embedding (Position Embeddings),句⼦ Embedding (Segment Embeddings)。最终将三个Embedding 求和的⽅式输⼊到下⼀层。
下⾯详细介绍下三个 Embedding。
Token Embeddings
通过建⽴字向量表将每个字转换成⼀个⼀维向量,作为模型输⼊。特别的,英⽂词汇会做更细粒度的切分,⽐如playing 或切割成 play 和 ##ing,中⽂⽬前尚未对输⼊⽂本进⾏分词,直接对单⼦构成为本的输⼊单位。将词切割成更细粒度的 Word Piece 是为了解决未登录词的常见⽅法。
假如输⼊⽂本 ”I like dog“。下图则为 Token Embeddings 层实现过程。输⼊⽂本在送⼊ Token Embeddings 层之前要先进性 tokenization 处理,且两个特殊的 Token 会插⼊在⽂本开头 [CLS]和结尾 [SEP]。
Bert 在处理英⽂⽂本时只需要 30522 个词,Token Embeddings 层会将每个词转换成 768 维向量,例⼦中 5 个Token 会被转换成⼀个 (6, 768) 的矩阵或 (1, 6, 768) 的张量。
token.png
Segment Embedding
Bert 能够处理句⼦对的分类任务,这类任务就是判断两个⽂本是否是语义相似的。句⼦对中的两个句⼦被简单的拼接在⼀起后送⼊模型中,Bert 如何区分⼀个句⼦对是两个句⼦呢?答案就是 Segment Embeddings。
Segement Embeddings 层有两种向量表⽰,前⼀个向量是把 0 赋值给第⼀个句⼦的各个Token,后⼀个向量是把1赋值给各个 Token,问答系统等任务要预测下⼀句,因此输⼊是有关联的句⼦。⽽⽂本分类只有⼀个句⼦,那么 Segement embeddings 就全部是 0。segment.png
Position Embedding
由于出现在⽂本不同位置的字/词所携带的语义信息存在差异(如 ”你爱我“ 和 ”我爱你“),你和我虽然都和爱字很接近,但是位置不同,表⽰的含义不同。
在 RNN 中,第⼆个 ”I“ 和第⼀个 ”I“ 表达的意义不⼀样,因为它们的隐状态不⼀样。对第⼆个 ”I“
来说,隐状态经过 ”I think therefore“ 三个词,包含了前⾯三个词的信息,⽽第⼀个 ”I“ 只是⼀个初始值。因此,RNN 的隐状态保证在不同位置上相同的词有不同的输出向量表⽰。
RNN.png
RNN 能够让模型隐式的编码序列的顺序信息,相⽐之下,Transformer 的⾃注意⼒层 (Self-Attention) 对不同位置出现相同词给出的是同样的输出向量表⽰。尽管 Transformer 中两个 ”I“ 在不同的位置上,但是表⽰的向量是相同的。
bert.png
Transformer 中通过植⼊关于 Token 的相对位置或者绝对位置信息来表⽰序列的顺序信息。作者测试⽤学习的⽅法来得到 Position Embeddings,最终发现固定位置和相对位置效果差不多,所以最后⽤的是固定位置的,⽽正弦可以处理更长的 Sequence,且可以⽤前⾯位置的值线性表⽰后⾯的位置。
偶数位置,使⽤正弦编码,奇数位置,使⽤余弦编码。
pos.png
sin.png
Bert 中处理的最长序列是 512 个 Token,长度超过 512 会被截取,Bert 在各个位置上学习⼀个向量来表⽰序列顺序的信息编码进来,这意味着 Position Embeddings 实际上是⼀个 (512, 768)的 lookup 表,表第⼀⾏是代表第⼀个序列的每个位置,第⼆⾏代表序列第⼆个位置。
最后,Bert 模型将 Token Embeddings (1, n, 768) + Segment Embeddings(1, n, 768) + Position Embeddings(1, n, 768) 求和的⽅式得到⼀个 Embedding(1, n, 768) 作为模型的输⼊。
任务1:Masked Language Model
Maked LM 是为了解决单向信息问题,现有的语⾔模型的问题在于,没有同时利⽤双向信息,如ELMO 号称是双向LM,但实际上是两个单向 RNN 构成的语⾔模型的拼接,由于时间序列的关系,RNN模型预测当前词只依赖前⾯出现过的词,对于后⾯的信息⽆从得知。
那么如何同时利⽤好前⾯的词和后⾯的词的语义呢?Bert 提出 Masked Language Model,也就是随机遮住句⼦中部分 Token,模型再去通过上下⽂语义去预测 Masked 的词,通过调整模型的参数使得模型预测正确率尽可能⼤。
怎么理解这⼀逻辑,Bert 预训练过程就是模仿我们学习语⾔的过程,要准确的理解⼀个句⼦或⼀段⽂本的语义,就要学习上下⽂关系,从上下⽂语义来推测空缺单词的含义。⽽ Bert 的做法模拟了英语中的完形填空,随机将⼀些单词遮住,让 Bert 模型去预测这个单词,以此达到学习整个⽂本语义的⽬的。
那么 Bert 如何做到”完形填空“的呢?
随机 mask 预料中 15% 的 Token,然后预测 [MASK] Token,与 masked token 对应的最终隐藏向量被
输⼊到词汇表上的 softmax 层中。这虽然确实能训练⼀个双向预训练模型,但这种⽅法有个缺点,因为在预训练过程中随机 [MASK] Token 由于每次都是全部 mask,预训练期间会记住这些 MASK 信息,但是在fine-tune期间从未看到过 [MASK] Token,导致预训练和 fine-tune 信息不匹配。
⽽为了解决预训练和 fine-tune 信息不匹配,Bert 并不总是⽤实际的 [MASK] Token 替换masked 词汇。
my dog is hairy → my dog is [MASK] 80%选中的词⽤[MASK]代替
my dog is hairy → my dog is apple  10%将选中的词⽤任意词代替
my dog is hairy → my dog is hairy  10%选中的词不发⽣变化
为什么 15% 的 Token 不完全 MASK?如果只有 MASK,这个预训练模型是有偏置的,也就是只能学到⼀种⽅式,⽤上下⽂去预测⼀个词,这导致 fine-tune 丢失⼀部分信息。
加上 10% 的随机词和 10% 的真实值是让模型知道,每个词都有意义,除了要学习上下⽂信息,还需要提防每个词,因为每个词都不⼀定是对的,对于 Bert 来说,每个词都需要很好的理解和预测。
有些⼈会疑惑,加了随机 Token,会让模型产⽣疑惑,从⽽不能学到真实的语义吗?对于⼈来
说,完形填空都不⼀定能做对,⽽将⽂本中某些词随机替换,更是难以理解,从概率⾓度来说,随机 Token 占⽐只有 15% * 10% = 1.5%,预料⾜够的情况下,这并不会影响模型的性能。
因为 [MASK] Token 占⽐变⼩,且预测难度加⼤的原因,所以 MASK 会花更多时间。
任务2:Next Sentence Prediction
在许多下游任务中,如问答系统 QA 和⾃然语⾔推理 NLI,都是建⽴在理解两个⽂本句⼦之间的关系基础上,这不是语⾔模型能直接捕捉到的。
为了训练⼀个理解句⼦关系的模型,作者提出 Next Sentence Prediction,也即是预训练⼀个下⼀句预测的⼆分类任务,这个任务就是每次训练前都会从语料库中随机选择句⼦ A 和句⼦
B,50% 是正确的相邻的句⼦,50% 是随机选取的⼀个句⼦,这个任务在预训练中能达到 97%-98% 的准确率,并且能很显著的提⾼ QA 和 NLI 的效果。
Input = [CLS] the man went to [MASK] store [SEP]
he bought a gallon [MASK] milk [SEP]
Label = IsNext
Input = [CLS] the man [MASK] to the store [SEP]
penguin [MASK] are flight ##less birds [SEP]
Label = NotNext
模型通过对 Masked LM 任务和 Next Sentence Prediction 任务进⾏联合训练,使模型输出的每个字 / 词的向量表⽰都能尽可能全⾯、准确地刻画输⼊⽂本(单句或语句对)的整体信息,为后续的微调任务提供更好的模型参数初始值。
Bert如何实现fine-tune
fine-tune.png
fine-tune 就是指在已经训练好的语⾔模型基础上,使⽤有标签的数据对参数进⾏调整,使其更好的适⽤于下游任务。如对于分类问题在语⾔模型基础上加⼀层 softmax ⽹络,然后再新的预料上重新训练进⾏ fine-tune。
Bert的主要贡献
Bert 采⽤深度双向 Transformer 语⾔模型,通过 Mask LM 来达到训练深度双向预训练模型,较之前使⽤单向语⾔模型训练更准确,信息量更⼤,且语义理解更准确。
论⽂表明,预训练模型能省去特定⼯程需要修改体系架构的⿇烦,Bert 是第⼀个基于 fine-tune 的语⾔模型,它在⼤量句⼦级和 Token 级任务上展现了很好的性能。
Bert 的成功,⼀个重要原因就是数据量⼤,计算资源丰富。BERT 训练数据采⽤了英⽂的开源语料 BooksCropus以及英⽂数据,⼀共有 33 亿个词。同时 BERT 模型的标准版本有1 亿的参数量,与 GPT 持平,⽽ BERT的⼤号版本有 3 亿多参数量,这应该是⽬前⾃然语⾔处理中最⼤的预训练模型了。
当然,这么⼤的模型和这么多的数据,训练的代价也是不菲的。⾕歌⽤了 16 个⾃⼰的 TPU 集(⼀共 64 块 TPU)来训练⼤号版本的 BERT,⼀共花了 4 天的时间。
对于是否可以复现预训练,作者在 Reddit 上有⼀个⼤致的回复,指出 OpenAI 当时训练GPT⽤了将近 1 个⽉的时间,⽽如果⽤同等的硬件条件来训练 BERT 估计需要 1 年的时间。不过他们会将已经训练好的模型和代码开源,⽅便⼤家训练好的模型上进⾏后续任务。
Bert原始论⽂

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。