GPT模型的预训练与微调

1 预训练

GPT使用的是阉割版的Transformer decoder。它取消了第二层的多头注意力,使用最下层带掩码的多头注意力。GPT使用多个这样的Transformer层。

以最后一层的输出计算损失。

在最后一层计算损失时,目标向量在概念上使用的是预测词的One-hot表示,而不是embedding矩阵里的向量。GPT的embedding矩阵向量是和transformer参数一起更新的。

2 下游任务微调

上图是4中不同的任务,采用不同的策略,模型中间的Transformer是之前预训练好的模型,输入和后面的附件网络可以自己设计。

参数调整方式:

1. 全参数微调 - 模型参数会变

这是最传统的方式,所有预训练参数都会更新

python

# 伪代码示例
from transformers import GPT2ForSequenceClassification

model = GPT2ForSequenceClassification.from_pretrained("gpt2")

# 默认情况下,所有参数都会更新
for batch in train_dataloader:
    outputs = model(**batch)
    loss = outputs.loss
    loss.backward()  # 计算所有参数的梯度
    optimizer.step() # 更新所有参数,包括预训练权重

特点

  • ✅ 预训练模型参数:会更新
  • ✅ 下游分类头:会更新
  • 更新比例:100%参数
  • 适用场景:数据量充足、计算资源丰富时

2. 冻结主干,仅训练分类头 - 模型参数不变

只更新下游任务添加的层,冻结预训练模型的所有参数

python

model = GPT2ForSequenceClassification.from_pretrained("gpt2")

# 冻结所有预训练参数
for param in model.parameters():
    param.requires_grad = False

# 只解冻分类头(下游添加的层)
for param in model.score.parameters():  # 分类头参数
    param.requires_grad = True

特点

  • ❌ 预训练模型参数:不变(冻结)
  • ✅ 下游分类头:会更新
  • 更新比例:通常<0.1%参数
  • 适用场景:小样本学习、计算资源有限

3. 参数高效微调 - 模型参数基本不变

这是当前的主流方法,只更新极少量参数:

LoRA微调

python

from peft import LoraConfig, get_peft_model

config = LoraConfig(
    r=8,  # 秩
    target_modules=["c_attn"],  # 只在注意力层添加LoRA适配器
)
model = get_peft_model(model, config)

# 训练时只有LoRA适配器参数会被更新
# 原始预训练参数保持不变

Prefix Tuning

python

from peft import PrefixTuningConfig

config = PrefixTuningConfig(
    task_type="CAUSAL_LM",
    num_virtual_tokens=20  # 只优化前缀令牌
)
model = get_peft_model(model, config)

参数高效微调的特点

  • ❌ 预训练模型参数:基本不变
  • ✅ 少量适配器参数:会更新(通常0.1%-2%总参数)
  • ✅ 下游分类头:会更新
  • 更新比例:0.1%-2%参数
  • 适用场景:当前最流行的方式

4. 分层微调 - 部分模型参数会变

选择性解冻某些层:

python

# 解冻最后几层,冻结底层
for name, param in model.named_parameters():
    if 'h.23' in name or 'h.22' in name or 'h.21' in name:  # 最后3层
        param.requires_grad = True
    else:  # 其他层冻结
        param.requires_grad = False

不同策略对比

微调策略预训练参数更新新增参数更新参数量训练速度效果
全参数微调✅ 100%✅ 100%全部通常最好
仅分类头❌ 0%✅ 100%极少最快通常较差
LoRA❌ 0%✅ 0.1-2%很少接近全参数
分层微调✅ 部分层✅ 100%中等中等较好

实际应用建议

  1. 数据量充足 + 计算资源丰富
    • → 全参数微调(模型参数会变)
    • 效果通常最好,但成本最高
  2. 数据量中等 + 资源有限
    • → LoRA等参数高效方法(模型参数基本不变)
    • 当前工业界主流选择
  3. 数据量很少 + 快速原型
    • → 仅训练分类头(模型参数不变)
    • 快速但效果有限
  4. 多任务学习
    • → Adapter-based方法(模型参数不变)
    • 便于管理多个任务

存储和部署影响

  • 全参数微调:需要保存整个模型的副本
  • 参数高效微调:只需保存适配器权重(几MB),可与原始模型共享基础权重

python

# LoRA只需保存很小的适配器
model.save_pretrained("./lora_adapters")  # 只保存适配器,大小约几MB

# 全参数微调需要保存整个模型
model.save_pretrained("./full_finetuned")  # 保存整个模型,大小与原始模型相同

总结

  • 如果使用全参数微调:模型本身的参数会变
  • 如果使用参数高效微调(LoRA等):模型本身的参数基本不变
  • 如果使用仅训练分类头:模型本身的参数不变

当前趋势:由于计算效率和可移植性的优势,参数高效微调已成为主流选择,在这种情况下,预训练模型参数基本保持不变,只更新少量适配器参数。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇