SFT Hyperparameters¶
这个 recipe 在 Mint Recursive 上跑一轮真实的监督微调 sweep。它用同一个小的 arithmetic chat 数据集,在几组超参数下分别训练,再比较最终的 training loss。
关键点:这个 recipe 不再手写 Datum。它用 recipe.supervised.conversation_to_datum() 和高层的 recipe.supervised.train.main(config) 训练循环。
Use Case¶
- Instruction tuning:训练模型按任务指令工作。
- Domain adaptation:在领域内的问答或聊天样本上微调。
- 小规模 grid search:在正式训练前比较 learning rate 和 LoRA rank。
- Recipe 调试:确认 Mint Recursive API key、renderer、tokenizer 和 SFT 训练循环能一起跑通。
Sweep 什么¶
默认情况下,recipes/sft_hyperparameters.py 会跑:
可以用环境变量覆盖:
MINT_SFT_STEPS=1 \
MINT_SFT_LRS=1e-5,5e-5 \
MINT_LORA_RANKS=8,16 \
python recipes/sft_hyperparameters.py
核心模式¶
recipe 先在内存里构造一个 supervised dataset:
class ArithmeticSFTDataset(recipe.supervised.types.SupervisedDataset):
def __init__(self, conversations, model_name, renderer_name, batch_size, max_length):
tokenizer = get_tokenizer(model_name)
renderer = recipe.renderers.get_renderer(renderer_name, tokenizer)
self.datums = [
recipe.supervised.conversation_to_datum(
conversation,
renderer,
max_length=max_length,
)
for conversation in conversations
]
self.batch_size = batch_size
def __len__(self):
return max(1, (len(self.datums) + self.batch_size - 1) // self.batch_size)
def get_batch(self, index):
start = (index * self.batch_size) % len(self.datums)
return self.datums[start : start + self.batch_size]
然后每组 grid item 调用标准 SFT trainer:
config = recipe.supervised.train.Config(
log_path="/tmp/mint-sft-sweep-lr1e-5-rank8",
model_name="Qwen/Qwen3-0.6B",
renderer_name="qwen3",
dataset_builder=ArithmeticSFTDatasetBuilder(...),
learning_rate=1e-5,
lora_rank=8,
max_steps=2,
save_every=999,
eval_every=999,
infrequent_eval_every=999,
ttl_seconds=3600,
)
await recipe.supervised.train.main(config=config)
完整源码:https://github.com/MindLab-Research/mint-quickstart/blob/main/recipes/sft_hyperparameters.py
运行¶
输出的最后会有这样一张表:
=== Grid Search Summary ===
LR Rank Steps Final train NLL Log path
------------------------------------------------------------------------------------------
1e-05 8 2 10.4975 /tmp/mint-sft-sweep-...-1em05-rank8
1e-05 16 2 10.4919 /tmp/mint-sft-sweep-...-1em05-rank16
5e-05 8 2 10.1574 /tmp/mint-sft-sweep-...-5em05-rank8
5e-05 16 2 9.4928 /tmp/mint-sft-sweep-...-5em05-rank16
Verified Run¶
已在 Mint Recursive 上验证:Qwen/Qwen3-0.6B,8 条生成的 arithmetic conversations,每组配置 2 steps:
| Learning rate | LoRA rank | Steps | Final train NLL |
|---|---|---|---|
1e-5 |
8 | 2 | 10.4975 |
1e-5 |
16 | 2 | 10.4919 |
5e-5 |
8 | 2 | 10.1574 |
5e-5 |
16 | 2 | 9.4928 |
Note
这些数字来自用于验证 API 和代码结构的小型 smoke 数据集。调参时,请使用自己的数据集,运行更多训练步,并比较验证指标。
为什么这个形状有效¶
chat messages
│
▼
conversation_to_datum()
│ 应用 renderer + assistant-token loss mask
▼
SupervisedDataset.get_batch()
│
▼
recipe.supervised.train.main(config)
│ 创建 LoRA TrainingClient,执行 forward/backward + optimizer steps
▼
metrics.jsonl + final checkpoint
这样 tokenization 和 loss mask 就和 Mint Recursive 用的 renderer 对齐了。它跑的也是更大的 supervised recipe 所用的同一套高层训练循环,所以这个 sweep 验证的是用户会复制的真实路径。