[AI]BERT 详解:从起源到实战

一、起源:BERT 为什么会出现

1. 时代背景(2018 年之前)

在 BERT 之前,NLP 的主流做法是为每个任务单独标注数据、单独训练一个模型:

  • 情感分析训一个模型,命名实体识别又训一个,问答再训一个......
  • 数据标注昂贵,小任务很难有充足标注数据
  • 词向量(Word2Vec、GloVe)是静态的:一个词只有一个向量,"苹果"在"吃水果"和"苹果公司"中表达完全相同------无法结合上下文

2. 关键技术铺垫

时间 工作 贡献
2017 Transformer(Google, 《Attention Is All You Need》) 提出自注意力机制,抛弃循环结构,可高度并行
2018 初 ELMo(AI2) 首次提出"预训练语言模型":根据上下文动态生成词向量(但仍基于 LSTM)
2018 6月 GPT-1(OpenAI) 首次用 Transformer Decoder 做预训练,但只能单向(从左往右)
2018 10月 BERT(Google) 用 Transformer Encoder + 双向预训练,11 项 NLP 基准全面刷新纪录(SQuAD、GLUE 等)

BERT 的论文《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》核心主张一句话概括:

"单向的语言模型(如 GPT)限制了预训练表示的能力。我们应该让模型在每个层都同时融合左右上下文。"

但双向预训练有一个技术难题:如果像传统语言模型那样"预测下一个词",双向模型会直接看到答案(左边看到右边),任务失去意义。BERT 的解决方案就是著名的 MLM(掩码语言模型)


二、原理细节

1. 整体架构

BERT = 纯 Encoder 的 Transformer 堆叠

复制代码
输入文本 → Token 嵌入 + 位置嵌入 + 段落嵌入 → [Encoder × N] → 上下文向量

两个官方版本:

版本 层数 隐藏维度 注意力头数 参数量
BERT-Base 12 768 12 1.1 亿
BERT-Large 24 1024 16 3.4 亿

最大输入长度:512 个 token

2. 输入表示(三个嵌入相加)

BERT 的每个输入 token 的最终向量 = Token Embedding + Segment Embedding + Position Embedding

特殊 token:

  • [CLS]:放在句首,它的最终输出向量被当作"整句话的表示",用于分类任务
  • [SEP]:句子分隔符,用于区分句子对
  • [MASK]:预训练时替换被遮住的词

3. 分词:WordPiece

BERT 不用整词切分,而是用 WordPiece:把词拆成子词(subword)。

  • 例:unbelievableun + ##believ + ##able## 表示接在前一个词后面)
  • 词表约 3 万,生僻词/新词总能拆成已知子词,不会遇到 OOV(未登录词)问题

4. 预训练任务一:MLM(Masked Language Model)

这是 BERT 的灵魂。

做法:随机选 15% 的 token,对它们:

  • 80% 替换为 [MASK]
  • 10% 替换为随机词
  • 10% 保持不变

然后让模型预测这些位置原本是什么词。

为什么要这样设计?

  • 全部换成 [MASK] → 预训练和微调不一致(微调时输入没有 [MASK]
  • 加入 10% 随机词和 10% 原词 → 迫使模型不能死记"看到 MASK 才预测",而是真正依赖上下文,同时让模型学会纠正错误输入
  • 双向性由此实现:预测被遮词时,左右两边的词都在场

代价:每次只预测 15% 的 token,收敛比 GPT 慢,需要更多训练步。

5. 预训练任务二:NSP(Next Sentence Prediction)

输入两个句子 A、B,模型判断 B 是否真是 A 的下一句(50% 是,50% 是随机句子)。

目的:让模型学会句子间关系(对问答、语义匹配有用)。

后来的 RoBERTa 等研究证明 NSP 收益很小甚至有害,将其去掉后性能反而更好------但它是理解 BERT 设计思路的重要一环。

6. 预训练数据与规模

  • BooksCorpus(8 亿词)+ 英文维基百科(25 亿词)
  • Base 训练 100 万步(约 16GB 文本,4 天,16 块 TPU)
  • 这么大的工程普通人做不了 → 所以实践方式是下载预训练权重,做微调

7. 自注意力在 BERT 里做了什么

每个 token 的向量会与所有其他 token 做注意力计算:

"它" ← 同时关注 "小明"、"书包"、"放学"......

多层注意力叠加后,"它" 的表示就融合了指代对象的语义------这就是"双向上下文理解"的底层机制。


三、实际微调使用(实战)

1. 通用范式

复制代码
下载 HuggingFace 上的 bert-base-chinese / bert-base-uncased
        ↓
准备任务数据(如:句子 + 标签)
        ↓
加任务头(线性分类层等),接上预训练模型
        ↓
小学习率(2e-5 ~ 5e-5)训练 2~4 个 epoch

2. 任务一:文本分类(最常用)

例如情感分析:在 [CLS] 输出向量上加一个线性层。

python 复制代码
import torch
from transformers import BertTokenizer, BertForSequenceClassification

# 1. 加载预训练模型和分词器
tokenizer = BertTokenizer.from_pretrained("bert-base-chinese")
model = BertForSequenceClassification.from_pretrained(
    "bert-base-chinese", num_labels=2   # 二分类:正面/负面
)

# 2. 数据编码
texts = ["这部电影太精彩了", "浪费了我两个小时"]
labels = torch.tensor([1, 0])  # 1=正面, 0=负面

enc = tokenizer(texts, padding=True, truncation=True,
                max_length=128, return_tensors="pt")
# enc: input_ids, attention_mask, token_type_ids

# 3. 训练
optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5)

model.train()
for _ in range(3):  # 3 个 epoch
    outputs = model(**enc, labels=labels)
    loss = outputs.loss
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()
    print("loss:", loss.item())

# 4. 推理
model.eval()
with torch.no_grad():
    logits = model(**enc).logits
    print("预测:", logits.argmax(dim=-1))  # tensor([1, 0])

关键超参数经验

  • 学习率:2e-5 ~ 5e-5(不能大,否则破坏预训练权重)
  • batch size:16 或 32
  • epoch:2~4(多了容易过拟合)
  • max_length:按任务定,多数分类任务 128~256 足够

3. 任务二:命名实体识别(NER)

对每个 token 的输出向量做分类,而不是只用 [CLS]

复制代码
输入:  李小明 在 北京 大学 读书
输出:  B-PER  O  B-LOC I-LOC O

BertForTokenClassification,数据要标注到 token 级(注意中文分词与 WordPiece 的切分对齐问题,这是实战中最繁琐的部分)。

4. 任务三:抽取式问答(QA)

BertForQuestionAnswering

  • 输入 = 问题 + [SEP] + passage
  • 输出两个指针:答案开始位置答案结束位置 的概率分布
  • 取 argmax(start)、argmax(end),切出原文片段即为答案

5. 任务四:句子对匹配(语义相似度)

输入 A + B,用 [CLS] 判断"是否相似"。这是搜索引擎 query-doc 相关性判断的经典用法。

6. 常见坑

问题 建议
学习率过大,loss 震荡 降到 2e-5 以下,加 warmup
过拟合(训练集好、验证集差) 减少 epoch、加 dropout、增数据
类别不平衡 加权 loss 或重采样
中文切分对不齐标签 用 tokenizer 的 offset_mapping 对齐
512 token 限制 长文档用滑窗切分、mean pooling 后拼接

7. 快速上手工具(不写训练代码)

bash 复制代码
pip install transformers datasets

配合 Trainer API 或自动微调工具(如 AutoGluon、LlamaFactory 类框架)可零代码微调。


四、应用:BERT 在哪些场景

BERT 是理解型模型,强项是"读懂"而非"写作":

  1. 搜索引擎与推荐

    • query 与文档的相关性排序(Google 2019 年起将 BERT 用于搜索排序)
    • 语义检索:query 和 doc 分别编码成向量,做向量相似度检索(双塔模型)
  2. 文本分类:情感分析、垃圾邮件识别、新闻分类、审核打标

  3. 信息抽取:NER(人名/地名/机构名)、关系抽取、事件抽取------金融、医疗、法律领域结构化数据抽取的标配底座

  4. 智能问答:FAQ 匹配、客服机器人(问题改写 + 检索 + 抽取式回答)

  5. 语义匹配:查重、相似问句归并、搜索词联想

  6. 作为 Embedding 底座:句向量 + 向量数据库,是很多 RAG 检索链路的组成部分

  7. 垂直领域微调:医疗 BERT(PubMedBERT)、法律 BERT、金融 BERT------在领域语料上继续预训练(领域自适应预训练,DAPT)后再微调,效果显著好于直接用通用 BERT


五、总结与延伸

BERT 的历史地位:证明了"大规模预训练 + 下游微调"这条路线可行,直接开启了 NLP 的预训练时代。

它之后的演进脉络(帮你定位 BERT 在模型谱系中的位置):

  • RoBERTa:去掉 NSP、更大批量更长训练 → 同规模更强
  • ALBERT:参数共享 + 矩阵分解,轻量版
  • DeBERTa:解耦注意力,理解任务一度霸榜
  • 生成方向:GPT 系列(Decoder 单向)最终通向大语言模型时代
  • 检索方向:Sentence-BERT(SBERT)把 BERT 改造成高效的句向量生成器,至今仍是很多 RAG 系统的检索核心

相关推荐
qyr67891 小时前
全球无硅导热垫片市场调研分析
大数据·人工智能·能源·无硅导热垫片
盼小辉丶1 小时前
PyTorch强化学习实战——分布式策略梯度
人工智能·pytorch·深度学习·强化学习
qq7422349841 小时前
OpenCV 之外的另一半工具箱:Supervision 视觉工程实战
人工智能·opencv·计算机视觉
doiito(Do It Together)1 小时前
【Agent Harness】Gliding Horse 最新进化:从“能学习”到“可验证的自主进化”
人工智能·rust·系统架构·开源
weixin_511840471 小时前
2026年9月19日 NVIDIA H200 企业级AI服务器学习
人工智能
wshzd1 小时前
LLM之Agent(八十五)|PI(二十四)RPC 模式与 JSON 事件流
人工智能
禁默1 小时前
没有公网 IP 怎么远程抓取服务器指标?node_exporter + Prometheus + cpolar 实战
人工智能·cpolar
汽车网络安全爱好者1 小时前
AI应用(四)之 AI 编程全流程
大数据·人工智能·elasticsearch
PPIO派欧云1 小时前
PPIO沙箱支持接入OpenAI Agents API,一键托管Agent Harness
人工智能