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 的推理流程:

GPT 自回归推理流程 输入 Token 序列 Token Embedding + Position Embedding N × Decoder Block Masked Multi-Head Self-Attention Feed Forward Network (FFN) Linear + Softmax 预测下一个 Token

你看,整个流程就是:输入 → 嵌入 → 过 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.7Bmeta-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