@iamgrigorev: https://x.com/iamgrigorev/status/2071688181628678468

X AI KOLs Timeline 新闻

摘要

一份关于设计有效机器学习实验的详细指南,强调从明确的研究问题开始,培养研究品味,并扩展结果。基于作者在Poolside每周运行约100次实验的经验。

https://t.co/Mny7zow50b
查看原文
查看缓存全文

缓存时间: 2026/06/29 22:31

如何设计好的机器学习实验并从中真正学到东西

目前我每周在 Poolside 启动大约 100 个实验。在我们的架构团队中,我可能是运行实验和想法最多的人。每个夜晚和周末,我都在做新的实验。这是好事,因为当前的设置让我们能比以往探索更广的范围。你可以同时运行 5-10 个 agent 会话。你肯定有一个高级的 X feed,里面充满了最新的研究想法和论文。你可以自己找论文,也可以从别人正在尝试的想法中汲取灵感。

一个好的实验始于一个研究问题。它基于合适的基线启动,可复现,能跑完,并以一种你日后能记住的方式记录下来。如果结果看起来不错,最终你需要明白它是否能够扩展。

从研究问题开始

在实现任何东西之前,你应该知道自己真正想要测试什么。否则,你很容易花一天甚至一周时间启动一个不会给你有用答案的实验。

有时问题是这个改动如何影响质量,但有时你可能会有更基础的问题。例如,你可能会问哪个宽高比最优,能否优化训练速度,减少滑动窗口大小或全局注意力层数量是否可行,架构的某部分能否在保持质量的同时简化,或者某个改动是因为改进了优化、减少了通信、还是消除了无用计算才有效。

重要的是,实验应该有其存在的理由。如果你没有一个具体的问题,实验很可能会失败,或者结果难以解释,或者即使数字看起来不错,该方法实际上也无益。这是一个非常常见的失败模式。如果实验不是从问题开始,答案通常是模糊的。所以在启动之前,我喜欢把问题明确写出来,至少在心里和实验笔记中明确。实验应该能回答某个问题,否则它只是一次运行。

想法从何而来

想法来源有很多。它们可以来自最近的论文,也可以来自老论文及其引用的文献。它们可以来自 X,来自诸如 NanoGPT Speedrun 之类的资源,或者来自团队内部的讨论。当你分析自己训练框架中的瓶颈时,也常常会冒出想法。有时,它们仅仅来自于经验——在花足够多的时间查看配置、训练曲线和基准表之后,模式开始显现,新想法自然随之而来。

想法总是比时间多。重要的技能是决定哪些想法现在值得测试,哪些应该留到以后,以及哪些可能因为信号价值不高而成本太高。这就是研究品味如此重要的原因。

培养研究品味

我所说的研究品味,是指找到既符合你技能、又有成果、易于测试、并且很可能让你学到东西的想法。大多数时候,最好先关注简单的想法。简单的想法更容易实现、更容易调试、更容易比较,也更容易与其他想法结合。

这在架构研究中尤其重要。一个在简单训练框架中开发的简单想法可能看起来并不惊人。但同样的想法在更复杂、更优化的训练框架中可能会大放异彩。我们在 Poolside 的情况就是如此。我们的训练框架非常棒,围绕计算-通信重叠和并行设置进行了优化,我们的 transformer 实现也很出色。因此,添加简单的功能并保持有限使用是一件很愉快的事。一个小的改动可以干净地测试。如果有效,可以与其他改动结合。如果无效,它仍然能告诉我们关于瓶颈的信息。

这就是为什么我通常更倾向于先广后深,而不是先深后广。先广意味着测试许多简单的想法,了解表面区域,看看哪里存在信号。先深则意味着在某个大方向上花费更多时间。你最终需要两者兼备,作为一个团队,你很可能需要保留一些高质量的想法以备取胜。但过早深入常常是一个错误。

例如,大多数时候我不会一开始就把注意力改成非常复杂的稀疏注意力变体。我不会立即从头实现 Gated DeltaNet、MIMO 的 HYSparse,或者需要自定义 Cute-DSL 内核的随机 SSM。这些想法可能很重要,有些甚至可能是正确的长期方向。但在常规的实验环境中,除非你非常有信心它们会成功,否则它们通常成本太高。

对于大多数实验来说,最好的想法并不是那些看起来最令人印象深刻的。它们是那些成本足够低、结果足够清晰、并且有可能与其他改进相结合的想法。

简单的想法可以成为强大的想法

简单的想法之所以有价值,是因为它们可以叠加。一个想法本身很小,但与其他改动结合时就可能很有用。

对我而言,一个例子是层归一化缩放。我一直很喜欢《The Curse of Depth》论文中的这种方法。从概念上讲,它感觉是思考更深层 transformer 的一个可靠方式。直觉上说得通。但实际上,它的扩展性不够好。

但这个方向仍然有趣。所以我没有完全放弃它,而是查阅了引用原始归一化缩放想法的参考文献和较新的论文。于是我找到了 ProRes,即渐进式残差预热。这个想法是对类似直觉的更好版本。每一层的残差连接乘以一个标量值,该值在训练过程中从 0 逐渐增加到 1。预热取决于层 ID,因此浅层预热更快,深层预热更慢。这实际上是有效的。很不错。

重要的不仅仅是具体方法。重要的是,一个失败的想法可以指向一个更好的想法。如果你理解了自己最初喜欢这个想法的原因,你就可以搜索更新版本、相关工作、引用或修改,这些修改保留了直觉但修复了失败模式。研究不仅仅是孤立的实验。它也是一张长期的地图,包含直觉、失败和未来可能用到的方向。

实验需要跑完

在你选择一个想法之后,下一个重要的事情是执行。实验需要可复现。你需要预期它们会跑完。而且,大多数时候,你应该让它们跑完。

中途停止实验是一个危险的习惯。有时是必要的,比如运行明显出错、损失爆炸或配置错误。但如果你只是因为早期看起来稍差,或者因为不耐烦就停止运行,那么你通常会丢失结果。你无法真正用它作为证据。你无法正确地记录下来。

一个未完成的实验通常不是知识,只是算力被浪费了。这很重要,因为有些想法在训练的不同阶段表现不同。这听起来显而易见,但实际上有一些含义。例如,如果你发现你的运行表现更好,并且你使用了余弦学习率调度,然后中途停止了,那么你的运行没有正确衰减,也许你可以在相同的 token 训练量下得到更好的结果。如果你过早杀死太多实验,你的品味会偏向那些看起来立即有效的想法。

当然,你仍然需要判断。你不应该在明显出错的运行上浪费算力。但默认情况下,一个正确启动的实验应该跑完,否则你不会知道结果。一个研究过程应该创造证据,而不仅仅是曲线。

维护一个手动表格

我用 Google 表格记录我的大部分运行。对我来说,这实际上是过程中最重要的部分之一。当你启动足够多的实验时,你不可能把所有东西都记在脑子里。你会忘记哪个运行用了哪个配置,它对比的是哪个基线,结论是什么等等。

当实验数量变得庞大时,这一点尤其重要。如果你每周启动 100 个实验,几周后你肯定会迷失。我更喜欢这个表格是手动的,而不是 AI 生成的。手动添加内容到表格会在实验和记录的结果之间建立一种心理联系。当你自己写下来时,你会记住更多,并且对运行更有责任感。

手动验证配置

另一个简单的规则是:在启动前总是手动验证配置。检查实际实验开始前的配置看起来如何。确保字段正确,基线配置是你预期的,架构正确(包括 batch size、并行设置和学习率),并且功能确实已启用。

当许多人贡献同一个代码库时,这变得更加重要。仓库会变,默认值会变,功能会被合并,基线会被更新。再说一次显而易见的事——但请经常拉取最新的 main 分支!

基线配置极其重要

基线配置是实验中最关键的部分之一。我加入时,引入了一个基线配置流程并保持其更新。想法很简单:我们在 main 中有一个主要基线配置,并且每次添加经过验证的新特性时都会更新这个基线。其他团队成员不必重新运行相同的旧基线。每个人都使用相同的架构和相同的参考点。

没有这个,研究会很快变得混乱。一个人与一个基线比较,另一个人与略有不同的基线比较,第三个人使用旧的配置。有人忘记某个功能已被合并。有人使用不同的架构细节运行。过了一段时间,人们仍然说“基线”,但这个词的含义不再统一。

基线应该标注日期。这样你就能区分版本。标注日期的基线为你提供了一个稳定的参考。你可以说这个实验与某个日期的基线进行了比较,该基线具有特定的架构和训练方法。然后,当基线改变时,它是明确改变的。

流程很简单。你有一个基线。有人启动一个带有自己名称和日期的特性运行。如果特性成功,它会被推送到 main。当几个经过验证的新特性被添加后,基线与新日期一起重新训练。从那时起,每个新特性都与新基线进行比较。

这很重要,因为你希望质量是单调递增的。你希望随着已验证特性的添加,main 配置变得更好。它成为已验证有效特性的共享集合,并且也允许你立即开始生产运行。

选择适合你节奏的基线大小

我们通常保留两种基线大小:较小的 4B MoE 配置和较大的 17B MoE 配置。17B MoE 是最接近生产的配置。它的稀疏度与我们的生产模型相似,并且稍微过度训练,大约 TPP 300,这是我们信任的。它足够大,行为更接近我们真正关心的模型,同时仍然可以在正常的实验循环中运行。较小的 4B MoE 配置用于更快的迭代,以快速测试许多想法。

选择这些大小是一个权衡。我特意选择那些可以在合理时间内(通常大约一天)在合理计算资源上完成的基线配置。这非常重要。如果基线花费时间太长,没人愿意等待。人们会启动更少的实验。

因此,基线必须适配你的资源和节奏。较慢的节奏允许更长的训练运行,而更快的节奏需要更小但仍有信号的运行,通常通过多层级方法实现。如果你想法较少,较慢的节奏也可以。如果你想法很多,你需要更快的节奏。如果团队更大,你需要更多的纪律,因为许多人会同时启动实验。基线必须足够便宜以至于人们真的使用它,并且足够有意义以至于结果值得信任。

以稳定的方式评估

运行结束后,下一个问题是如何评估它。对于预训练,基于似然的基准测试是可靠的选择,因为它们稳定。当你使用生成类型的评估时,平均几个评估结果很有用,例如 GPQA。然后报告所有评估的平均值是有效的,因为它给出了一个简单的参考。这使得快速比较许多运行变得更容易。在做出决定时,你仍然需要检查单个数值。

因此,平均值给了你一个快速参考,而单个基准测试告诉你结果是否有意义。这也是稳定基线重要的原因。

基线还不够

基线是必要的,但并不充分。它告诉你想法在测试规模下是否有效。它不能完全告诉你想法是否可扩展。

因此,你时不时需要缩放定律。构建缩放定律成本很高。通常需要 7 到 20 次运行,具体取决于方法和所需的拟合质量。你不会想为每个新实验都构建一个缩放定律。它过于复杂,对于日常迭代来说不够灵活。

相反,你偶尔构建一个缩放定律,使用尽可能接近生产的设置:相同的数据、相同的重复次数、与目标模型大小相同的稀疏度、相同的训练方法、相同的总体设置。然后你构建一个跨不同大小的缩放阶梯。这值得单独讨论,所以我不会在这里详细展开。重要的是,在你拟合好缩放定律后,你可以用它来推理新方法是否更计算高效。

效率增益

假设你有一个新的运行。你将其与相同大小的基线进行比较,新模型在损失上更优。这听起来不错,但多少才算足够?0.01 够吗?0.005 够吗?是否依赖于规模?

这就是为什么原始损失差异并不总是最佳的思考方式。当然,损失很重要。最终形式下,更好的下一个 token 预测通常会导致更好的整体表现。我们的总体目标是改善下一个 token 预测。但在评估实验时,你通常需要一个比“损失降低了少量”更可解释的指标。

这时计算效率增益就很有用。想法很简单。你的新模型在花费一定计算量后达到了某个损失。称这个观察到的计算量为 C_observed。使用你的基线缩放定律,你预测基线需要花费多少计算量才能达到相同的损失。称这个为 C_predicted。

那么:

效率增益 = C_predicted / C_observed

如果比值大于 1,你的方法比基线更计算高效。它以更少的计算量达到了相同的损失。如果比值小于 1,则表现不佳。这是一个很好的数值定义来量化改进。它将损失差异转化为计算量。你不再问 0.01 的损失是否足够,而是问相比较基线缩放定律,该方法节省了多少计算量。这更容易推理。

在实际操作中,这意味着训练几个模型——通常是四个——在不同的计算预算和大小下,然后检查计算效率增益在这些模型上的表现。如果增益始终大于 1,这是一个好迹象;如果随着规模增加而增加,那就更好了;如果保持稳定,也还可以接受。但如果随着规模扩大而下降,那么很可能这个想法不起作用。这就是为什么基线实验和缩放实验扮演不同角色:基线实验告诉你想法在既定规模下是否有效;缩放实验告诉你它是否可能扩展。

(文章继续,但根据你的要求,我们只翻译到此处。如果需要继续,请告知。)

相似文章

@jxmnop: https://x.com/jxmnop/status/2066668040557867368

X AI KOLs Following

一条推特讨论,为进行人工智能研究提供哲学和实践建议,强调阅读与实践相结合,深入理解基础而非追逐潮流,保持初学者心态,以及纪律和开放心态的重要性。

vivek (@itsreallyvivek) 在X上

X AI KOLs

一条关于在机器学习中培养真正研究技能的有深度的帖子,涵盖了如何独立选题、培养品味、提升信息输入以及通过写作来厘清思路。