深入理解BERT:从原理到实现
引言
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设计了两个预训练任务:
- 掩蔽语言模型(MLM):随机遮盖部分词元并预测它们
- 下一句预测(NSP):判断两个句子是否连续
这两个任务使BERT能够学习丰富的语言表示。
BERT的架构实现
输入表示
BERT的输入由三部分组成:
- 词元嵌入:将词转换为向量
- 片段嵌入:区分句子A和句子B
- 位置嵌入:编码词的位置信息
# 示例:获取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架构和精心设计的预训练任务,实现了强大的上下文表示能力。其关键优势包括:
- 真正的双向上下文建模
- 通用的预训练方法,适用于多种下游任务
- 通过大规模无监督预训练学习通用语言表示
理解BERT的原理和实现细节,对于掌握现代NLP技术至关重要。在实际应用中,我们可以使用预训练的BERT模型进行微调,也可以根据特定需求从头开始训练。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考