深度学习中的优化器之SGD with Polyak Averaging 算法原理与实现细节
您提供的已讲题目列表中已包含多个优化器相关主题,其中明确列出了“深度学习中的优化器之SGD with Polyak Averaging算法原理与实现细节”。根据您的指令,此题目已讲过,不应重复。
我将为您讲解一个在列表中尚未出现,且具有重要理论意义和实践价值的深度学习优化算法:
深度学习中的在线自然梯度(Online Natural Gradient)与K-FAC近似算法原理
题目描述
传统的随机梯度下降(SGD)在参数空间中沿梯度下降最快的方向更新。然而,这忽略了参数空间本身的几何特性。自然梯度下降(Natural Gradient Descent, NGD)考虑模型概率分布的黎曼几何结构,在分布空间中沿最速下降方向更新,这通常能带来更稳定、更快的收敛。本题目将深入讲解在线自然梯度的核心思想,并详细解析其用于大规模深度神经网络的实用近似算法——Kronecker因子近似曲率(Kronecker-Factored Approximate Curvature, K-FAC) 的原理、推导与实现细节。
解题过程详解
步骤一:自然梯度下降的基本动机与原理
-
传统梯度的局限性:
- SGD的更新规则为:
θ = θ - η * ∇L(θ),其中∇L(θ)是损失函数L对参数θ的梯度。 - 这个更新在欧几里得参数空间中度量距离。但对于神经网络这样的概率模型,参数
θ的微小变化对模型输出分布p(y|x; θ)的影响程度并非均匀。参数空间的欧氏距离不能准确反映模型分布之间的差异。
- SGD的更新规则为:
-
自然梯度的定义:
- 自然梯度转而考虑在模型预测分布的流形(Manifold)上进行优化。它通过费雪信息矩阵(Fisher Information Matrix, FIM) 重新定义梯度方向。
- 费雪信息矩阵
F衡量了参数θ的变化对模型分布p的敏感度。对于负对数似然损失,FIM定义为期望的二阶导数(海森矩阵)的期望,也等价于梯度外积的期望:F = E[∇ log p * (∇ log p)^T]。 - 自然梯度定义为:
∇_N L(θ) = F^{-1} * ∇L(θ)。 - 更新规则变为:
θ = θ - η * F^{-1} * ∇L(θ)。这个更新方向是在分布空间的KL散度意义下的最速下降方向。
-
直观理解:
- 可以把
F看作一个“度量张量”,F^{-1}对原始梯度进行重新缩放和旋转。在损失变化敏感的方向(FIM特征值大),自然梯度更新步长较小,避免震荡;在不敏感的方向,步长较大,加速收敛。这类似于一种自动的、各向异性的预处理。
- 可以把
步骤二:从自然梯度到在线自然梯度
-
计算挑战:
- 对于有数百万甚至数十亿参数的深度神经网络,费雪矩阵
F是一个巨大的N×N矩阵(N为参数量)。直接计算、存储和求逆F^{-1}在计算上是完全不可行的。
- 对于有数百万甚至数十亿参数的深度神经网络,费雪矩阵
-
在线近似:
- “在线”指的是我们利用训练过程中得到的样本梯度,以在线(或随机)的方式近似费雪矩阵,而无需遍历整个数据集。
- 核心近似公式:
F ≈ E[ (∇ log p) * (∇ log p)^T ]。在随机优化中,我们通常使用当前mini-batch的梯度外积作为F的无偏估计,即F_t ≈ g_t * g_t^T,其中g_t是当前批次的梯度。这被称为经验费雪矩阵。
步骤三:K-FAC算法:一种高效的近似方法
为了克服计算难题,K-FAC算法对费雪矩阵进行了两种关键近似,使其变得可处理。
-
近似一:块对角近似(Block-Diagonal Approximation)
- 不强求完整的
F,而是假设不同神经网络层之间的参数梯度是独立的。这样,整个网络的费雪矩阵被近似为一个块对角矩阵,每个对角块F_l对应第l层的参数。 - 这大大简化了问题,因为现在只需要独立地处理每一层的
F_l。
- 不强求完整的
-
近似二:Kronecker因子分解(Kronecker-Factored Approximation)
- 这是K-FAC的核心创新。对于全连接层或卷积层,其前向传播公式为
s = W * a(忽略偏置,其中W是权重矩阵,a是该层的输入激活向量)。 - 该层权重
W的梯度可以写为:∇_W L = (∇_s L) * a^T,其中∇_s L是该层输出的误差梯度。 - 基于此,该层经验费雪矩阵块
F_l的期望可以被近似为两个低秩矩阵的Kronecker积:
F_l ≈ E[ (a * a^T) ] ⊗ E[ (∇_s L) * (∇_s L)^T ] = A ⊗ G - 其中:
A = E[a * a^T]是输入激活向量a的二阶矩(协方差)。G = E[(∇_s L) * (∇_s L)^T]是输出误差梯度∇_s L的二阶矩。⊗表示Kronecker积。
- 为什么这很高效?
A是一个(n_in × n_in)矩阵,G是一个(n_out × n_out)矩阵,n_in和n_out是层的输入输出维度。它们的大小远小于完整的F_l矩阵(大小为(n_in * n_out) × (n_in * n_out))。- 计算
A和G的逆变得可行。利用Kronecker积的性质(A ⊗ G)^{-1} = A^{-1} ⊗ G^{-1},我们可以高效地计算自然梯度更新:
vec(∆W) = -η * (G^{-1} ⊗ A^{-1}) * vec(∇_W L)
其中vec(·)是矩阵向量化操作。在实际更新中,可以通过解两个连续的线性系统来实现,无需显式构造大矩阵:
∆W = η * G^{-1} * (∇_W L) * A^{-1}
- 这是K-FAC的核心创新。对于全连接层或卷积层,其前向传播公式为
步骤四:K-FAC的实现细节与技巧
-
估计
A和G:- 在实际的随机优化中,我们使用移动平均(指数平滑)来在线估计
A和G,而不是精确的期望。 - 例如:
A_t = β * A_{t-1} + (1-β) * (a_t * a_t^T) / batch_size,G同理。
- 在实际的随机优化中,我们使用移动平均(指数平滑)来在线估计
-
求逆与正则化:
- 为了数值稳定性,在求逆
A^{-1}和G^{-1}之前,会加入一个小的阻尼系数γ:(A + γI)和(G + γI)。这对应于在自然梯度更新中混合一小部分传统梯度。
- 为了数值稳定性,在求逆
-
更新周期:
- 计算和求逆
A和G有一定开销。因此,通常不会每个迭代都更新它们,而是每隔T个迭代(例如100或1000步)重新估计和求逆一次,在此期间使用固定的预处理矩阵。
- 计算和求逆
-
算法流程(伪代码描述):
初始化参数 θ, 初始化 A, G 的估计值为单位阵(或零矩阵),设置阻尼 γ, 动量系数 α, 更新周期 T
for 迭代 t = 1, 2, ... do
采样mini-batch数据
前向传播,计算损失 L
反向传播,计算梯度 g_t = ∇L(θ_t)
if t % T == 0 then
计算当前批次的 A_batch 和 G_batch
用指数平均更新全局估计 A, G
计算预处理矩阵 P = (G + γI)^{-1} ⊗ (A + γI)^{-1} 的分解(或等效表示)
end if
# 计算预处理梯度(自然梯度方向)
g_nat = P * g_t
# 应用带动量的更新
v_t = α * v_{t-1} + g_nat
θ_{t+1} = θ_t - η * v_t
end for
总结
在线自然梯度与K-FAC算法的本质是为随机梯度下降提供一个更符合模型几何结构的预处理矩阵。通过块对角和Kronecker因子分解这两大近似,它将一个无法处理的巨大矩阵求逆问题,分解为对各层两个较小矩阵的估计和求逆,从而使得自然梯度下降的思想得以应用于大规模深度网络。与Adam等一阶自适应优化器相比,K-FAC利用了更多的二阶曲率信息,在诸如小批量情景下的强化学习、自然语言处理和某些图像识别任务中,常能表现出更快的收敛速度和更好的泛化性能,尽管其实现复杂度和计算开销也相对更高。