上一篇:[[Train]] 下一篇:[[Least Squares Method]]
我们先通过一个详细数值例子来演示一个简单神经网络如何被训练,使用梯度下降法(Gradient Descent)。然后详细讲解 SGD 和 Adam 的区别与工作原理,并附上具体数值例子。
我们定义一个最简单的网络:
模型公式: $$ \hat{y} = w \cdot x + b $$
假设我们只有一个训练样本:
初始参数:
$$ z = w \cdot x + b = 1.0 \cdot 2 + 0 = 2 $$ $$ \hat{y} = z = 2 $$ $$ L = \frac{1}{2}(\hat{y} - y)^2 = \frac{1}{2}(2 - 4)^2 = \frac{1}{2} \cdot 4 = 2.0 $$
损失对输出的导数: $$ \frac{\partial L}{\partial \hat{y}} = \hat{y} - y = 2 - 4 = -2 $$
链式法则:
对权重 $w$ 的梯度: $$ \frac{\partial L}{\partial w} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial w} = -2 \cdot x = -2 \cdot 2 = -4 $$
对偏置 $b$ 的梯度: $$ \frac{\partial L}{\partial b} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial b} = -2 \cdot 1 = -2 $$
$$ w := w - \eta \cdot \frac{\partial L}{\partial w} = 1.0 - 0.1 \cdot (-4) = 1.0 + 0.4 = 1.4 $$ $$ b := b - \eta \cdot \frac{\partial L}{\partial b} = 0.0 - 0.1 \cdot (-2) = 0.0 + 0.2 = 0.2 $$
SGD 只是将梯度下降用于单一样本: $$ \theta := \theta - \eta \cdot \nabla_\theta L(\theta) $$ 例子同上,就是每次都基于一个样本更新,不保留历史信息。
Adam 同时使用了:
再进行偏差修正: $$ \hat{m}_t = \frac{m_t}{1 - \beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1 - \beta_2^t} $$
更新参数: $$ \theta := \theta - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} $$
Adam 更新步长更平滑,适应性调整每个参数的学习率。
| 方法 | 记忆历史梯度 | 每步学习率 | 收敛速度 | 稳定性 |
|---|---|---|---|---|
| SGD | 否 | 固定 | 较慢 | 震荡 |
| Adam | 是(均值+方差) | 自适应 | 快 | 稳定 |
我们通过一个具体的例子,从损失函数的梯度计算开始,到Adam优化器的参数更新,详细说明其每一步计算过程。我们选用的例子是:最后一层是Softmax,损失函数是交叉熵(cross-entropy),优化器为Adam。
模型输出层是 softmax:
假设输出层有 3 个类别,神经网络最后一层的输出(logits)为:
$$
z = [2.0, 1.0, 0.1]
$$
真实标签(one-hot 编码)为: $$ y = [1, 0, 0] $$
损失函数为交叉熵(Cross-Entropy): $$ L = -\sum_{i=1}^{3} y_i \log(\hat{y}_i) $$
先计算 softmax 概率:
$$ \hat{y}i = \frac{e^{z_i}}{\sum{j} e^{z_j}} $$
计算:
$e^{2.0} \approx 7.389$ $e^{1.0} \approx 2.718$ $e^{0.1} \approx 1.105$
归一化:
$$ \hat{y} = \left[ \frac{7.389}{11.212}, \frac{2.718}{11.212}, \frac{1.105}{11.212} \right] \approx [0.659, 0.242, 0.099] $$
$$ L = -\log(0.659) \approx 0.417 $$
交叉熵 + softmax 的梯度(对 logits $z$)是: $$ \frac{\partial L}{\partial z_i} = \hat{y}_i - y_i $$
所以:
$$ \frac{\partial L}{\partial z} = [0.659 - 1, 0.242 - 0, 0.099 - 0] = [-0.341, 0.242, 0.099] $$
假设这些梯度是我们要求的参数梯度(例如 softmax 层前的权重某一行的梯度)。
Adam 是基于动量法 + RMSProp,它维护两个变量:
我们只看第一个时间步(t = 1):
$$ g = [-0.341, 0.242, 0.099] $$
$$ m_t = \beta_1 \cdot m_{t-1} + (1 - \beta_1) \cdot g $$ $$ m_1 = 0.9 \cdot 0 + 0.1 \cdot g = 0.1 \cdot g = [-0.0341, 0.0242, 0.0099] $$
$$ v_t = \beta_2 \cdot v_{t-1} + (1 - \beta_2) \cdot g^2 $$
计算 $g^2 = [0.116, 0.0586, 0.0098]$(平方逐元素)
$$ v_1 = 0 + 0.001 \cdot g^2 = [0.000116, 0.0000586, 0.0000098] $$
$$ \hat{m}_1 = \frac{m_1}{1 - \beta_1} = \frac{m_1}{0.1} = [-0.341, 0.242, 0.099] $$
$$ \hat{v}_1 = \frac{v_1}{1 - \beta_2} = \frac{v_1}{0.001} = [0.116, 0.0586, 0.0098] $$
参数更新公式: $$ \theta_{t+1} = \theta_t - \alpha \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} $$
计算分母的平方根:
注意这些恰好和 $\hat{m}_1$ 的值相等,因此:
$$ \frac{\hat{m}_1}{\sqrt{\hat{v}_1} + \epsilon} \approx [1.0029, 1.0004, 1.0000] $$
那么:
$$ \Delta \theta = -0.01 \cdot [1.0029, 1.0004, 1.0000] \approx [-0.01003, -0.01000, -0.01000] $$
| 参数 | 含义 | 作用 |
|---|---|---|
| $\alpha$ | 学习率 | 控制更新步长 |
| $\beta_1$ | 一阶动量衰减 | 控制历史梯度的“记忆”程度 |
| $\beta_2$ | 二阶动量衰减 | 控制平方梯度的平滑程度 |
| $\epsilon$ | 防止除零 | 确保数值稳定性 |
| $m_t$ | 梯度的一阶滑动平均 | 方向感(惯性) |
| $v_t$ | 梯度平方的滑动平均 | 缩放因子,防止剧烈振荡 |
| 偏差校正 | 修正初始化为0带来的偏差 | 提升早期更新精度 |
上一篇:[[Train]] 下一篇:[[Least Squares Method]]