Bonus:LLM 训练全景手册(框架 / 训练模式 / 输入输出 / 最简测试)
不重复网上「100 行 PyTorch 训练 GPT-2」的入门文,只讲生产/工业级。跟 Day 8 vLLM 推理对照看:训练完模型 → vLLM 服务化。
0. 训练全景:一张图理清
Pre-train (PT) ──→ Base model (Qwen2.5-3B-Base, Llama-3-8B)
下一 token 预测 │
│ Continued Pre-training (CPT, 领域语料,仍是下一 token)
↓
SFT (Supervised ──→ Instruct model (Qwen2.5-3B-Instruct)
Fine-Tuning) │ 学指令格式
│
┌──────────────┼──────────────┐
↓ ↓ ↓
DPO / ORPO KTO / GRPO PPO + Reward Model ← 偏好对齐 / RLHF
│
↓
Aligned model (生产可用)
可叠加能力(任何阶段):
- LoRA / QLoRA / DoRA PEFT, 省显存
- Distillation 小学大
- Quantization-aware Training 训练时就量化
记住:Pre-train / SFT / 偏好对齐(DPO/PPO/GRPO/...)= 3 大阶段。后面要么全参微调,要么 PEFT。
1. 选型矩阵:什么场景用什么框架
| 场景 | 推荐 | 备选 |
|---|---|---|
| 1 张 GPU 全参微调 < 7B | HuggingFace transformers.Trainer + Accelerate | TRL SFTTrainer |
| 1 张 GPU QLoRA 微调 7B~70B | Unsloth(单卡最快)/ LLaMA-Factory | Axolotl |
| 多卡 / 多机 全参 7B~70B | DeepSpeed ZeRO-3 + LLaMA-Factory | FSDP + Accelerate |
| 多卡 / 多机 全参 70B+(训练!) | Megatron-LM / Megatron-DeepSpeed | NeMo |
| DPO / ORPO / KTO | TRL DPOTrainer / KTOTrainer | LLaMA-Factory |
| PPO / GRPO(RLHF) | TRL PPOTrainer / GRPOTrainer | OpenRLHF / verl(大规模) |
| 多模态(VLM) | LLaMA-Factory(支持 Qwen2-VL/MiniCPM) | transformers + 自写 |
| Diffusion 训练 | diffusers + Accelerate | OneTrainer / kohya_ss |
| 超长上下文训练(128K+) | Megatron-LM + Sequence Parallel | DeepSpeed-Ulysses |
| 从零 pre-train | Megatron-LM | Mosaic Composer / nanoGPT(玩具) |
新人工具链首选 LLaMA-Factory:UI + CLI 都有,90% 工业场景够用,内部封装了 DeepSpeed/FSDP/TRL/PEFT。
2. 主流框架横评
2.1 PyTorch 原生(DDP / FSDP)
原理:
- DDP(DistributedDataParallel):每张卡有模型完整副本,前向独立,反向 all-reduce 梯度。显存被模型 N 倍占用(N=卡数)。
- FSDP(Fully Sharded Data Parallel):模型分片到所有卡,前向/反向时按需 all-gather。显存 ≈ 模型大小 / N。
启动命令:
# DDP(单机多卡)
torchrun --nproc_per_node=8 train.py \
--bf16 --output_dir ./out
# FSDP(单机多卡, accelerate 包装更简单)
accelerate launch --config_file fsdp_config.yaml train.py
重要参数:
--sharding_strategy FULL_SHARD(ZeRO-3 等价)/SHARD_GRAD_OP(ZeRO-2)--mixed_precision bf16(A100 / H100 必开)--gradient_checkpointing(省显存换计算 ~30%)--cpu_offload(FSDP 把权重 offload 到 CPU,跑 70B on 单卡)
何时不用:业务模型小 + 团队不强时直接用 transformers.Trainer,它内部已经接 FSDP/DeepSpeed。
2.2 HuggingFace transformers.Trainer(最常用基线)
原理:把 PyTorch 训练循环封装成 1 个 Trainer 对象,自动接 DDP/FSDP/DeepSpeed/Accelerate,自动处理日志/checkpoint/eval/早停。业界第一基线,出了问题先 reproduce 这个再说。
启动:
from transformers import Trainer, TrainingArguments
args = TrainingArguments(
output_dir="./out",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4, # 等效 batch 16
learning_rate=2e-5,
bf16=True,
deepspeed="ds_z3.json", # 直接指 DeepSpeed 配置,自动接
save_strategy="steps",
save_steps=500,
logging_steps=10,
report_to="tensorboard",
)
Trainer(model=model, args=args, train_dataset=ds, tokenizer=tok).train()
关键参数速记:
per_device_train_batch_size×gradient_accumulation_steps= 等效 batch(撑显存就调后者)learning_rate:2e-5(SFT)/ 5e-6(DPO)/ 1e-4(LoRA);warmup_ratio0.03;lr_scheduler_type默认cosinebf16=True(A100/H100 必开)+gradient_checkpointing=True(省 30%+ 显存)max_grad_norm1.0(梯度裁剪)+weight_decay0.01eval_strategy="steps"+save_total_limit=3(省盘)+dataloader_num_workers≥ 4- 分布式:
deepspeed="ds_z3.json"或fsdp="full_shard auto_wrap"
2.3 DeepSpeed(ZeRO 1/2/3)
原理:微软方案,ZeRO 把「显存爆炸」的 3 大件分片:
- ZeRO-1:优化器状态分片(Adam 一阶/二阶矩,占 8× 模型 fp32)
- ZeRO-2:+ 梯度分片
- ZeRO-3:+ 模型权重分片(= FSDP)
- ZeRO-Infinity:+ offload 到 NVMe/CPU
典型 ds_z3.json:
{
"bf16": {"enabled": true},
"zero_optimization": {
"stage": 3,
"offload_optimizer": {"device": "cpu"},
"offload_param": {"device": "none"},
"overlap_comm": true,
"contiguous_gradients": true,
"reduce_bucket_size": 5e8
},
"gradient_accumulation_steps": "auto",
"train_micro_batch_size_per_gpu": "auto",
"wall_clock_breakdown": false
}
启动:
deepspeed --num_gpus=8 train.py --deepspeed ds_z3.json
# 或通过 transformers Trainer 内部自动启
DeepSpeed vs FSDP 怎么选:
- DeepSpeed:生态最久 / CPU offload 成熟 / 微软优化 / 70B+ 全参微调首选
- FSDP:PyTorch 原生 / 跟 HF 集成更新 / 配置更简单
- 都能用时,新项目选 FSDP(社区方向)
2.4 Megatron-LM / Megatron-DeepSpeed
原理:NVIDIA 出的预训练专用框架。引入:
- Tensor Parallelism(TP):矩阵切片到多卡(GEMM 横切 / 竖切)
- Pipeline Parallelism(PP):模型按 layer 切到多机
- Sequence Parallelism(SP):配合 TP 进一步切 LayerNorm/Dropout
- 3D 并行:DP × TP × PP,百亿+ 模型必需
何时用:7B 以下用 DDP+FSDP 够,13B+ 全参训练考虑 Megatron。GPT-3、Llama-3 系列等大厂用它。
学习成本:高(配置 + 命令复杂,要懂 3D 并行原理)
启动示意(70B Llama 8 机 64 卡):
torchrun --nproc_per_node=8 --nnodes=8 --node_rank=$RANK \
--master_addr=$MASTER_IP --master_port=6000 \
pretrain_gpt.py \
--tensor-model-parallel-size 8 \
--pipeline-model-parallel-size 8 \
--sequence-parallel \
--num-layers 80 --hidden-size 8192 --num-attention-heads 64 \
--micro-batch-size 1 --global-batch-size 1024 \
--lr 1e-4 --train-iters 100000 \
--data-path /data/c4/llama_text_document \
--tokenizer-type Llama2Tokenizer \
--bf16 --use-flash-attn
2.5 LLaMA-Factory(2024-2025 工业最热)
一站式封装,UI(llamafactory-cli webui)+ CLI,把 transformers/TRL/PEFT/DeepSpeed/FSDP 串成一个 yaml 配置即跑。支持模型 100+(Qwen / Llama / Mistral / DeepSeek / Phi / Yi / Baichuan / ChatGLM / Gemma 等),模式覆盖 PT / SFT / RM / PPO / DPO / ORPO / KTO / SimPO / GRPO,PEFT 含 LoRA / QLoRA / DoRA / GaLore / BAdam,多模态支持 Qwen2-VL / LLaVA / MiniCPM-V。
启动(yaml 配置 → CLI):
# qwen_sft.yaml
model_name_or_path: Qwen/Qwen2.5-3B-Instruct
stage: sft # pt / sft / rm / ppo / dpo / kto / orpo
do_train: true
finetuning_type: lora # full / lora / freeze
lora_target: all # 所有 linear 都加 LoRA
lora_rank: 16
lora_alpha: 32
lora_dropout: 0.05
dataset: alpaca_zh_demo # 内置 demo 或自定义
template: qwen
cutoff_len: 2048
overwrite_cache: true
preprocessing_num_workers: 16
output_dir: saves/qwen2.5-3b/lora/sft
logging_steps: 5
save_steps: 200
plot_loss: true
overwrite_output_dir: true
per_device_train_batch_size: 1
gradient_accumulation_steps: 8
learning_rate: 1.0e-4
num_train_epochs: 3.0
lr_scheduler_type: cosine
warmup_ratio: 0.1
bf16: true
ddp_timeout: 180000000
llamafactory-cli train qwen_sft.yaml
# 或 webui:
llamafactory-cli webui # 浏览器 7860,点选配置导出 yaml
LLaMA-Factory 不是底层框架,是个集成器。但因为它包装了主流所有训练模式,生产 SFT/DPO 默认用它能省 80% 时间。
2.6 TRL:Transformers Reinforcement Learning
HuggingFace 官方 RL/对齐库。提供的 Trainer:SFTTrainer(监督微调,与 transformers Trainer 区别小)、RewardTrainer(RM)、PPOTrainer、DPOTrainer、KTOTrainer、ORPOTrainer、GRPOTrainer(DeepSeek-R1 用)。
最简 DPO:
from trl import DPOTrainer, DPOConfig
config = DPOConfig(
output_dir="./dpo_out", beta=0.1, # 偏好强度
learning_rate=5e-7, # 远小于 SFT (5e-7 ~ 5e-6)
num_train_epochs=1, per_device_train_batch_size=2, bf16=True,
)
DPOTrainer(
model=model, ref_model=ref_model, # frozen 参考(可 None,内部 copy)
args=config, train_dataset=ds, # 含 prompt/chosen/rejected
tokenizer=tok,
).train()
2.7 PEFT:LoRA / QLoRA / DoRA
原理:
- LoRA:冻结原 weight,加
A·B两个低秩矩阵(rank=r),只训这俩。显存 = 原 1/100,效果 95%。 - QLoRA:LoRA + 原 weight 4bit 量化加载。24GB 卡跑 65B 模型。
- DoRA:LoRA 进阶,把 weight 分解为 magnitude + direction,direction 用 LoRA,精度提升、速度持平。
典型 QLoRA 配置:
from peft import LoraConfig, get_peft_model
from transformers import BitsAndBytesConfig
bnb = BitsAndBytesConfig(
load_in_4bit=True, bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16, bnb_4bit_use_double_quant=True,
)
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-7B", quantization_config=bnb, device_map="auto")
lora = LoraConfig(
r=16, lora_alpha=32, lora_dropout=0.05,
target_modules=["q_proj","k_proj","v_proj","o_proj",
"gate_proj","up_proj","down_proj"], # attention + MLP
task_type="CAUSAL_LM", use_dora=False, # True 改 DoRA
)
model = get_peft_model(model, lora)
model.print_trainable_parameters()
# 典型输出: trainable params: 40M / 7.6B (0.5%)
LoRA rank 选取:
- r=4 ~ 8:风格微调 / 简单 instruction
- r=16:通用 SFT(默认)
- r=64 ~ 128:接近全参效果,但已经很贵
- 一般
alpha = 2 × r
2.8 Unsloth:单卡 GPU 最快微调
重写 PyTorch attention/MLP kernel,单 GPU 比标准 transformers 快 2-5×,显存省 30-70%。只支持单卡(2024-Q4 才出多卡)。何时用:1 张消费卡(4090 / A100-40G)做 LoRA/QLoRA。
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
"unsloth/Qwen2.5-7B-Instruct-bnb-4bit",
max_seq_length=4096, dtype=None, load_in_4bit=True,
)
model = FastLanguageModel.get_peft_model(
model, r=16, lora_alpha=32,
target_modules=["q_proj","k_proj","v_proj","o_proj",
"gate_proj","up_proj","down_proj"],
)
# 后续用普通 SFTTrainer
2.9 大规模 RLHF:OpenRLHF / verl
TRL 的 PPO/GRPO 只到 single-node。多机分布式 RLHF 要协调 Actor(训练中)+ Reference(frozen,提供 KL)+ Reward(frozen)+ Critic(Actor + value head)4 个模型的切分和 Rollout 数据流转,复杂度高。
- OpenRLHF(字节系出品):基于 Ray + DeepSpeed,70B 全参 PPO 在 32×A100 跑得动。
- verl(火山引擎):HybridFlow 论文落地,RLHF 抽象更优雅。
何时用:模型 > 13B + 全参 RLHF。学术/工业前沿。
2.10 Axolotl
跟 LLaMA-Factory 同类(yaml 配置 → 跑训练),社区驱动,对新模型支持更快(Llama-3 / Mistral 类新模型 24h 内适配)。二选一即可:中文场景 LLaMA-Factory 更熟,英文 Axolotl 社区更活。
2.11 TorchTitan / xtuner / vLLM 训练用
- TorchTitan:Meta 2024 出的 PyTorch 原生大规模训练 demo 项目,纯 PyTorch + FSDP2 + Tensor Parallel,演示如何不用 Megatron 也能训百亿模型。学习 PyTorch 原生分布式的最佳读物。
- xtuner:上海 AI Lab 的训练框架,主打 InternLM 系列,集成 DeepSpeed/FSDP/序列并行,支持长上下文(200K+)。
- vLLM 训练用:vLLM 主要做推理,但 v0.6 起支持把 rollout(生成阶段)接到 OpenRLHF / verl 里跑 PPO/GRPO,rollout 提速 3-5×。生产 RLHF 几乎都拿 vLLM 当 rollout backend。
2.12 实验跟踪:WandB / TensorBoard / SwanLab
| 维度 | WandB | TensorBoard | SwanLab |
|---|---|---|---|
| 部署 | SaaS(免费个人,team 付费) | 本地 | 国内 SaaS / 自建 |
| 集成 | report_to="wandb" | report_to="tensorboard" | report_to="swanlab" |
| 优势 | 生态最强 / 协作好 | 离线无依赖 | 国内访问快 / 免费 / WandB 兼容 |
| 工业默认 | 是 | 否(只小项目用) | 国内团队渐多 |
生产建议:训练 yaml 加 report_to: ["tensorboard", "wandb"] 双写,即使 WandB 出问题也有 TB 备份。
3. 显存计算:训练为什么这么吃显存
训练显存 4 大块(以 7B 模型 fp16 为例,无任何优化):
| 项 | 公式 | 7B 示例 |
|---|---|---|
| 模型参数 | params × 2 bytes(fp16) | 14 GB |
| 梯度 | params × 2 bytes | 14 GB |
| 优化器状态(Adam) | params × 8 bytes(fp32 一阶+二阶矩) | 56 GB |
| Activation(前向缓存) | batch × seq × hidden × layers × ~6 bytes | 10~30 GB |
| 合计 | ~100 GB |
结论:7B 全参微调要 ≥ 1 张 A100-80G,或 2 张 A100-40G + ZeRO-2。
省显存的几把刀:
| 技术 | 显存节省 | 速度代价 |
|---|---|---|
gradient_checkpointing | activation -50% ~ -70% | +20% ~ +30% 训练时间 |
| ZeRO-2(梯度+优化器分片) | optimizer/grad / N | 通信增加 |
| ZeRO-3 / FSDP(全分片) | 全部 / N | 通信进一步增加 |
cpu_offload | optimizer → CPU RAM | 慢 2~5× |
| LoRA(rank=16) | 梯度 + 优化器 ≈ 0 | 训练参数 < 1% |
| QLoRA(4bit + LoRA) | 模型 14GB → 4GB | 推理速度持平 |
真实参考:7B 全参 SFT 要 8×A100-80G + ZeRO-3;7B LoRA r=16 单 A100-40G 够;7B QLoRA 单 4090(24G)够;70B 全参 SFT 要 32×A100-80G + Z3 + offload;70B QLoRA 单 A100-80G 极限。
4. 并行策略对比:DDP / DP / FSDP / ZeRO
| 策略 | 显存分布 | 通信开销 | 何时用 |
|---|---|---|---|
| DP(单进程多卡) | 每卡完整副本 | 主卡 GPU 瓶颈 | 已废弃 |
| DDP | 每卡完整副本 | all-reduce 梯度 | 模型 < 单卡显存的一半 |
| ZeRO-1 | optimizer / N | reduce-scatter | 小模型省 optimizer |
| ZeRO-2 | optimizer + grad / N | reduce-scatter | 中等模型常用 |
| ZeRO-3 / FSDP | optimizer + grad + param / N | + all-gather param | 模型 > 单卡显存 |
| TP(Tensor Parallel) | matrix 切分 | all-reduce 中间激活 | 单层 > 单卡,Megatron |
| PP(Pipeline Parallel) | layer 分段 | 段间发送 micro-batch | 多机层间分布 |
经验:DDP < ZeRO-2 < ZeRO-3,通信代价递增、显存节省递增。8 卡内 FSDP/Z3 通常够;跨节点再叠 TP/PP 组成 3D 并行。ZeRO-3 和 FSDP 在数学上等价,实现细节不同。
5. 训练模式深度(每个含原理 + 数据 + 命令 + 产物 + 最简测试)
5.1 Pre-training(PT)
原理:在大量无标注语料上做下一 token 预测(causal LM loss),从零或继续训。
数据:
- 输入:长文本(一行一篇 / 多行 chunked)
- 格式:纯文本 / JSONL
{"text": "..."}/ Parquet - 量级:B 量级 token(10B+ 才有意义)
LLaMA-Factory 命令:
stage: pt
finetuning_type: full # PT 一般全参
dataset: c4_demo # 自己的预训语料
template: empty # PT 不用 chat template
cutoff_len: 4096
产物:model.safetensors(全参 ckpt)+ config.json + tokenizer + trainer_state.json(loss 历史)。
最简跑通:用 HuggingFaceTB/SmolLM2-135M + 100 row wikitext,max_steps: 10,2 分钟内 loss 从 ~3.5 降到 ~3.0(CPU 也可跑)。
5.2 SFT:Supervised Fine-Tuning(最常用)
原理:在 instruction-output pairs 上训,只对 output 算 loss,prompt 部分 mask 掉。
数据格式(Alpaca):
{"instruction": "翻译成英文", "input": "你好", "output": "Hello"}
ShareGPT 多轮:
{"conversations": [
{"from": "human", "value": "你是谁?"},
{"from": "gpt", "value": "我是 Qwen。"},
{"from": "human", "value": "几岁?"},
{"from": "gpt", "value": "我是模型,没年龄。"}
]}
LLaMA-Factory 命令:
stage: sft
finetuning_type: lora # 或 full / freeze
template: qwen # 关键! chat template 决定 input 格式
dataset: alpaca_zh_demo
cutoff_len: 2048
mask_history: true # 多轮时只对最后一轮 assistant 算 loss
产物(LoRA 模式):adapter_model.safetensors(LoRA 权重,几十 MB)+ adapter_config.json + chat_template.jinja。全参模式产物同 PT(完整模型 + tokenizer + config)。
最简跑通:Qwen2.5-0.5B-Instruct + alpaca_zh_demo(50 sample)+ LoRA,max_steps: 20,单卡 24G GPU 上 15 分钟内 loss 从 ~2.0 降到 ~1.5。完整端到端见第 7 节。
5.3 DPO:Direct Preference Optimization
原理:SFT 后的对齐技术,绕过 Reward Model + PPO,直接用偏好对优化。比 PPO 简单 100×,效果接近。
Loss:-log σ(β × (log π(chosen) - log π_ref(chosen) - log π(rejected) + log π_ref(rejected)))
数据格式:
{
"prompt": "如何减肥?",
"chosen": "通过控制饮食 + 规律运动,逐步减少热量摄入...",
"rejected": "吃减肥药,几天瘦 10 斤。"
}
LLaMA-Factory:
stage: dpo
finetuning_type: lora
dataset: dpo_zh_demo
template: qwen
pref_beta: 0.1 # 偏好强度,经典 0.1
learning_rate: 5.0e-6 # 远小于 SFT(大于会破坏 SFT 后的能力)
产物:LoRA adapter 或全参 ckpt。最简跑通:在已 SFT 过的 0.5B 模型上 + dpo_en_demo + max_steps: 30。
5.4 ORPO:Odds Ratio Preference Optimization
DPO 进化版,不需要 SFT 阶段,SFT + DPO 一步到位(公式融合),适合从 base 直接对齐。数据同 DPO(prompt/chosen/rejected)。
stage: orpo
finetuning_type: lora
pref_beta: 0.1
learning_rate: 8.0e-6
5.5 KTO:Kahneman-Tversky Optimization
不需要 pair(chosen/rejected),**只要「这个 response 好还是不好」**单值标签,数据更易收集。
{"prompt": "...", "completion": "...", "label": true} // true = 好
{"prompt": "...", "completion": "...", "label": false} // false = 不好
stage: kto
pref_beta: 0.1
5.6 PPO:Proximal Policy Optimization(经典 RLHF)
原理:3 个模型同时跑:
- Actor(policy,训练中)
- Critic(value head,估优势)
- Reward Model(frozen,给打分)
- 加 KL 约束防止偏离 SFT 太远
优点:上限高(GPT-4 / Claude 用)。 缺点:训练不稳 / 显存 4× / 调参难。
前置:需要先训 Reward Model。
stage: ppo
reward_model: ./saves/rm_qwen # 训好的 RM
finetuning_type: lora
ppo_buffer_size: 1
ppo_score_norm: true
top_k: 0
top_p: 0.9
DPO 够用时不要碰 PPO,工业 80% 项目已转 DPO/ORPO。
5.7 GRPO:Group Relative Policy Optimization
原理:DeepSeek-R1 / DeepSeek-Math 用的算法。无 Critic 网络(省 1 个模型),group sampling 算相对优势。
为啥火:训推理能力(数学 / 代码)效果好,而且比 PPO 省显存 25%。
stage: grpo
reward_funcs: # 可写 reward 函数(代码可执行 / math 答案匹配)
- format_reward
- accuracy_reward
num_generations: 8 # 每 prompt 采 8 个 response 作 group
5.8 Reward Model(RM)训练
训练一个 base model 输出 single scalar score。loss 是 pair-wise:-log σ(r_chosen - r_rejected)。数据同 DPO,产物 = model with value head(v_head.bin)+ 主模型。
stage: rm
finetuning_type: lora
dataset: rm_zh_demo
5.9 Continued Pre-training(CPT)
SFT 之前 / 之后,继续用领域语料做 next-token 预测。适合「通用 model + 法律/医疗/代码」场景。关键:learning rate 小(2e-5,跟 PT 一样);一般加 5-20% 原 pretrain 语料防遗忘(rehearsal)。
stage: pt
finetuning_type: lora # CPT + LoRA 是常见组合,省显存
dataset: legal_corpus_10b_token
5.10 Knowledge Distillation
大模型(teacher)给小模型(student)当监督信号。三种姿势:hard distill(teacher 生成 SFT 数据 → student 直接 SFT)、soft distill(KL(student_logits, teacher_logits))、on-policy(student 生成 → teacher 改正 → student 学)。工业最常见 hard distill:用 GPT-4 / Claude 生成 100K 高质量 SFT 数据训自己的 7B。
5.11 多模态训练(VLM)
结构:Vision Encoder(CLIP/SigLIP/InternViT)+ Projector + LLM。三阶段训练:Stage 1 冻 ViT + LLM 只训 Projector(图文 align)→ Stage 2 冻 ViT 训 Projector + LLM(指令跟随)→ Stage 3 全参微调(RLHF/DPO)。
# LLaMA-Factory Qwen2-VL 微调
model_name_or_path: Qwen/Qwen2-VL-7B-Instruct
stage: sft
visual_inputs: true # 关键
template: qwen2_vl
dataset: llava_mix_demo
freeze_vision_tower: true # Stage 1/2 都冻
6. 输入/输出文件详解
6.1 训练数据格式
| 格式 | 用途 | 备注 |
|---|---|---|
.jsonl | 单行单 sample | 工业最常用 |
.parquet | 列存压缩 | 数据量 > 100GB 用 |
.arrow | HF Dataset 默认 | 训练时自动转 |
| streaming | datasets.load_dataset(..., streaming=True) | 数据远超内存时 |
6.2 输出文件结构(全参 vs LoRA 对比)
saves/qwen2.5-3b/full/sft/ ← 全参微调
├── config.json # 模型架构配置
├── generation_config.json # 默认 sampling 参数
├── model-0000{1,2}-of-00002.safetensors + index.json
├── tokenizer.json + tokenizer_config.json + special_tokens_map.json
├── trainer_state.json # 训练历史(loss/lr 曲线)
├── training_args.bin # 训练参数(用于 resume)
├── {all,train,eval}_results.json
└── checkpoint-1000/ # 中间 checkpoint
└── ... (同上 + optimizer.pt + rng_state.pth)
saves/qwen2.5-3b/lora/sft/ ← LoRA 模式
├── adapter_config.json # rank/alpha/target_modules
├── adapter_model.safetensors # 仅 LoRA 权重(~40MB)
├── chat_template.jinja
├── tokenizer.json + tokenizer_config.json + special_tokens_map.json
├── trainer_state.json
└── README.md
关键文件解读:
| 文件 | 内容 | 修改影响 |
|---|---|---|
config.json | hidden_size / num_layers 等架构超参 | 改了 = 不一样模型,不可加载 |
tokenizer_config.json 内 chat_template | jinja 模板控制 prompt 格式 | 改 = inference 输出格式变 |
generation_config.json | 默认 temperature/top_p/max_new_tokens | 不影响 weight,可改 |
trainer_state.json | 完整 loss/lr/step 曲线 | 拷给 monitoring / 绘图 |
6.3 转格式(推理优化)
# safetensors → GGUF (llama.cpp / Ollama 用)
python llama.cpp/convert_hf_to_gguf.py /path/to/model --outfile model.gguf
# safetensors → AWQ INT4 (vLLM 友好)
python -m awq.entry --model_path /path/to/model \
--w_bit 4 --q_group_size 128 --version GEMM \
--save_path /path/to/model-awq
# safetensors → GPTQ
python -m auto_gptq --model_path /path/to/model --bits 4 \
--group_size 128 --save_path ...
# LoRA adapter merge 回 base(生成完整 model 可被 vLLM 加载)
python -m peft.merge_lora --base_model Qwen/Qwen2.5-7B \
--adapter ./adapter --output ./merged
7. 最简完整测试:从零跑通端到端
场景:Qwen2.5-0.5B + LoRA SFT 在 50 行 alpaca 数据上跑 20 step。
环境准备(单 GPU 24G 即可,A800 切 1g.5gb MIG 也行):
# 1. 装依赖
pip install -U llamafactory[torch,metrics] bitsandbytes
# 2. clone LLaMA-Factory 内置 demo 数据
git clone https://github.com/hiyouga/LLaMA-Factory
cd LLaMA-Factory
# 3. 写 yaml
cat > smoke_sft.yaml <<EOF
model_name_or_path: Qwen/Qwen2.5-0.5B-Instruct
stage: sft
do_train: true
finetuning_type: lora
lora_target: all
lora_rank: 8
lora_alpha: 16
template: qwen
dataset: alpaca_zh_demo # 内置 50 sample
cutoff_len: 1024
max_samples: 50
output_dir: /tmp/smoke_sft
overwrite_output_dir: true
logging_steps: 1
save_steps: 50
plot_loss: true
per_device_train_batch_size: 1
gradient_accumulation_steps: 4
learning_rate: 1.0e-4
max_steps: 20
lr_scheduler_type: cosine
warmup_ratio: 0.1
bf16: true
EOF
# 4. 跑
llamafactory-cli train smoke_sft.yaml
预期输出(15 分钟内):
[INFO] trainable params: 1,081,344 || all params: 495M (0.22%)
Step 1/20 | loss: 2.13 | lr: 1e-5 | grad_norm: 0.51
Step 5/20 | loss: 1.87 | lr: 5e-5
Step 10/20 | loss: 1.62 | lr: 1e-4
Step 15/20 | loss: 1.51 | lr: 8e-5
Step 20/20 | loss: 1.44 | lr: 5e-5
[INFO] Training completed. Loss curve saved to training_loss.png
产物在 /tmp/smoke_sft/:adapter_config.json / adapter_model.safetensors / chat_template.jinja / training_loss.png / trainer_state.json 等。
验证推理 + 服务化(跟 Day 8 联动):
# 1. 直接用 LoRA + base 推理
llamafactory-cli chat \
--model_name_or_path Qwen/Qwen2.5-0.5B-Instruct \
--adapter_name_or_path /tmp/smoke_sft \
--template qwen --finetuning_type lora
# 2. Merge adapter 回 base
llamafactory-cli export \
--model_name_or_path Qwen/Qwen2.5-0.5B-Instruct \
--adapter_name_or_path /tmp/smoke_sft \
--template qwen --finetuning_type lora \
--export_dir /tmp/smoke_merged --export_size 5
# 3. 起 vLLM 服务
python -m vllm.entrypoints.openai.api_server \
--model /tmp/smoke_merged --served-model-name my-qwen-sft --port 8000
# 4. 调用
curl localhost:8000/v1/chat/completions \
-d '{"model":"my-qwen-sft","messages":[{"role":"user","content":"你好"}]}'
8. K8s 上跑训练:TrainingJob CRD 草案
跟 Day 13.A LLM Operator 同理,可写 TrainingJob CRD:
apiVersion: training.bootcamp.local/v1
kind: TrainingJob
metadata: {name: qwen-sft-job-001}
spec:
baseModel: Qwen/Qwen2.5-7B-Instruct
stage: sft # pt / sft / dpo / orpo / kto / ppo / grpo
finetuningType: lora # full / lora / qlora
loraConfig: {rank: 16, alpha: 32, targetModules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]}
dataset: {source: s3://bucket/alpaca-zh.jsonl, template: qwen, cutoffLen: 4096}
hyperparams: {epochs: 3, perDeviceBatchSize: 1, gradientAccumulation: 8, learningRate: 1.0e-4}
resources: {gpuCount: 4, gpuType: A800, distributedFramework: deepspeed_z3} # ddp / fsdp / deepspeed_z3
output:
target: s3://bucket/saves/qwen-sft-job-001/
pushToRegistry: harbor.local/models/qwen-sft:v1 # 训完自动 push
monitoring: {wandb: true, tensorboard: true}
Reconciler 工作:解析 spec → 生成 LLaMA-Factory yaml → 创建 Job(NVIDIA Device Plugin GPU 申请 + Longhorn PVC 存 checkpoint)→ 训练完成 push merged model 到 Harbor → 触发 LLMService CR(Day 13.A)自动起 vLLM。TrainingJob CRD → LLMService CRD 一气呵成即工业级 AI Platform 的样子。
K8s 训练调度的两大方案:Volcano(CNCF batch scheduler,gang scheduling + 队列优先级 + fair share)和 MPI Operator(Kubeflow,跑 horovod / mpirun 风格多机训练)。Megatron / DeepSpeed 多机训练强烈建议加 Volcano:单纯 Deployment 启 N 个 pod 时 K8s 不保证同时起,半数 Pending 时另一半已在 NCCL all-reduce 等不到对端,30 分钟超时整个 Job 失败。
9. 跟 Day 1-14 的联动
| 训练阶段 | bootcamp 中的位置 |
|---|---|
| 数据存储 | Day 4 Longhorn(PVC 存训练 checkpoint) |
| 训练任务调度 | Day 6(HPA on queue depth)/ Day 10(MIG 切片让多个 LoRA 训练并行) |
| 镜像与制品 | Day 7 Harbor(训练镜像 + 训完 model push) |
| GitOps 训练 | Day 7 ArgoCD(TrainingJob CR 通过 Git 管) |
| 训练监控 | Day 6 + Day 9(Prometheus 业务/GPU 双重监控) |
| 训完即服务化 | Day 8 vLLM + Day 13.A LLMService CRD |
| 多集群训练 | Day 13.B Karmada(跨地域 GPU 池) |
| 故障恢复 | Day 12 SOP(checkpoint resume 即可) |
面试常见题
Q1:训练和推理对算力的需求差别在哪?
三个数量级差异:
- 显存:训练 ≈ 模型大小 × 6~8(params + grad + Adam 一阶/二阶 + activation),推理 ≈ 模型大小 × 1.5(params + KV cache)。7B 训练要 ~100GB,推理 fp16 只要 ~14GB。
- 算力 FLOPS:训练前向 + 反向 = 推理 3× FLOPS / token,再叠加 batch 通常 2~8,单 step 算力比推理 1 个 token 高 1~2 个数量级。
- 通信:训练有 all-reduce / all-gather 梯度,推理几乎不通信(除了 TP)。训练对 IB / NVLink 带宽敏感,推理对单卡显存带宽敏感。
延伸:训练用 A100/H100 + IB,推理用 A10/L40s + PCIe 即可。同一张 A100 用于推理是浪费。
Q2:LoRA / QLoRA 显存优化的原理是什么?
LoRA 核心:冻结原 weight W,加两个低秩矩阵 A∈R^(d×r) 和 B∈R^(r×d),前向变成 Wx + BAx。只训 A, B。
- 梯度:只有
A, B有梯度,参数量从 7B 降到 ~40M(rank=16,覆盖 attention + MLP),梯度显存 -99% - 优化器状态:Adam 一阶/二阶矩只针对
A, B,optimizer state -99% - activation:仍然要保存
W前向的中间激活,这块没省(gradient checkpointing 才能省)
QLoRA 在 LoRA 基础上把 W 用 4bit NF4 量化加载(compute dtype 仍 bf16),模型权重 14GB → 4GB。24G 卡能跑 65B QLoRA。代价:训练慢 30%,推理 merge 回 bf16 后无影响。
Q3:FSDP 和 DeepSpeed ZeRO 的区别?
数学上 FSDP ≈ ZeRO-3:都是把 param + grad + optimizer 分片到所有 GPU,前向/反向时按需 all-gather。实现差异:
| 维度 | FSDP | DeepSpeed |
|---|---|---|
| 出身 | PyTorch 原生(2.0+) | 微软外部库 |
| API | 直接 wrap nn.Module | 通过 config json |
| CPU offload | 有,相对新 | 成熟,ZeRO-Infinity 还能 offload 到 NVMe |
| HF Trainer | 配置更简单(fsdp="full_shard") | 配置项多但功能全 |
| 通信 overlap | 自动 | 需调 overlap_comm: true |
经验:新项目 8 卡以内 FSDP,70B+ 全参 + CPU offload 选 DeepSpeed。两者不能混用。
Q4:训练的 4 种并行策略各解决什么问题?
| 并行 | 切什么 | 解决的瓶颈 |
|---|---|---|
| 数据并行(DP/DDP/FSDP) | batch 切到多卡,每卡完整或分片的模型 | 数据吞吐不够 |
| 张量并行(TP) | 单个矩阵切到多卡(GEMM 横切/竖切) | 单层 weight > 单卡显存 |
| 流水线并行(PP) | 模型按 layer 段切到多机 | 整体 layer 放不下,跨节点 |
| 序列并行(SP) | 单条样本 seq 维度切片 | 单条 seq 太长(128K+) |
实战组合:7B 单机 8 卡 FSDP;70B 单机 8 卡 FSDP + CPU offload;70B 多机 DP × TP(Megatron,TP=8);175B 多机 DP × TP × PP 3D 并行;128K 长上下文再叠 SP。
Q5:训练任务怎么 K8s 化?为什么不直接 Deployment + N pod?
直接 Deployment 起 N 个 pod 的两个致命问题:
- 没有 gang scheduling:K8s 调度器一个一个 pod 处理,可能 4 个起来 4 个 Pending。已起的 4 个在 NCCL
init_process_group()等其余 worker,30 分钟超时整个 Job 失败,GPU 时间白烧。 - 没有协调启动顺序:rank=0 是 master,其他 worker 要等 master ready 才能注册,Deployment 是无序的,要自己写探活。
解决方案:
- Volcano:CNCF batch scheduler,引入 PodGroup 概念,一组 pod 要么全调度,要么全不调度,还能配 fair share / 队列 / 优先级抢占。
- MPI Operator(Kubeflow):跑 Horovod / mpirun 风格,管 launcher pod 启 N 个 worker,处理 hostfile + SSH 互信。
- PyTorchJob / Training Operator:原生 PyTorch DDP/FSDP 友好,把
MASTER_ADDR / WORLD_SIZE / RANK注入每个 pod。
生产实践:底层 Volcano 调度,上层包 TrainingJob CRD,把 LLaMA-Factory yaml + Volcano PodGroup 一起生成。
延伸
- 训完即服务化:Day 8 vLLM + Day 13.A LLMService CRD,TrainingJob 完成 → 自动 push Harbor → 触发 LLMService 起 vLLM 服务。
- 多集群训练:Day 13.B Karmada 跨地域 GPU 池,把不同 region 的 A100 池子统一调度。
- checkpoint 容错:长训练(> 24h)必开
save_steps+ Longhorn PVC,pod 挂了 resume 即可。Megatron 还支持 elastic training,节点掉了自动 reshard。