深入理解BERT:从原理到实现

深入理解BERT:从原理到实现

d2l-zh 《动手学深度学习》:面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。 d2l-zh 项目地址: https://gitcode.com/gh_mirrors/d2/d2l-zh

引言

BERT(Bidirectional Encoder Representations from Transformers)是自然语言处理领域里程碑式的模型,它通过创新的预训练方法大幅提升了各种NLP任务的性能。本文将带您深入理解BERT的核心思想、架构设计以及实现细节。

上下文表示的发展历程

从静态词向量到动态词向量

传统词嵌入模型(如Word2Vec和GloVe)为每个词分配固定的向量表示,无法处理一词多义现象。例如,"bank"在"river bank"和"bank account"中含义不同,但传统模型会给出相同的表示。

上下文敏感表示

为了解决这个问题,研究者提出了上下文敏感的词表示方法:

  • ELMo:使用双向LSTM生成词表示
  • GPT:基于Transformer解码器的单向语言模型

这些方法各有优缺点,而BERT则融合了它们的优势。

BERT的核心创新

双向Transformer编码器

BERT使用Transformer编码器作为基础架构,通过自注意力机制实现真正的双向上下文建模。与GPT不同,BERT在预训练时可以同时利用左右两侧的上下文信息。

创新的预训练任务

BERT设计了两个预训练任务:

  1. 掩蔽语言模型(MLM):随机遮盖部分词元并预测它们
  2. 下一句预测(NSP):判断两个句子是否连续

这两个任务使BERT能够学习丰富的语言表示。

BERT的架构实现

输入表示

BERT的输入由三部分组成:

  1. 词元嵌入:将词转换为向量
  2. 片段嵌入:区分句子A和句子B
  3. 位置嵌入:编码词的位置信息
# 示例:获取BERT输入序列
def get_tokens_and_segments(tokens_a, tokens_b=None):
    tokens = ['<cls>'] + tokens_a + ['<sep>']
    segments = [0] * (len(tokens_a) + 2)
    if tokens_b:
        tokens += tokens_b + ['<sep>']
        segments += [1] * (len(tokens_b) + 1)
    return tokens, segments

BERT编码器实现

BERT编码器基于Transformer架构,但加入了可学习的位置嵌入:

class BERTEncoder(nn.Module):
    def __init__(self, vocab_size, num_hiddens, ...):
        super().__init__()
        self.token_embedding = nn.Embedding(vocab_size, num_hiddens)
        self.segment_embedding = nn.Embedding(2, num_hiddens)
        self.pos_embedding = nn.Parameter(torch.randn(1, max_len, num_hiddens))
        self.blks = nn.Sequential([EncoderBlock(...) for _ in range(num_layers)])

预训练任务实现

掩蔽语言模型

MLM任务随机遮盖15%的词元,并预测这些词元:

class MaskLM(nn.Module):
    def __init__(self, vocab_size, num_hiddens):
        super().__init__()
        self.mlp = nn.Sequential(
            nn.Linear(num_hiddens, num_hiddens),
            nn.ReLU(),
            nn.LayerNorm(num_hiddens),
            nn.Linear(num_hiddens, vocab_size))

下一句预测

NSP任务预测两个句子是否连续:

class NextSentencePred(nn.Module):
    def __init__(self, num_inputs):
        super().__init__()
        self.output = nn.Linear(num_inputs, 2)

BERT模型整合

将编码器和预训练任务整合为完整的BERT模型:

class BERTModel(nn.Module):
    def __init__(self, vocab_size, num_hiddens, ...):
        super().__init__()
        self.encoder = BERTEncoder(...)
        self.mlm = MaskLM(vocab_size, num_hiddens)
        self.nsp = NextSentencePred(num_hiddens)

总结

BERT通过创新的双向Transformer架构和精心设计的预训练任务,实现了强大的上下文表示能力。其关键优势包括:

  1. 真正的双向上下文建模
  2. 通用的预训练方法,适用于多种下游任务
  3. 通过大规模无监督预训练学习通用语言表示

理解BERT的原理和实现细节,对于掌握现代NLP技术至关重要。在实际应用中,我们可以使用预训练的BERT模型进行微调,也可以根据特定需求从头开始训练。

d2l-zh 《动手学深度学习》:面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。 d2l-zh 项目地址: https://gitcode.com/gh_mirrors/d2/d2l-zh

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

汪萌娅Gloria

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

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

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

打赏作者

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

抵扣说明:

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

余额充值