Skip to content

Commit e7f63e0

Browse files
authoredAug 17, 2021
ch14.5-14.10 (d2l-ai#940)
* ch14.5-14.10
1 parent f1f0d4e commit e7f63e0

File tree

8 files changed

+267
-268
lines changed

8 files changed

+267
-268
lines changed
 

‎chapter_natural-language-processing-pretraining/bert-dataset.md

+49-58
Large diffs are not rendered by default.

‎chapter_natural-language-processing-pretraining/bert-pretraining.md

+29-30
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# 培训前培训 BERT
1+
# 预训练BERT
22
:label:`sec_bert-pretraining`
33

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进行预训练
55

66
```{.python .input}
77
from d2l import mxnet as d2l
@@ -17,17 +17,17 @@ import torch
1717
from torch import nn
1818
```
1919

20-
首先,我们加载 Wikitext-2 数据集作为用于掩码语言建模和下一句话预测的预训练示例的小组。批次大小为 512,BERT 输入序列的最大长度为 64。请注意,在原始的 BERT 模型中,最大长度为 512
20+
首先,我们加载WikiText-2数据集作为小批量的预训练样本,用于遮蔽语言模型和下一句预测。批量大小是512,BERT输入序列的最大长度是64。注意,在原始BERT模型中,最大长度是512
2121

2222
```{.python .input}
2323
#@tab all
2424
batch_size, max_len = 512, 64
2525
train_iter, vocab = d2l.load_data_wiki(batch_size, max_len)
2626
```
2727

28-
## 培训前培训 BERT
28+
## 预训练BERT
2929

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个自注意头
3131

3232
```{.python .input}
3333
net = d2l.BERTModel(len(vocab), num_hiddens=128, ffn_num_hiddens=256,
@@ -48,7 +48,7 @@ devices = d2l.try_all_gpus()
4848
loss = nn.CrossEntropyLoss()
4949
```
5050

51-
在定义训练循环之前,我们定义了一个助手函数 `_get_batch_loss_bert`鉴于训练示例的数量,此函数[**计算蒙版语言建模的损失和下一句预测任务的损失**]。请注意,BERT 预训练的最后损失只是蒙版语言建模损失和下一句预测损失的总和
51+
在定义训练代码实现之前,我们定义了一个辅助函数`_get_batch_loss_bert`给定训练样本,该函数计算遮蔽语言模型和下一句子预测任务的损失。请注意,BERT预训练的最终损失是遮蔽语言模型损失和下一句预测损失的和
5252

5353
```{.python .input}
5454
#@save
@@ -63,16 +63,16 @@ def _get_batch_loss_bert(net, loss, vocab_size, tokens_X_shards,
6363
tokens_X_shards, segments_X_shards, valid_lens_x_shards,
6464
pred_positions_X_shards, mlm_weights_X_shards, mlm_Y_shards,
6565
nsp_y_shards):
66-
# Forward pass
66+
# 前向传播
6767
_, mlm_Y_hat, nsp_Y_hat = net(
6868
tokens_X_shard, segments_X_shard, valid_lens_x_shard.reshape(-1),
6969
pred_positions_X_shard)
70-
# Compute masked language model loss
70+
# 计算遮蔽语言模型损失
7171
mlm_l = loss(
7272
mlm_Y_hat.reshape((-1, vocab_size)), mlm_Y_shard.reshape(-1),
7373
mlm_weights_X_shard.reshape((-1, 1)))
7474
mlm_l = mlm_l.sum() / (mlm_weights_X_shard.sum() + 1e-8)
75-
# Compute next sentence prediction loss
75+
# 计算下一句子预测任务的损失
7676
nsp_l = loss(nsp_Y_hat, nsp_y_shard)
7777
nsp_l = nsp_l.mean()
7878
mlm_ls.append(mlm_l)
@@ -89,21 +89,22 @@ def _get_batch_loss_bert(net, loss, vocab_size, tokens_X,
8989
segments_X, valid_lens_x,
9090
pred_positions_X, mlm_weights_X,
9191
mlm_Y, nsp_y):
92-
# Forward pass
92+
# 前向传播
9393
_, mlm_Y_hat, nsp_Y_hat = net(tokens_X, segments_X,
9494
valid_lens_x.reshape(-1),
9595
pred_positions_X)
96-
# Compute masked language model loss
96+
# 计算遮蔽语言模型损失
9797
mlm_l = loss(mlm_Y_hat.reshape(-1, vocab_size), mlm_Y.reshape(-1)) *\
9898
mlm_weights_X.reshape(-1, 1)
9999
mlm_l = mlm_l.sum() / (mlm_weights_X.sum() + 1e-8)
100-
# Compute next sentence prediction loss
100+
# 计算下一句子预测任务的损失
101101
nsp_l = loss(nsp_Y_hat, nsp_y)
102102
l = mlm_l + nsp_l
103103
return mlm_l, nsp_l, l
104104
```
105105

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` )。
107108

108109
```{.python .input}
109110
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):
112113
step, timer = 0, d2l.Timer()
113114
animator = d2l.Animator(xlabel='step', ylabel='loss',
114115
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+
# 遮蔽语言模型损失的和,下一句预测任务损失的和,句子对的数量,计数
117117
metric = d2l.Accumulator(4)
118118
num_steps_reached = False
119119
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):
156156
step, timer = 0, d2l.Timer()
157157
animator = d2l.Animator(xlabel='step', ylabel='loss',
158158
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+
# 遮蔽语言模型损失的和,下一句预测任务损失的和,句子对的数量,计数
161160
metric = d2l.Accumulator(4)
162161
num_steps_reached = False
163162
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):
191190
f'{str(devices)}')
192191
```
193192

194-
我们可以绘制 BERT 预训期间的蒙版语言建模损失和下一句话预测损失
193+
在预训练过程中,我们可以绘制出遮蔽语言模型损失和下一句预测损失
195194

196195
```{.python .input}
197196
#@tab all
198197
train_bert(train_iter, net, loss, len(vocab), devices, 50)
199198
```
200199

201-
## [**用BERT表示文本**]
200+
## 用BERT表示文本
202201

203-
在预训练 BERT 之后,我们可以用它来表示单个文本、文本对或其中的任何词元。以下函数返回 `tokens_a``tokens_b` 中所有词元的 BERT (`net`) 表示形式
202+
在预训练BERT之后,我们可以用它来表示单个文本、文本对或其中的任何词元。下面的函数返回`tokens_a``tokens_b`中所有词元的BERT(`net`)表示
204203

205204
```{.python .input}
206205
def get_bert_encoding(net, tokens_a, tokens_b=None):
@@ -224,43 +223,43 @@ def get_bert_encoding(net, tokens_a, tokens_b=None):
224223
return encoded_X
225224
```
226225

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表示的前三个元素
228227

229228
```{.python .input}
230229
#@tab all
231230
tokens_a = ['a', 'crane', 'is', 'flying']
232231
encoded_text = get_bert_encoding(net, tokens_a)
233-
# Tokens: '<cls>', 'a', 'crane', 'is', 'flying', '<sep>'
232+
# 词元: '<cls>', 'a', 'crane', 'is', 'flying', '<sep>'
234233
encoded_text_cls = encoded_text[:, 0, :]
235234
encoded_text_crane = encoded_text[:, 2, :]
236235
encoded_text.shape, encoded_text_cls.shape, encoded_text_crane[0][:3]
237236
```
238237

239-
[**现在考虑一对句子“起重机司机来了”和“他刚离开”**]。同样`encoded_pair[:, 0, :]` 是预训练的 BERT 整个句子对的编码结果。请注意,polysemy 词元 “鹤” 的前三个元素与上下文不同时的前三个元素不同。这支持 BERT 表示是上下文相关的
238+
现在考虑一个句子“a crane driver came”和“he just left”。类似地`encoded_pair[:, 0, :]`是来自预训练BERT的整个句子对的编码结果。注意,多义词元“crane”的前三个元素与上下文不同时的元素不同。这支持了BERT表示是上下文敏感的
240239

241240
```{.python .input}
242241
#@tab all
243242
tokens_a, tokens_b = ['a', 'crane', 'driver', 'came'], ['he', 'just', 'left']
244243
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',
246245
# 'left', '<sep>'
247246
encoded_pair_cls = encoded_pair[:, 0, :]
248247
encoded_pair_crane = encoded_pair[:, 2, :]
249248
encoded_pair.shape, encoded_pair_cls.shape, encoded_pair_crane[0][:3]
250249
```
251250

252-
在 :numref:`chap_nlp_app` 中,我们将为下游自然语言处理应用程序微调预训练的 BERT 模型。
251+
在 :numref:`chap_nlp_app` 中,我们将为下游自然语言处理应用微调预训练的BERT模型。
253252

254253
## 小结
255254

256-
* 原来的 BERT 有两个版本,其中基本模型有 1.1 亿个参数,而大型模型有 3.4 亿个参数
257-
* 在预训练 BERT 之后,我们可以用它来表示单个文本、文本对或其中的任何词元。
258-
* 在实验中,当上下文不同时,同一个词元具有不同的 BERT 表示形式。这支持 BERT 表示是上下文相关的
255+
* 原始的BERT有两个版本,其中基本模型有1.1亿个参数,大模型有3.4亿个参数
256+
* 在预训练BERT之后,我们可以用它来表示单个文本、文本对或其中的任何词元。
257+
* 在实验中,同一个词元在不同的上下文中具有不同的BERT表示。这支持BERT表示是上下文敏感的
259258

260259
## 练习
261260

262-
1. 在实验中,我们可以看到,蒙版语言建模损失明显高于下一个句子预测损失。为什么?
263-
2. 将 BERT 输入序列的最大长度设置为 512(与原始 BERT 模型相同)。使用原始 BERT 模型的配置,例如 $\text{BERT}_{\text{LARGE}}$。运行此部分时你会遇到任何错误吗?为什么?
261+
1. 在实验中,我们可以看到遮蔽语言模型损失明显高于下一句预测损失。为什么?
262+
2. 将BERT输入序列的最大长度设置为512(与原始BERT模型相同)。使用原始BERT模型的配置,如$\text{BERT}_{\text{LARGE}}$。运行此部分时是否遇到错误?为什么?
264263

265264
:begin_tab:`mxnet`
266265
[Discussions](https://discuss.d2l.ai/t/390)

0 commit comments

Comments
 (0)
Please sign in to comment.