ELL3N HSU
← 项目介绍

ENGINEERING / WORKFLOW

从样本到 Adapter:SFT + LoRA

沿十个模块理解数据门禁、监督训练、低秩适配与独立评测,逐步追踪输入如何变成输出。

教学模拟:示例不是实际训练数据,播放顺序不代表运行耗时,也不提供模型质量或性能结论。

跳到参数实验室 ↓

节点粗实线表示当前步骤,虚线表示已浏览,细线表示待浏览;箭头表示教学数据流。

PT01

数据准备

审核后的五段输入与目标 Python 文件组成一条样本。

输入
虚构剧本:无效请求不得改变状态。
执行
将 rules、scenario、api、framework、reference 与 target 分开,记录 source_group 和审核状态。
输出
可追溯、审核通过的训练候选样本。
为什么需要
target 是监督答案,不是推理时提供的输入。

上游: 开始 → 下游: 数据审计

PT02

数据审计

训练前先过结构门禁;业务正确性仍需人工审核。

输入
候选样本与可选的冻结基准清单。
执行
检查字段、分组隔离、审核标记、重复 target 和 Python 语法;配置基准清单后检查排除关系。
输出
通过校验的样本;格式错误或重叠数据被拒绝。
为什么需要
exclude_manifests 为空不代表已经完成基准隔离检查。

上游: 数据准备 → 下游: 提示构造

PT03

提示构造

训练和生成共用 common.messages()。

输入
不含 target 的五段输入。
执行
构造 system 和 user 消息,再应用锁定 tokenizer 的聊天模板。
输出
编码和生成共同使用的提示前缀。
为什么需要
共用模板可避免训练与推理格式漂移。

上游: 数据审计 → 下游: 分词与标签掩码

PT04

分词与标签掩码

提示 token 参与预测条件,但不直接计入监督损失。

输入
提示与 assistant 标准答案。
执行
验证提示前缀,编码完整序列,将提示标签设为 -100;超长直接报错,不静默截断。
输出
input_ids、attention_mask 与仅监督答案的 labels。
为什么需要
每条样本都必须保留监督 token,并正确界定答案起点。

上游: 提示构造 → 下游: 前向计算与 SFT 损失

PT05

前向计算与 SFT 损失

Trainer 调用因果语言模型;train.py 没有手写前向循环。

输入
编码序列与带掩码的标签。
执行
Teacher forcing 预测下一个 token。概念式 L = −Σ log P(y_t | x, y_<t) / T,仅统计有效目标位置;模型内部对齐错位一格的 logits 与标签。
输出
监督损失标量与自动微分计算图。
为什么需要
token loss 提供训练信号,不能证明业务正确性。

上游: 分词与标签掩码 → 下游: 反向传播与梯度累积

PT06

反向传播与梯度累积

Trainer/PyTorch 管理自动微分和梯度累积。

输入
连续 micro-batch 的损失。
执行
向可训练 LoRA 参数反向传播,累积到更新时点;项目将 micro-batch 固定为 1。
输出
交给优化器的累积梯度。
为什么需要
一次 micro-batch 前反向不一定等于一次 optimizer step。

上游: 前向计算与 SFT 损失 → 下游: AdamW 与学习率调度

PT07

AdamW 与学习率调度

项目通过 TrainingArguments 选择 adamw_torch。

输入
累积梯度、历史动量估计与当前学习率。
执行
AdamW 更新可训练参数,随后推进调度器并清理梯度;此处 Transformers 4.57.1 默认线性衰减,无 warmup。
输出
更新后的 LoRA 权重与下一学习率。
为什么需要
改变 max_steps 同时改变训练长度和线性衰减轨迹。

上游: 反向传播与梯度累积 → 下游: LoRA 参数与 Adapter

PT08

LoRA 参数与 Adapter

LoRA 在训练开始前已注入;本步骤解释更新对象与最终保存产物。

输入
冻结的基础 W,以及 q_proj/v_proj 上可训练的 A、B。
执行
使用 W + (α/r)BA;trainer.train() 完成后检查 adapter 参数确有变化,再保存 adapter 与 tokenizer。
输出
与锁定基础模型版本配套的 adapter。
为什么需要
LoRA 减少可训练参数,但基础权重和激活仍占内存。

上游: AdamW 与学习率调度 → 下游: B0/B1 生成

PT09

B0/B1 生成

B0 使用基础模型;B1 加载与其兼容的 adapter。

输入
相同的冻结基准提示与生成设置。
执行
通过 generate_items 贪心解码,在 inference_mode 下运行并检查基座版本;max_new_tokens 限制新增输出。
输出
候选脚本与生成记录;生成流程不执行候选代码。
为什么需要
固定设置才能解释差异;生成代码不等于代码已被验证。

上游: LoRA 参数与 Adapter → 下游: 基准评估

PT10

基准评估

自动层与独立执行、人工评审回答不同问题。

输入
同一 suite、规则和评分器版本下的 B0/B1 候选脚本。
执行
检查 L0 形式、L1 框架、L2 依据、L2.5 oracle;L3 执行与 L4 人工评审独立进行,再逐任务配对比较。
输出
分层证据与逐任务变化,而非虚构准确率。
为什么需要
训练 loss 降低本身不能证明脚本可用或能泛化。

上游: B0/B1 生成 → 下游: 完成此轮阅读

POST-TRAINING / PARAMETER LAB

参数实验室

确定性教学计算,不会训练模型或改写项目配置。N=56、矩阵维度和 token 计数都是假设;结果不是 loss、准确率、耗时或内存实测。

30/112 按钮只更改 max_steps,并把超出预算的观察光标与 warmup 调回有效范围;其他参数保持当前选择。

有效 batch1
曝光30
近似 epoch0.5357
LR5.0000e-5
LoRA 参数16,384
LoRA 缩放2
训练 tokens1,280
生成预算上界3,072

训练长度检查: 通过 · 详细公式与曲线 ↓

更新预算:Step / Batch / Epoch
定义、配置与使用条件

有效训练池的样本条数,不是原始 JSONL 行数。

模板 / 默认
56 为教学假设;仓库不提供此默认值
项目位置
train.py 过滤 split=train 后的 encoded 长度
探索范围与条件
可用 28/40/56/112 比较小数据情景;页面允许 1–1,000,000。
参数关系
epochs ≈ steps × effective batch / N;N 越小,同预算重复曝光越多。
典型风险
把 N 设大不能创造数据多样性;过小训练池易记忆,需独立评测。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT01

定义、配置与使用条件

每个训练进程一次 forward/backward 处理的样本数。

模板 / 默认
项目写死为 1
项目位置
train.py · per_device_train_batch_size
探索范围与条件
教学范围 1–32;实际增加前需确认 RAM,当前 CPU 路径为 1。
参数关系
与 accumulation、processes 相乘得到有效 batch。
典型风险
大 batch 增加激活内存;小 batch 的梯度更易波动。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT06

定义、配置与使用条件

一次 optimizer 更新前累积的 micro-batch 数。

模板 / 默认
cpu-long 模板为 1
项目位置
configs/cpu-long.json · gradient_accumulation_steps
探索范围与条件
先试 1/2/4/8,保持曝光量比较;教学上限 128。
参数关系
固定 steps 时增加累积会增加曝光;同曝光仍不等于同优化轨迹。
典型风险
过大使每次更新更慢、更新次数可能减少;小值不保证更稳定。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT06

定义、配置与使用条件

参与数据并行训练的进程数,不是 CPU threads。

模板 / 默认
当前单 CPU 进程按 1
项目位置
运行拓扑;不是 cpu-long 的 threads 字段
探索范围与条件
1 是当前路径;2/4/8 仅作分布式数学对照,页面上限 16。
参数关系
参与 B_eff;分布式采样补齐可能影响实际曝光。
典型风险
增加进程需要分布式代码与资源,不能靠此输入部署;通信也有成本。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT06

定义、配置与使用条件

optimizer 的更新预算,而不是 micro-batch 个数。

模板 / 默认
cpu-long 模板为 30;112 为教学对照
项目位置
configs/cpu-long.json · max_steps;CLI --max-steps 可覆盖
探索范围与条件
先比较 30 与 112;按 N、目标 epoch 和 batch 规划,页面上限 100,000。
参数关系
同时改变曝光预算与线性 LR 衰减进度。
典型风险
过少可能训练不足,过多可能记忆训练集;没有效果单调提升保证。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT07

线性学习率计划
定义、配置与使用条件

线性调度的峰值/基础更新尺度。

模板 / 默认
cpu-long 模板为 1e-4
项目位置
configs/cpu-long.json · learning_rate
探索范围与条件
LoRA 可比较 5e-5/1e-4/2e-4;0–0.01 是演示输入边界,并非推荐范围。
参数关系
与 scheduler、batch 及 α/r 共同影响更新。
典型风险
过大可能不稳定,过小更新缓慢;0 表示无学习率更新。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT07

定义、配置与使用条件

先从零线性升至 η₀ 的更新步数。

模板 / 默认
未显式配置;Transformers 4.57.1 默认 0
项目位置
train.py 的 TrainingArguments 未传 warmup;需另加配置才会改变训练
探索范围与条件
当前为 0;教学可比较 0 与少量步数,必须 0 ≤ warmup < max_steps。
参数关系
占用总预算的一部分,改变后续衰减区间。
典型风险
过长会让短训练大部分处于小 LR;0 不代表所有训练都不需要 warmup。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT07

定义、配置与使用条件

曲线上已经完成多少次 optimizer 更新的位置。

模板 / 默认
15 为观察光标默认值,不是训练配置
项目位置
教学光标;真实日志对应 Trainer global_step
探索范围与条件
0–max_steps;0 是初始状态,末步后 LR 为 0。
参数关系
移动光标只检查当前计划,不改变总曝光预算。
典型风险
不能把光标值当作已发生的训练;日志中的时点需核对实现。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT07

单层 LoRA 数学实验
定义、配置与使用条件

A 的行数与 B 的列数,限制增量矩阵的最大秩。

模板 / 默认
cpu-long 模板为 8
项目位置
configs/cpu-long.json · lora_r
探索范围与条件
通常逐项比较 4/8/16/32;教学上限 256 且不超过任一维度。
参数关系
P=r(d_in+d_out);固定 α 时增大 r 会减小 α/r。
典型风险
增大 rank 增加容量和训练参数,但不保证质量提高;较小 rank 可能限制表达。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT08

定义、配置与使用条件

普通 LoRA 的增量缩放分子;本项目未启用 rsLoRA。

模板 / 默认
cpu-long 模板为 16
项目位置
configs/cpu-long.json · lora_alpha
探索范围与条件
固定 r 比较 α=r、2r;0–1024 是教学范围。
参数关系
scale=α/r;不改变 A/B 参数量。
典型风险
过大增量尺度可能不稳定;α=0 关闭此增量,不能理解为免费训练。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT08

定义、配置与使用条件

单个线性层输入向量长度。

模板 / 默认
1024 为数学示例,非 Qwen 层形状
项目位置
仅教学输入;真实模型层需实际检查
探索范围与条件
可比较 128–4096 的假设层;页面允许 1–16384。
参数关系
A ∈ R^(r×d_in),W ∈ R^(d_out×d_in)。
典型风险
较大维度增加参数与计算;不可乘以猜测的层数冒充模型总量。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT08

定义、配置与使用条件

单个线性层输出向量长度。

模板 / 默认
1024 为数学示例,非 Qwen 层形状
项目位置
仅教学输入;真实模型层需实际检查
探索范围与条件
可比较 128–4096 的假设层;页面允许 1–16384。
参数关系
B ∈ R^(d_out×r);BA 与 W 形状相同。
典型风险
维度改变的是数学层定义;LoRA 仍需保存基座权重与激活,不能据此推断峰值内存。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT08

训练与生成 token 预算
定义、配置与使用条件

应用 chat template 后的提示前缀长度,包含格式 token。

模板 / 默认
1024 是合成计数,不由真实 tokenizer 得出
项目位置
common.py · encode_sample 中 len(prompt)
探索范围与条件
按实际 token 审计选择;页面范围 1–32768 只用于边界演示。
参数关系
参与 forward,但其 labels=-100;生成也用此提示前缀。
典型风险
长提示增加上下文和计算成本;短提示若缺资料也不能靠训练补全事实。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT04

定义、配置与使用条件

assistant 目标尾部参与直接 token loss 的长度。

模板 / 默认
256 是合成计数
项目位置
common.py · full[len(prompt):]
探索范围与条件
按实际目标编码测量;教学范围 1–32768,零监督会被拒绝。
参数关系
训练长度=prompt+supervised;与 max_new_tokens 不是同一参数。
典型风险
答案过长增加训练开销;过短或缺失目标不能提供完整监督。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT04

定义、配置与使用条件

完整训练序列上限;此项目也用它检查生成提示长度。

模板 / 默认
cpu-long 模板为 8192
项目位置
configs/cpu-long.json · max_length
探索范围与条件
先审计长度再比较 2048/4096/8192;页面上限 32768 并非模型支持保证。
参数关系
prompt+supervised 超限会拒绝,不静默截断,也不是固定 padding 长度。
典型风险
过小会拒绝样本;过大并不延长实际样本,却可能允许高内存长序列进入。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT04

定义、配置与使用条件

生成阶段最多新增的 token 数,EOS 可提前结束。

模板 / 默认
benchmark CLI 默认 2048;快速 generate.py 默认 256
项目位置
scripts/bench/run_generate.py · --max-new-tokens
探索范围与条件
按输出长度审计比较 256/1024/2048;教学上限 32768,需满足模型上下文约束。
参数关系
生成预算上界=prompt+max_new_tokens;不改变训练序列上限。
典型风险
过小容易截断代码;过大增加生成预算,不保证业务正确或一定生成到上限。

对应源码 / 依据 ↗ · 参数字典 ↗ · 公式与实验 ↗ · 回到相关模块 PT09

边界规则:必须为有效数字;计数为整数;warmup < max_steps;current step ≤ max_steps;r ≤ min(d_in,d_out)。超限训练序列会作为拒绝示例显示。

样本曝光计划

B_eff = b × g × w = 1

exposures ≈ S × B_eff = 30

epochs ≈ exposures / N = 0.5357

这是完整 batch 的近似规划。DataLoader 轮末不足批量、跨 epoch 累积和分布式采样补齐可能改变实际曝光;不是逐样本运行记录。

LoRA:一个假设线性层

ΔW = (α/r)BA · scale = α/r = 2

P = r(d_in + d_out) = 16,384 个参数

W: d_out × d_in = 1,048,576 · 1.5625%

A: 8 × 1024; B: 1024 × 8; BA: 1024 × 1024

上述百分比是单层 adapter 与完整矩阵参数量的比值,非全模型节省率。基座权重和激活仍占内存;更大 rank 不保证更好的独立评测结果。

学习率曲线,不是训练 loss

η(s) = η₀·s/W (s < W);之后 η₀·max(0, (S−s)/(S−W))

当前更新后 LR: 5.0000e-5

1.0e-400112

实线:当前计划;短虚线:30 steps / warmup=0;点线:112 steps / warmup=0。纵轴按同一 η₀,横轴按更新次数。相同计划的曲线会重合;预算结束后的零线只为对照延长,不表示继续训练。

修改 max_steps 不只是延长训练,也改变同一步数的线性衰减进度。曲线是公式,不是实际日志;调度状态按已完成更新数解释。

训练标签与生成预算

条形左侧:prompt(label=-100);右侧:监督尾部。长度为合成计数,不代表真实 tokenization。

训练总长度: 1,280 · 可通过长度检查

生成提示检查: 可通过 · 提示 + 新 token 预算上界: 3,072

训练超长会拒绝而非截断;prompt 仍参与 forward,只是不直接计入 loss。生成还受 EOS 与真实模型上下文约束,实际输出不一定达到 max_new_tokens。