4. Transformer与预训练模型:从架构到Embedding
这一章,我们来聊聊Transformer和它的两个“明星孩子”——BERT和。说实话,很多同学一开始接触这些概念,会觉得特别抽象。什么Self-Attention、多头机制,听着就头大。
但你别急。我当年刚入行时也一样,看了三遍还是懵的。后来自己动手写了个简化版的Transformer,才真正搞明白。嗯,今天我就用最直白的方式,把这些核心概念给你讲透。
4.1 Transformer架构核心:Self-Attention
Transformer的核心,说白了就是Self-Attention机制。它解决了什么问题?简单说:让模型在生成某个词的时候,能“看到”句子里的所有其他词,并且知道哪些词更重要。
举个例子。句子是“The animal didn't cross the street because it was too tired”。这里的“it”指的是什么?是人还是动物?传统模型很难判断。但Self-Attention可以——它会计算“it”和“animal”之间的关联权重,发现它们关系最紧密。
核心公式(简化版):
Attention(Q, K, V) = softmax(Q × K^T / √d_k) × V
Q是查询向量,K是键向量,V是值向量。d_k是向量维度,除以√d_k是为了防止内积过大。
我在项目中遇到过一个问题:当句子长度超过512时,Self-Attention的计算量会爆炸。为什么?因为它的复杂度是O(n²)。你想想看,句子长度翻倍,计算量就变成四倍。所以后来有了Longformer、BigBird这些变体,专门处理长文本。
4.1.1 多头注意力机制
Transformer不是只用一个Attention,而是用多个“头”。每个头关注不同的语义空间。比如一个头关注语法关系,另一个头关注语义相似度。
我个人习惯把多头注意力想象成“多个专家会诊”。每个专家从不同角度分析问题,最后综合意见。这样比单个专家更全面,也更鲁棒。
小技巧: 实际项目中,头数一般设为8或16。头数太少,表达能力不够;头数太多,计算开销大,而且容易过拟合。我一般从8开始调。
4.1.2 位置编码
Transformer没有循环结构,它不知道词的顺序。所以需要位置编码来告诉模型“这个词在第几个位置”。
原始用的是正弦和余弦函数。为什么?因为这种编码方式可以表示相对位置关系。比如位置3和位置5的编码差,能反映出它们之间的距离。
我曾经踩过一个坑:直接用随机初始化位置编码,结果模型训练不收敛。后来换成预训练好的位置编码,效果立竿见影。嗯,这里要注意,位置编码的选择对长文本任务影响很大。
4.2 BERT的Embedding机制
BERT是Transformer的Encoder部分。它的Embedding机制有三个组成部分: Embedding、Segment Embedding和Position Embedding。
我刚开始用BERT时,最困惑的就是Segment Embedding。它用来区分两个句子。比如做问答任务时,问题和上下文是两段不同的文本,Segment Embedding告诉模型“这是第一句”还是“第二句”。
| Embedding类型 | 维度 | 作用 | 我的经验 |
|---|---|---|---|
| Embedding | 768 | 将词转换为向量 | 中文用WordPiece分词,注意OOV问题 |
| Segment Embedding | 768 | 区分句子A/B | 单句任务时全部设为0 |
| Position Embedding | 768 | 表示位置信息 | 最大长度512,超长文本需要截断 |
BERT的预训练任务有两个:Masked Language Model(MLM)和Next Sentence Prediction(NSP)。MLM随机遮住15%的词,让模型去预测。NSP判断两个句子是否连续。
避坑指南: 我曾经在微调BERT时,忘记把Segment Embedding加上去。结果模型在双句任务上表现极差。后来排查了半天才发现这个问题。所以,如果你用BERT做句子对任务,一定要检查Segment Embedding是否正确配置。
4.3 的Embedding机制
用的是Transformer的Decoder部分。和BERT最大的区别是:是自回归的,只能看到左边的词,看不到右边的。
这就意味着的Embedding机制里,没有Segment Embedding(因为它只处理单句),但多了一个Masked Self-Attention。这个Mask的作用是:在计算第i个词的Attention时,只能看到位置1到i的词,后面的词都遮住。
我刚开始做文本生成时,试过用BERT来做。结果发现它生成的内容前后矛盾。为什么?因为BERT能看到整个句子,它生成时“作弊”了。而老老实实地从左到右生成,反而效果更好。
关键区别:
- BERT:双向上下文,适合理解任务(分类、NER、QA)
- :单向上下文,适合生成任务(文本生成、对话、代码生成)
4.3.1 的Tokenization
使用Byte-Pair Encoding(BPE)进行分词。它会把常见的子词合并成更大的单元。比如“playing”可能被分成“play”和“ing”。
我个人习惯在中文任务中,先用jieba分词,然后再用BPE。这样能减少词汇表大小,同时保留语义信息。不过要注意,的原始分词器对中文支持不太好,建议用中文预训练版本。
经验分享: 如果你做中文生成任务,推荐使用的中文版本或者ChatGLM。它们的Embedding机制针对中文做了优化,效果比直接用原版好很多。
4.4 BERT vs :Embedding对比
我们来做个对比。BERT和虽然都基于Transformer,但Embedding机制差异很大。
| 对比维度 | BERT | |
|---|---|---|
| 架构 | Encoder only | Decoder only |
| 注意力方向 | 双向 | 单向(从左到右) |
| Embedding组成 | + Segment + Position | + Position |
| 预训练任务 | MLM + NSP | 语言模型(预测下一个词) |
| 适用场景 | 理解任务 | 生成任务 |
| 我的推荐 | 分类、NER、QA | 文本生成、对话、翻译 |
你可能会问:那能不能把两者结合起来?当然可以。比如T5模型就用了Encoder-Decoder架构,既有双向注意力,又有自回归生成。不过那是另一个话题了。
嗯,这一章的内容就到这里。Transformer的Embedding机制是理解所有预训练模型的基础。你只要掌握了Self-Attention、BERT的双向机制和的单向机制,后面的模型学起来就会轻松很多。