AI 学院 · LLM大模型线 · 节点 07 / 14

从零预训练实操:亲手训出第一个模型

这是全课程最重要的一课:在你自己的 Mac 上,从零预训练一个 50M 小模型。你会亲手看到 loss 下降、亲手采样出连贯文本——「训练能力」的第一块里程碑,与规模无关。全程约 2–3 小时(含训练等待)。

状态 手把手 · 必修前置 06 训练目标 · Python 地基预计 2–3 小时(含约 90 分钟挂机训练)
本课模式:六步走,每步都有「复制命令 → 预期输出 → 出错怎么办 → 检查点」。全程照做,你就能交出一份「我自己训的模型」+ 一份训练日志。这是 Lumen L0.0 的完整预演。

📋 本课你将完成

步骤 1

环境检查(5 分钟)

未完成

🎯 这一步的目标:确认 Python、git 可用。nanoGPT 是纯 Python,小模型在 Mac CPU 上就能跑,不需要 GPU。

检查 Python 与 git
python3 --version
git --version
▶ 预期输出(点开对照)
Python 3.10.x
git version 2.x.x
如果出现:zsh: command not found: python3
怎么办:macOS 自带 python3(Xcode 工具)。先跑:xcode-select --install 装命令行工具,再重试。
创建课程工作目录(建议固定)
mkdir -p ~/llm-course && cd ~/llm-course
▶ 预期输出(点开对照)
(无输出即成功)
✅ 检查点:python3 --version 能打印版本号。
步骤 2

克隆 nanoGPT(5 分钟)

未完成

🎯 这一步的目标:拿到 Karpathy 的开源 GPT 实现——约 300 行核心代码的极简训练器。

克隆仓库
cd ~/llm-course
git clone https://github.com/karpathy/nanoGPT
cd nanoGPT
▶ 预期输出(点开对照)
Cloning into 'nanoGPT'...
remote: Enumerating objects: ..., done.
(出现 nanoGPT 目录即成功)
安装依赖
pip3 install -r requirements.txt
▶ 预期输出(点开对照)
Collecting torch...
Successfully installed torch numpy tiktoken ...(有 Successfully 即可)
如果出现:pip3 报 externally-managed-environment 错误
怎么办:macOS 新版 Python 限制。建议建虚拟环境:python3 -m venv venv && source venv/bin/activate,再重跑 pip install。
如果出现:torch 安装失败/很慢
怎么办:CPU 版足够小模型用。pip3 install torch --index-url https://download.pytorch.org/whl/cpu 可加速。
✅ 检查点:cd nanoGPT 后 ls 能看到 train.py、sample.py、config/ 目录。
步骤 3

第一次跑:莎士比亚小语料(10 分钟)

未完成

🎯 这一步的目标:用内置的 shakespeare 语料把整条管道跑通——先跑通,再求好。这一步几十秒一轮,是「安全网」。

预处理语料
python3 data/shakespeare/prepare.py
▶ 预期输出(点开对照)
length of dataset in characters: 1,115,394
all the unique characters: ...
train has 1,003,854 tokens
val has 111,540 tokens
小规模试跑(500 步)
python3 train.py config/train_shakespeare_char.py --max_iters=500 --out_dir=out-shake
▶ 预期输出(点开对照)
step 0: train loss 4.3662, val loss 4.3830
step 100: train loss 2.0981, val loss 2.1217
step 500: train loss 1.5902, val loss 1.6311
(看到 loss 稳步下降就是成功!)
采样看效果
python3 sample.py --out_dir=out-shake --max_new_tokens=300
▶ 预期输出(点开对照)
(输出一段莎士比亚风格文本——可能有错字,但已经「像英文」了。这就是预训练的意义可视化)
✅ 检查点:500 步训练完成,loss 从 4.x 降到 1.6 左右,采样输出「像英文」。
步骤 4

准备 TinyStories 语料(15 分钟)

未完成

🎯 这一步的目标:换用为小模型设计的专用语料——33M 模型都能讲连贯故事,你的 50M 也能。

下载 TinyStories(约 210MB)
cd ~/llm-course
mkdir -p tinystories && cd tinystories
curl -L -o tinystories.txt https://huggingface.co/datasets/roneneldan/TinyStories/resolve/main/TinyStories-train.txt
▶ 预期输出(点开对照)
  % Total    % Received % Xferd  Average Speed ...
100  213M  100  213M    0     0   ...(下载完成)
如果出现:curl 报 404 / 无法访问
怎么办:HuggingFace 偶尔不稳定。备选镜像:把域名换成 hf-mirror.com 再试:curl -L -o tinystories.txt https://hf-mirror.com/datasets/roneneldan/TinyStories/resolve/main/TinyStories-train.txt
转成 nanoGPT 二进制格式
cd ~/llm-course/tinystories
python3 -c 'import tiktoken, numpy as np; enc = tiktoken.get_encoding("gpt2"); data = open("tinystories.txt", encoding="utf-8").read(); ids = enc.encode_ordinary(data); print("tokens:", len(ids)); arr = np.array(ids, dtype=np.uint16); arr.tofile("tinystories.bin"); print("saved")'
▶ 预期输出(点开对照)
tokens: 46,000,000(约 4 千万个 token)
saved
如果出现:ModuleNotFoundError: No module named 'tiktoken'
怎么办:pip3 install tiktoken,再重跑。
✅ 检查点:tinystories.bin 生成成功。
步骤 5

配置 50M 模型并正式训练(60–90 分钟,可挂机)

未完成

🎯 这一步的目标:用 TinyStories 训一个约 50M 参数的小模型,完整跑 2 万步。这是「你亲手训过的第一个模型」。

建数据集目录并放入数据
cd ~/llm-course/nanoGPT
mkdir -p data/tinystories
mv ~/llm-course/tinystories/tinystories.bin data/tinystories/
▶ 预期输出(点开对照)
(无输出即成功)
复制配置文件
cp config/train_shakespeare_char.py config/train_tinystories.py
▶ 预期输出(点开对照)
(无输出即成功)
编辑配置(nano 编辑器)
nano config/train_tinystories.py
▶ 预期输出(点开对照)
(在编辑器里修改以下几行:
  dataset = 'tinystories'   ← 数据集目录名
  max_iters = 20000         ← 训练步数
  eval_interval = 500       ← 每 500 步评估一次
  n_layer = 8               ← 层数
  n_head = 8                ← 注意力头数
  n_embd = 512              ← 向量维度(≈50M 参数)
保存:Ctrl+O 回车,退出:Ctrl+X)
开始训练(挂机即可)
python3 train.py config/train_tinystories.py --out_dir=out-story
▶ 预期输出(点开对照)
step 0: train loss 10.98, val loss 10.98
step 500: train loss 5.02, val loss 5.11
step 5000: train loss 3.10, val loss 3.22
step 20000: train loss 2.61, val loss 2.78
(看到 loss 稳步下降就是成功!)
✅ 检查点:训练跑完 2 万步,最终 train loss ≈ 2.5–3.0。
步骤 6

采样评估 + 写训练日志(15 分钟)

未完成

🎯 这一步的目标:训完不算完——用训练中没见过的开头采样,人工判断质量,并把一切记进 manifest。这是「评估先于训练」的最小版。

让模型续写一个故事开头
python3 sample.py --out_dir=out-story --start="Once upon a time, there was a little rabbit" --max_new_tokens=200
▶ 预期输出(点开对照)
(模型会续写出一段连贯的英文小故事——小模型能讲连贯故事,这就是 TinyStories 的魔力)
换个主题测泛化
python3 sample.py --out_dir=out-story --start="The cat and the dog" --max_new_tokens=150
▶ 预期输出(点开对照)
(另一个主题的续写——验证模型不是背下了训练集)
✅ 检查点:两次采样都产出「连贯、主题相关」的文本,并写好了训练日志(见下方模板)。
🧪 交互实验 · loss 曲线模拟器

真实训练 90 分钟前,先用模拟器建立「loss 曲线长什么样」的直觉。拖动学习率:太大 → 震荡不降;太小 → 降得慢;合适 → 平稳下降。

3e-4
适中

橙色 = train loss,蓝色 = val loss。注意:val 曲线拐头向上 = 过拟合;lr 太大曲线像锯齿 = 要调小。真实训练里这两条线就是你的仪表盘。

❓ 老师答疑(卡住了先看这里)

❓ 为什么先训莎士比亚 500 步?不是浪费时间吗?
完全不是。莎士比亚只有几 MB,几十秒一轮——它让你在不花时间、不花算力的情况下先验证「代码能跑、loss 会降、采样能出文本」。管道跑通后再换大语料,这叫「先小后大」——是省钱的方法论,不是绕路。
❓ TinyStories 训练要 90 分钟,我等不起怎么办?
可以缩水:把 max_iters 改成 5000、n_embd 改成 256(约 10M 参数),20 分钟内跑完。训练量小一点不影响你学会「怎么看 loss、怎么采样」。先跑通,再跑满。
❓ 为什么我的 loss 和教程里的不完全一样?
完全正常。随机种子、机器速度、库版本都会让曲线有微小差异。看趋势(是否下降)和数量级(是否 3.x→2.x),不要逐位对齐。
❓ train loss 比 val loss 低很多,是坏事吗?
有点差距是正常的(模型见过训练数据)。但如果 val 曲线拐头向上而 train 还在降——就是过拟合:模型在背数据,没学到规律。对策:减步数、加数据、或缩小模型。
❓ 这个模型是中文的还是英文的?
TinyStories 是英文语料,所以模型只会英文。如果你想要中文模型,把语料换成中文数据集(如 SkyPile 的小切片)——管道一模一样,只是换数据。这正好说明「数据决定能力层」。
❓ 训练中途断了怎么办?
nanoGPT 默认定期存 checkpoint(out-story/ckpt.pt)。重新运行 train.py 时会自动续训。别慌,从头来过的只有耐心。

📝 自测清单(全勾才算过)

全勾 → 节点 07 / 14 完成。未勾 → 回看对应步骤,别急着往前走。

📚 推荐资料