.. raw:: html <!-- # Pretraining BERT --> .. _sec_bert-pretraining: Tiá»n Huấn luyện BERT ==================== .. raw:: html <!-- With the BERT model implemented in :numref:`sec_bert` and the pretraining examples generated from the WikiText-2 dataset in :numref:`sec_bert-dataset`, we will pretrain BERT on the WikiText-2 dataset in this section. --> Trong phần nà y, sá» dụng mô hình BERT đã được láºp trình trong :numref:`sec_bert` và các mẫu dữ liệu tiá»n huấn luyện được tạo ra từ táºp dữ liệu WikiText-2 trong :numref:`sec_bert-dataset`, ta sẽ tiá»n huấn luyện BERT trên táºp dữ liệu nà y. .. code:: python from d2l import mxnet as d2l from mxnet import autograd, gluon, init, np, npx npx.set_np() .. raw:: html <!-- To start, we load the WikiText-2 dataset as minibatches of pretraining examples for masked language modeling and next sentence prediction. The batch size is 512 and the maximum length of a BERT input sequence is 64. Note that in the original BERT model, the maximum length is 512. --> Äầu tiên, ta nạp các mẫu dữ liệu của táºp dữ liệu WikiText-2 thà nh các minibatch cho quá trình tiá»n huấn luyện hai tác vụ: mô hình hóa ngôn ngữ có mặt nạ và dá»± Ä‘oán câu tiếp theo. KÃch thÆ°á»›c batch là 512 và độ dà i tối Ä‘a của chuá»—i đầu và o BERT là 64. LÆ°u ý rằng trong mô hình BERT gốc, Ä‘á»™ dà i tối Ä‘a nà y là 512. .. code:: python batch_size, max_len = 512, 64 train_iter, vocab = d2l.load_data_wiki(batch_size, max_len) .. raw:: html <!-- ## Pretraining BERT --> Tiá»n Huấn luyện BERT -------------------- .. raw:: html <!-- The original BERT has two versions of different model sizes :cite:`Devlin.Chang.Lee.ea.2018`. The base model ($\text{BERT}_{\text{BASE}}$) uses 12 layers (Transformer encoder blocks) with 768 hidden units (hidden size) and 12 self-attention heads. The large model ($\text{BERT}_{\text{LARGE}}$) uses 24 layers with 1024 hidden units and 16 self-attention heads. Notably, the former has 110 million parameters while the latter has 340 million parameters. For demonstration with ease, we define a small BERT, using 2 layers, 128 hidden units, and 2 self-attention heads. --> Mô hình BERT gốc có hai phiên bản vá»›i hai kÃch thÆ°á»›c mô hình khác nhau :cite:`Devlin.Chang.Lee.ea.2018`. Mô hình cÆ¡ bản (:math:`\text{BERT}_{\text{BASE}}`) sá» dụng 12 tầng (khối mã hóa của Transformer) vá»›i 768 nút ẩn (kÃch thÆ°á»›c ẩn) và tầng tá»± táºp trung 12 đầu. Mô hình lá»›n (:math:`\text{BERT}_{\text{LARGE}}`) sá» dụng 24 tầng vá»›i 1024 nút ẩn và tầng tá»± táºp trung 16 đầu. Äáng chú ý là tổng số lượng tham số trong mô hình đầu tiên là 110 triệu, còn ở mô hình thứ hai là 340 triệu. Äể minh há»a thì ta định nghÄ©a mô hình BERT nhá» dÆ°á»›i đây, sá» dụng 2 tầng vá»›i 128 nút ẩn và tầng tá»± táºp trung 2 đầu. .. code:: python net = d2l.BERTModel(len(vocab), num_hiddens=128, ffn_num_hiddens=256, num_heads=2, num_layers=2, dropout=0.2) devices = d2l.try_all_gpus() net.initialize(init.Xavier(), ctx=devices) loss = gluon.loss.SoftmaxCELoss() .. raw:: html <!-- Before defining the training loop, we define a helper function `_get_batch_loss_bert`. Given the shard of training examples, this function computes the loss for both the masked language modeling and next sentence prediction tasks. Note that the final loss of BERT pretraining is just the sum of both the masked language modeling loss and the next sentence prediction loss. --> Ta sẽ định nghÄ©a hà m há»— trợ ``_get_batch_loss_bert`` trÆ°á»›c khi bắt đầu láºp trình vòng lặp cho quá trình huấn luyện. Hà m nà y nháºn đầu và o là má»™t batch các mẫu huấn luyện và tÃnh giá trị mất mát đối vá»›i hai tác vụ mô hình hóa ngôn ngữ có mặt nạ và dá»± Ä‘oán câu tiếp theo. LÆ°u ý rằng mất mát cuối cùng của tác vụ tiá»n huấn luyện BERT chỉ là tổng mất mát của cả hai tác vụ nói trên. .. code:: python #@save def _get_batch_loss_bert(net, loss, vocab_size, tokens_X_shards, segments_X_shards, valid_lens_x_shards, pred_positions_X_shards, mlm_weights_X_shards, mlm_Y_shards, nsp_y_shards): mlm_ls, nsp_ls, ls = [], [], [] for (tokens_X_shard, segments_X_shard, valid_lens_x_shard, pred_positions_X_shard, mlm_weights_X_shard, mlm_Y_shard, nsp_y_shard) in zip( tokens_X_shards, segments_X_shards, valid_lens_x_shards, pred_positions_X_shards, mlm_weights_X_shards, mlm_Y_shards, nsp_y_shards): # Forward pass _, mlm_Y_hat, nsp_Y_hat = net( tokens_X_shard, segments_X_shard, valid_lens_x_shard.reshape(-1), pred_positions_X_shard) # Compute masked language model loss mlm_l = loss( mlm_Y_hat.reshape((-1, vocab_size)), mlm_Y_shard.reshape(-1), mlm_weights_X_shard.reshape((-1, 1))) mlm_l = mlm_l.sum() / (mlm_weights_X_shard.sum() + 1e-8) # Compute next sentence prediction loss nsp_l = loss(nsp_Y_hat, nsp_y_shard) nsp_l = nsp_l.mean() mlm_ls.append(mlm_l) nsp_ls.append(nsp_l) ls.append(mlm_l + nsp_l) npx.waitall() return mlm_ls, nsp_ls, ls .. raw:: html <!-- Invoking the two aforementioned helper functions, the following `train_bert` function defines the procedure to pretrain BERT (`net`) on the WikiText-2 (`train_iter`) dataset. Training BERT can take very long. Instead of specifying the number of epochs for training as in the `train_ch13` function (see :numref:`sec_image_augmentation`), the input `num_steps` of the following function specifies the number of iteration steps for training. --> Sá» dụng hai hà m há»— trợ được Ä‘á» cáºp ở trên, hà m ``train_bert`` dÆ°á»›i đây sẽ định nghÄ©a quá trình tiá»n huấn luyện BERT (``net``) trên táºp dữ liệu WikiText-2 (``train_iter``). Việc huấn luyện BERT có thể mất rất nhiá»u thá»i gian. Do đó, thay vì truyá»n và o số lượng epoch huấn luyện nhÆ° trong hà m ``train_ch13`` (:numref:`sec_image_augmentation`), ta sá» dụng tham số ``num_steps`` trong hà m sau để xác định số vòng lặp huấn luyện. .. code:: python #@save def train_bert(train_iter, net, loss, vocab_size, devices, log_interval, num_steps): trainer = gluon.Trainer(net.collect_params(), 'adam', {'learning_rate': 1e-3}) step, timer = 0, d2l.Timer() animator = d2l.Animator(xlabel='step', ylabel='loss', xlim=[1, num_steps], legend=['mlm', 'nsp']) # Sum of masked language modeling losses, sum of next sentence prediction # losses, no. of sentence pairs, count metric = d2l.Accumulator(4) num_steps_reached = False while step < num_steps and not num_steps_reached: for batch in train_iter: (tokens_X_shards, segments_X_shards, valid_lens_x_shards, pred_positions_X_shards, mlm_weights_X_shards, mlm_Y_shards, nsp_y_shards) = [gluon.utils.split_and_load( elem, devices, even_split=False) for elem in batch] timer.start() with autograd.record(): mlm_ls, nsp_ls, ls = _get_batch_loss_bert( net, loss, vocab_size, tokens_X_shards, segments_X_shards, valid_lens_x_shards, pred_positions_X_shards, mlm_weights_X_shards, mlm_Y_shards, nsp_y_shards) for l in ls: l.backward() trainer.step(1) mlm_l_mean = sum([float(l) for l in mlm_ls]) / len(mlm_ls) nsp_l_mean = sum([float(l) for l in nsp_ls]) / len(nsp_ls) metric.add(mlm_l_mean, nsp_l_mean, batch[0].shape[0], 1) timer.stop() if (step + 1) % log_interval == 0: animator.add(step + 1, (metric[0] / metric[3], metric[1] / metric[3])) step += 1 if step == num_steps: num_steps_reached = True break print(f'MLM loss {metric[0] / metric[3]:.3f}, ' f'NSP loss {metric[1] / metric[3]:.3f}') print(f'{metric[2] / timer.sum():.1f} sentence pairs/sec on ' f'{str(devices)}') .. raw:: html <!-- We can plot both the masked language modeling loss and the next sentence prediction loss during BERT pretraining. --> Ta có thể vẽ đồ thị hà m mất mát ứng vá»›i hai tác vụ mô hình hóa ngôn ngữ có mặt nạ và dá»± Ä‘oán câu tiếp theo trong quá trình tiá»n huấn luyện BERT. .. code:: python train_bert(train_iter, net, loss, len(vocab), devices, 1, 50) .. parsed-literal:: :class: output MLM loss 7.901, NSP loss 0.740 21269.1 sentence pairs/sec on [gpu(0)] .. figure:: output_bert-pretraining_vn_e425f8_11_1.svg .. raw:: html <!-- ## Representing Text with BERT --> Biểu diá»…n Văn bản vá»›i BERT -------------------------- .. raw:: html <!-- After pretraining BERT, we can use it to represent single text, text pairs, or any token in them. The following function returns the BERT (`net`) representations for all tokens in `tokens_a` and `tokens_b`. --> Ta có thể sá» dụng mô hình BERT đã tiá»n huấn luyện để biểu diá»…n má»™t văn bản Ä‘Æ¡n, cặp văn bản hay má»™t token bất kỳ trong văn bản. Hà m sau sẽ trả vá» biểu diá»…n của mô hình BERT (``net``) cho toà n bá»™ các token trong ``tokens_a`` và ``tokens_b``. .. code:: python def get_bert_encoding(net, tokens_a, tokens_b=None): tokens, segments = d2l.get_tokens_and_segments(tokens_a, tokens_b) token_ids = np.expand_dims(np.array(vocab[tokens], ctx=devices[0]), axis=0) segments = np.expand_dims(np.array(segments, ctx=devices[0]), axis=0) valid_len = np.expand_dims(np.array(len(tokens), ctx=devices[0]), axis=0) encoded_X, _, _ = net(token_ids, segments, valid_len) return encoded_X .. raw:: html <!-- Consider the sentence "a crane is flying". Recall the input representation of BERT as discussed in :numref:`subsec_bert_input_rep`. After inserting special tokens “<cls>†(used for classification) and “<sep>†(used for separation), the BERT input sequence has a length of six. Since zero is the index of the “<cls>†token, `encoded_text[:, 0, :]` is the BERT representation of the entire input sentence. To evaluate the polysemy token "crane", we also print out the first three elements of the BERT representation of the token. --> Xét câu “a crane is flyingâ€. Hãy nhá»› lại biểu diá»…n đầu và o của BERT được thảo luáºn trong :numref:`subsec_bert_input_rep`, sau khi thêm các token đặc biệt “<cls>†(dùng cho phân loại) và “<sep>†(dùng để ngăn cách), chiá»u dà i của chuá»—i đầu và o BERT là 6. Vì 0 là chỉ số của token “<cls>â€, ``encoded_text[:, 0, :]`` là biểu diá»…n BERT của toà n bá»™ câu đầu và o. Äể đánh giá token Ä‘a nghÄ©a “craneâ€, ta sẽ in cả ba phần tỠđầu tiên trong biểu diá»…n BERT của token nà y. .. code:: python tokens_a = ['a', 'crane', 'is', 'flying'] encoded_text = get_bert_encoding(net, tokens_a) # Tokens: '<cls>', 'a', 'crane', 'is', 'flying', '<sep>' encoded_text_cls = encoded_text[:, 0, :] encoded_text_crane = encoded_text[:, 2, :] encoded_text.shape, encoded_text_cls.shape, encoded_text_crane[0][:3] .. parsed-literal:: :class: output ((1, 6, 128), (1, 128), array([ 0.6976905 , 0.98500854, -0.7272007 ], ctx=gpu(0))) .. raw:: html <!-- Now consider a sentence pair "a crane driver came" and "he just left". Similarly, `encoded_pair[:, 0, :]` is the encoded result of the entire sentence pair from the pretrained BERT. Note that the first three elements of the polysemy token "crane" are different from those when the context is different. This supports that BERT representations are context-sensitive. --> Bây giá», ta sẽ xem xét cặp câu “a crane driver came†và “he just leftâ€. TÆ°Æ¡ng tá»± nhÆ° trên, ``encoded_pair[:, 0, :]`` là kết quả mã hóa của cặp câu nà y thông qua BERT đã được tiá»n huấn luyện. LÆ°u ý rằng khi token Ä‘a nghÄ©a “crane†xuất hiện trong ngữ cảnh khác nhau, ba phần tỠđầu tiên trong biểu diá»…n BERT token nà y cÅ©ng thay đổi. Äiá»u nà y thể hiện rằng biểu diá»…n BERT có tÃnh nhạy ngữ cảnh. .. code:: python tokens_a, tokens_b = ['a', 'crane', 'driver', 'came'], ['he', 'just', 'left'] encoded_pair = get_bert_encoding(net, tokens_a, tokens_b) # Tokens: '<cls>', 'a', 'crane', 'driver', 'came', '<sep>', 'he', 'just', # 'left', '<sep>' encoded_pair_cls = encoded_pair[:, 0, :] encoded_pair_crane = encoded_pair[:, 2, :] encoded_pair.shape, encoded_pair_cls.shape, encoded_pair_crane[0][:3] .. parsed-literal:: :class: output ((1, 10, 128), (1, 128), array([ 0.6613879, 1.0305922, -0.6988825], ctx=gpu(0))) .. raw:: html <!-- In :numref:`chap_nlp_app`, we will fine-tune a pretrained BERT model for downstream natural language processing applications. --> Ở :numref:`chap_nlp_app`, ta sẽ tinh chỉnh mô hình BERT đã được tiá»n huấn luyện vá»›i má»™t số tác vụ xuôi dòng trong xá» lý ngôn ngữ tá»± nhiên. Tóm tắt ------- .. raw:: html <!-- * The original BERT has two versions, where the base model has 110 million parameters and the large model has 340 million parameters. * After pretraining BERT, we can use it to represent single text, text pairs, or any token in them. * In the experiment, the same token has different BERT representation when their contexts are different. This supports that BERT representations are context-sensitive. --> - Mô hình BERT gốc có hai phiên bản, trong đó mô hình cÆ¡ bản có 110 triệu tham số và mô hình lá»›n có 340 triệu tham số. - Ta có thể sá» dụng mô hình BERT đã được tiá»n huấn luyện để biểu diá»…n má»™t văn bản Ä‘Æ¡n, cặp văn bản hay má»™t token bất kỳ. - Trong thà nghiệm trên, ta đã thấy rằng cùng má»™t token có thể có nhiá»u cách biểu diá»…n khác nhau vá»›i những ngữ cảnh khác nhau. Äiá»u nà y thể hiện rằng biểu diá»…n BERT có tÃnh nhạy ngữ cảnh. Bà i táºp ------- .. raw:: html <!-- 1. In the experiment, we can see that the masked language modeling loss is significantly higher than the next sentence prediction loss. Why? 2. Set the maximum length of a BERT input sequence to be 512 (same as the original BERT model). Use the configurations of the original BERT model such as $\text{BERT}_{\text{LARGE}}$. Do you encounter any error when running this section? Why? --> 1. Kết quả thà nghiệm trên cho thấy mất mát ứng vá»›i tác vụ mô hình hóa ngôn ngữ có mặt nạ cao hÆ¡n đáng kể so vá»›i tác vụ dá»± Ä‘oán câu tiếp theo. Hãy giải thÃch hiện tượng nà y. 2. Thay đổi chiá»u dà i tối Ä‘a của chuá»—i đầu và o BERT thà nh 512 (giống vá»›i mô hình BERT gốc) và sá» dụng cấu hình của mô hình BERT gốc nhÆ° là :math:`\text{BERT}_{\text{LARGE}}`. Bạn có gặp lá»—i khi chạy lại thà nghiệm không? Giải thÃch tại sao. Thảo luáºn --------- - Tiếng Anh: `MXNet <https://discuss.d2l.ai/t/390>`__ - Tiếng Việt: `Diá»…n Ä‘Ã n Machine Learning CÆ¡ Bản <https://forum.machinelearningcoban.com/c/d2l>`__ Những ngÆ°á»i thá»±c hiện --------------------- Bản dịch trong trang nà y được thá»±c hiện bởi: - Äoà n Võ Duy Thanh - Bùi Thị Cẩm Nhung - Nguyá»…n Văn Quang - Phạm Minh Äức - Nguyá»…n Văn CÆ°á»ng *Lần cáºp nháºt gần nhất: 12/09/2020. (Cáºp nháºt lần cuối từ ná»™i dung gốc: 21/07/2020)*