title: Bert

BERT模型

BERT (Bidirectional Encoder Representations from Transformers) 是一种突破性的预训练语言模型,通过双向上下文表示和掩码语言建模任务,显著提升了各种自然语言理解任务的性能。

BERT的诞生背景

BERT由Google AI研究团队于2018年提出,发表在论文《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》中,主要解决了以往语言模型只能单向处理上下文的限制。

BERT模型结构图

发布后,BERT迅速在11项NLP任务上取得了当时的最佳结果,掀起了预训练语言模型的研究热潮。

核心创新

BERT的双向上下文表示能力是其最大的创新,这使得模型可以同时考虑单词左右两侧的上下文信息,大幅增强了语言理解能力。

BERT的主要创新点包括:

  1. 双向Transformer编码器:同时利用左右上下文信息
  2. 掩码语言模型(MLM):随机遮蔽15%的词元并预测它们
  3. 下一句预测(NSP):预测两个句子是否连续出现
  4. 预训练-微调范式:通用预训练+任务特定微调

以下是BERT预训练任务的简化实现:

import torch
import torch.nn as nn
import random

def create_masked_input(tokens, vocab, mask_token_id, mask_prob=0.15):
    masked_tokens = tokens.clone()
    labels = torch.ones_like(tokens) * -100  # -100作为忽略的标签
    
    for i in range(len(tokens)):
        prob = random.random()
        if prob < mask_prob:
            labels[i] = tokens[i].clone()
            prob /= mask_prob
            
            if prob < 0.8:  # 80%概率替换为[MASK]
                masked_tokens[i] = mask_token_id
            elif prob < 0.9:  # 10%概率替换为随机词
                masked_tokens[i] = random.randint(0, len(vocab)-1)
            # 10%概率保持不变
    
    return masked_tokens, labels

模型架构

BERT基于Transformer的编码器部分构建,有两个主要版本:

版本层数隐藏层维度注意力头数参数量
BERT-Base12768121.1亿
BERT-Large241024163.4亿

输入表示

BERT的输入由三种嵌入共同组成:

  1. 词元嵌入(Token Embeddings):WordPiece分词后的词元表示
  2. 段嵌入(Segment Embeddings):区分不同段落/句子
  3. 位置嵌入(Position Embeddings):提供词元位置信息

这三种嵌入相加后作为模型输入:

BERT输入表示

预训练过程

BERT的预训练包括两个任务:

掩码语言模型(MLM)

  • 随机遮蔽输入中15%的词元
  • 80%替换为[MASK]标记
  • 10%替换为随机词元
  • 10%保持不变
  • 训练模型预测被遮蔽的原始词元

下一句预测(NSP)

  • 50%选择文档中连续的两个句子
  • 50%选择来自不同文档的两个句子
  • 训练模型预测第二个句子是否是第一个句子的真实后续

"预训练是通往通用人工智能的重要步骤,BERT的成功表明了无监督学习的强大潜力。" —— Jacob Devlin (BERT第一作者)

微调应用

BERT的通用表示可以通过微调适应多种下游任务:

  1. 序列分类:添加分类层处理[CLS]标记的表示
  2. 序列标注:为每个词元的表示添加标注层
  3. 问答:预测答案的起始和结束位置
  4. 句对任务:同时输入两个句子进行关系判断
from transformers import BertForSequenceClassification
import torch.nn as nn

class BertClassifier(nn.Module):
    def __init__(self, num_classes=2):
        super(BertClassifier, self).__init__()
        self.bert = BertForSequenceClassification.from_pretrained(
            'bert-base-uncased', 
            num_labels=num_classes
        )
        
    def forward(self, input_ids, attention_mask, token_type_ids):
        return self.bert(
            input_ids=input_ids,
            attention_mask=attention_mask,
            token_type_ids=token_type_ids
        )

BERT的影响

BERT的出现带来了深远影响:

  • 研究方向转变:推动了预训练-微调范式的普及
  • 技术进步:引发了一系列改进版本的研发
  • 应用拓展:促进了NLP技术在各行业的应用
  • 商业价值:为企业级NLP解决方案提供了核心技术

BERT家族

BERT的成功催生了大量改进版本和变种:

RoBERTa

  • 移除NSP任务
  • 使用更大批量和更多数据
  • 动态掩码策略
  • 取得了比BERT更好的效果

ALBERT

  • 参数共享减少模型大小
  • 嵌入层因式分解
  • 句子顺序预测代替NSP
  • 在同等性能下大幅减少参数量

DistilBERT

  • 知识蒸馏压缩模型
  • 保留BERT 97%的性能
  • 参数量减少40%
  • 推理速度提升60%

ELECTRA

  • 使用替换检测预训练
  • 训练效率大幅提升
  • 在同等计算资源下性能更好

尽管后来出现了更多强大的模型,BERT作为NLP发展的里程碑,其设计思想和技术创新仍然深刻影响着现代语言模型的发展方向。

局限性

BERT也存在一些局限性:

  • 生成能力弱:不适合文本生成任务
  • 上下文长度限制:最大处理512个词元
  • 预训练-微调差距:预训练任务与某些下游任务差异较大
  • 计算资源需求高:训练和部署成本较高

小结

BERT代表了NLP领域的重要变革,通过双向Transformer和创新的预训练任务,为文本表示提供了更强大的基础。它不仅在技术上取得了突破,还改变了整个行业的研究和应用方向。虽然现在已有更先进的模型,但BERT的原理和方法仍然是现代NLP系统的重要组成部分,其学术和工业影响力不可低估。