993 字
5 分钟
分布式机器学习:随机梯度下降(SGD)及其变体
2026-05-17
无标签

考虑线性回归的例子#

输入 x∈Rn\mathbf{x}\in\mathbb{R}^n 输出 y∈Ry\in\mathbb{R} 模型参数 w∈Rn\mathbf{w}\in\mathbb{R}^n 训练数据 {(xi,yi)}i=1m\{(\mathbf{x}_i,y_i)\}_{i=1}^m 目标函数(损失函数):

L(w)=1m∑i=1m(yi−wTxi)2=1m∣∣Xw−y∣∣2L(\mathbf{w}) = \frac{1}{m}\sum_{i=1}^m (y_i - \mathbf{w}^T\mathbf{x}_i)^2=\frac{1}{m}||\mathbf{X}\mathbf{w}-\mathbf{y}||^2

NN 为样本数量,DD 为特征维度(包含偏置就是D=n+1D=n+1)。对于大规模数据,NN 和 DD 都很大。

三种复杂度#

如果解正规方程,w=(XTX)−1XTy\mathbf{w}=(\mathbf{X}^T\mathbf{X})^{-1}\mathbf{X}^T\mathbf{y} 计算复杂度 O(ND2)+O(D3)O(ND^2)+O(D^3) 不适合大规模数据。更不用考虑不可逆的情况了。

如果用梯度下降,计算复杂度 O(ND)O(ND)表示遍历一次全部样本并计算所有特征所需的浮点运算次数,每次迭代需要遍历所有数据。小数据量时可以接受,但对于大规模数据,迭代一次就很慢了。

如果用随机梯度下降(SGD),每次迭代只需要计算一个样本的梯度,计算复杂度 O(D)O(D) 适合大规模数据。

  • SGD把复杂度降下来了,但梯度的方差(噪声)上去了,收敛速度慢了。后续会介绍一些改进SGD的方法,如动量、Adam等。

随机梯度下降(SGD)和mini-batch SGD#

把梯度下降的参数更新公式统一成:

w(t+1)←w(t)−η1∣S∣∑i∈S∇Fi(w(t))\mathbf{w^{(t+1)}} \leftarrow \mathbf{w}^{(t)} - \eta \frac{1}{|S|}\sum_{i \in S} \nabla F_i(\mathbf{w}^{(t)})

其中 Fi(w)F_i(\mathbf{w}) 是第 ii 个样本的损失函数(如线性回归中的 (yi−wTxi)2(y_i - \mathbf{w}^T\mathbf{x}_i)^2).

SS 是一个样本子集(mini-batch),大小为 ∣S∣|S|,通常远小于总样本数 NN.

η\eta 是学习率,控制每次更新的步长。

∣S∣=b|S|=b, bb 体现了gd,sgd,mini-batch sgd的区别:

  • GD(Gradient Descent):∣S∣=N|S|=N,每次迭代使用全部样本计算梯度。
  • SGD(Stochastic Gradient Descent):∣S∣=1|S|=1,每次迭代随机选择一个样本计算梯度。
  • Mini-batch SGD:1<∣S∣<N1 < |S| < N,每次迭代使用一个小批量的样本计算梯度,常见的 ∣S∣|S| 取值有 32、64、128 等。

bb 的性能影响:

  • 较小的 bb 节省单次迭代计算成本,但会增加梯度噪声,导致误差表现更差

  • 较大的批次大小能降低梯度噪声并提供更优的误差收敛性,但会提高计算成本每次迭代的开销

alt text

其他SGD的变体#

方便起见,记∇E(w(t))=1∣S∣∑i∈S∇Fi(w(t))\nabla E(\mathbf{w}^{(t)}) =\frac{1}{|S|}\sum_{i \in S} \nabla F_i(\mathbf{w}^{(t)}),当前迭代所用的样本集合(一个样本或一个小批量)的平均梯度。

Momentum(动量)#

普通sgd:梯度噪声大,更新方向震荡,在梯度很小或平坦区域,收敛极慢

动量方法在更新参数时引入了一个额外的变量 vv 和动量系数 γ(=0.9)\gamma(=0.9) 来积累之前的梯度信息:

v(t+1)=γv(t)+η∇E(w(t))w(t+1)=w(t)−v(t+1)\begin{aligned} v^{(t+1)} &= \gamma v^{(t)} + \eta \nabla E(\mathbf{w}^{(t)}) \\ \mathbf{w}^{(t+1)} &= \mathbf{w}^{(t)} - v^{(t+1)} \end{aligned}

效果:

  • 在梯度方向一致时加速收敛

  • 在梯度方向频繁改变时减少震荡

NAG涅斯捷罗夫加速梯度#

问题:动量法在某些情况下可能会过度积累之前的梯度信息,导致更新过头(overshooting),尤其是在接近最优解时。

NAG计算梯度的点不是当前点(E的括号里),而是将要更新到的点:

v(t+1)=γv(t)+η∇E(w(t)−γv(t))w(t+1)=w(t)−v(t+1)\begin{aligned} v^{(t+1)} &= \gamma v^{(t)} + \eta \nabla E(\mathbf{w}^{(t)} - \gamma v^{(t)}) \\ \mathbf{w}^{(t+1)} &= \mathbf{w}^{(t)} - v^{(t+1)} \end{aligned}

自适应学习率方法-AdaGrad#

公式:

gi(t)=∑j=1t(∇E(w(j)))i2wi(t+1)=wi(t)−ηgi(t)+ϵ(∇E(w(t)))i\begin{aligned} g_i^{(t)} &= \sum_{j=1}^t (\nabla E(\mathbf{w}^{(j)}))_i^2 \\ \mathbf{w}_i^{(t+1)} &= \mathbf{w}_i^{(t)} - \frac{\eta}{\sqrt{g_i^{(t)} + \epsilon}} (\nabla E(\mathbf{w}^{(t)}))_i \end{aligned}

每个参数有自己的学习率:经常更新的参数学习率变小,稀疏参数学习率较大

学习率,自动递减

缺点:累积梯度平方和会越来越大,导致学习率最终趋近于 0,训练过早停止

自适应学习率方法-Adam#

同时利用一阶矩(均值) 和二阶矩(未中心化的方差) 自适应调整学习率

相当于 RMSprop + 动量

m(t+1)=β1m(t)+(1−β1)∇E(w(t))v(t+1)=β2v(t)+(1−β2)(∇E(w(t)))2m^(t+1)=m(t+1)1−β1t+1v^(t+1)=v(t+1)1−β2t+1w(t+1)=w(t)−ηv^(t+1)+ϵm^(t+1)\begin{aligned} m^{(t+1)} &= \beta_1 m^{(t)} + (1 - \beta_1) \nabla E(\mathbf{w}^{(t)}) \\ v^{(t+1)} &= \beta_2 v^{(t)} + (1 - \beta_2) (\nabla E(\mathbf{w}^{(t)}))^2 \\ \hat{m}^{(t+1)} &= \frac{m^{(t+1)}}{1 - \beta_1^{t+1}} \\ \hat{v}^{(t+1)} &= \frac{v^{(t+1)}}{1 - \beta_2^{t+1}} \\ \mathbf{w}^{(t+1)} &= \mathbf{w}^{(t)} - \frac{\eta}{\sqrt{\hat{v}^{(t+1)} + \epsilon}} \hat{m}^{(t+1)} \end{aligned}

优点

  • 对超参数鲁棒,收敛快

  • 适用于稀疏梯度、非平稳目标

  • 通常比纯 SGD 或动量法表现更好

分布式机器学习:随机梯度下降(SGD)及其变体
https://biscuit0613.github.io/posts/cs-core/dsml-sgd/
作者
Biscuit
发布于
2026-05-17
许可协议
CC BY-NC-SA 4.0
RPC1:socket套接字
分布式机器学习:同步和异步随机梯度下降(SGD)