一字一诗
LESSON 26 / 26

独立改进与迁移训练

这一课完成什么

独立完成一次改进实验,并掌握把训练迁移到其他机器的基本方法。结课时,你应该能解释模型如何接出下一字、改一个设置重新训练、根据记录定位一种问题,再用 CLI 调用自己的版本。

做对照实验:每次只改一个条件

保留旧模型和记录,再建立新实验。相同材料和评估方法下,只改变一个条件,才比较容易理解改进来自哪里。

做对照实验:每次只改一个条件
用文字逐步读这张图
  1. 写下问题:增加层数有没有帮助;先作一个预测
  2. 保留基线:旧模型与旧设置;不要覆盖
  3. 只改一项:层数、步数或宽度;其余尽量一致
  4. 记录代价:耗时、内存、参数量;不只看误差
  5. 同法评估:同样抽样题与输入;保留不理想结果
  6. 解释取舍:是否值得增加资源;再决定下一步
租更大机器一定能写好诗吗?

算力让更大的实验成为可能,但数据、任务格式、训练设置和评估仍决定能学到什么。

先完成一项小改动

选择一个问题,例如五言重复较多、某个关键词控制较弱,或希望缩短训练时间。写下假设:只改变哪一项、为什么可能有帮助、用哪些固定题检查。复制配置到新文件,在新目录训练,保留原模型供比较。

bash
./poet lesson 26
cp configs/tiny.json configs/my-experiment.json
./poet train --config configs/my-experiment.json --run-dir artifacts/runs/my-experiment --steps 1000
./poet write --checkpoint artifacts/runs/my-experiment/best.pt --start 春 --seed 42

不要一开始同时改层数、宽度、材料、学习率和采样参数。那样即使效果变化,也很难知道原因。实验记录至少包含配置、材料版本、设备、训练步数、耗时、验证误差和固定生成题的全部输出。

本机与租用机器的选择

这次本机已经能够完成约 488 万参数的训练,先利用已有设备即可。若后续想加快更大模型或多轮对照,再考虑租一台带 NVIDIA 图形处理器的 Linux 机器。比较机器时,看实际可用显存、按时计费规则、磁盘是否另计费和停止后是否继续收费;价格应在下单前查询,不把课程里的示例当作当前报价。

建议先租最短的试用时段,运行同一段短跑测出速度和内存,再推算预算。训练速度会受模型、批数量、软件版本和设备影响,不能只根据显卡名字承诺耗时。租用、付费和上传都由你明确决定,课程本身不会自动开通机器。

把训练迁移过去

复制源代码、配置、依赖版本记录和已经整理好的 artifacts/data。若继续已有训练,还要带上 latest.pt。无需复制本机 .venv,因为 Mac 的程序包不能直接当作 Linux 环境使用。

在新机器安装相容的 Python 与 PyTorch。若使用 NVIDIA,按 PyTorch 官方安装选择器 为该机器选择合适的计算版本。macOS 的锁定环境用于本机复现;云端需要验证驱动与计算版本的兼容性,并保存自己的环境记录。

bash
python -m poetry_gpt doctor
python -m poetry_gpt train --config configs/tiny.json --run-dir artifacts/runs/cloud-check --steps 100 --device cuda

doctor 必须显示 NVIDIA 加速可用。先检查 100 步,再正式训练。生成模型文件后下载回本机,使用 --checkpoint 指向它;字表已经包含在模型中。原诗重复检查还需要对应的本地材料目录。

可以怎样继续扩展

这些扩展各自需要材料和验收标准。不要只增加一个命令参数,就把未实现的能力显示为已支持。

结课检查

请独立回答:字编号与向量有什么区别?为什么训练要遮挡未来位置?误差怎样改变参数?best 与 latest 有何区别?程序的字数约束和模型学到的能力怎样区分?你能用一次真实实验说明自己改动带来的影响吗?

参考答案要点

编号是固定索引,向量是可学习的数字行;遮挡保证训练条件与逐字生成一致;误差通过自动求导产生梯度,再由优化器更新参数;best 用于最佳验证阶段的生成,latest 带恢复训练状态;字数规则由程序执行,词语和关联来自模型预测。最后一问必须用你自己的配置、日志和固定题输出作答,单凭主观印象不足以完成对照。

动手补全一小段

先运行上面的完整实验,再复制本课起始文件为自己的练习。starter 有意留空 solve 函数;补全后运行文件,底部检查会告诉你是否符合本课要求。卡住时打开参考答案,比较每一步。

bash
cp lessons/26/starter.py lessons/26/my_exercise.py
# 编辑 my_exercise.py 中的 solve 函数,然后运行:
.venv/bin/python lessons/26/my_exercise.py
# 对照完整答案:
.venv/bin/python lessons/26/solution.py

下载起始代码 · 下载参考答案

展开本课补全练习的完整参考答案
python
"""第 26 课补全练习:统计真正独立的参数。修改 solve,保持下方检查不变。"""
import math, io, argparse
import torch
from torch import nn
from torch.nn import functional as F
torch.set_num_threads(2)
torch.manual_seed(26)

def solve(model):
    return sum(p.numel() for p in model.parameters())

model=nn.Linear(3,2)
assert solve(model)==8
print("本课补全练习通过。")
展开本课完整、可独立运行的实验代码
python
"""本课独立实验;在仓库根目录执行 .venv/bin/python lessons/26/experiment.py。"""
import sys, json, math
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
import torch
from torch import nn
from torch.nn import functional as F
from poetry_gpt.common import ROOT, DEFAULT_DATA, read_json, read_jsonl
from poetry_gpt.model import ModelConfig, PoetryGPT, CausalAttention, Block
from poetry_gpt.data import Tokenizer, SPECIAL, clean_record, keywords_for
from poetry_gpt.labs import show
torch.set_num_threads(2)
torch.manual_seed(26)

for name in ['tiny', 'poet']:
    config = read_json(ROOT / f'configs/{name}.json')
    size = read_json(DEFAULT_DATA / 'manifest.json')['vocab_size'] if (DEFAULT_DATA / 'manifest.json').exists() else 6000
    model = PoetryGPT(ModelConfig(vocab_size=size, **config['model']))
    show(f'{name} 参数数量', model.parameter_count())
print('同一材料、同一评估题,只改一个设置,另开训练目录记录。')
下载本课实验