1
- # 培训前培训 BERT
1
+ # 预训练BERT
2
2
:label : ` sec_bert-pretraining `
3
3
4
- 随着在 :numref:` sec_bert ` 中实施了 BERT 模型,以及 :numref:` sec_bert-dataset ` 中从 WikiText-2 数据集生成的预训练示例,我们将在本节的 WikiText-2 数据集上预训练 BERT 。
4
+ 利用 :numref:` sec_bert ` 中实现的BERT模型和 :numref:` sec_bert-dataset ` 中从WikiText-2数据集生成的预训练样本,我们将在本节中在WikiText-2数据集上对BERT进行预训练 。
5
5
6
6
``` {.python .input}
7
7
from d2l import mxnet as d2l
@@ -17,17 +17,17 @@ import torch
17
17
from torch import nn
18
18
```
19
19
20
- 首先,我们加载 Wikitext-2 数据集作为用于掩码语言建模和下一句话预测的预训练示例的小组。批次大小为 512,BERT 输入序列的最大长度为 64。请注意,在原始的 BERT 模型中,最大长度为 512 。
20
+ 首先,我们加载WikiText-2数据集作为小批量的预训练样本,用于遮蔽语言模型和下一句预测。批量大小是512,BERT输入序列的最大长度是64。注意,在原始BERT模型中,最大长度是512 。
21
21
22
22
``` {.python .input}
23
23
#@tab all
24
24
batch_size, max_len = 512, 64
25
25
train_iter, vocab = d2l.load_data_wiki(batch_size, max_len)
26
26
```
27
27
28
- ## 培训前培训 BERT
28
+ ## 预训练BERT
29
29
30
- 原来的 BERT 有两个不同型号尺寸 :cite:` Devlin.Chang.Lee.ea.2018 ` 的版本。基本型号 ($\text{BERT}_ {\text{BASE}}$)使用 12 层(变压器编码器块),其中包含 768 个隐藏单元(隐藏尺寸)和 12 个自我注意头。大型模型 ($\text{BERT}_ {\text{LARGE}}$)使用 24 层,其中有 1024 个隐藏单元和 16 个自我注意头 。值得注意的是,前者有 1.1 亿个参数,而后者有 3.4 亿个参数。为了轻松进行演示,我们定义了 [ ** 一个小型BERT,它使用2层、128个隐藏单位和2个自我注意头 ** ] 。
30
+ 原始BERT :cite:` Devlin.Chang.Lee.ea.2018 ` 有两个不同模型尺寸的版本。基本模型 ($\text{BERT}_ {\text{BASE}}$)使用12层(Transformer编码器块),768个隐藏单元(隐藏大小)和12个自注意头。大模型 ($\text{BERT}_ {\text{LARGE}}$)使用24层,1024个隐藏单元和16个自注意头 。值得注意的是,前者有1.1亿个参数,后者有3.4亿个参数。为了便于演示,我们定义了一个小的BERT,使用了2层、128个隐藏单元和2个自注意头 。
31
31
32
32
``` {.python .input}
33
33
net = d2l.BERTModel(len(vocab), num_hiddens=128, ffn_num_hiddens=256,
@@ -48,7 +48,7 @@ devices = d2l.try_all_gpus()
48
48
loss = nn.CrossEntropyLoss()
49
49
```
50
50
51
- 在定义训练循环之前,我们定义了一个助手函数 ` _get_batch_loss_bert ` 。鉴于训练示例的数量,此函数 [ ** 计算蒙版语言建模的损失和下一句预测任务的损失 ** ] 。请注意,BERT 预训练的最后损失只是蒙版语言建模损失和下一句预测损失的总和 。
51
+ 在定义训练代码实现之前,我们定义了一个辅助函数 ` _get_batch_loss_bert ` 。给定训练样本,该函数计算遮蔽语言模型和下一句子预测任务的损失 。请注意,BERT预训练的最终损失是遮蔽语言模型损失和下一句预测损失的和 。
52
52
53
53
``` {.python .input}
54
54
#@save
@@ -63,16 +63,16 @@ def _get_batch_loss_bert(net, loss, vocab_size, tokens_X_shards,
63
63
tokens_X_shards, segments_X_shards, valid_lens_x_shards,
64
64
pred_positions_X_shards, mlm_weights_X_shards, mlm_Y_shards,
65
65
nsp_y_shards):
66
- # Forward pass
66
+ # 前向传播
67
67
_, mlm_Y_hat, nsp_Y_hat = net(
68
68
tokens_X_shard, segments_X_shard, valid_lens_x_shard.reshape(-1),
69
69
pred_positions_X_shard)
70
- # Compute masked language model loss
70
+ # 计算遮蔽语言模型损失
71
71
mlm_l = loss(
72
72
mlm_Y_hat.reshape((-1, vocab_size)), mlm_Y_shard.reshape(-1),
73
73
mlm_weights_X_shard.reshape((-1, 1)))
74
74
mlm_l = mlm_l.sum() / (mlm_weights_X_shard.sum() + 1e-8)
75
- # Compute next sentence prediction loss
75
+ # 计算下一句子预测任务的损失
76
76
nsp_l = loss(nsp_Y_hat, nsp_y_shard)
77
77
nsp_l = nsp_l.mean()
78
78
mlm_ls.append(mlm_l)
@@ -89,21 +89,22 @@ def _get_batch_loss_bert(net, loss, vocab_size, tokens_X,
89
89
segments_X, valid_lens_x,
90
90
pred_positions_X, mlm_weights_X,
91
91
mlm_Y, nsp_y):
92
- # Forward pass
92
+ # 前向传播
93
93
_, mlm_Y_hat, nsp_Y_hat = net(tokens_X, segments_X,
94
94
valid_lens_x.reshape(-1),
95
95
pred_positions_X)
96
- # Compute masked language model loss
96
+ # 计算遮蔽语言模型损失
97
97
mlm_l = loss(mlm_Y_hat.reshape(-1, vocab_size), mlm_Y.reshape(-1)) *\
98
98
mlm_weights_X.reshape(-1, 1)
99
99
mlm_l = mlm_l.sum() / (mlm_weights_X.sum() + 1e-8)
100
- # Compute next sentence prediction loss
100
+ # 计算下一句子预测任务的损失
101
101
nsp_l = loss(nsp_Y_hat, nsp_y)
102
102
l = mlm_l + nsp_l
103
103
return mlm_l, nsp_l, l
104
104
```
105
105
106
- 调用上述两个辅助函数,以下` train_bert ` 函数定义了[ ** 在Wikitext-2(` train_iter ` )数据集上预训练BERT(` net ` )** ] 的过程。培训 BERT 可能需要很长时间。以下函数的输入 ` num_steps ` 没有像 ` train_ch13 ` 函数那样指定训练的时代数量(参见 :numref:` sec_image_augmentation ` ),而是指定训练的迭代步数。
106
+
107
+ 通过调用上述两个辅助函数,下面的` train_bert ` 函数定义了在WikiText-2(` train_iter ` )数据集上预训练BERT(` net ` )的过程。训练BERT可能需要很长时间。以下函数的输入` num_steps ` 指定了训练的迭代步数,而不是像` train_ch13 ` 函数那样指定训练的迭代周期数(参见 :numref:` sec_image_augmentation ` )。
107
108
108
109
``` {.python .input}
109
110
def train_bert(train_iter, net, loss, vocab_size, devices, num_steps):
@@ -112,8 +113,7 @@ def train_bert(train_iter, net, loss, vocab_size, devices, num_steps):
112
113
step, timer = 0, d2l.Timer()
113
114
animator = d2l.Animator(xlabel='step', ylabel='loss',
114
115
xlim=[1, num_steps], legend=['mlm', 'nsp'])
115
- # Sum of masked language modeling losses, sum of next sentence prediction
116
- # losses, no. of sentence pairs, count
116
+ # 遮蔽语言模型损失的和,下一句预测任务损失的和,句子对的数量,计数
117
117
metric = d2l.Accumulator(4)
118
118
num_steps_reached = False
119
119
while step < num_steps and not num_steps_reached:
@@ -156,8 +156,7 @@ def train_bert(train_iter, net, loss, vocab_size, devices, num_steps):
156
156
step, timer = 0, d2l.Timer()
157
157
animator = d2l.Animator(xlabel='step', ylabel='loss',
158
158
xlim=[1, num_steps], legend=['mlm', 'nsp'])
159
- # Sum of masked language modeling losses, sum of next sentence prediction
160
- # losses, no. of sentence pairs, count
159
+ # 遮蔽语言模型损失的和,下一句预测任务损失的和,句子对的数量,计数
161
160
metric = d2l.Accumulator(4)
162
161
num_steps_reached = False
163
162
while step < num_steps and not num_steps_reached:
@@ -191,16 +190,16 @@ def train_bert(train_iter, net, loss, vocab_size, devices, num_steps):
191
190
f'{str(devices)}')
192
191
```
193
192
194
- 我们可以绘制 BERT 预训期间的蒙版语言建模损失和下一句话预测损失 。
193
+ 在预训练过程中,我们可以绘制出遮蔽语言模型损失和下一句预测损失 。
195
194
196
195
``` {.python .input}
197
196
#@tab all
198
197
train_bert(train_iter, net, loss, len(vocab), devices, 50)
199
198
```
200
199
201
- ## [ ** 用BERT表示文本** ]
200
+ ## 用BERT表示文本
202
201
203
- 在预训练 BERT 之后 ,我们可以用它来表示单个文本、文本对或其中的任何词元。以下函数返回 ` tokens_a ` 和 ` tokens_b ` 中所有词元的 BERT ( ` net ` ) 表示形式 。
202
+ 在预训练BERT之后 ,我们可以用它来表示单个文本、文本对或其中的任何词元。下面的函数返回 ` tokens_a ` 和 ` tokens_b ` 中所有词元的BERT( ` net ` )表示 。
204
203
205
204
``` {.python .input}
206
205
def get_bert_encoding(net, tokens_a, tokens_b=None):
@@ -224,43 +223,43 @@ def get_bert_encoding(net, tokens_a, tokens_b=None):
224
223
return encoded_X
225
224
```
226
225
227
- [ ** 考虑“起重机在飞 ”这句话** ] , 回想一下 :numref:` subsec_bert_input_rep ` 中讨论的 BERT 的输入表示形式。插入特殊词元 “< cls > ”(用于分类)和 “< sep > ”(用于分隔)后,BERT 输入序列的长度为 6。由于零是 “< cls >” 词元的索引,所以 ` encoded_text[:, 0, :] ` 是整个输入句子的 BERT 表示。为了评估 polysemy 词元 “鹤”,我们还打印了代币 BERT 表示的前三个元素 。
226
+ 考虑“a crane is flying ”这句话。 回想一下 :numref:` subsec_bert_input_rep ` 中讨论的BERT的输入表示。插入特殊标记“ & lt ; cls& gt ; ”(用于分类)和“ & lt ; sep& gt ; ”(用于分隔)后,BERT输入序列的长度为6。因为零是“ & lt ; cls& gt ; ”词元, ` encoded_text[:, 0, :] ` 是整个输入语句的BERT表示。为了评估一词多义词元“crane”,我们还打印出了该词元的BERT表示的前三个元素 。
228
227
229
228
``` {.python .input}
230
229
#@tab all
231
230
tokens_a = ['a', 'crane', 'is', 'flying']
232
231
encoded_text = get_bert_encoding(net, tokens_a)
233
- # Tokens: '<cls>', 'a', 'crane', 'is', 'flying', '<sep>'
232
+ # 词元: '<cls>', 'a', 'crane', 'is', 'flying', '<sep>'
234
233
encoded_text_cls = encoded_text[:, 0, :]
235
234
encoded_text_crane = encoded_text[:, 2, :]
236
235
encoded_text.shape, encoded_text_cls.shape, encoded_text_crane[0][:3]
237
236
```
238
237
239
- [ ** 现在考虑一对句子“起重机司机来了 ”和“他刚离开” ** ] 。同样 ,` encoded_pair[:, 0, :] ` 是预训练的 BERT 整个句子对的编码结果。请注意,polysemy 词元 “鹤” 的前三个元素与上下文不同时的前三个元素不同。这支持 BERT 表示是上下文相关的 。
238
+ 现在考虑一个句子“a crane driver came ”和“he just left”。类似地 ,` encoded_pair[:, 0, :] ` 是来自预训练BERT的整个句子对的编码结果。注意,多义词元“crane”的前三个元素与上下文不同时的元素不同。这支持了BERT表示是上下文敏感的 。
240
239
241
240
``` {.python .input}
242
241
#@tab all
243
242
tokens_a, tokens_b = ['a', 'crane', 'driver', 'came'], ['he', 'just', 'left']
244
243
encoded_pair = get_bert_encoding(net, tokens_a, tokens_b)
245
- # Tokens: '<cls>', 'a', 'crane', 'driver', 'came', '<sep>', 'he', 'just',
244
+ # 词元: '<cls>', 'a', 'crane', 'driver', 'came', '<sep>', 'he', 'just',
246
245
# 'left', '<sep>'
247
246
encoded_pair_cls = encoded_pair[:, 0, :]
248
247
encoded_pair_crane = encoded_pair[:, 2, :]
249
248
encoded_pair.shape, encoded_pair_cls.shape, encoded_pair_crane[0][:3]
250
249
```
251
250
252
- 在 :numref:` chap_nlp_app ` 中,我们将为下游自然语言处理应用程序微调预训练的 BERT 模型。
251
+ 在 :numref:` chap_nlp_app ` 中,我们将为下游自然语言处理应用微调预训练的BERT模型。
253
252
254
253
## 小结
255
254
256
- * 原来的 BERT 有两个版本,其中基本模型有 1.1 亿个参数,而大型模型有 3.4 亿个参数 。
257
- * 在预训练 BERT 之后 ,我们可以用它来表示单个文本、文本对或其中的任何词元。
258
- * 在实验中,当上下文不同时,同一个词元具有不同的 BERT 表示形式。这支持 BERT 表示是上下文相关的 。
255
+ * 原始的BERT有两个版本,其中基本模型有1.1亿个参数,大模型有3.4亿个参数 。
256
+ * 在预训练BERT之后 ,我们可以用它来表示单个文本、文本对或其中的任何词元。
257
+ * 在实验中,同一个词元在不同的上下文中具有不同的BERT表示。这支持BERT表示是上下文敏感的 。
259
258
260
259
## 练习
261
260
262
- 1 . 在实验中,我们可以看到,蒙版语言建模损失明显高于下一个句子预测损失 。为什么?
263
- 2 . 将 BERT 输入序列的最大长度设置为 512(与原始 BERT 模型相同)。使用原始 BERT 模型的配置,例如 $\text{BERT}_ {\text{LARGE}}$。运行此部分时你会遇到任何错误吗 ?为什么?
261
+ 1 . 在实验中,我们可以看到遮蔽语言模型损失明显高于下一句预测损失 。为什么?
262
+ 2 . 将BERT输入序列的最大长度设置为512(与原始BERT模型相同)。使用原始BERT模型的配置,如 $\text{BERT}_ {\text{LARGE}}$。运行此部分时是否遇到错误 ?为什么?
264
263
265
264
:begin_tab:` mxnet `
266
265
[ Discussions] ( https://discuss.d2l.ai/t/390 )
0 commit comments