《Bilevel Autoresearch》费曼式深度总结
下面我按三个层次来收束这件事:
1. 一句话总纲:这篇论文到底在讲什么? 2. 五个关键洞见:这项工作真正“新”在哪里? 3. 如果你要拿来用:如何在自己的系统里“抄作业”?
---
1. 一句话总纲
把这篇论文压到一句话就是:
> 以前的自动研究只会“自动做实验”,这篇工作让它开始“自动发明更好的做实验的方法”,而且外层发明者和内层干活的人,用的是同一个LLM,性能却能在真实基准上提升约 5 倍。
换个费曼味的说法:
- Karpathy 的 autoresearch = 一个很能干但有偏见的厨师,天天在厨房试配方
- Bilevel Autoresearch = 再加一个“会写厨房规则的厨师”,专门改写“厨师是怎么思考菜谱”的那段程序
- 而且这两个其实是同一个人(同一个 LLM),只是被放在了两个不同的“角色位”上
2. 五个关键洞见(每一个都足够支撑一个方向的研究)
洞见一:双层优化,把“超参数向量”升级成“搜索程序”
传统双层优化的形式是:
$$ \min_{\phi} F(\phi, \theta^*(\phi)) \quad \text{s.t. } \theta^*(\phi) \in \arg\min_{\theta} f(\theta, \phi) $$
- 过去:
- θ = 模型参数
- φ = 一小撮连续超参数(学习率系数、正则系数等)
- 这篇论文:
- θ = 内层 autoresearch 在改的那些训练配置(超参数等)
- φ = 一段 Python 代码 = “内层搜索逻辑本身”
- 以前你调的是“旋钮的刻度”(φ 是几个实数)
- 现在你调的是“整个调音台的电路设计”(φ 是一个程序)
---
洞见二:三层结构里,真正值钱的是 Level 2,而不是“聪明一点的参数调度”
论文里有四种设定(用你的语言稍微重新命名一下):
- A:只用 Karpathy 风格的 Level 1 内层搜索
- B:Level 1 + 一个“小助手”Level 1.5,只会做:
- 冻结/解冻经常失败的参数
- 给点“探索提示语”
- C:Level 1 + 1.5 + Level 2(能改机制的外层)
- D:Level 1 + Level 2(不要 1.5,只要真正的元层)
- A:约 −0.009
- B:约 −0.006(甚至没比 A 明显好)
- C:约 −0.045
- D:约 −0.034
1. “多加一层参数小聪明”(Level 1.5)几乎没啥卵用 2. 真正带来质变的是:允许外层直接改“搜索机制代码”(Level 2) 3. Level 1.5 顶多是锦上添花,Level 2 才是雪中送炭
费曼式翻译:
> 你不是在“更用力地拧同一个螺丝”,而是终于意识到: > 可能应该换一把螺丝刀。
---
洞见三:外层不是“参数更大”,而是“视角更高”
很重要的一点:
- 内层:LLM 读
train.py,基于当前配置和历史,提新超参数、跑 300 秒训练、看 val_bpb、接受/拒绝 - 外层:同一个 LLM,但它读的是:
- 完整的
runner.py(内层逻辑) - 历史所有 proposal + 结果轨迹
- 然后经历 4 步:
重点:外层并不更聪明,它只是“看到了代码 + 历史轨迹”这一更大的上下文。
直观比喻:
- 同一个人:
- 一会儿被塞进厨房,只负责炒菜(内层)
- 一会儿被拉出来看录像回放和菜谱源代码,让他写“新的炒菜规则”(外层)
> 把同一个模型摆到更高的抽象层,而不是一味追求更大、更贵的模型。
---
洞见四:三种涌现出来的机制,实质上都是在“强制越界自己的先验”
外层自动产生的典型机制有三类(在多个重复中出现):
1. Tabu Search Manager(禁忌搜索)
- 维护
tabu_list,记录最近失败的配置或参数值区间 - 在生成新 proposal 时,自动避开这些“禁区”
- 效果:
- 如果 LLM 本能地爱反复尝试“看起来合理”的方向(比如更大 batch),Tabu 会说:“不行,这条路你已经撞墙好几次了,必须换方向。”
- 给“哪一个参数/方向该被尝试”分配一个 UCB 分数(平均奖励 + 探索项)
- 对高不确定性但有潜力的方向,创造“被尝试的机会”
- 效果:
- 平衡“顺势而为”(exploitation)和“逆人性探索”(exploration)
- 分析历史上参数共同变化的相关性矩阵
- 显式挑选“互相尽量正交”的参数对,做成系统组合实验
- 效果:
- 打破“某些超参数永远绑在一起调”的共线性
- 让系统分清:“到底是谁在起作用?”
> 这三类机制本质上都在有意识地对抗 LLM 自己的“理性偏见”,逼它去试“它平时觉得不太合理”的区域。
而在 Karpathy 那个 GPT 预训练基准上,这种“强制反直觉探索”直接导致了一个非常具体、可解释的发现:
- 原 baseline 的
TOTAL_BATCH_SIZE= 219 - 这是为了配合 H100 的吞吐设定的
- 在 RTX 5090 + 300 秒预算下,更小的 batch(217–218)反而更好,因为:
- 在同样时间内可以跑更多步更新
- 对这个模型尺寸 & 预算,是更合适的 sweet spot
- 纯 Level 1:因为先验(“大 batch 一般更好”),几乎总是往 batch 更大的方向试
- 带 Level 2 的组(C/D):
- 禁忌搜索 + 正交探索
- 逼着系统反方向探索“减小 batch”,最后才找到了这个关键点
> “LLM 不是已经把论文都看完了吗?为什么还需要这样的大费周章?”
因为:看过 ≠ 会主动怀疑自己的先验;Level 2 的存在,就是制度性地制造“怀疑与越界”。
---
洞见五:“如果能元优化自己,那原则上可以元优化任何可度量的东西”
这是作者最后给出的那句核心原则,可以直接当作“这一代 autoresearch 的纲领”:
> 如果 autoresearch 能对自身做 meta-autoresearch,那原则上它就能对任何有可测量目标的系统做 meta-autoresearch。
翻译成工程语言,就是:
- 只要你能提供:
- 一个可编辑资产(某个系统的“可改部分”——代码、配置、规则等)
- 一个标量指标(可自动算的好坏分数)
- 一个固定实验预算(一次尝试的资源上限)
- 那么,理论上:
- 你不仅可以做“自动调参”(Level 1)
- 还可以做“自动发明调参算法”(Level 2)
- 长期目标甚至是:“自动发明做这件事的科学方法”
3. 如果你要“抄作业”:一个可操作的落地蓝图
如果你不是只想理解,而是准备自己搞一个“简化版 Bilevel Autoresearch”,可以照着下面的清单来:
步骤一:先搞一个 Karpathy 式 Level 1 循环
最小可行要素:
1. 选定一个 可编辑资产(比如某个训练脚本 train.py 或某个系统配置文件)
2. 定义一个 标量指标(比如验证 loss、准确率、延迟、收益等)
3. 实现一个 固定时间/资源的训练或运行周期(比如“每次试验最多跑 300 秒”)
4. 用 LLM 做简单的循环:
- 读当前资产(代码/配置)
- 提出一个修改 diff
- 应用、运行一次实验、记录指标
- 指标更好就保留,否则回滚
步骤二:实现“软版 Level 1.5”(可选,但有助于诊断)
虽然论文里 1.5 单独没啥提升,但它有个重要作用:把搜索轨迹结构化。
你可以:
- 每 N 次内层实验,汇总:
- 哪些参数被改了几次
- 哪些改动从没带来好处
- 然后:
- 给 LLM 一段“探索建议提示语”
- 或者标记一些参数为“暂时冻结”
步骤三:实现缩减版 Level 2(从一个机制开始)
真正的核心是这层。可以先做一个轻量版本,只围绕一个机制家族展开,比如禁忌搜索:
1. 给外层 LLM 的输入:
- 当前的
runner/ 搜索逻辑代码 - 最近 K 轮的搜索历史(参数 → 指标)
- “请基于这些历史,发现搜索模式的问题,并生成一个
TabuManager或类似类,用于: - 维护最近失败配置列表
- 提供一个
is_tabu(config)接口供内层调用”
- 写入一个单独的
.py文件 - 在内层逻辑中插入调用,例如:
if not tabu_manager.is_tabu(candidate_config):
# 才允许这次实验
4. 加一层简单的安全带:
- 动态 import 新模块,跑一个小的 dry-run 单测
- 不过就回滚到老逻辑
步骤四:引导 LLM 去“借用”别的领域方法
和论文类似,你可以在外层的 prompt 里显式写上几个领域名,例如:
- “可以考虑组合优化、Bandit、多臂老虎机、贝叶斯优化、实验设计等方向的启发式。”
---
4. 最后一层费曼式升华:这篇论文点亮的其实是“视角”
如果只用一句比较哲学的话来评价这篇工作:
> 它证明了:我们不一定要造一个“更聪明”的脑,而是可以先学会让同一个脑,用两种不同的方式看自己。
- 内层 = “我在做事”
- 外层 = “我在研究我怎么做事”
- 而两层之间真正的桥梁,不是神秘的“意识”,而是一段可以被改写与回滚的 Python 代码。
- 你完全可以先用现有 LLM,把问题拆成“执行”和“改写执行规则”两份来玩
- 只要你能:
- 记录历史(轨迹)
- 暴露规则(代码)
- 给出分数(标量指标)
- 递归的火花就有了点燃的条件。