BERT自然语言处理框架深度解析:从Transformer到双向预训练模型

文章目录


一、为什么需要BERT?传统方法的局限

在BERT出现之前,NLP领域主要面临两大痛点:传统RNN的串行计算瓶颈 与word2vec词向量的静态表示问题。

1.1 传统RNN网络的问题

RNN(循环神经网络)通过隐藏状态 h 1 → h 2 → ⋯ → h m h_1 \rightarrow h_2 \rightarrow \dots \rightarrow h_m h1→h2→⋯→hm 依次处理序列,存在以下缺陷:

  1. 串行依赖导致训练慢 :必须等 h 1 h_1 h1 计算完成才能计算 h 2 h_2 h2,无法并行化,序列越长训练时间越长。
  2. 并行计算效果差:难以在多台服务器上同时训练同一个网络,无法充分利用GPU集群。

1.2 传统word2vec的问题

  1. 词向量训练好后不再改变:无论上下文如何,同一个词的向量永远相同。
  2. 无法区分多义词:不同语境下的同一词语含义不同,但共享同一个向量。例如"机车"在台湾俚语中指"罗嗦",而在普通话中指"摩托车",静态向量无法区分。

核心结论 :我们需要一种能根据上下文动态生成词向量 、并且可以并行计算的模型架构------这正是Transformer与BERT诞生的背景。


二、BERT框架概述

BERT (B idirectional E ncoder R epresentations from Transformers)是基于Transformer编码器的双向预训练语言模型。

特性 说明
模型结构 基于Transformer的Encoder部分,采用多层自注意力机制和前馈神经网络
核心能力 预训练学习丰富的语言表示,可迁移到各类NLP下游任务
预训练任务 遮蔽语言模型(MLM)+ 下一句预测(NSP)
双向性 预测一个词时同时考虑左右两侧上下文(区别于GPT的单向自回归)
微调方式 在特定任务数据集上进一步训练,适配下游任务
历史影响 刷新11项NLP基准测试记录,奠定预训练模型范式,催生RoBERTa、ALBERT等后续工作

三、Transformer基础架构

BERT的核心骨架是Transformer的Encoder部分。要理解BERT,必须先理解Transformer。

3.1 Encoder-Decoder编码解码框架

Encoder-Decoder(编码-解码)是大部分注意力模型的基础框架,主要用于处理序列到序列(Seq2Seq) 问题------输入一个序列,输出另一个序列,且两个序列长度可以不同。

典型应用场景:

  • 机器翻译:输入英文序列 → 输出中文序列
  • 文本摘要:输入文章全文 → 输出摘要
  • 问答系统:输入问题 → 输出答案

工作流程:

复制代码
输入序列 <x1, x2, ..., xn>  →  [Encoder]  →  语义编码C  →  [Decoder]  →  输出序列 <y1, y2, ..., ym>
  • Encoder(编码器):将输入序列编码为一个语义向量C,C中存储了整个输入序列的信息。传统实现可用RNN/LSTM/GRU/BiLSTM等。
  • Decoder(解码器):根据语义编码C,逐步解码生成输出序列。
  • 编码与解码方式可任意组合:Encoder用BiLSTM,Decoder用GRU,完全可以。

通俗理解:翻译"Bonjour"时,大脑先把这个词的概念提取出来(编码),再从英语词库中找到对应的"Hello"(解码)。提取出来的"概念"就是语义向量C。

3.2 Self-Attention自注意力机制

核心问题:一句话中哪些词是重点?如何让计算机自动关注到话语中的关键词?

Self-Attention(自注意力)通过让每个词与序列中所有词计算关联程度,动态捕捉上下文语义。

第一步:构造Q、K、V三个矩阵

输入词向量通过三个可训练的权重矩阵 W Q W^Q WQ、 W K W^K WK、 W V W^V WV 分别投影得到:

  • Q(Query,查询):当前词"主动查询"其他词
  • K(Key,键):其他词"等待被查询"的特征
  • V(Value,值):其他词实际携带的信息特征

q i = x i ⋅ W Q , k i = x i ⋅ W K , v i = x i ⋅ W V q_i = x_i \cdot W^Q, \quad k_i = x_i \cdot W^K, \quad v_i = x_i \cdot W^V qi=xi⋅WQ,ki=xi⋅WK,vi=xi⋅WV

第二步:计算注意力得分

每个词的Q与序列中所有词的K计算内积,表示匹配程度:

Score ( q i , k j ) = q i ⋅ k j \text{Score}(q_i, k_j) = q_i \cdot k_j Score(qi,kj)=qi⋅kj

  • q 1 ⋅ k 1 q_1 \cdot k_1 q1⋅k1:第1个词与自身的匹配度
  • q 1 ⋅ k 2 q_1 \cdot k_2 q1⋅k2:第1个词与第2个词的匹配度

第三步:归一化(Scaling)

直接内积在维度较大时数值会很大,导致Softmax梯度消失。因此除以 d k \sqrt{d_k} dk 进行缩放:

Attention ( Q , K , V ) = Softmax ( Q K T d k ) V \text{Attention}(Q, K, V) = \text{Softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=Softmax(dk QKT)V

其中 d k d_k dk 是K向量的维度。这一步归一化的作用是:防止维度增大导致内积值过大,保持梯度稳定。

第四步:加权求和

归一化后的注意力权重与V相乘求和,得到每个词的最终特征表示 z i z_i zi。

关键特性 :每个词的Q会与整个序列中每一个K计算得分,再基于得分分配V的权重。因此同样的词在不同句子中会得到不同的特征向量------这正是解决word2vec静态表示问题的核心。
并行优势:Q、K、V矩阵可以一次性并行计算,完全避免了RNN的串行依赖,极大提升了训练速度。

3.3 Multi-Head Attention多头注意力

卷积神经网络中用多组卷积核提取不同特征图。同理,Transformer中用多组Q、K、V可以得到多种词的特征表达。

多头机制的工作流程:

  1. 拆分多头 :将 d m o d e l d_{model} dmodel 维的Q、K、V拆分为 h h h 个低维子空间(通常 h = 8 h=8 h=8),每个头独立计算Attention。
  2. 并行计算 :每个头独立输出 Z 0 , Z 1 , ... , Z h − 1 Z_0, Z_1, \dots, Z_{h-1} Z0,Z1,...,Zh−1,分别关注不同的语义信息(有的头关注语法,有的头关注指代关系)。
  3. 拼接 :将所有头的输出沿特征维度拼接: Concat ( Z 0 , Z 1 , ... , Z h − 1 ) \text{Concat}(Z_0, Z_1, \dots, Z_{h-1}) Concat(Z0,Z1,...,Zh−1)。
  4. 线性降维 :拼接后通过一个全连接层 W O W^O WO 降维,得到最终输出。

MultiHead ( Q , K , V ) = Concat ( head 1 , ... , head h ) W O \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \dots, \text{head}_h) W^O MultiHead(Q,K,V)=Concat(head1,...,headh)WO

其中 head i = Attention ( Q W i Q , K W i K , V W i V ) \text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V) headi=Attention(QWiQ,KWiK,VWiV)。

3.4 多层堆叠

单层Self-Attention的表达能力有限,实际使用时将多个Encoder Layer堆叠起来(类似CNN堆多层卷积):

复制代码
输入Embedding → [Encoder Layer 1] → [Encoder Layer 2] → ... → [Encoder Layer N] → 输出表示

BERT-base堆叠了12层,BERT-large堆叠了24层。层数越多,模型能捕捉的语义层次越深。

3.5 位置编码(Positional Encoding)

问题:Self-Attention本身是"无序"的------它只关心句子中有哪些词,不关心词的顺序。但语序对语言至关重要("我打你" vs "你打我")。

因此必须引入位置信息。

方法一:0-1范围归一化位置

复制代码
我喜欢吃洋葱      → [0, 0.16, 0.32, ..., 1.0]
我真的不喜欢吃洋葱 → [0, 0.125, 0.25, ..., 1.0]

缺陷:句子长度不同,相同位置的编码值不同,无法跨句子比较位置。

方法二:1-n正整数编号

复制代码
我喜欢吃洋葱      → [1, 2, 3, 4, 5, 6]
我真的不喜欢吃洋葱 → [1, 2, 3, 4, 5, 6, 7]

缺陷:句子越长,后面的数字越大,导致位置权重被数值大小扭曲。

方法三:三角函数位置编码(Transformer采用)

Transformer作者设计了基于正弦/余弦的位置编码公式:

P E ( p o s , 2 i ) = sin ⁡ ( p o s 10000 2 i / d m o d e l ) PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) PE(pos,2i)=sin(100002i/dmodelpos)

P E ( p o s , 2 i + 1 ) = cos ⁡ ( p o s 10000 2 i / d m o d e l ) PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right) PE(pos,2i+1)=cos(100002i/dmodelpos)

  • pos:词在句子中的位置(从0开始)
  • d m o d e l d_{model} dmodel:词向量的维度
  • i i i :维度索引( i = 0 , 1 , ... , d m o d e l / 2 − 1 i = 0, 1, \dots, d_{model}/2 - 1 i=0,1,...,dmodel/2−1)
  • 偶数维 用sin,奇数维用cos

最终输入 :将词向量(Word Embedding)与位置编码(Positional Encoding)逐点相加:

Input = WordEmbedding + PositionalEncoding \text{Input} = \text{WordEmbedding} + \text{PositionalEncoding} Input=WordEmbedding+PositionalEncoding

优点:

  1. PE值分布在 − 1 , 1 -1, 1 −1,1 区间,不会随序列长度增长而放大。
  2. 不同句子中相同位置的PE值相同(如pos=0时PE=0),具有跨句子的泛化能力。
  3. 相对位置可被学习: P E p o s + k PE_{pos+k} PEpos+k 可以表示为 P E p o s PE_{pos} PEpos 的线性函数。

3.6 Add & Norm 残差与归一化

每个Encoder Layer内部包含两个关键操作:

  • Add(残差连接) :将Attention的输入直接加到输出上(类似ResNet的shortcut),缓解深层网络梯度消失问题。

    Output = Sublayer ( x ) + x \text{Output} = \text{Sublayer}(x) + x Output=Sublayer(x)+x

  • Norm(Layer Normalization):对每个样本的特征做归一化,加速收敛、稳定训练。

完整子层结构:

复制代码
x → Multi-Head Attention → Add(x + attn_output) → Norm → Feed Forward → Add → Norm → 输出

3.7 Transformer整体框架

Transformer整体由Encoder堆栈和Decoder堆栈组成:

  • Encoder侧:N层Encoder Layer,每层包含 Multi-Head Attention + Feed Forward(两层全连接)。
  • Decoder侧:N层Decoder Layer,包含 Masked Multi-Head Attention + Encoder-Decoder Attention + Feed Forward。
  • Feed Forward层:一个两层的全连接神经网络,中间激活函数为ReLU/GELU。

重要区分 :BERT只用了Encoder部分,没有Decoder。这是BERT与GPT(只用Decoder)、原始Transformer(两者都用)的核心结构区别。

3.8 Decoder的Shifted Right操作

Decoder在训练时使用"Shifted Right"技巧:

  • 将目标输出序列右移一位,最左侧添加起始符 <sos>(Start Of Sentence)。
  • 训练时解码器以 <sos> 开头,逐步预测下一个词。

示例(中译英任务):

  • 输入:我爱中国
  • 目标输出:I love China
  • Decoder输入(shifted right):<sos> I love China
  • Decoder输出预测:I love China <eos>

这样解码器在生成每个词时,都能基于已经生成的前缀进行预测,实现自回归生成。


四、BERT预训练任务详解

BERT在大规模无标注语料上进行预训练,使用两个自监督任务:

4.1 Masked Language Model(MLM)遮蔽语言模型

核心思想:随机遮蔽输入中15%的词,让模型根据上下文预测被遮蔽的词。这就是"完形填空"任务。

15%的Masking策略细节(BERT论文的重要设计):

被选中的15%的词中:

  • 80% 替换为 [MASK] 标记,如"我今天去面试" → "我MASK天去MASK试"
  • 10% 随机替换为另一个词(防止模型过度依赖MASK标记)
  • 10% 保持原词不变(降低预训练与微调的差距)

为什么按字Mask而不是按词Mask?

因为词的组合太多(今天、明天、后天、上午、下午......),按字Mask的预测空间更小,模型更容易学。

双向性的体现:预测被Mask的词时,模型同时看到左右两侧的上下文------这正是BERT"双向"的含义。

4.2 Next Sentence Prediction(NSP)下一句预测

核心思想:判断两个句子A和B在原文中是否是连续的上下句。

输入构造:

复制代码
[CLS] 句子A [SEP] 句子B [SEP]

正样本(Label = IsNext):

复制代码
[CLS] 我今天去面试 [SEP] 准备好了简历 [SEP]   →  Label: yes

负样本(Label = NotNext):

复制代码
[CLS] 我今天去面试 [SEP] 中午吃了包子 [SEP]   →  Label: no

特殊标记说明:

标记 全称 作用
[CLS] Classification Token 放在序列开头,最终输出用于分类任务;训练中也作为一个普通token参与学习
[SEP] Separator Token 分隔两个句子,或表示单句结束
[MASK] Mask Token MLM任务中被遮蔽的位置

为什么需要NSP?

许多下游任务(如问答QA、自然语言推理NLI)需要理解句子间的关系,NSP让模型学到句间连贯性,而不仅仅是单词语义。


五、BERT模型变体与参数规格

BERT论文中发布了两个版本:

模型规格 层数(Encoder) 隐藏维度 Attention头数 参数量 适用场景
BERT-base 12 768 12 ~110M 日常微调、资源有限场景
BERT-large 24 1024 16 ~340M 追求SOTA效果、算力充足场景

其他关键超参数:

  • 最大序列长度:512 tokens
  • Batch Size:128,000 words
  • 训练步数:1,000,000步
  • 训练数据:BooksCorpus(8亿词)+ English Wikipedia(25亿词)
  • 优化器:Adam, β 1 = 0.9 \beta_1=0.9 β1=0.9, β 2 = 0.999 \beta_2=0.999 β2=0.999, LR = 1 e − 4 \text{LR}=1e-4 LR=1e−4
  • Warmup Steps:10,000

六、BERT微调与下游应用

预训练完成后,BERT可以通过微调(Fine-tuning) 适配各类下游NLP任务。微调时将预训练参数初始化,用下游任务数据继续训练即可。

常见下游任务与微调方式

任务类型 输入示例 微调方式
文本分类 单句 → 情感/主题类别 取[CLS]输出接分类层
命名实体识别(NER) 句子 → 每个词的实体标签 对每个token输出接分类层
问答系统(QA) 问题+段落 → 答案起止位置 预测答案的start/end span
自然语言推理(NLI) 前提+假设 → 蕴含/矛盾/中立 用[CLS]做句对分类
文本相似度 句子A+句子B → 相似度分数 句对表示接回归层

BERT的灵活性:只需在Encoder输出后接一个简单的任务层(分类层/span预测层等),几乎所有NLP任务都能适配------这是BERT通用性强的根本原因。


七、总结

  1. BERT的本质:一个基于Transformer Encoder的双向预训练语言模型,通过MLM和NSP两个自监督任务学习深层语言表示。
  2. 技术突破 :
    • 双向上下文建模( vs GPT的单向)
    • Self-Attention并行计算( vs RNN的串行)
    • 预训练+微调范式(取代任务定制模型)
  3. 关键组件:Self-Attention → Multi-Head → 位置编码 → 残差连接 → LayerNorm → 多层堆叠。

BERT的历史地位

BERT开启了NLP的"预训练时代",后续涌现了大量改进模型:

  • RoBERTa:去掉NSP、更大batch、更多数据,进一步提升效果
  • ALBERT:缩小参数量(跨层参数共享、词向量分解),提升训练效率
  • DistilBERT:模型蒸馏,参数量减少40%,速度提升60%,保留97%效果
  • GPT系列:Decoder路线的自回归预训练,走向生成式AI
相关推荐
小oo呆3 小时前
【自然语言处理与大模型】自然语言处理的漫漫长路之深度学习时代
人工智能·深度学习·自然语言处理
小oo呆3 小时前
【自然语言处理与大模型】自然语言处理的漫漫长路之文本向量化
人工智能·自然语言处理
金牛的技术笔记7 小时前
BERT增量微调实战:冻结BERT,用ChnSentiCorp训练中文情感分类器
人工智能·深度学习·bert
布吉岛的石头1 天前
Java 程序员第 50 阶段13:对齐税 alignment tax 是什么
人工智能·深度学习·transformer
米饭是菜qy1 天前
深度学习Transformer详细介绍
人工智能·深度学习·transformer
Eloudy1 天前
《Attention Is All You Need》的 Encoder–Decoder Transformer 一次完整训练
llm·transformer
Solange__1 天前
AI世界模型、3D场景生成和游戏引擎怎么选?按5类任务比较交互、物理与导出
开发语言·人工智能·游戏·平面·3d·自然语言处理·游戏引擎
Solange__1 天前
物流园区怎么用AI生成3D调度预演?从道路底图、车辆转弯到网页评审
图像处理·人工智能·游戏·3d·ai·自然语言处理·关卡设计
Zzj_tju2 天前
长期记忆让智能体更可靠,还是让错误持续累积?
人工智能·机器学习·语言模型·自然语言处理