本目录是 CS336 作业 5:Alignment(对齐与推理强化学习) 的复现教程,包含:
- 官方英文讲义:
cs336_spring2025_assignment5_alignment.pdf - 中文版讲义:
cs336_spring2025_assignment5_alignment_zh.md - 补充作业(安全 & RLHF,可选):
cs336_spring2025_assignment5_supplement_safety_rlhf.pdf - 个人学习笔记:
README.ipynb
如果你只是想“把代码跑起来 + 做完作业要求的实验”,可以按本文档从上到下依次执行。
cs336_alignment/evaluate_math.py:零样本基线评估脚本(对应讲义 §3,当前默认用 GSM8K 代替 MATH)sft_math_reasoning.py:SFT 实验脚本(对应讲义 §4,含数据规模 sweep + 过滤后数据实验)sft_math_reasoning_ei.py:专家迭代(Expert Iteration)脚本(对应讲义 §5)grpo_experiments.py:GRPO 及一系列消融/排行榜实验脚本(对应讲义 §7–9,基于 Typer 的 CLI)sft_helper.py:你需要实现的 SFT & 评分相关核心函数(tokenize_prompt_and_output等)gpro_helper.py:你需要实现的 GRPO/策略梯度相关核心函数(compute_group_normalized_rewards等)drgrpo_grader.py:奖励函数实现(r1_zero_reward_fn、question_only_reward_fn)log.py:日志与生成样例记录工具(log_generations)prompts/:提示模板r1_zero.prompt:默认 R1-Zero 提示question_only.prompt:只保留{question}的提示(用于提示消融)
data/gsm8k/test.jsonl:评测集(当前作为 MATH 的替代品)math12k/sft_gpt-oss-120b.jsonl:使用教师模型根据原 math 12k 蒸馏得到的带推理轨迹 SFT 数据sft/sft_gpt-oss-120b_filtered.jsonl:在sft_gpt-oss-120b.jsonl基础上,过滤只保留“答案正确”的 SFT 数据
results/:各类实验输出(评测结果、日志等)wandb/:各类实验记录
更详细的背景与代码讲解,可以参考:
- 讲义中文版:
cs336_spring2025_assignment5_alignment_zh.md - 分步讲解文档:
README.ipynb
- 推荐使用 Python 3.11–3.12(
pyproject.toml中已限定>=3.11,<3.13) - 本仓库使用
uv管理虚拟环境与依赖 - 依赖声明见
pyproject.toml,主要包括:torch、transformers、vllm、flash-attn、acceleratemath-verify、wandb、pytest等
遵循官方作业的步骤,我们分两步安装(先跳过 flash-attn 再整体安装):
uv sync --no-install-package flash-attn
uv sync如果你希望显式激活虚拟环境(可选):
source .venv/bin/activate- 代码默认使用 Qwen2.5-Math-1.5B 作为基础模型,并假设它位于:
/home/magnus-share/xuhu/model/Qwen2___5-Math-1___5B
- 如果你的模型路径不同,请修改以下文件中的
MODEL_PATH/BASE_MODEL等常量:cs336_alignment/evaluate_math.pycs336_alignment/sft_math_reasoning.pycs336_alignment/sft_math_reasoning_ei.pycs336_alignment/grpo_experiments.py中的GRPOConfig.base_model
建议使用带有至少 80GB 显存的 GPU(运行完整 SFT / GRPO 实验时更推荐 2*80GB 级别)。
本节对应讲义中的各个大题,给出“直接能跑”的脚本入口,方便你做作业与复现实验。如果你没有那么多资源从头复现,但是又想要看下结果,我们也提供了实验记录可直接访问:
- SFT 实验记录:https://wandb.ai/xuhu0115-sju/cs336-a5-sft-v3/reports/SFT---VmlldzoxNjMyNzcwMQ?accessToken=m394f64hkl5x8w0jl009n2ei6rj840zr6xnhtoa1jbp89xmvvvxz2o5yskggr5kp
- SFT_EI 实验记录:https://wandb.ai/xuhu0115-sju/cs336-a5-sft-ei/reports/SFT_EI---VmlldzoxNjMyNzc4NQ
- GRPO 实验记录:https://wandb.ai/xuhu0115-sju/cs336-a5-grpo/reports/GRPO---VmlldzoxNjMyNzU2Nw?accessToken=nrc0axnuk9qmovpv9kb4o5vfgshek2emf7bzo03llwywkdppnuzpvwlv4gp9693s
所有的内容讲解和结果分析都在README.ipynb,不知道从哪里开始的可以直接跳到这!
- 脚本:
cs336_alignment/evaluate_math.py - 当前默认:
MODEL_PATH指向本地 Qwen2.5-Math-1.5BMATH_VALIDATION_PATH = "data/gsm8k/test.jsonl"(用 GSM8K 代替 MATH)- 提示模板使用
cs336_alignment/prompts/r1_zero.prompt
运行方式:
uv run python cs336_alignment/evaluate_math.py运行结束后,你会得到:
- 终端打印的整体指标(
answer_accuracy/format_rate/reward_mean等) - 结果文件:
results/base/zero_shot_math_evaluation.jsonl- 每一行是一条样本,包含问题、模型生成、奖励拆分等信息
这些结果可以直接用于回答讲义中关于 (1,1)/(1,0)/(0,0) 三类样本数量与误差来源分析的问题。
- 脚本:
cs336_alignment/sft_math_reasoning.py - 功能:
- 在
data/sft/sft_gpt-oss-120b.jsonl上做不同数据规模的 SFT({128, 256, 512, 1024, full}) - 在过滤后的
data/sft/sft_gpt-oss-120b_filtered.jsonl上重复上述实验 - 使用
evaluate_vllm+r1_zero_reward_fn在data/gsm8k/test.jsonl上评估
- 在
运行方式(一次性跑完所有 SFT 实验):
uv run python cs336_alignment/sft_math_reasoning.py输出:
- 结果目录:
results/sft_experiments_*/*/step_*/results.jsonl:每次评估的详细生成与奖励- 通过
wandb记录的训练 / 评估曲线(loss、acc、熵等)
- 脚本:
cs336_alignment/sft_math_reasoning_ei.py - 功能:
- 在当前基础模型或 SFT 模型上生成推理轨迹
- 过滤掉错误的轨迹,只在“专家样本”上继续训练
- 记录每一轮 EI 后验证集上的表现与 token 熵变化
运行方式(示例,实际请参考脚本头部注释和你自己的 GPU 资源情况):
uv run python cs336_alignment/sft_math_reasoning_ei.py输出:
- 对应的
results/ei_*目录 wandb中的 EI 步数 vs 验证准确率 / 熵曲线
这些结果可用于回答讲义中关于 专家迭代提升、与纯 SFT 对比 的问题。
- 核心脚本:
cs336_alignment/grpo_experiments.py - 该脚本使用 Typer 提供命令行接口,包含:
- 学习率扫描:
lr_sweep - 基线比较:
baselines - 长度归一化:
length_norm - 分组标准差归一化:
std_norm - 离策略 GRPO:
off_policy/off_policy_sweep - 裁剪消融:
clip_ablation - 提示消融:
prompt_ablation - 排行榜挑战:
leaderboard
- 学习率扫描:
先查看所有可用子命令:
uv run python cs336_alignment/grpo_experiments.py --help示例(学习率扫描实验):
uv run python cs336_alignment/grpo_experiments.py lr-sweep每个子命令会:
- 构造对应的
GRPOConfig(如学习率、是否使用分组标准差、长度归一化方式等) - 调用
run_grpo_experiment执行完整的 GRPO 训练循环 - 在
results/grpo_*目录下保存评测结果,并通过wandb记录训练 / 评估曲线
你可以基于这些结果回答讲义中关于:
- 学习率扫描
- 基线(无基线 vs 分组归一化)
- 长度归一化(
masked_meanvsmasked_normalize) - 分组标准差归一化开关
- 在策略 vs 离策略 + 裁剪是否必要
- R1-Zero 提示 vs question-only 提示
等所有 GRPO 相关问题。
若完全按 Stanford CS336 的作业要求来完成,你最终需要提交:
writeup.pdf:包含所有书面问题的答案- 建议在写作中直接引用:
- 零样本基线脚本与结果
- SFT / EI / GRPO 实验脚本对应的曲线与定量比较
- 你在
demo.md或其他笔记中整理的观察与思考
- 建议在写作中直接引用:
code.zip:包含你实现的所有代码- 至少包括:
cs336_alignment/sft_helper.pycs336_alignment/gpro_helper.py- 你修改或新增的实验脚本(如
evaluate_math.py、sft_math_reasoning*.py、grpo_experiments.py等)
- 至少包括:
如果你只是将本仓库作为 个人研究与复现实验 playground,仍然建议:
- 保持上述文件结构不变,方便以后对照官方讲义
- 在
README.ipynb或新的 Markdown 中记录你自己额外做的实验与想法
-
Q:刚装好环境就
ImportError/CUDA error?- 请确认:
torch版本与你的 CUDA 驱动匹配- GPU 上是否有足够显存(尤其是同时跑 vLLM + HF 模型时)
- 如在 Mac / CPU 环境下,仅能跑小批量或只做逻辑测试,vLLM 相关脚本可能无法实用地跑完。
- 请确认:
-
Q:
results/目录太大怎么办?- 可以定期把不需要的结果目录(如早期调试版本)打包/删除,只保留你最终用于写作和复现实验的结果。
-
Q:如果作业讲义或本地实现有出入,以哪个为准?
- 优先以官方讲义 + tests 为准。
- 本地脚本(如
evaluate_math.py/sft_math_reasoning.py/grpo_experiments.py)是基于讲义要求做的一个“可直接跑的实现/模板”,你完全可以根据需要修改。
如有进一步想在此基础上扩展自己的研究想法,欢迎给我们pr!