Skip to content

第4天:Transformer与大语言模型(2017-2022)

学习目标

  • 理解Transformer架构的诞生背景和核心思想
  • 掌握Self-Attention机制的原理
  • 了解BERT和GPT系列的演进
  • 掌握预训练+微调范式
  • 理解大语言模型时代的特点

课程内容

1. Transformer的诞生

1.1 RNN的局限性

问题1:序列处理

  • RNN必须按顺序处理序列
  • 无法并行计算
  • 训练效率低

问题2:长期依赖

  • 即使是LSTM,长序列仍有困难
  • 信息在传递中逐渐丢失
  • 难以捕捉长距离关系

问题3:固定长度表示

  • 最后的隐藏状态需要编码整个序列
  • 信息压缩导致损失
  • 难以表示复杂关系

1.2 Transformer的突破

2017年:Google发表《Attention Is All You Need》

核心思想

  • 完全基于注意力机制
  • 抛弃RNN和CNN
  • 实现完全并行计算
  • 捕捉长距离依赖

影响

  • 开启了NLP的新时代
  • 成为大语言模型的基础
  • 推动了多模态AI的发展

2. Transformer架构

2.1 整体架构

Encoder-Decoder结构

输入 → Encoder → Decoder → 输出

Encoder

  • 多层堆叠
  • 每层包含Self-Attention和Feed-Forward Network
  • 处理输入序列

Decoder

  • 多层堆叠
  • 每层包含Self-Attention、Encoder-Decoder Attention和Feed-Forward Network
  • 生成输出序列

2.2 Self-Attention机制

2.2.1 基本思想

核心思想:计算序列中每个元素与其他所有元素的相关性。

示例

句子:"The cat sat on the mat"

对于单词"cat":
- 与"The"的相关性:0.1
- 与"cat"的相关性:0.9
- 与"sat"的相关性:0.3
- 与"on"的相关性:0.2
- 与"the"的相关性:0.1
- 与"mat"的相关性:0.4

"cat"的表示 = 0.1*"The" + 0.9*"cat" + 0.3*"sat" + 0.2*"on" + 0.1*"the" + 0.4*"mat"

2.2.2 数学表达

Query、Key、Value

Q = X * W_Q
K = X * W_K
V = X * W_V

注意力分数

Attention(Q, K, V) = softmax(QK^T / √d_k) * V

步骤

  1. 计算Query和Key的点积
  2. 除以√d_k进行缩放
  3. 应用softmax得到注意力权重
  4. 用权重加权Value

示例

python
import numpy as np

def scaled_dot_product_attention(Q, K, V):
    """
    Q: (seq_len, d_k)
    K: (seq_len, d_k)
    V: (seq_len, d_v)
    """
    # 计算注意力分数
    scores = np.dot(Q, K.T) / np.sqrt(Q.shape[-1])
    
    # 应用softmax
    attention_weights = np.exp(scores) / np.sum(np.exp(scores), axis=-1, keepdims=True)
    
    # 加权Value
    output = np.dot(attention_weights, V)
    
    return output, attention_weights

# 示例
X = np.random.randn(6, 512)  # 6个词,512维
W_Q = np.random.randn(512, 64)
W_K = np.random.randn(512, 64)
W_V = np.random.randn(512, 64)

Q = np.dot(X, W_Q)
K = np.dot(X, W_K)
V = np.dot(X, W_V)

output, weights = scaled_dot_product_attention(Q, K, V)
print("Output shape:", output.shape)
print("Attention weights shape:", weights.shape)

2.2.3 Multi-Head Attention

基本思想:使用多个注意力头,捕捉不同的关系。

结构

输入
├─ Head 1: Attention(Q1, K1, V1)
├─ Head 2: Attention(Q2, K2, V2)
├─ Head 3: Attention(Q3, K3, V3)
└─ Head 4: Attention(Q4, K4, V4)
→ 拼接 → 线性变换 → 输出

数学表达

MultiHead(Q, K, V) = Concat(head_1, ..., head_h) * W^O
head_i = Attention(Q * W_i^Q, K * W_i^K, V * W_i^V)

优势

  • 捕捉多种关系
  • 增强表达能力
  • 提高模型性能

示例

python
class MultiHeadAttention:
    def __init__(self, d_model, num_heads):
        self.d_model = d_model
        self.num_heads = num_heads
        self.d_k = d_model // num_heads
        
        # 权重矩阵
        self.W_Q = np.random.randn(d_model, d_model)
        self.W_K = np.random.randn(d_model, d_model)
        self.W_V = np.random.randn(d_model, d_model)
        self.W_O = np.random.randn(d_model, d_model)
    
    def forward(self, X):
        batch_size, seq_len, d_model = X.shape
        
        # 计算Q, K, V
        Q = np.dot(X, self.W_Q)
        K = np.dot(X, self.W_K)
        V = np.dot(X, self.W_V)
        
        # 重塑为多头
        Q = Q.reshape(batch_size, seq_len, self.num_heads, self.d_k).transpose(0, 2, 1, 3)
        K = K.reshape(batch_size, seq_len, self.num_heads, self.d_k).transpose(0, 2, 1, 3)
        V = V.reshape(batch_size, seq_len, self.num_heads, self.d_k).transpose(0, 2, 1, 3)
        
        # 计算注意力
        scores = np.dot(Q, K.transpose(0, 1, 3, 2)) / np.sqrt(self.d_k)
        attention_weights = np.exp(scores) / np.sum(np.exp(scores), axis=-1, keepdims=True)
        output = np.dot(attention_weights, V)
        
        # 合并多头
        output = output.transpose(0, 2, 1, 3).reshape(batch_size, seq_len, d_model)
        
        # 线性变换
        output = np.dot(output, self.W_O)
        
        return output

2.3 Position Encoding

问题:Self-Attention没有位置信息,无法区分词序。

解决方案:添加位置编码。

公式

PE_{pos, 2i} = sin(pos / 10000^(2i/d_model))
PE_{pos, 2i+1} = cos(pos / 10000^(2i/d_model))

示例

python
def positional_encoding(seq_len, d_model):
    """
    seq_len: 序列长度
    d_model: 模型维度
    """
    PE = np.zeros((seq_len, d_model))
    
    for pos in range(seq_len):
        for i in range(d_model):
            if i % 2 == 0:
                PE[pos, i] = np.sin(pos / (10000 ** (i / d_model)))
            else:
                PE[pos, i] = np.cos(pos / (10000 ** ((i - 1) / d_model)))
    
    return PE

# 示例
PE = positional_encoding(100, 512)
print("Positional encoding shape:", PE.shape)

2.4 Feed-Forward Network

结构

FFN(x) = max(0, xW1 + b1)W2 + b2

作用

  • 非线性变换
  • 增强表达能力
  • 捕捉复杂模式

2.5 残差连接和层归一化

残差连接

Output = LayerNorm(x + Sublayer(x))

层归一化

LayerNorm(x) = γ * (x - μ) / √(σ² + ε) + β

作用

  • 加速训练
  • 稳定梯度
  • 防止梯度消失

2.6 完整的Transformer Block

Encoder Block

输入
├─ Multi-Head Self-Attention
├─ Add & Norm
├─ Feed-Forward Network
└─ Add & Norm
→ 输出

Decoder Block

输入
├─ Masked Multi-Head Self-Attention
├─ Add & Norm
├─ Multi-Head Encoder-Decoder Attention
├─ Add & Norm
├─ Feed-Forward Network
└─ Add & Norm
→ 输出

3. BERT系列

3.1 BERT(Bidirectional Encoder Representations from Transformers)

2018年:Google发表BERT

核心思想

  • 使用Transformer Encoder
  • 双向上下文理解
  • 预训练+微调范式

3.1.1 预训练任务

任务1:Masked Language Model(MLM)

方法

  • 随机mask输入序列中15%的token
  • 预测被mask的token

示例

原始句子:"The cat sat on the mat"
Mask后:"The [MASK] sat on the [MASK]"
预测:"cat", "mat"

Mask策略

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

任务2:Next Sentence Prediction(NSP)

方法

  • 给定两个句子,预测它们是否连续

示例

句子A:"The cat sat on the mat"
句子B:"It was very comfortable"
预测:是(连续)

3.1.2 模型架构

BERT-Base

  • 12层Transformer Encoder
  • 768维隐藏层
  • 12个注意力头
  • 110M参数

BERT-Large

  • 24层Transformer Encoder
  • 1024维隐藏层
  • 16个注意力头
  • 340M参数

3.1.3 微调

方法

  • 使用预训练的BERT作为特征提取器
  • 在下游任务上添加任务特定的层
  • 微调整个模型或部分层

示例

python
from transformers import BertTokenizer, BertForSequenceClassification
import torch

# 加载预训练模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)

# 输入文本
text = "This movie is great!"
inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True)

# 预测
outputs = model(**inputs)
logits = outputs.logits
predictions = torch.argmax(logits, dim=-1)

print("Prediction:", predictions.item())

3.2 BERT的变体

3.2.1 RoBERTa(Robustly optimized BERT approach)

改进

  • 更大的训练数据
  • 更长的训练时间
  • 移除NSP任务
  • 更大的batch size
  • 动态masking

3.2.2 ALBERT(A Lite BERT)

改进

  • 参数共享
  • 句子顺序预测(SOP)代替NSP
  • 更少的参数

3.2.3 DistilBERT

改进

  • 知识蒸馏
  • 更少的层数
  • 更快的推理速度

3.2.4 ELECTRA

改进

  • 替代token检测(RTD)
  • 更高效的预训练

4. GPT系列

4.1 GPT-1(2018)

核心思想

  • 使用Transformer Decoder
  • 单向自回归语言建模
  • 预训练+微调范式

模型架构

  • 12层Transformer Decoder
  • 768维隐藏层
  • 12个注意力头
  • 117M参数

预训练任务

  • 给定前面的token,预测下一个token

示例

输入:"The cat sat on the"
预测:"mat"

4.2 GPT-2(2019)

改进

  • 更大的模型(1.5B参数)
  • 更多的训练数据(WebText)
  • 更好的零样本能力

模型规模

  • GPT-2 Small: 117M参数
  • GPT-2 Medium: 345M参数
  • GPT-2 Large: 774M参数
  • GPT-2 XL: 1.5B参数

能力

  • 文本生成
  • 故事创作
  • 代码生成
  • 翻译

4.3 GPT-3(2020)

突破

  • 巨大的模型(175B参数)
  • 强大的few-shot学习能力
  • 展示了scaling laws

模型规模

  • GPT-3 Ada: 350M参数
  • GPT-3 Babbage: 1.3B参数
  • GPT-3 Curie: 6.7B参数
  • GPT-3 Davinci: 175B参数

能力

  • 文本生成
  • 问答
  • 翻译
  • 代码生成
  • 数学推理

Few-shot Learning

Zero-shot: 直接给出任务描述
One-shot: 给出一个示例
Few-shot: 给出几个示例

示例

Zero-shot:
输入:"翻译成中文:Hello world"
输出:"你好世界"

One-shot:
输入:
"翻译成中文:Hello world -> 你好世界
翻译成中文:Good morning"
输出:"早上好"

Few-shot:
输入:
"翻译成中文:Hello world -> 你好世界
翻译成中文:Good morning -> 早上好
翻译成中文:How are you"
输出:"你好吗"

4.4 GPT-3.5(2022)

改进

  • 更好的指令跟随能力
  • 更强的推理能力
  • ChatGPT的基础

ChatGPT

  • 基于GPT-3.5
  • RLHF(Reinforcement Learning from Human Feedback)
  • 对话能力
  • 代码能力

RLHF过程

  1. SFT(Supervised Fine-tuning):使用人工标注的数据微调
  2. RM(Reward Model):训练奖励模型
  3. PPO(Proximal Policy Optimization):使用强化学习优化

5. 预训练+微调范式

5.1 预训练

目标:在大规模无标注数据上学习通用表示。

数据

  • 文本:维基百科、Common Crawl、书籍
  • 代码:GitHub、Stack Overflow
  • 多模态:图像-文本对

任务

  • MLM(Masked Language Model)
  • NSP(Next Sentence Prediction)
  • 自回归语言建模

5.2 微调

目标:在下游任务上适应预训练模型。

方法

  • 全量微调:微调所有参数
  • 部分微调:只微调部分层
  • 参数高效微调(PEFT):只微调少量参数

示例

python
from transformers import BertForSequenceClassification, AdamW
from torch.utils.data import DataLoader

# 加载预训练模型
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)

# 优化器
optimizer = AdamW(model.parameters(), lr=2e-5)

# 训练循环
model.train()
for epoch in range(3):
    for batch in train_dataloader:
        optimizer.zero_grad()
        outputs = model(**batch)
        loss = outputs.loss
        loss.backward()
        optimizer.step()

5.3 提示工程(Prompt Engineering)

核心思想:通过设计提示(prompt)来引导模型生成期望的输出。

技巧

  • Few-shot:提供示例
  • Chain-of-Thought:引导推理过程
  • Role-playing:设定角色
  • Format specification:指定输出格式

示例

Few-shot:
"Q: 1+1=?
A: 2
Q: 2+2=?
A: 4
Q: 3+3=?
A:"

Chain-of-Thought:
"Q: 如果我有3个苹果,吃了1个,又买了2个,我现在有几个苹果?
A: 让我们一步步思考:
1. 最初有3个苹果
2. 吃了1个,剩下3-1=2个
3. 又买了2个,现在有2+2=4个
答案:4个苹果"

6. 多模态AI的兴起

6.1 CLIP(Contrastive Language-Image Pre-training)

2021年:OpenAI发表CLIP

核心思想

  • 联合训练图像和文本编码器
  • 学习图像和文本的对齐
  • 零样本图像分类

训练方法

  • 对比学习
  • 正样本对:图像-文本匹配
  • 负样本对:图像-文本不匹配

应用

  • 零样本图像分类
  • 图像检索
  • 文本检索

示例

python
import clip
import torch
from PIL import Image

# 加载模型
device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load("ViT-B/32", device=device)

# 准备图像和文本
image = preprocess(Image.open("cat.jpg")).unsqueeze(0).to(device)
text = clip.tokenize(["a dog", "a cat", "a bird"]).to(device)

# 计算特征
with torch.no_grad():
    image_features = model.encode_image(image)
    text_features = model.encode_text(text)
    
    # 计算相似度
    logits_per_image, logits_per_text = model(image, text)
    probs = logits_per_image.softmax(dim=-1).cpu().numpy()

print("Label probs:", probs)

6.2 DALL-E

2021年:OpenAI发布DALL-E

核心思想

  • 文本生成图像
  • 基于Transformer架构
  • 展示了生成式AI的潜力

DALL-E 2(2022)

  • 更高的图像质量
  • 更大的模型
  • 更强的理解能力

6.3 Stable Diffusion

2022年:Stability AI发布Stable Diffusion

核心思想

  • 文本生成图像
  • 基于扩散模型
  • 开源、可商用

优势

  • 开源
  • 可本地运行
  • 社区活跃

7. 大语言模型时代的特点

7.1 技术特点

Scaling Laws

  • 模型性能随参数量、数据量、计算量增加而提升
  • 涌现能力(Emergent Abilities)
  • 超大规模模型展现出小模型没有的能力

涌现能力

  • 上下文学习
  • 指令跟随
  • 推理能力
  • 代码生成

7.2 应用特点

通用性

  • 一个模型可以处理多种任务
  • 无需针对每个任务训练
  • 提示即可使用

创造性

  • 文本生成
  • 图像生成
  • 代码生成
  • 音乐生成

7.3 产业影响

AI应用爆发

  • ChatGPT
  • GitHub Copilot
  • Midjourney
  • DALL-E

行业变革

  • 软件开发
  • 内容创作
  • 客服
  • 教育

实践任务

任务1:实现Self-Attention

目标:从零实现Self-Attention机制。

要求

  1. 实现Scaled Dot-Product Attention
  2. 实现Multi-Head Attention
  3. 可视化注意力权重
  4. 在简单任务上测试

代码框架

python
import numpy as np
import matplotlib.pyplot as plt

class ScaledDotProductAttention:
    def __init__(self, d_k):
        self.d_k = d_k
    
    def forward(self, Q, K, V):
        """
        Q: (batch_size, seq_len, d_k)
        K: (batch_size, seq_len, d_k)
        V: (batch_size, seq_len, d_v)
        """
        # 计算注意力分数
        scores = np.dot(Q, K.transpose(0, 2, 1)) / np.sqrt(self.d_k)
        
        # 应用softmax
        attention_weights = np.exp(scores) / np.sum(np.exp(scores), axis=-1, keepdims=True)
        
        # 加权Value
        output = np.dot(attention_weights, V)
        
        return output, attention_weights

class MultiHeadAttention:
    def __init__(self, d_model, num_heads):
        self.d_model = d_model
        self.num_heads = num_heads
        self.d_k = d_model // num_heads
        self.attention = ScaledDotProductAttention(self.d_k)
        
        # 权重矩阵
        self.W_Q = np.random.randn(d_model, d_model)
        self.W_K = np.random.randn(d_model, d_model)
        self.W_V = np.random.randn(d_model, d_model)
        self.W_O = np.random.randn(d_model, d_model)
    
    def forward(self, X):
        """
        X: (batch_size, seq_len, d_model)
        """
        batch_size, seq_len, d_model = X.shape
        
        # 计算Q, K, V
        Q = np.dot(X, self.W_Q)
        K = np.dot(X, self.W_K)
        V = np.dot(X, self.W_V)
        
        # 重塑为多头
        Q = Q.reshape(batch_size, seq_len, self.num_heads, self.d_k).transpose(0, 2, 1, 3)
        K = K.reshape(batch_size, seq_len, self.num_heads, self.d_k).transpose(0, 2, 1, 3)
        V = V.reshape(batch_size, seq_len, self.num_heads, self.d_k).transpose(0, 2, 1, 3)
        
        # 计算注意力
        output, attention_weights = self.attention.forward(Q, K, V)
        
        # 合并多头
        output = output.transpose(0, 2, 1, 3).reshape(batch_size, seq_len, d_model)
        
        # 线性变换
        output = np.dot(output, self.W_O)
        
        return output, attention_weights

# 测试
batch_size = 2
seq_len = 10
d_model = 512
num_heads = 8

X = np.random.randn(batch_size, seq_len, d_model)
mha = MultiHeadAttention(d_model, num_heads)
output, weights = mha.forward(X)

print("Output shape:", output.shape)
print("Attention weights shape:", weights.shape)

# 可视化注意力权重
plt.figure(figsize=(10, 8))
plt.imshow(weights[0, 0], cmap='viridis')
plt.colorbar()
plt.title('Attention Weights (Head 1, Batch 1)')
plt.xlabel('Key Position')
plt.ylabel('Query Position')
plt.show()

任务2:使用预训练模型

目标:使用Hugging Face的预训练模型。

要求

  1. 使用BERT进行文本分类
  2. 使用GPT-2进行文本生成
  3. 使用CLIP进行图像分类
  4. 分析模型输出

代码框架

python
from transformers import BertTokenizer, BertForSequenceClassification, GPT2LMHeadModel, GPT2Tokenizer
import torch

# BERT文本分类
def bert_classification(text):
    tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
    model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)
    
    inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True)
    outputs = model(**inputs)
    logits = outputs.logits
    predictions = torch.argmax(logits, dim=-1)
    
    return predictions.item()

# GPT-2文本生成
def gpt2_generation(prompt, max_length=100):
    tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
    model = GPT2LMHeadModel.from_pretrained('gpt2')
    
    inputs = tokenizer(prompt, return_tensors='pt')
    outputs = model.generate(**inputs, max_length=max_length, num_return_sequences=1)
    
    generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
    return generated_text

# 测试
text = "This movie is great!"
print("BERT Classification:", bert_classification(text))

prompt = "Once upon a time"
print("GPT-2 Generation:", gpt2_generation(prompt))

任务3:提示工程

目标:研究不同提示策略的效果。

要求

  1. 设计不同的提示
  2. 测试Zero-shot、One-shot、Few-shot
  3. 测试Chain-of-Thought
  4. 分析提示效果

示例

python
def zero_shot(prompt):
    # Zero-shot提示
    return prompt

def one_shot(prompt, example):
    # One-shot提示
    return f"{example}\n\n{prompt}"

def few_shot(prompt, examples):
    # Few-shot提示
    examples_str = "\n\n".join(examples)
    return f"{examples_str}\n\n{prompt}"

def chain_of_thought(prompt):
    # Chain-of-Thought提示
    return f"{prompt}\n\n让我们一步步思考:"

# 测试
question = "如果我有3个苹果,吃了1个,又买了2个,我现在有几个苹果?"

# Zero-shot
print("Zero-shot:")
print(zero_shot(question))

# One-shot
example = "Q: 1+1=?\nA: 2"
print("\nOne-shot:")
print(one_shot(question, example))

# Few-shot
examples = [
    "Q: 1+1=?\nA: 2",
    "Q: 2+2=?\nA: 4",
    "Q: 3+3=?\nA: 6"
]
print("\nFew-shot:")
print(few_shot(question, examples))

# Chain-of-Thought
print("\nChain-of-Thought:")
print(chain_of_thought(question))

课后作业

作业1:BERT vs GPT

题目:比较BERT和GPT的架构和能力。

要求

  1. 分析BERT和GPT的架构差异
  2. 比较预训练任务
  3. 比较适用场景
  4. 撰写1500字的分析报告

作业2:预训练模型微调

题目:在下游任务上微调预训练模型。

要求

  1. 选择一个预训练模型(如BERT)
  2. 选择一个下游任务(如情感分析)
  3. 微调模型
  4. 评估性能

作业3:提示工程研究

题目:研究提示工程的效果。

要求

  1. 设计多种提示策略
  2. 在不同任务上测试
  3. 比较提示效果
  4. 总结最佳实践

参考资料

必读文献

  1. Vaswani, A., et al. (2017). "Attention Is All You Need". NeurIPS.

    • Transformer原始论文
  2. Devlin, J., et al. (2019). "BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding". NAACL.

    • BERT原始论文
  3. Brown, T., et al. (2020). "Language Models are Few-Shot Learners". NeurIPS.

    • GPT-3原始论文
  4. Radford, A., et al. (2021). "Learning Transferable Visual Models From Natural Language Supervision". ICML.

    • CLIP原始论文

推荐阅读

  1. Howard, J., & Ruder, S. (2018). "Universal Language Model Fine-tuning for Text Classification". ACL.

    • ULMFiT论文
  2. Liu, Y., et al. (2019). "RoBERTa: A Robustly Optimized BERT Pretraining Approach". arXiv.

    • RoBERTa论文
  3. Ouyang, L., et al. (2022). "Training language models to follow instructions with human feedback". NeurIPS.

    • InstructGPT论文

在线资源

  1. Hugging Face Transformers: https://huggingface.co/docs/transformers/

    • Transformers库文档
  2. The Illustrated Transformer: https://jalammar.github.io/illustrated-transformer/

    • Transformer可视化解释
  3. OpenAI API: https://platform.openai.com/docs/

    • OpenAI API文档

扩展阅读

Transformer变体

  • Child, R., et al. (2019). "Generating Long Sequences with Sparse Transformers". arXiv.

    • Sparse Transformer
  • Beltagy, I., Peters, M. E., & Cohan, A. (2020). "Longformer: The Long-Document Transformer". arXiv.

    • Longformer

多模态AI

  • Ramesh, A., et al. (2021). "Zero-Shot Text-to-Image Generation". ICML.

    • DALL-E论文
  • Rombach, R., et al. (2022). "High-Resolution Image Synthesis with Latent Diffusion Models". CVPR.

    • Stable Diffusion论文

下节预告

下一节我们将学习生成式AI爆发(2022-2023),了解ChatGPT现象、AIGC技术、Prompt Engineering、AI应用爆发,以及它们如何开启生成式AI时代。


架构师AI杜公众号二维码

扫描二维码关注"架构师AI杜"公众号,获取更多技术内容和最新动态