33. Fine Tuning Readiness | 微调 Readiness
难度: Medium | 环境: CPU-first | 标签: 训练微调, 微调准备, 可行性检查 | 目标人群: 训练机制学习者
🚀 云端运行环境
本章节的实战代码可以点击以下链接在免费 GPU 算力平台上直接运行:
本节导读
33 关注微调实验开始前最容易被忽略的 readiness 判断:训练计划是否写清楚了,数据规模和预算是否匹配,评测目标是否真的对应当前训练范围。32 先回答数据是不是已经整理到可训练状态,而 33 再进一步回答:即使数据可用,这次微调是否真的已经具备启动条件,还是还停留在“想法上可做、工程上还没准备好”的阶段。
这一节不设计完整训练系统,也不追求复杂 project management,而是先把微调启动前的三个最小判断固定下来:训练计划是否明确,时间/显存预算是否可承受,最后是否值得升级成完整项目页。它在训练微调路线里承担的是项目收口前补链的“最后一道闸门”:前面已经把 LoRA 方案、数据入口和训练闭环补齐,这一节专门负责判断任务是否真的可以进入 60 这样的项目化验证。学完后,你应该能看清“计划 -> 预算 -> 是否立项 -> 项目收口”这条 readiness 链路,而不是把实验失败后才归因到准备不足。
关键词: training plan, budget, evaluation, readiness
前置阅读
导语: 这一节同时承接训练闭环、长上下文扩展和数据准备三条线:先知道训练怎么跑、数据怎么进,再回来看一项微调任务是否真的准备好了启动。
- 09. SFT Training Loop | SFT 训练循环
- 13. End-to-End Fine-Tuning Experiment | 端到端微调实验
- 32. Data Engineering for SFT | SFT 数据工程
相关阅读
导语: 学完 readiness 判断后,下一步就该沿项目线继续走:把已经通过检查的任务推进到真实微调验证,同时回看组页,确认这条从场景到立项的微调主线是否完整闭环。
Step 1: 先把训练计划写清楚
- 固定模型、数据规模、训练步数、batch size 和评测窗口。
- 明确目标是提升 loss、格式稳定性,还是特定任务指标。
- 如果计划本身写不清楚,后面的实验结论大概率不可复用。
Step 2: 把资源预算和训练范围对齐
- 训练闭环至少要对齐数据规模、训练时长和显存预算。
- 如果目标比预算大很多,应优先缩范围,而不是直接开始训练。
- 先看“是否能完成”,再看“能否做得更好”。
Step 3: 用 readiness 判断是否进入项目页
- 预留页的价值在于提前判断是否值得继续扩成项目。
- 只有计划、预算和评测都达标,才应该推进到完整项目验证。
Step 4: 动手实战
- 补全
summarize_training_plan,汇总训练计划。 - 补全
check_training_budget,判断预算是否够用。 - 补全
recommend_finetuning_scope,输出是否进入项目页。
提示
- 这页不是让你设计完整训练系统,而是先做一次最小 readiness 检查:计划是否清楚,预算是否够,是否值得继续升级成项目页。
TODO 1先把训练计划里的核心字段收出来,不要在这里扩展额外策略。TODO 2只比较时间预算和显存预算是否满足,最后再合成budget_ok。TODO 3先看目标是否存在、数据规模是否大于 0、预算是否通过,再决定是否promote_to_project。
from typing import Dict, Listdef summarize_training_plan(config: Dict[str, object]) -> Dict[str, object]:
"""
TODO 1: 汇总训练计划的最小信息。
"""
# 提示:只需要返回 goal、dataset_size、total_steps、eval_every 这 4 个字段。
# goal = ???
# dataset_size = ???
# total_steps = ???
# eval_every = ???
raise NotImplementedError
def check_training_budget(config: Dict[str, object], available_hours: float, available_memory_gb: float) -> Dict[str, object]:
"""
TODO 2: 判断训练预算是否足够。
"""
# 提示:先分别判断 estimated_hours 和 peak_memory_gb 是否在预算内,
# 再合成 budget_ok = time_ok and memory_ok。
# time_ok = ???
# memory_ok = ???
# budget_ok = ???
raise NotImplementedError
def recommend_finetuning_scope(summary: Dict[str, object], budget: Dict[str, object]) -> Dict[str, object]:
"""
TODO 3: 输出是否进入项目页。
"""
# 提示:先判断 goal 是否存在、dataset_size 是否大于 0、budget_ok 是否为 True,
# 再给出 promote_to_project 和 reason。
# promote = ???
# reason = ???
raise NotImplementedErrordef test_finetuning_readiness_template():
try:
config = {'goal': 'improve_instruction_following', 'dataset_size': 20000, 'total_steps': 1200, 'eval_every': 100, 'estimated_hours': 6.0, 'peak_memory_gb': 14.0}
summary = summarize_training_plan(config)
assert summary['goal'] == 'improve_instruction_following'
assert summary['dataset_size'] == 20000
budget = check_training_budget(config, available_hours=8.0, available_memory_gb=16.0)
assert budget['budget_ok'] is True
decision = recommend_finetuning_scope(summary, budget)
assert decision['promote_to_project'] is True
print('测试通过:微调 readiness 页面模板可以工作。')
except NotImplementedError:
raise
except (AttributeError, NameError, TypeError, ValueError, AssertionError) as e:
raise NotImplementedError('请先完成 TODO 代码!') from e
test_finetuning_readiness_template()🛑 STOP HERE 🛑
请先尝试自己完成代码并跑通测试。
如果你正在 Colab 中运行,并且遇到困难没有思路,可以向下滚动查看参考答案。
参考代码与解析
代码
def summarize_training_plan(config: Dict[str, object]) -> Dict[str, object]:
"""
TODO 1: 汇总训练计划的最小信息。
"""
# 提示:只需要返回 goal、dataset_size、total_steps、eval_every 这 4 个字段。
# goal = ???
# dataset_size = ???
# total_steps = ???
# eval_every = ???
return {
'goal': config.get('goal', ''),
'dataset_size': int(config.get('dataset_size', 0)),
'total_steps': int(config.get('total_steps', 0)),
'eval_every': int(config.get('eval_every', 0)),
}
def check_training_budget(config: Dict[str, object], available_hours: float, available_memory_gb: float) -> Dict[str, object]:
"""
TODO 2: 判断训练预算是否足够。
"""
# 提示:先分别判断 estimated_hours 和 peak_memory_gb 是否在预算内,
# 再合成 budget_ok = time_ok and memory_ok。
# time_ok = ???
# memory_ok = ???
# budget_ok = ???
time_ok = float(config.get('estimated_hours', 0.0)) <= available_hours
memory_ok = float(config.get('peak_memory_gb', 0.0)) <= available_memory_gb
return {'time_ok': time_ok, 'memory_ok': memory_ok, 'budget_ok': time_ok and memory_ok}
def recommend_finetuning_scope(summary: Dict[str, object], budget: Dict[str, object]) -> Dict[str, object]:
"""
TODO 3: 输出是否进入项目页。
"""
# 提示:先判断 goal 是否存在、dataset_size 是否大于 0、budget_ok 是否为 True,
# 再给出 promote_to_project 和 reason。
# promote = ???
# reason = ???
promote = bool(summary.get('goal')) and summary.get('dataset_size', 0) > 0 and budget.get('budget_ok', False)
reason = '训练计划和预算已对齐' if promote else '训练计划或预算尚未就绪'
return {'promote_to_project': promote, 'reason': reason}解析
TODO 1:summarize_training_plan 先把训练计划里的最小字段固定下来,只保留 goal、dataset_size、total_steps 和 eval_every,让后面的预算判断和项目判断都建立在同一份计划摘要上。
TODO 2:check_training_budget 负责把时间预算和显存预算拆开判断。先分别得到 time_ok 和 memory_ok,再合成 budget_ok,避免把“预算不足”混成一个模糊结论。
TODO 3:recommend_finetuning_scope 负责输出是否值得升级成项目页。只有当目标存在、数据规模有效、预算通过时,才建议 promote_to_project = True,把这页真正变成一张 readiness 决策页,而不是空泛占位页。
