4、语言模型基础:自回归语言模型原理、GPT系列模型架构、从预训练到指令微调、Hugging Face模型加载与推理
好,咱们进入正题。这一章聊的是语言模型的基础,说白了就是搞清楚「GPT 这类模型到底是怎么工作的」。我当年刚接触这个领域时,也被一堆术语绕得头晕。但别怕,咱们一步步拆开看。
4.1 自回归语言模型原理
自回归语言模型,名字听着唬人,其实核心就一句话:根据前面的词,预测下一个词。
你想想看,我们平时说话是不是这样?「今天天气真...」,你脑子里自然就会接「好」或者「热」。模型也是一样。它把一句话拆成一个个 token(词或子词),然后逐个预测。
数学上,它计算的是条件概率:
P(w₁, w₂, ..., wₙ) = P(w₁) × P(w₂|w₁) × P(w₃|w₁,w₂) × ... × P(wₙ|w₁,...,wₙ₋₁)
嗯,这里要注意:自回归模型只能从左往右看,不能回头。这和 BERT 那种双向模型完全不同。我在项目中遇到过有人把 GPT 当 BERT 用,结果效果惨不忍睹——因为 GPT 根本看不到后面的词。
核心要点:自回归 = 单向 + 逐词预测。这是 GPT 系列模型的根基。
4.2 GPT系列模型架构
GPT 的架构,说白了就是 Transformer 的 Decoder 部分。但做了几个关键改动:
- Masked Self-Attention:每个 token 只能看到自己和左边的 token。右边的一律遮住。
- Layer Normalization 位置调整:GPT-2 开始把 LayerNorm 放到了 Attention/FFN 之前(Pre-Norm),训练更稳定。
- 激活函数:GPT-1 用 GELU,GPT-2/3 沿用。我试过换成 ReLU,收敛速度确实差一截。
我画了一张图,帮你理清 GPT 的推理流程:
你看,整个流程就是:输入 → 嵌入 → 过 N 层 Decoder → 输出概率 → 选下一个词。然后把这个词拼回输入,继续预测下一个。这就是所谓的「自回归」。
我的经验:GPT-3 有 1750 亿参数,96 层 Decoder。但别被数字吓到,核心架构和 GPT-1(12 层)一模一样。只是更大、数据更多。
4.3 从预训练到指令微调
这里有个关键问题:预训练好的 GPT 只会「续写」,不会「回答问题」。
你给它「中国的首都是」,它可能会接「北京」,也可能接「一个古老的城市」。因为它学的是统计规律,不是事实。
所以我们需要 指令微调(Instruction Tuning)。说白了就是:拿一堆「问题-答案」对,让模型学会按指令行事。
| 阶段 | 数据 | 目标 | 典型模型 |
|---|---|---|---|
| 预训练 | 海量互联网文本(TB 级) | 学习语言规律、知识 | GPT-3, LLaMA |
| 指令微调 | 人工标注的指令数据(万级) | 学会遵循指令、对话 | InstructGPT, ChatGPT |
| RLHF | 人类偏好排序数据 | 对齐人类价值观 | ChatGPT, Claude |
我曾经踩过一个坑:直接用预训练模型做问答,结果模型输出一堆无关的续写。后来才明白——预训练和指令微调是两码事。你想想看,一个只会背字典的人,你问他「今天吃什么」,他当然答非所问。
避坑指南:千万不要在预训练阶段加入指令数据。预训练需要的是「无监督续写」,指令数据会破坏模型的语言分布。我见过有人这么干,结果模型变得只会回答问题,不会正常写文章了。
4.4 Hugging Face模型加载与推理
好,理论说完了,咱们上手实操。Hugging Face 的 transformers 库是必备工具。我建议你直接用它加载 GPT-2 试试。
先装包:
pip install transformers torch
然后加载模型和分词器:
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "gpt2" # 也可以换成 "gpt2-medium", "gpt2-large"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)
嗯,这里要注意:GPT-2 没有 pad_token。我习惯手动设置:
tokenizer.pad_token = tokenizer.eos_token # 用 eos_token 代替
推理代码很简单:
input_text = "中国的首都是"
inputs = tokenizer(input_text, return_tensors="pt")
# 生成
outputs = model.generate(
inputs.input_ids,
max_length=50,
temperature=0.7,
do_sample=True,
pad_token_id=tokenizer.eos_token_id
)
result = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(result)
你会看到模型输出类似「中国的首都是北京,也是一座历史悠久的城市...」。但注意,GPT-2 是英文模型,中文效果一般。换成 uer/gpt2-chinese-cluecorpussmall 会好很多。
我的习惯:生成时一定设 temperature。0.7 左右比较平衡。低于 0.3 太死板,高于 1.0 容易胡言乱语。另外 max_length 别设太大,否则显存容易爆。
如果你想用 GPT-3 级别的模型,Hugging Face 上也有 EleutherAI/gpt-neo-2.7B 或 meta-llama/Llama-2-7b-hf。但注意:大模型需要 GPU。我建议先在 CPU 上用小模型跑通流程,再上 GPU。
最后分享一个调试技巧:打印模型的配置,看看它有多少层、多少头:
print(model.config)
# 输出示例:GPT2Config {
# "n_layer": 12,
# "n_head": 12,
# "n_embd": 768,
# "vocab_size": 50257
# }
这样你就能直观感受到,GPT-2 small 是 12 层、12 头、768 维。GPT-3 是 96 层、96 头、12288 维。差了整整 8 倍。
好了,这一章的内容就到这。记住:自回归是核心,架构是 Decoder,微调是关键,Hugging Face 是工具。把这四点吃透,后面 RLHF 的路就好走了。
公众号:蓝海资料掘金营,微信deep3321