从零理解BERT与Transformer:NLP新手的架构解析与实践指南

1次阅读
没有评论

共计 2269 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

背景痛点

在自然语言处理(NLP)领域,传统的 RNN/LSTM 模型长期占据主导地位,但它们存在一个致命缺陷:梯度消失问题。当处理长序列文本时,RNN 需要将信息一步步传递,而 LSTM 虽然通过门控机制有所缓解,但在超长文本(如超过 100 个词)中仍会丢失早期信息。例如:

  • RNN 的梯度计算公式为 $\frac{\partial L}{\partial W} = \sum_{t=1}^T \frac{\partial L}{\partial y_T} \frac{\partial y_T}{\partial h_t} (\prod_{k=t}^{T-1} \frac{\partial h_{k+1}}{\partial h_k}) \frac{\partial h_t}{\partial W}$,当 $T$ 较大时连乘项会指数级缩小
  • 传统词向量模型(如 Word2Vec)是静态的,无法解决一词多义问题(例如 ”bank” 在金融和河岸场景中的差异)

Transformer 架构解析

从零理解 BERT 与 Transformer:NLP 新手的架构解析与实践指南 图:Transformer 的 Encoder-Decoder 结构

Transformer 通过完全摒弃循环结构,采用 Self-Attention 机制实现并行计算。其核心是三个矩阵:

  1. Query(查询向量):当前词需要获取的信息
  2. Key(键向量):其他词的标识特征
  3. Value(值向量):实际的特征表示

自注意力计算公式为:
$$\text{Attention}(Q,K,V) = \text{softmax}(\frac{QK^T}{\sqrt{d_k}})V$$
其中 $d_k$ 是向量的维度,缩放因子用于防止点积过大导致 softmax 饱和。

BERT 实战代码示例

import torch
from transformers import BertTokenizer, BertModel

# 初始化 tokenizer(特殊标记处理)tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
text = "[CLS] This is a classification example [SEP]"
tokens = tokenizer.tokenize(text)  # 自动添加 [CLS] 和[SEP]

# 加载预训练模型
model = BertModel.from_pretrained('bert-base-uncased')
inputs = tokenizer(text, return_tensors="pt")  # 自动转换为 PyTorch 张量

# 微调层实现
class BertClassifier(torch.nn.Module):
    def __init__(self, dropout=0.1):
        super().__init__()
        self.bert = BertModel.from_pretrained('bert-base-uncased')
        self.dropout = torch.nn.Dropout(dropout)
        self.linear = torch.nn.Linear(768, 2)  # 假设二分类

    def forward(self, input_ids):
        outputs = self.bert(input_ids)
        pooled = outputs.last_hidden_state[:, 0]  # 取 [CLS] 标记对应的向量
        return self.linear(self.dropout(pooled))

优化实践技巧

  1. 长文本处理
  2. 当文本超过 512token 时,可采用:

    • 滑动窗口法(stride=128)
    • 关键句抽取(如 TF-IDF 权重最高的句子)
  3. 学习率 warmup

    from transformers import get_linear_schedule_with_warmup
    scheduler = get_linear_schedule_with_warmup(
        optimizer, 
        num_warmup_steps=100,  # 前 100 步线性增长
        num_training_steps=1000
    )

  4. 混合精度训练

    from torch.cuda.amp import GradScaler
    scaler = GradScaler()
    with torch.cuda.amp.autocast():
        loss = model(inputs).loss
    scaler.scale(loss).backward()
    scaler.step(optimizer)

常见问题避坑

  • 显存管理
  • batch_size=32 时约需 16GB 显存
  • 可通过 gradient_accumulation_steps=4 模拟更大 batch

  • 中文处理

  • 需使用 bert-base-chinese 版本
  • 注意中文无需空格分词,直接输入连续文本

延伸思考

  1. 领域适应性评估
  2. 使用困惑度 (Perplexity) 衡量语言模型拟合程度
  3. 检查专业术语的 embedding 相似度(如医学术语对)

  4. BERT vs GPT 注意力差异

  5. BERT 采用双向注意力(可看到前后文)
  6. GPT 使用单向掩码(只能看到左侧上下文)
    # BERT 的 attention_mask
    [1, 1, 1, 1, 0, 0]  # 0 表示 padding 部分
    
    # GPT 的 attention_mask
    [1, 0, 0, 0, 0, 0]  # 严格单向
    [1, 1, 0, 0, 0, 0]

实践心得

通过这次从理论到实践的完整流程,最大的收获是理解了 Transformer 如何通过注意力机制实现全局信息捕捉。在实际微调时,学习率 warmup 和梯度裁剪能显著提升训练稳定性。建议初学者先从小规模数据集(如 IMDB 影评)开始实验,逐步掌握超参数调整的技巧。

正文完
 0
评论(没有评论)