English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

访客
1 / ?
返回课程列表

梯度脉冲的来源

一個平静的小批量和一个震惊的小批量

大多数小批量产生梯度的合理大小。对于已经大致符合数据的模型,交叉熵损失保持在一个狭窄的范围内;反向传播将该信号传递回作为梯度的相似大小。


一些小批量没有。梯度脉冲的三种来源:


1. 异常示例。 一个具有极端 token 结合的单个序列产生远离均值的损失和远离均值的梯度。

2. 数值边缘情况。 接近零的 softmax denominator,一个 NaN 产生的 layernorm,一个 FP16 溢出。每个都可以产生比典型梯度大几个数量级的梯度。

3. 分布变化。 在单个训练运行期间切换数据源,会让模型震惊于一个新的分布。ANDREA 的贪心每 7 到 42 步骤重新排列源权重。每次切换都是一个小的分布变化。


ANDREA-120M v1:脉冲瀑布

v1 没有梯度裁剪。贪心在 7 到 42 步骤内从 bandit 提供数据源,先是 repo-docs(列表结构),然后是 gutenberg(长篇大论),然后是 hermes3-general(问答)。每次转换都产生了梯度脉冲:每个脉冲都推动了权重进入 120M 规模的退化吸引子。


关键事实。 ANDREA-12M 在没有裁剪的情况下survived相同的bandit。较小的权重矩阵在梯度震惊时保持健壮;一个坏的小批量无法像对 120M 一样推动 12M 参数进入脱离控制的吸引子。裁剪随着模型规模而变得越来越重要。

全局 L2 范数裁剪

两种选择:按张量或全局

两种方法来限制梯度的大小:


按张量裁剪。 独立地裁剪每个梯度张量。嵌入梯度被裁剪到其自身范数;注意力梯度被裁剪到其自身范数。简单,但扭曲了相对规模:一个张量中的小脉冲(现在零梯度)与另一个张量中的巨大梯度(未受影响)成对出现。


全局 L2 范数裁剪。 将所有梯度视为一个大向量。计算总的 L2 范数跨越每个参数。如果范数超过 max_norm,缩放每个梯度的相同因子。保留了相对大小跨越张量。


ANDREA 使用全局。Pascanu 等人(2013年)从实际证明了全局截断优于转换器训练的每个张量。


数学计算

计算全局 L2 范数:


norm = sqrt(sum over all params of g_i^2)


如果 norm <= max_norm,梯度保持不变。 如果 norm > max_norm,将每个梯度按 max_norm / norm 缩放:


g_i_clipped = g_i * (max_norm / norm)


缩放后,新的范数恰好等于 max_norm。 ANDREA 使用 max_norm = 1.0

计算缩放因子

假设在一次训练步骤中,全局 L2 范数计算为 `3.5`。 ANDREA 的 `max_norm = 1.0`。计算 (a) 应用到的缩放因子、(b) 缩放后全局 L2 范数等于多少、(c) 如果未裁剪范数为 `0.4` 而不是 `3.5`。展示你的计算。

梯度范数计算为什么需要三个内核

原始算法无法在 GPU 上运行

全局 L2 范数计算的伪代码:


total = 0
for each param p:
  for each element g in p.grad:
    total += g * g
norm = sqrt(total)

在 GPU 上,这个原始循环由于两个原因而失败:


1. 顺序累加。一个单独的 total 累加器使得每个线程都要等待其他线程,破坏了 GPU 并行性。

2. 异构张量。 ANDREA-120M 有极其不同形状的张量:嵌入(8449 x 768),注意力 QKV(768 x 768),层规范化(768)。一个内核不能高效地遍历所有形状。


ANDREA 的三个内核流水线

将工作分成三个 CUDA 内核放入 microgpt_cuda.cu


Kernel 1: k_grad_norm_partial. 对于每个参数张量,计算部分和平方和。每个线程块减少张量的一个部分;结果写入一个小的临时缓冲区。并行性:每个部分一个块,所有张量中有数百个块。


Kernel 2: k_grad_norm_final. 将临时缓冲区减少到一个标量。取其平方根。一个小的内核,运行在微秒内。


Kernel 3: k_grad_scale. 如果 norm > max_norm,计算 scale = max_norm / norm & 将每个梯度元素乘以 scale。一次遍历所有梯度张量,完全并行。


顺序很重要:Pre-Adam

梯度裁剪管道在AdamW更新 mv 或任何参数之前运行。为什么?


裁剪的梯度喂给AdamW的指数移动平均值。如果允许一个峰值流入 mv,它将破坏那些运行平均值并在多个步骤后拖慢恢复的过程。将裁剪放在Adam之前将峰值的影响限制在单个糟糕的步骤。


裁剪梯度的3个CUDA内核

为什么三个内核而不是一个内核?

假设有人提出将 `k_grad_norm_partial` 和 `k_grad_norm_final` 合并为一个内核,该内核在一个遍历中计算整个全局范数。给出一个具体的原因,说明这种合并将在GPU上失败或性能更差。参考GPU线程块如何共享内存并同步。

为什么没有裁剪杀死了v1

盖特源转换每7到42步

安德烈的盗贼在阶段性地进行。每个阶段持续7、14、21、28或42步(随机选择)。在每个阶段界限处,源权重会发生变化:也许repo-docs从0.1跳到0.6,gutenberg从0.4降到0.1,hermes3-general从0.5升到0.7。


每个过渡都是对模型的分布性冲击。损失短暂上升。梯度与之一起上升:一个正在最小化损失的模型原来针对gutenberg风格的文章,现在看到的是repo-docs风格的列表结构,梯度携带了纠正信号,可以是10倍或100倍于常规幅度。


v1失败模式

没有裁剪,那些10-100倍梯度脉冲会流入AdamW的mv平均值。AdamW的平滑意味着脉冲效果在实际差的批次之后的多个步骤内持续。与无权重衰减(v1中的vanilla Adam)相结合,脉冲驱动的权重更新在阶段内不断累积,直到权重漂移到一个退化吸引子:一个词的logit主导softmax,采样输出就是那个词,训练环境包含那个词,梯度强化了那个词。重复锁定。


v2稳定性

v2添加了裁剪max_norm = 1.0,并与AdamW和LR预热一起使用。脉冲对mv的影响受到了限制;权重无法以峰值lr max_norm = 0.0003 1.0 = 0.0003每个参数每步的速度漂移。阶段过渡仍然产生脉冲,但这些脉冲在到达优化器之前就被限制了。


结果:v2(经过数据过滤v2.5和v3修饰)达到了事实回忆,多段连贯性,以及在生物和信号处理样本上的9.5/10的外部评分。


能力-脆弱性耦合

相同的盗贼。相同的数据。相同的超参数,除了裁剪。为什么12M能够在没有裁剪的情况下生存,而120M却崩溃了?


两种相互累积的因素:


1. 更大的权重矩阵存储更多的吸引子。 一个768x768注意力投影有59万个参数;即使是权重漂移的微小变化,也会产生有意义的注意力行为变化。一个384x384注意力投影有14.7万个参数并保持在一个更受限的子空间。

2. 更多的层次意味着更多的乘法交互。 v3有12个transformer层(与12M的6层相比)。脉冲通过12层的递增非线性传播;每个层都可以放大前一个层的漂移。


脆弱性与容量相互累积。裁剪在某个规模阈值以上变得必不可少;安德烈将这个阈值设定在了12M和120M参数之间。

诊断v1倒灌

假设在 v1 训练的第 50,000 步时,一个单独的 mini-batch 产生一个梯度的全局 L2 范数为 50.0 (典型的批次产生~0.5)。在随后的 10 步中,如果后续批次的梯度范数恢复到典型水平,AdamW 的第一时刻值 `m` 将如何演变?考虑如何通过 beta1=0.9 使 `m = beta1 * m + (1 - beta1) * g` 传播冲击.

裁剪在何处应用?

除了 ANDREA 的带有贪心驱动的课程外,请列出一个其他的训练场景,在那里全局 L2 梯度裁剪同样重要,并说明它的原因是什么。

相邻活动

三个子女将裁剪链接到:


- 活动 10: AdamW。 裁剪保护 AdamW 的 mv 不受冲击污染。没有裁剪,一个坏的批次将在 50+ 步内污染优化器状态。

- 活动 11: LR 温和。 温和减慢 lr;裁剪减慢 g。一起:在第 1 步时,最坏情况下的参数更新量为 lr_after_warmup max_norm = 1.5e-7 1.0 = 1.5e-7,而没有任何保护措施时为 0.0003 * 50 = 0.015。裁剪和温和相结合,最坏情况下的早期更新量减少了 100,000 倍。

- 活动 14: 多臂带有贪心。 带有贪心的阶段长度 (7 到 42 步) 是为了防止任何一个来源在短时间内主导;裁剪使得这些频繁的转换变得安全。


剪辑是转换器训练中的最便宜稳定性胜利: 3个小的CUDA内核,每步微秒,决定了是否有120万+模型收敛或崩溃。