后摩智能 AI Infra 实习


Q: 梯度下降怎么求导?链式求导法则?

梯度下降是神经网络训练的核心优化算法:沿损失函数梯度的反方向更新参数,逐步逼近局部最小值。

更新规则:w = w - lr * dL/dw,其中 lr 是学习率,dL/dw 是损失 L 对参数 w 的偏导数。

链式法则(Chain Rule):复合函数求导的基本工具。若 L = f(g(w)),则 dL/dw = dL/dg * dg/dw。多层网络中每层都是复合函数,梯度通过链式法则从输出层逐层传播回输入层。

反向传播(Backpropagation)就是链式法则的系统化应用:

  1. 前向传播:计算每层输出并保存中间结果(激活值)
  2. 反向传播:从 loss 出发,逐层计算梯度。每层利用保存的激活值和上游梯度计算本层参数的梯度
  3. 时间复杂度与前向相同(约 2x 前向),这是深度学习可训练的基础

PyTorch 的 Autograd:动态记录计算图(每个 tensor 操作形成一条 grad_fn 链),反向时自动遍历图执行链式法则。


Q: ReLU激活函数在0点如何求导?

ReLU 定义:f(x) = max(0, x) = { x, if x > 0; 0, if x <= 0 }

导数

  • x > 0:f’(x) = 1
  • x < 0:f’(x) = 0
  • x = 0:严格来说不可导(左导数 = 0,右导数 = 1,不相等)

实践处理:定义 x=0 处导数为 0(或 1,或 0.5,不同框架可能不同,PyTorch 用 0)。这是次梯度(subgradient)的概念——对于凸函数在不可导点取次梯度集中的任一值即可。

为什么不影响训练

  1. 浮点数精确等于 0 的概率极小(趋近于 0)
  2. 即使偶尔发生,梯度为 0 只是该步不更新,不会导致错误
  3. SGD 的随机性保证了不会永远停在 0 点

ReLU 的问题:Dead ReLU——如果某些神经元输出始终 <0(梯度始终为 0),该神经元永远无法恢复。解决:LeakyReLU(x<0 时 f(x)=0.01x)、GELU/SiLU(平滑近似,无死区)。


Q: Softmax的实现及溢出问题?

标准公式:softmax(x_i) = exp(x_i) / sum_j(exp(x_j))

将任意实数向量映射为概率分布(所有元素 >0 且和为 1)。

溢出问题

  • 上溢:exp(x) 当 x > 710(FP64)或 x > 88(FP32)时溢出为 inf
  • 下溢:exp(x) 当 x 很小负数时下溢为 0,导致分母可能为 0

解决方案——Safe Softmax(减最大值)

1
2
m = max(x)
softmax(x_i) = exp(x_i - m) / sum_j(exp(x_j - m))

数学等价性证明

1
2
3
exp(x_i - m) / sum(exp(x_j - m)) 
= exp(x_i) * exp(-m) / (sum(exp(x_j)) * exp(-m))
= exp(x_i) / sum(exp(x_j))

减去 max 后最大的指数变为 exp(0)=1,不会上溢;其他值变为负数的 exp,可能下溢为 0 但不影响结果(它们概率就应该接近 0)。

实现要点:需要两遍遍历(第一遍求 max,第二遍计算 exp 和 sum)。Online Softmax 优化为一遍同时维护 running max 和 running sum。