NLP学习之:BERT论文复现(2)token embedding + segment embedding + position embedding

BERT 的 Embedding

  • BERT 和 Transformer 在 Embedding 的时候有两个区别:
    • 由于 BERT 采用了两个句子拼接后作为一个 sample 的方法,我们需要在输入的时候嵌入当前的词属于第一句话还是第二句话这个信息,因此我们需要 segment embedding
    • BERT 也需要编码位置信息因为他在这一点继承了 Transformer 的 self attention 操作,但是 BERT 的位置信息既可以和 Transformer 一样采用位置编码(Positional encoding)的方法用固定的 sin, cos 函数来实现,也可以采用将位置信息输入 embedding 层让他自己学习出更好的位置表示

代码复现

"""
 @Time    : 2022/10/22
 @Author  : Peinuan qin
 """
import torch
import torch.nn as nn
from transformers import BertTokenizer,BertModel, BertConfig
from Dataset import BERTDataset


class PositionalEmbedding(nn.Embedding):
    def __init__(self, d_model, max_len=512):
        super(PositionalEmbedding, self).__init__(max_len, d_model, padding_idx=0)


class SegmentEmbedding(nn.Embedding):
    def __init__(self, d_model, segement_num=2):
        super(SegmentEmbedding, self).__init__(segement_num, d_model, padding_idx=0)


class TokenEmbedding(nn.Embedding):
    def __init__(self, d_model, vocab_size,):
        super(TokenEmbedding, self).__init__(vocab_size, d_model, padding_idx=0)


class BERTEmbedding(nn.Module):
    def __init__(self, vocab_size, d_model, drop_rate=0.1):
        super(BERTEmbedding, self).__init__()
        # super(BERTEmbedding, self).__init__()
        self.token_embedding = TokenEmbedding(d_model, vocab_size)
        self.position_embedding = PositionalEmbedding(d_model)
        self.segment_embedding = SegmentEmbedding(d_model)
        self.dropout = nn.Dropout(drop_rate)

    def forward(self, sequence, segment_labels, position_ids):
        x = self.token_embedding(sequence) + self.segment_embedding(segment_labels) + self.position_embedding(position_ids)

        return self.dropout(x)


if __name__ == '__main__':
    model_name = '../bert_pretrain_base/'
    d_model = 768
    config = BertConfig.from_pretrained(model_name)
    tokenizer = BertTokenizer.from_pretrained(model_name)
    model = BertModel.from_pretrained(model_name)
    bert_embedding = BERTEmbedding(vocab_size=config.vocab_size, d_model=d_model)

    dataset = BERTDataset(corpus_path="./corpus_chinese.txt"
                          , tokenizer=tokenizer
                          , seq_len=20)

    sample = dataset[0]
    input_ids = sample['input_ids']
    segment_labels = sample['segment_labels']
    # 是固定的 [0, ..., seq_len-1]
    position_ids = torch.tensor([i for i in range(len(input_ids))])
    print(sample)
    x = bert_embedding(input_ids, segment_labels, position_ids)
    print(x)
  • 看不懂 main 函数中前半截操作可以参考上篇文章 ,我采用了 huggingface 提供的预训练模型来提供 tokenizer词表
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暖仔会飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值