class BERTEncoder(nn.Module):"""BERT编码器"""def __init__(self, vocab_size, num_hiddens, norm_shape, ffn_num_input,ffn_num_hiddens, num_heads, num_layers, dropout,max_len=1000, key_size=768, query_size=768, value_size=768,**kwargs):super(BERTEncoder, self).__init__(**kwargs)self.token_embedding = nn.Embedding(vocab_size, num_hiddens)self.segment_embedding = nn.Embedding(2, num_hiddens)self.blks = nn.Sequential()for i in range(num_layers):self.blks.add_module(f"{i}", d2l.EncoderBlock(key_size, query_size, value_size, num_hiddens, norm_shape,ffn_num_input, ffn_num_hiddens, num_heads, dropout, True))# 在BERT中,位置嵌入是可学习的self.pos_embedding = nn.Parameter(torch.randn(1, max_len, num_hiddens))def forward(self, tokens, segments, valid_lens):# 在以下代码段中,X的形状保持不变:(批量大小,最大序列长度,num_hiddens)X = self.token_embedding(tokens) + self.segment_embedding(segments)X = X + self.pos_embedding.data[:, :X.shape[1], :]for blk in self.blks:X = blk(X, valid_lens)return X
4.预训练任务
预训练包括两个任务:掩蔽语言模型和下一句预测 。前者能够编码双向上下文来表示单词,而后者则显式地建模文本对之间的逻辑关系 。
掩蔽语言模型
语言模型使用左侧的上下文预测词元 。为了双向编码上下文以表示每个词元,BERT随机掩蔽词元并使用来自双向上下文的词元以自监督的方式预测掩蔽词元 。此任务称为掩蔽语言模型() 。
在这个预训练任务中,将随机选择15%的词元作为预测的掩蔽词元 。要预测一个掩蔽词元而不使用标签作弊,一个简单的方法是总是用一个特殊的“”替换输入序列中的词元 。然而,特殊词元“”不会出现在微调中 。为了避免预训练和微调之间的这种不匹配,如果为预测而屏蔽词元(例如,在“this movie is great”中选择掩蔽和预测“great”),则在输入中将其替换为:
请注意,在15%的概率中,有10%的概率插入了随机词元 。这种偶然的噪声鼓励BERT在其双向上下文编码中不那么偏向于掩蔽词元(尤其是当标签词元保持不变时) 。
class MaskLM(nn.Module):"""BERT的掩蔽语言模型任务"""def __init__(self, vocab_size, num_hiddens, num_inputs=768, **kwargs):super(MaskLM, self).__init__(**kwargs)self.mlp = nn.Sequential(nn.Linear(num_inputs, num_hiddens),nn.ReLU(),nn.LayerNorm(num_hiddens),nn.Linear(num_hiddens, vocab_size))def forward(self, X, pred_positions):"""输入BERTEncoder的编码结果和用于预测的词元位置,输出是这些位置的预测结果"""num_pred_positions = pred_positions.shape[1]pred_positions = pred_positions.reshape(-1)batch_size = X.shape[0]batch_idx = torch.arange(0, batch_size)# 假设batch_size=2,num_pred_positions=3# 那么batch_idx = tensor([0, 0, 0, 1, 1, 1])batch_idx = torch.repeat_interleave(batch_idx, num_pred_positions)masked_X = X[batch_idx, pred_positions]masked_X = masked_X.reshape((batch_size, num_pred_positions, -1))mlm_Y_hat = self.mlp(masked_X)return mlm_Y_hat
文章插图
下一句预测
尽管掩蔽语言建模能够编码双向上下文来表示单词,但它不能显式地建模文本对之间的逻辑关系 。为了帮助理解两个文本序列之间的关系,BERT在预训练中考虑了一个二元分类任务——下一句预测(Next) 。在为预训练生成句子对时,有一半的概率它们确实是标签为“真”的连续句子;在另一半的概率里,第二个句子是从语料库中随机抽取的,标记为“假” 。
由于编码器中的自注意力,特殊词元“”的BERT表示已经对输入的两个句子进行了编码 。因此,多层感知机分类器的输出层(self.)以X作为输入,其中X是多层感知机隐藏层的输出,而MLP隐藏层的输入是编码后的“”词元 。
- 一、主流的固态硬盘
- 企业如何解决多头领导问题,为什么企业多头领导、均不负责
- 企业微信是干什么用的,微信的二维码是干什么用的
- 汉景帝的一夜风流换来了汉朝的二百年天下
- 中国男篮十大帅哥 中国之最帅哥
- 2023中国十大最受欢迎炸鸡汉堡品牌:塔斯汀第三、华莱士第四 中国之最受
- 追风赏月、静心养神、休闲避暑,来天然氧吧大吸一口清新空气~ 威远吉尼斯记录
- NBA新赛季奢侈税排行:勇士1.8亿财大气粗,篮网仅第二,湖人第六 ba奢侈税历史之最
- 中国历史名人勤学、励志、育人、诚信、齐家、治国等100个小故事 历史之最作文素材初中
- 中华第一大姓,从黄帝时期到明清,58位王姓历史名人 历史王姓名人之最