想象你是一支万人登山队的队长,队伍分成几十个分队,每队背负着完全不同的装备。登顶的命令只有一条:“全体向前一步。”可是重装分队和轻装分队听到同样的口令时,重装队员踉跄,轻装队员已经冲出去老远。深度学习里的“大批量训练”正是这个场景:当 batch size 被推到 64K 甚至更大,模型里几十个层就像负重不等的分队,而普通优化器对所有人的步长要求只有一个全局学习率。LAMB 优化器的出现,就像给每个分队派了一位经验丰富的向导——不是给所有人同一个步长,而是先称一称每队装备的重量(参数范数),再看看他们打算迈多大步(更新范数),然后为每个队校准一个“信任比率”。这样,重装队不会摔跤,轻装队不会跑偏。下面我们就沿着这条登山路线,把 LAMB 从“大队难题”一路聊到“BERT 实战”。

岗位关联

掌握 LAMB,你的模型训练就能从“大批量就崩”的困境里解放出来——尤其在千亿参数大模型和超长预训练任务中,这是显著缩短训练时间的关键钥匙。

目录
  1. 可视化演示
  2. 大批量训练难题
  3. LAMB核心思想
  4. 算法机制解析
  5. BERT预训练实践
  6. 与Adam对比
  7. 工程调优点
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示编译器代码优化阶段如何通过DAG(有向无环图)识别并消除公共子表达式,减少冗余计算,优化基本块内的指令序列。

本节配有交互动效(进入视口后自动加载,约 3KB)。

原始DAG(未优化) 构建基本块的DAG表示 红色节点标记重复计算 t1=a+b, t2=a+b(重复) 存在冗余的公共子表达式

大批量训练难题

当指挥官的哨声只有一声,但队伍里有人背帐篷、有人背绳索、有人背氧气瓶,要求所有人迈出完全一样的步幅,这支队伍很快就会东倒西歪。深度学习里的大批量训练也有类似的尴尬:我们把 batch size 从 256 提高到 64K,本意是让每一步的梯度估计更平滑、更高效,但如果优化器给所有层一个统一学习率,某些层的参数步长会突然过大,另一些层却几乎不动。

这里面的核心矛盾是“层间尺度差异”。一个深层网络里,Embedding 层、Attention 层、FFN 层的参数范数可能相差好几个数量级。梯度经过多层反向传播后,各层的梯度范数更是参差不齐。Adam 这样的优化器虽然对每个参数都有自适应学习率,但它并没有考虑“这一层当前参数有多大”,于是当 batch 极大、学习率需要等比放大时,某一层就会成为最先“爆”的短板。

也正是这种不稳定性,让大批量训练常被形容为“悬崖边上跳舞”。想要不摔下去,要么小心翼翼地把学习率调得极小,让训练慢得难以接受;要么换一种能感知层间差异的步长策略。LAMB 就是为此而来的。

LAMB核心思想

这位经验丰富的向导不会只说一句“走”,而是先看一眼每个分队的装备总重量,再看一眼他们原本计划推出去的那一步有多大。如果一步迈得比装备重量还夸张,就把它收回来一些;如果一步明显太保守,就放大一些。在 LAMB 里,“装备总重量”是当前层的参数范数,而“计划推出去的一步”是 Adam 风格的原始更新方向。

用数学语言说,对第 \(i\) 层参数:

其中 \(\theta_t^{(i)}\) 是第 \(i\) 层的权重,\(\Delta_t^{(i)}\) 是由一阶矩和二阶矩计算出的 Adam 更新方向。这个比值 \(\displaystyle \frac{\|\theta_t^{(i)}\|}{\|\Delta_t^{(i)}\|}\) 就是“信任比率”。

这样一来,即使不同层重量悬殊,它们在每一次更新里走过的“相对距离”却能保持相近。登山队既能整体推进,又不会有人一脚踩空。

θt+1(i)=θt(i)−η ∥θt(i)∥∥Δt(i)∥ Δt(i)\displaystyle \theta_{t+1}^{(i)} = \theta_t^{(i)} - \eta\,\frac{\|\theta_t^{(i)}\|}{\|\Delta_t^{(i)}\|}\,\Delta_t^{(i)}
  1. 当前层参数\(\theta_t^{(i)}\) 表示第 \(i\) 层在时间 \(t\) 的权重向量,可以是二维矩阵,也可以被看成一个大向量。
    θt(i)\theta_t^{(i)}
  2. Adam更新方向\(\Delta_t^{(i)}\) 是这一层在不考虑层间差异时,Adam 本来要走的“原始一步”。
    Δt(i)=m^t(i)v^t(i)+ε\Delta_t^{(i)} = \frac{\hat m_t^{(i)}}{\sqrt{\hat v_t^{(i)}} + \varepsilon}
  3. 信任比率用参数范数除以更新方向范数,得到“这一脚相对装备重量来说该放大还是收小”。
    rt(i)=∥θt(i)∥∥Δt(i)∥r_t^{(i)} = \frac{\|\theta_t^{(i)}\|}{\|\Delta_t^{(i)}\|}
  4. 最终更新学习率 \(\eta\) 乘上信任比率,再乘上原始更新方向,让每一层的绝对步长与其参数尺度挂钩。
    θt+1(i)=θt(i)−η rt(i) Δt(i)\theta_{t+1}^{(i)} = \theta_t^{(i)} - \eta\, r_t^{(i)}\,\Delta_t^{(i)}

算法机制解析

想要真正驾驭 LAMB,不能只记住一个公式,还要看懂它和 Adam 共同使用的“仪表盘”。LAMB 保留了 Adam 对每个参数的动量估计和梯度二阶矩估计,只是多了一层“逐层裁判”。

首先,一阶矩 \(m\) 记录梯度方向的平滑趋势,二阶矩 \(v\) 记录梯度数值的平滑幅度。因为训练刚开始时这两项都偏小,还需要做偏差校正:

校正之后,LAMB 再计算该层的原始更新方向,并套上信任比率:

看到这里会发现,LAMB 并没有抛弃 Adam,而是在 Adam 的“脚下”按层加了可伸缩的弹簧:方向仍然由动量决定,但迈步大小由该层参数尺度说了算。

m^t(i)=β1mt−1(i)+(1−β1)gt(i)1−β1t,v^t(i)=β2vt−1(i)+(1−β2)(gt(i))21−β2t\displaystyle\begin{aligned}\hat m_t^{(i)} &= \frac{\beta_1 m_{t-1}^{(i)} + (1-\beta_1)g_t^{(i)}}{1-\beta_1^t},\\\hat v_t^{(i)} &= \frac{\beta_2 v_{t-1}^{(i)} + (1-\beta_2)\left(g_t^{(i)}\right)^2}{1-\beta_2^t}\end{aligned}
  1. 更新方向用偏差校正后的动量除以二阶矩的平方根,得到 Adam 式方向。
    Δt(i)=m^t(i)v^t(i)+ε\Delta_t^{(i)} = \frac{\hat m_t^{(i)}}{\sqrt{\hat v_t^{(i)}}+\varepsilon}
  2. 信任比率比较当前参数范数和更新方向范数,判断这一步相对该层是否“太大”或“太小”。
    rt(i)=∥θt(i)∥∥Δt(i)∥r_t^{(i)} = \frac{\|\theta_t^{(i)}\|}{\|\Delta_t^{(i)}\|}
  3. 裁剪映射\(\phi(\cdot)\) 通常把信任比率限制在例如 \([0.1, 10]\) 的范围内,防止极端更新。
    ϕ(rt(i))=min⁡(max⁡(rt(i),0.1),10)\phi\left(r_t^{(i)}\right) = \min\left(\max\left(r_t^{(i)}, 0.1\right), 10\right)
  4. 参数更新学习率、裁剪后的信任比率、更新方向三者相乘,得到这一层真正踏出的一步。
    θt+1(i)=θt(i)−ηt ϕ ⁣(rt(i))Δt(i)\theta_{t+1}^{(i)} = \theta_t^{(i)} - \eta_t\,\phi\!\left(r_t^{(i)}\right)\Delta_t^{(i)}

BERT预训练实践

当整套指挥系统第一次用在大规模探险队上,效果让所有人惊喜。BERT 这类预训练模型层数深、参数多,以往想缩短预训练时间,最直接的办法是加大 batch 并提高并行度,但 Adam 在超大批次下很难稳定收敛。LAMB 的出现,让 BERT 也能像滑雪一样顺着大批次赛道全力冲刺。

在 Google 当年的实验中,使用 LAMB 配合约 64K 的 batch size,BERT-Large 预训练在 1024 块 TPU 上大约 76 分钟就能完成,而传统方案动辄需要数天甚至数周。更关键的是,模型在 GLUE 等下游任务上的精度没有明显损失,有些任务甚至略有提升。这个结果让研究者意识到:阻碍超大批量训练的并非硬件,而是优化器缺乏层间感知能力。

从工程视角看,这相当于把每层参数的更新步长从“一刀切”变成“量体裁衣”。Embedding 层参数巨大,但更新方向可能很小;注意力层的参数范数小,却需要相对更大的更新。LAMB 通过信任比率让每一层都处在安全的前进区间,于是通信效率和大 batch 吞吐量真正转化为训练时长的缩短。

与Adam对比

如果 Adam 是只发统一登山鞋的教练,那 LAMB 就是会按每个人脚码配鞋的向导。Adam 的“自适应”体现在参数维度:每个参数根据自身历史梯度调整这次更新的数值大小。但它并不会问一句“你这个层整体有多大”。对于一个 MobileNet 这样只有几层的模型,问题不大;可对于一个几十层的 Transformer,层间参数尺度差异会被极大的 batch 放大。

LAMB 与 Adam 有三个关键区别。第一,Adam 使用全局学习率乘以每个参数的归一化梯度,LAMB 则额外计算每一层的信任比率。第二,Adam 的更新范数可能远小于或远大于参数范数,而 LAMB 会让更新范数与参数范数保持一个相对稳定的比例。第三,在 batch size 较小时,LAMB 往往和 Adam 表现接近,优势不明显;但当 batch 增大到 64K 甚至 128K 时,Adam 需要极其精细的学习率搜索,LAMB 却依然稳如磐石。

这并不意味着 LAMB 永远更好。小 batch 下 Adam 已经足够稳定,LAMB 多出的范数计算和每层缩放反而增加了一点开销。真正的定位是“大批量训练的钥匙”,用来开启数据并行、模型并行和超长预训练带来的规模红利。

工程调优点

最好的登山队长,也要有补给计划、天气窗口和应急预案。LAMB 不是魔法,工程上还要注意几个细节:

第一,学习率热身(warm-up)几乎是必需品。训练最初几百步,梯度估计还不稳,先用一个较小的学习率起步,再逐步升高到峰值,可以有效避免早期爆炸。第二,信任比率需要裁剪。如果不加限制,某层参数范数偶尔接近零时,信任比率会异常大,导致参数猛烈跳动。常见做法是把 \(r\) 限制在 \([0.1, 10]\) 左右。第三,默认超参数可以直接沿用 Adam 的习惯:\(\beta_1=0.9\)、\(\beta_2=0.999\)、\(\varepsilon=10^{-6}\) 或 \(10^{-8}\),在此基础上再对峰值学习率做一次小范围搜索。第四,永远要监控损失曲线和逐层更新范数。如果某层更新范数突然异常,及时减小裁剪上限或调整热身步数。

把这些工程细节看成给登山队配的安全绳:LAMB 解决“步长分层”的核心问题,而热身和裁剪解决“极端天气”下的意外风险。两者配合,才敢真正开足马力冲上超大批量这座高峰。

AI 应用场景

BERT类大模型预训练

阶段:模型预训练 / 优化器选择

解决的问题:传统 Adam 在大 batch 下需要反复搜索学习率,稍大一点就损失抖动甚至无法收敛;LAMB 让 64K 甚至更大 batch 稳定训练,吞吐量优势真正落地。

具体案例:某团队预训练中文 BERT,原先单机 batch 256 需要三周。换成 LAMB 后,配合 128 张 GPU 和 64K batch,训练时间压缩到两天左右,下游分类和匹配任务准确率基本持平。团队不需要再为“学习率调到多少合适”熬夜试参。

大规模推荐系统 Embedding 层训练

阶段:大规模稀疏模型训练 / 优化器调优

解决的问题:推荐模型里 Embedding 表参数量巨大,参数范数和 MLP 层相差几十倍;统一学习率很容易让 Embedding 梯度爆炸或 MLP 收敛过慢。

具体案例:某推荐平台的点击率模型包含 10 亿级 Embedding 参数和 3 层 MLP。使用 LAMB 后,Embedding 层更新幅度被自动校准,团队把训练 batch 从 8K 提升到 32K,训练速度提升约 2.5 倍,线上 AUC 没有下降。

Python 演示

python59 行
import numpy as np  class LAMB:    def __init__(self, params, lr=0.01, betas=(0.9, 0.999), eps=1e-6, max_trust=10.0):        self.params = params        self.lr = lr        self.beta1, self.beta2 = betas        self.eps = eps        self.max_trust = max_trust        self.ms = [np.zeros_like(p) for p in params]        self.vs = [np.zeros_like(p) for p in params]        self.t = 0     def step(self, grads):        self.t += 1        for i in range(len(self.params)):            p = self.params[i]            g = grads[i]            self.ms[i] = self.beta1 * self.ms[i] + (1 - self.beta1) * g            self.vs[i] = self.beta2 * self.vs[i] + (1 - self.beta2) * g * g            m_hat = self.ms[i] / (1 - self.beta1 ** self.t)            v_hat = self.vs[i] / (1 - self.beta2 ** self.t)            update = m_hat / (np.sqrt(v_hat) + self.eps)            p_norm = np.linalg.norm(p)            u_norm = np.linalg.norm(update)            trust = 1.0 if u_norm == 0 else p_norm / u_norm            trust = min(trust, self.max_trust)            p -= self.lr * trust * update  def make_data(n=128):    x = np.random.randn(n, 4)    w = np.array([1.5, -2.0, 3.0, -0.5])    y = x.dot(w) + 0.1 * np.random.randn(n)    return x, y  def train():    x, y = make_data()    hidden = np.random.randn(4, 3) * 0.2    out = np.random.randn(3, 1) * 0.2    params = [hidden, out]    opt = LAMB(params, lr=0.1)    for epoch in range(50):        h = np.maximum(x.dot(hidden), 0)        pred = h.dot(out)        loss = np.mean((pred - y[:, None]) ** 2)        d = 2 * (pred - y[:, None]) / len(x)        g_out = h.T.dot(d)        g_hidden = (d.dot(out.T) * (x.dot(hidden) > 0))        g_hidden = x.T.dot(g_hidden)        opt.step([g_hidden, g_out])        if epoch % 10 == 0:            print('epoch', epoch, 'loss', round(float(loss), 4))  if __name__ == '__main__':    train()
目的:用纯 NumPy 实现一个简版 LAMB,在一个两层小网络上演示逐层信任比率如何驱动参数更新。
  1. self.ms[i] = self.beta1 * self.ms[i] + (1 - self.beta1) * g维护一阶矩,记录梯度方向的平滑趋势。
  2. self.vs[i] = self.beta2 * self.vs[i] + (1 - self.beta2) * g * g维护二阶矩,记录梯度幅度的平滑估计。
  3. update = m_hat / (np.sqrt(v_hat) + self.eps)先算出标准的 Adam 更新方向。
  4. trust = 1.0 if u_norm == 0 else p_norm / u_norm计算信任比率,即参数范数对更新范数的比值。
  5. p -= self.lr * trust * update用学习率、信任比率和更新方向一起修该层参数。

常见误区

误区听说 LAMB 是专门为 64K batch 设计的,所以平时用 256 或 512 的 batch 就不能用 LAMB,否则效果会变差。

正解LAMB 并没有“排斥小 batch”。它只是在超大批量下优势最明显。小 batch 下 LAMB 的表现通常与 Adam 相当,只是多了一点范数计算开销。如果你不想在几个优化器之间切换,直接从 Adam 换成 LAMB 一般不会带来灾难性后果。

为何常见:论文和宣传都强调 64K batch 和“超大批量训练”,容易让人误以为 LAMB 的适用范围只有大 batch。

误区LAMB 是“Layer-wise adaptive”,那它应该像 schedule 一样,给每一层安排一个独立学习率,训练过程中保持不变。

正解LAMB 的信任比率每一步都在变化:它依赖当前时刻的权重范数和更新方向范数,因此同一层在不同迭代里会拿到完全不同的缩放比例。它不是离线规划好的固定学习率,而是逐 step、逐层动态计算的。

为何常见:“层自适应”这个词容易让人联想到按层设置超参数,忽略了它本质上是在更新公式里加入了一个动态比值。

误区加入信任比率就是为了放大更新,所以把裁剪上限调得很大甚至不裁剪,模型应该跑得更快。

正解信任比率过大会让某层参数的相对变化过大,梯度可能直接震荡甚至发散。信任比率的正确目标是让每层相对更新幅度保持在合理区间,而不是一味放大。裁剪到 10 左右是常见安全操作。

为何常见:人们容易把“自适应”理解为“自动加速”,忽略了稳定向前才是优化器的第一目标。

误区LAMB 号称“无需精细调节学习率”,所以训练时可以直接用一个固定学习率跑到底,不需要热身和衰减。

正解LAMB 降低的是对大 batch 场景下学习率搜索的敏感度,但并没有完全消除对学习率调度的需求。训练初期梯度统计不稳,热身依然能显著降低损失爆炸概率;训练后期适当衰减也有助于收敛到更平缓的区域。

为何常见:摘要里的“无需精细调节”被过度解读成“完全不需要调学习率”,其实它指的是大幅减少试错次数,而不是取消所有的学习率策略。

面试题

Q1. LAMB 中“Layer-wise”的核心含义是什么?

单选题 · easy

  • A.每个样本单独调整学习率
  • B.每层网络使用独立缩放步长← 正确答案
  • C.每个 batch 动态改变一次层数
  • D.逐层冻结网络中的参数

答案:B。LAMB 的“Layer-wise”是指在 Adam 更新方向基础上,按每一层的参数范数计算独立信任比率,从而让每层更新步长独立缩放。A 是样本级、C 是结构改变、D 是训练策略,都不符合。

Q2. LAMB 中的“信任比率”主要作用是什么?

单选题 · easy

  • A.固定全局学习率
  • B.按参数范数调整该层更新幅度← 正确答案
  • C.增大梯度估计的噪声
  • D.减少训练时的显存占用

答案:B。信任比率等于该层参数范数除以更新方向范数,本质是校准这一层“该迈多大步”。它不直接修改显存,也不会故意增加噪声,更不是把学习率固定住。

Q3. LAMB 相比 Adam 最主要的改进是什么?

单选题 · mid

  • A.只使用一阶矩,不用二阶矩
  • B.引入逐层信任比率缩放← 正确答案
  • C.取消了偏差校正过程
  • D.强制要求使用更大的 batch

答案:B。LAMB 保留 Adam 的一阶矩、二阶矩和偏差校正,只是在更新方向外乘了一个逐层信任比率。它不强制要求大 batch,只是在超大批次下优势更明显。

Q4. 在 BERT 预训练中,LAMB 最突出的价值是什么?

单选题 · mid

  • A.减少模型的参数量
  • B.让超大批次训练稳定收敛← 正确答案
  • C.提高单卡推理的速度
  • D.完全避免使用梯度

答案:B。LAMB 让 64K 甚至更大的 batch 稳定训练,从而把分布式吞吐量转化为训练时间的大幅缩短。它不改变模型结构,也不影响推理,更不可能绕开梯度。

Q5. LAMB 算法中会计算以下哪些量?

多选题 · mid

  • A.一阶矩 m← 正确答案
  • B.二阶矩 v← 正确答案
  • C.信任比率 r← 正确答案
  • D.特征图尺寸

答案:ABC。LAMB 完整保留了 Adam 的一阶矩和二阶矩计算,并额外计算逐层信任比率。特征图尺寸是网络结构信息,不是优化器计算量。

Q6. LAMB 中的信任比率裁剪技术解决什么问题?

单选题 · hard

  • A.防止极端更新导致训练发散← 正确答案
  • B.将梯度全部置为零
  • C.让学习率自动翻倍
  • D.把一个大 batch 切分为小 batch

答案:A。当某层参数范数接近零或更新范数极小时,信任比率可能异常大。裁剪就是为了把这个比值限制在合理区间,避免一步迈出“悬崖”。

Q7. 超大批量训练中全局学习率难以调节的原因有哪些?

多选题 · hard

  • A.各层参数范数差异大← 正确答案
  • B.各层梯度更新尺度不均← 正确答案
  • C.GPU 数量太多
  • D.数据增强倍数过高

答案:AB。层间参数范数和梯度尺度差异是核心原因:同一个全局学习率无法同时适配重量悬殊的层。GPU 数量和数据增强是训练资源配置问题,不是学习率敏感的本质原因。

Q8. 使用 LAMB 训练非常大的 batch 时,以下哪项组合最有利于稳定?

单选题 · hard

  • A.不热身、不裁剪信任比率
  • B.关闭二阶矩,只保留一阶矩
  • C.逐层信任比率加上裁剪← 正确答案
  • D.每次更新前清空第一矩

答案:C。LAMB 的灵魂是逐层信任比率;裁剪能防止极端缩放。不热身、关闭二阶矩或清空一阶矩都会破坏优化器正常统计,导致训练稳定性下降。

Q9. 关于 LAMB 与 Adam,下列说法正确的是?

多选题 · mid

  • A.两者都使用一阶矩和二阶矩← 正确答案
  • B.LAMB 额外引入了逐层缩放← 正确答案
  • C.小 batch 下 LAMB 必定更慢
  • D.LAMB 更适合大批量分布式训练← 正确答案

答案:ABD。LAMB 可以理解为 Adam 加上逐层信任比率。小 batch 下 LAMB 通常只是与 Adam 相当,未必更慢也未必更快;它的优势主要在大批量场景。

Q10. 某层参数范数为 0.2,Adam 更新方向范数为 0.4,若不裁剪,信任比率是多少?

单选题 · extreme

  • A.0.5,步长相对缩小← 正确答案
  • B.2.0,步长相对放大
  • C.1.0,步长基本不变
  • D.0.2,步长大幅缩小

答案:A。信任比率 = 参数范数 / 更新方向范数 = 0.2 / 0.4 = 0.5,小于 1,所以该层步长会被缩小。这也体现了 LAMB 如何用范数比值动态调节每层步长。