BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
相关信息
论文地址:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
代码(Pytorch版):https://github.com/jadore801120/attention-is-all-you-need-pytorch/tree/master?tab=readme-ov-file
资源:
概述
BERT(Bidirectional Encoder Representations from Transformers)是一种Transformer的双向编码器,旨在通过在左右上下文中共有的条件计算来预先训练来自无标号文本的深度双向表示。因此,经过预先训练的BERT模型只需一个额外的输出层就可以进行微调,从而为各种自然语言处理任务生成最新模型。
也是我们常说的 【预训练】+【微调】
BERT的核心思想如下:
-
随机遮挡句子中一个或多个单词,让Encoder根据句子上下文预测被遮挡的单词(Predict Masked Word)
-
将两个句子拼接,让Encoder判断两个句子是否为原文中相邻的句子(Predict Next Sentence)
BERT通过上述两个任务,预训练Transformer模型Encoder网络。
作者给出了两种不同大小的bert
模型:
-
BERT-Base
:12 LayersTransformer Encoder
,768 Hidden(隐藏单元),12 Head,110M Parameters. -
BERT-Large
:24 LayersTransformer Encoder
,1024Hidden(隐藏单元),16 Head,340M Parameters.
Bert直接引用了Transformer架构中的Encoder模块,舍弃了Decoder模块, 由多个Encoder block模块堆叠而成,这样便自动拥有了双向编码能力和强大的特征提取能力。
Embedding
BERT
的输入Embedding
模块由三部分组成:
-
Token Embeddings
:输入文本中的每个单词或字符转换为一个固定维度的向量。Base
版为768维,Large
版为1024维。 -
Position Embeddings
:单词或字符在句子中的位置信息。BERT
中的位置嵌入是可学习的,它会随着模型的训练而更新,非固定的三角函数。 -
Segment Embeddings
:用于区分同一输入序列中不同句子的来源。对于多句输入,BERT
会为每个句子分配一个不同的段编号,来区分它们。Segment Embeddings
的取值通常是0和1,如果输入包含两个句子,通常第一个句子的token
会被赋予全0的向量,第二个句子的token会被赋予全1的向量。下图是一个示例。
Pre-training
BERT
的预训练过程主要包括两个阶段:Masked Language Model(MLM)
和Next Sentence Prediction(NSP)
。
Masked Language Model(MLM)
目标:填空,教导BERT
上下文
为了训练深度双向表示(deep bidirectional representation),在训练过程中,会对每个序类中的15%token
随机进行掩码(替换为[MASK]
),并且让模型只预测掩码词,而BERT学会从上下文中预测这些单词。这有助于BERT理解单词彼此之间的关系,无论是在前面还是在后面。
事实上,[MASK] token
在fine-tuning期间不会出现,因此对于每个被选中的token
,有80%的概率直接用[MASK]
标记替换,10%的概率用随机的一个单词替换(这有助于模型学习理解上下文的重要性,而不仅仅是依赖于[MASK]
标记),剩下的10%则保持不变(这有助于模型在微调阶段更好地处理未遮蔽的单词)。
如图,假设输入句子为[the cat sat on the mat]
,被随机遮挡的单词为[cat]
,那么BERT
的输出为:
-
80%的时候是
[MASK]
:[the [[MASK]] sat on the mat]
-
10%的时候是随机单词:
[the [bike] sat on the mat]
-
10%的时候是原词:
[the [cat] sat on the mat]
这样做使得编码器不知道此次需要预测哪些token
或已被随机token
替换,因此模型被迫保留每个token
的分布上下文表示。(is forced to keep a distributional contextual representation of every input token)
Next Sentence Prediction(NSP)
目标:教导BERT
理解句子之间的关系
从文本数据中生成训练数据集,抽取两个句子,并将两个句子拼接,两个句子中间用[SEP]
符号分隔,在拼接形成的句子前添加一个[CLS]
符号([CLS]
是用于分类的标记;[SEP]
用于分隔句子。)。其中训练集的50%为文本中相邻的两个句子,另外50%为随机抽取的不相邻两个句子。训练集中相邻句子的标签设置为1,不相邻句子的标签设置为0。
在
BERT
的后续版本中,Next Sentence Prediction(NSP)
任务被废弃了。因为研究人员发现这个任务对下游任务的性能提升有限,因此在BERT
的一些后续变体中被弃用了。
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
在训练
BERT
时,为了不使模型认为[MASK]
符号原本就归属于训练句子,在随机遮挡单词时采用了将一定数量的[MASK]
替换成句子中原本的单词,将一定数量的[MASK]
符号替换成随机单词等等小技巧。
Fine-tuning
self-attention
机制允许 BERT
对任何下游任务建模 —— 无论是 single text 还是 text pairs —— 只需要适当替换输入和输出,因此对 BERT
进行微调是非常方便的。
根据自然语言处理(NLP)下游任务输入和输出形式的不同,微调任务可以分为四类,分别是句对分类、单句分类、文本问答和单句标注
The General Language Understanding Evaluation (GLUE) benchmark
GLUE是各种自然语言理解任务的集合,为了对 GLUE 进行微调,我们使用对应于第一个输入标记[CLS]
的输出向量\(C \in \mathbb{R}^H\),引入一个新的分类层进行分类操作。
The Stanford Question Answering Dataset (SQuAD v1.1)
SQuAD v1.1 是100k个公开来源的question/answer对的集合,通常给定一个问题和一个维基百科段落(包含答案),任务是预测文章中的答案文本跨度。
我们将问题和段落表示为单个打包序列输入(输入格式为[CLS]+问题+[SEP]+段落信息
),在fine-tuning,我们引入一个起始向量\(S \in \mathbb{R}^H\)和一个结束向量\(E \in \mathbb{R}^H\),来计算答案的开始和结束。
开始位置的计算公式:
结束位置的计算公式:
从位置 i 到位置 j (i <= j>)的候选跨度的分数定义为:
最大分值的范围用作预测
SQuAD 2.0 task
SQuAD 2.0 任务通过允许提供的段落中不存在答案的可能性来扩展 SQuAD 1.1 问题定义,从而使问题更加现实。
若不存在答案,则计算一个没有答案的得分:
其中\(C\)就是[CLS]
的对应输出,此时如果没有答案的分数要比找到的答案的分数要好,那么就预测为没有答案。
The Situations With Adversarial Generations (SWAG) dataset
BERT简洁实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
|
总结
-
深度双向预训练表示:
与以往的语言表示模型不同,BERT旨在通过联合考虑所有层中的左侧和右侧上下文来预训练深度双向表示。这使得BERT能够在预训练阶段捕获更丰富的语言特征。
-
简化的任务特定架构修改:
预训练的BERT模型可以通过添加少量额外的输出层来微调(fine-tune),从而适应广泛的任务,如问答和语言推断,而无需对模型架构进行大量特定任务的修改。
-
多项自然语言处理任务的新最佳结果:
BERT在十一个自然语言处理任务上取得了新的最先进结果,包括将GLUE基准的分数推高到80.5%(绝对提高了7.7个百分点),MultiNLI准确率提高到86.7%(提高了4.6个百分点),SQuAD v1.1问答测试的F1分数提高到93.2(提高了1.5个百分点),以及SQuAD v2.0测试的F1分数提高到83.1(提高了5.1个百分点)。
-
预训练任务的重要性(预训练词嵌入,
性能优于从头开始学习的嵌入):BERT通过使用“掩码语言模型”(Masked Language Model, MLM)和“下一句预测”%(Next Sentence Prediction, NSP)任务来展示深度双向预训练的重要性。MLM任务通过随机掩盖输入中的一些标记,然后预测这些掩盖标记的原始词汇ID,从而使得模型能够融合左右上下文。NSP任务则通过预测两个文本片段之间的关系来训练模型理解句子间的关系。