机器学习数学基础专题【左扬精讲】— 梯度下降:从批量到自适应的参数优化演进
机器学习数学基础专题【左扬精讲】— 梯度下降:从批量到自适应的参数优化演进
梯度下降算法(Gradient Descent)是机器学习、深度学习、优化理论中最核心的算法之一。
它是训练神经网络、求解最小二乘问题、机器学习模型参数优化的基石。本篇文章将深入剖析梯度下降算法的数学原理、几何直觉、各种变体,以及在实际工程中的调参技巧。
梯度下降 优化算法 学习率 收敛 批量/随机/小批量
学习重点
必须掌握:
- 梯度下降的核心思想:沿梯度负方向迭代
- 学习率(learning rate)对收敛的影响
- 批量梯度下降、随机梯度下降、小批量梯度下降的区别
- 梯度消失与梯度爆炸问题
需要了解:
- 动量(Momentum)、Adam 等自适应学习率方法
- 学习率衰减策略
- 梯度下降与正规方程的对比
一、梯度下降的核心思想
What — 梯度下降是什么?
梯度下降是一种一阶迭代优化算法,用于找到函数的局部最小值。其核心思想是:从一个初始点出发,沿着函数值下降最快的方向(即负梯度方向)逐步移动,直到达到一个局部最小值(或近似最小值)。
Why — 为什么沿负梯度方向下降最快?
在多元函数微分学中,梯度 ∇ f(x) 指向函数增长最快的方向。因此,沿 -∇ f(x) 方向,函数值下降最快。
用数学语言描述:对于函数 f(x),在 x_k 处的泰勒展开:
f(x_k + α d) ≈ f(x_k) + α d^T ∇ f(x_k)
其中 d 是搜索方向。当 d = -∇ f(x_k) 时,d^T ∇ f = -||∇ f||^2 < 0,函数值必然下降。
没有梯度下降会发生什么?
- 无法高效求解大规模非线性优化问题
- 神经网络的参数无法训练,因为损失函数通常没有解析解
- 只能依赖暴力搜索或随机采样,效率极低
想象你站在一座山上(函数曲面的某点),想要走到山谷(局部最小值)。由于大雾弥漫,你只能看到脚下的坡度(梯度信息)。最明智的选择是:沿着坡度最陡的方向下山。这个"沿最陡方向下山"的过程,就是梯度下降。
但这个比喻也有局限性:登山者可能最终只到达了一个小山谷(局部最小),而不是最深的山谷(全局最小)。这也是梯度下降的固有问题。
函数 f(x,y) 的等高线图
等高线
╱ ╲
╱ 峰 ╲ ↑
╱ ↖ ╲ 梯度
╱ ╲ 方向
╱ ╲ ↓
╱ ↘梯度 ╲ ╱ ╲
╱ 方向 ╲ ╱ ╲
╱ ╲╱ ╲
╱________________________╲
从起点开始,沿负梯度方向迭代
最终收敛到局部最小值点
二、梯度下降的数学推导
What — 梯度下降的迭代公式
梯度下降的基本迭代公式为:
x_k+1 = x_k - α ∇ f(x_k
其中:
- x_k 是第 k 次迭代的参数向量
- α > 0 是学习率(step size / learning rate)
- ∇ f(x_k 是目标函数在 x_k 处的梯度
How — 收敛性分析
对于凸函数,梯度下降可以收敛到全局最优解。收敛速度取决于:
- 学习率 α:太大导致振荡,太小收敛慢
- 条件数 κ:κ = (λ_max)/(λ_min),条件数越大,收敛越慢
对于二次函数 f(x) = (1)/(2_x^TA)/(x) - b)^Tx)(A) 对称正定),收敛速度为:
||x_k - x)^*||_2 ≤ ((κ - 1)/(κ + 1)^k ||x_0 - x)^*||_2
可以看到,当 κ 很大时,收敛速度接近线性,但很慢。
学习率选择经验法则
对于标准化后的特征,学习率 α ∈ [0.001, 1.0] 是常见的搜索范围。具体值需要通过实验确定:
- 太小:收敛太慢,浪费计算资源
- 太大:在最优点附近振荡,无法收敛
- 最佳:刚好能在最小值附近稳定振荡
三、三种梯度下降变体
三种变体的核心区别在于每次迭代使用的样本数量
| 类型 | 每次迭代样本 | 优点 | 缺点 |
|---|---|---|---|
| 批量梯度下降 (BGD) | 全部样本 n 个 | 收敛稳定,方向准确 | 计算慢,内存大 |
| 随机梯度下降 (SGD) | 1 个样本 | 快,支持在线学习 | 方向噪声大,振荡 |
| 小批量梯度下降 (MBGD) | b 个样本 (b << n) | 平衡速度和稳定性 | 需要调参 batch_size |
Batch Gradient Descent(批量梯度下降)
使用全部 n 个样本计算梯度:
θ := θ - α (1)/(n)Σ_i=1^n∇_θ L^(i)(θ)
特点:
- 梯度方向准确,每次下降稳定
- 计算复杂度 O(n),对于大规模数据非常慢
- 无法处理无法一次性载入内存的数据集
def batch_gradient_descent(X, y, theta, alpha, n_iterations):
"""
批量梯度下降
参数:
X: 特征矩阵 (n_samples, n_features)
y: 目标向量 (n_samples,)
theta: 初始参数 (n_features,)
alpha: 学习率
n_iterations: 迭代次数
返回:
theta: 优化后的参数
"""
m = len(y)
for i in range(n_iterations):
# 计算全部样本的预测值
predictions = X @ theta
# 计算全部样本的平均梯度
gradients = (1/m) * X.T @ (predictions - y)
# 更新参数
theta = theta - alpha * gradients
# 每100次打印损失
if i % 100 == 0:
cost = (1/(2*m)) * np.sum((predictions - y) ** 2)
print(f"Iteration {i}: Cost = {cost:.6f}")
return theta
Stochastic Gradient Descent(随机梯度下降)
每次只使用 1 个样本:
θ := θ - α ∇_θ L^(i)(θ)
特点:
- 计算极快,适合大规模数据
- 梯度有噪声,可以逃离局部最优
- 收敛路径振荡,需要更多迭代次数
- 支持在线学习(流式数据)
import numpy as np
def stochastic_gradient_descent(X, y, theta, alpha, n_epochs):
"""
随机梯度下降
每次迭代随机选择一个样本更新
"""
m = len(y)
for epoch in range(n_epochs):
# 打乱数据顺序
indices = np.random.permutation(m)
for i in indices:
# 单个样本的预测
xi = X[i:i+1] # shape: (1, n_features)
yi = y[i]
# 计算单个样本的梯度
prediction = xi @ theta
gradient = xi.T * (prediction - yi) # shape: (n_features, 1)
# 更新参数
theta = theta - alpha * gradient.flatten()
# 每个epoch计算一次总损失
predictions = X @ theta
cost = (1/(2*m)) * np.sum((predictions - y) ** 2)
print(f"Epoch {epoch}: Cost = {cost:.6f}")
return theta
Mini-Batch Gradient Descent(小批量梯度下降)
每次使用 b 个样本(通常 b ∈ [32, 256]):
θ := θ - α (1)/(b)Σ_i=j^j+b-1∇_θ L^(i)(θ)
特点:
- 利用向量化加速,计算效率高
- 梯度噪声适中,稳定性与速度平衡
- 是深度学习中的标准方法(TensorFlow、PyTorch 默认使用)
import numpy as np
def mini_batch_gradient_descent(X, y, theta, alpha, batch_size, n_epochs):
"""
小批量梯度下降(深度学习标准做法)
参数:
batch_size: 每个batch的样本数(通常32/64/128/256)
"""
m = len(y)
n_batches = int(np.ceil(m / batch_size))
for epoch in range(n_epochs):
# 打乱数据
indices = np.random.permutation(m)
X_shuffled = X[indices]
y_shuffled = y[indices]
for b in range(n_batches):
start_idx = b * batch_size
end_idx = min((b + 1) * batch_size, m)
X_batch = X_shuffled[start_idx:end_idx]
y_batch = y_shuffled[start_idx:end_idx]
# 计算batch梯度
predictions = X_batch @ theta
gradients = (1/batch_size) * X_batch.T @ (predictions - y_batch)
# 更新参数
theta = theta - alpha * gradients
# 每个epoch计算一次总损失
predictions = X @ theta
cost = (1/(2*m)) * np.sum((predictions - y) ** 2)
print(f"Epoch {epoch}: Cost = {cost:.6f}")
return theta
三种梯度下降对比总结
- BGD:适合小数据集、离线训练、需要稳定收敛的场景
- SGD:适合超大规模数据、在线学习、需要探索能力的场景
- MBGD:深度学习标配,batch_size 通常设为 32/64/128/256
四、学习率的选择与衰减策略
学习率是梯度下降最重要的超参数
学习率 α 决定了每次更新的步长。如果 α 太大,算法会在最优点附近振荡甚至发散;如果 α 太小,收敛速度会非常慢。
常见的学习率衰减策略
- 步长衰减(Step Decay):每隔固定 epoch 将学习率降低一个因子
α_t = α_0 · γ^⌊ t / T ⌋
- 指数衰减(Exponential Decay):
α_t = α_0 · e^-λ t
- 余弦退火(Cosine Annealing):
α_t = α_min + (1)/(2)(α_max - α_min)(1 + cos((tπ)/(T)
- 学习率 warmup:开始时逐渐增大学习率,稳定后再衰减
import numpy as np
class LearningRateScheduler:
"""学习率调度器"""
def __init__(self, initial_lr, decay_type='step', decay_rate=0.1,
decay_epochs=30, warmup_epochs=5):
self.initial_lr = initial_lr
self.decay_type = decay_type
self.decay_rate = decay_rate
self.decay_epochs = decay_epochs
self.warmup_epochs = warmup_epochs
def get_lr(self, epoch):
"""获取当前epoch的学习率"""
# Warmup阶段
if epoch < self.warmup_epochs:
return self.initial_lr * (epoch + 1) / self.warmup_epochs
# 衰减阶段
if self.decay_type == 'step':
# 步长衰减
factor = self.decay_rate ** (epoch // self.decay_epochs)
return self.initial_lr * factor
elif self.decay_type == 'exponential':
# 指数衰减
return self.initial_lr * np.exp(-0.1 * epoch)
elif self.decay_type == 'cosine':
# 余弦退火
T = 100 # 总epoch数
return self.initial_lr * (1 + np.cos(np.pi * epoch / T)) / 2
else:
return self.initial_lr
# 使用示例
scheduler = LearningRateScheduler(
initial_lr=0.1,
decay_type='step',
decay_rate=0.1,
decay_epochs=30
)
for epoch in range(100):
lr = scheduler.get_lr(epoch)
if epoch % 10 == 0:
print(f"Epoch {epoch}: LR = {lr:.6f}")
如何调试学习率
建议使用 Learning Rate Finder 方法:从很小的学习率(如 10^-8)开始,每次迭代增大学习率,记录损失函数的变化。找到损失开始下降最快的区间,选择该区间内偏小的值作为初始学习率。
五、梯度下降的 Python 实现
实战:使用梯度下降求解线性回归
让我们用梯度下降来实现一个完整的线性回归模型,对比三种变体的效果。
import numpy as np
import matplotlib.pyplot as plt
# 生成模拟数据
np.random.seed(42)
n_samples = 1000
X = 2 * np.random.rand(n_samples, 1)
y = 4 + 3 * X + np.random.randn(n_samples, 1) * 0.5
# 添加偏置项
X_b = np.c_[np.ones((n_samples, 1)), X]
# 可视化
plt.figure(figsize=(10, 4))
plt.scatter(X, y, alpha=0.5)
plt.xlabel('x')
plt.ylabel('y')
plt.title('模拟数据集')
plt.show()
def gradient_descent_linear_regression(X, y, alpha=0.1, n_iterations=1000,
batch_size=None, verbose=True):
"""
通用梯度下降线性回归
参数:
batch_size: None表示批量, 1表示随机, >1表示小批量
"""
m, n = X.shape
theta = np.zeros((n, 1)) # 初始化参数
history = [] # 记录损失历史
for iteration in range(n_iterations):
if batch_size is None:
# 批量梯度下降
predictions = X @ theta
gradients = (1/m) * X.T @ (predictions - y)
elif batch_size == 1:
# 随机梯度下降
idx = np.random.randint(m)
xi = X[idx:idx+1]
yi = y[idx]
prediction = xi @ theta
gradient = xi.T * (prediction - yi)
gradients = gradient
else:
# 小批量梯度下降
indices = np.random.choice(m, batch_size, replace=False)
X_batch = X[indices]
y_batch = y[indices]
predictions = X_batch @ theta
gradients = (1/batch_size) * X_batch.T @ (predictions - y_batch)
# 更新参数
theta = theta - alpha * gradients
# 记录损失
cost = (1/(2*m)) * np.sum((X @ theta - y) ** 2)
history.append(cost)
if verbose and iteration % 100 == 0:
print(f"Iteration {iteration}: Cost = {cost:.4f}")
return theta, history
# 测试三种方法
print("=" * 50)
print("批量梯度下降 (BGD)")
print("=" * 50)
theta_bgd, _ = gradient_descent_linear_regression(X_b, y, alpha=0.1, n_iterations=1000, batch_size=None)
print("\n" + "=" * 50)
print("随机梯度下降 (SGD)")
print("=" * 50)
theta_sgd, _ = gradient_descent_linear_regression(X_b, y, alpha=0.1, n_iterations=1000, batch_size=1)
print("\n" + "=" * 50)
print("小批量梯度下降 (MBGD, batch=32)")
print("=" * 50)
theta_mbgd, _ = gradient_descent_linear_regression(X_b, y, alpha=0.1, n_iterations=1000, batch_size=32)
print(f"\n真实参数: [4, 3]")
print(f"BGD 估计: [{theta_bgd[0,0]:.4f}, {theta_bgd[1,0]:.4f}]")
print(f"SGD 估计: [{theta_sgd[0,0]:.4f}, {theta_sgd[1,0]:.4f}]")
print(f"MBGD 估计: [{theta_mbgd[0,0]:.4f}, {theta_mbgd[1,0]:.4f}]")
六、梯度消失与梯度爆炸
深层神经网络的天敌
当神经网络层数很深时,梯度在反向传播过程中可能会变得非常小(梯度消失)或非常大(梯度爆炸),导致训练困难。
梯度消失(Vanishing Gradient)
在反向传播中,梯度通过链式法则传递:
(∂ L)/(∂ W^[1]) = (∂ L)/(∂ A^[n]) · (∂ A^[n])/(∂ Z^[n]) · … · (∂ Z^[2])/(∂ A^[1]) · (∂ A^[1])/(∂ W^[1])
如果每层的梯度都小于 1,连乘后梯度会指数级衰减趋近于零。
后果:前几层的参数几乎不更新,网络无法有效学习深层特征。
梯度爆炸(Exploding Gradient)
如果每层的梯度都大于 1,连乘后梯度会指数级增长。
后果:参数更新步长过大,导致权重震荡或溢出(NaN)。
1. 权重初始化策略
- Xavier 初始化:W ∼ N)(0, (2)/(n_in+n_out)
- He 初始化:W ∼ N)(0, (2)/(n_in)(适合 ReLU)
2. 激活函数选择
- ReLU 及其变体(Leaky ReLU, PReLU)可以缓解梯度消失
- 避免使用 Sigmoid/Tanh(梯度饱和)
3. 残差连接(ResNet)
a^[l+1] = a^[l] + Conv(a^[l])
梯度可以直接流过恒等路径,避免连乘效应。
4. 梯度裁剪(Gradient Clipping)
当梯度范数超过阈值时,将其缩放到阈值范围内。
def gradient_clipping(gradients, max_norm=5.0):
"""
梯度裁剪:防止梯度爆炸
如果梯度的L2范数超过max_norm,
将梯度缩放到max_norm
"""
total_norm = np.sqrt(np.sum([np.sum(g**2) for g in gradients]))
clip_coef = max_norm / (total_norm + 1e-6)
if clip_coef < 1:
clipped_gradients = [g * clip_coef for g in gradients]
return clipped_gradients, True # 表示进行了裁剪
return gradients, False # 没有裁剪
# 示例
gradients = [np.array([2.0, 3.0, 5.0]), np.array([1.0, 4.0])]
clipped, was_clipped = gradient_clipping(gradients, max_norm=5.0)
print(f"裁剪前梯度范数: {np.sqrt(2**2 + 3**2 + 5**2 + 1**2 + 4**2):.4f}")
print(f"裁剪后梯度范数: {np.sqrt(np.sum([np.sum(g**2) for g in clipped])):.4f}")
print(f"是否裁剪: {was_clipped}")
七、改进算法:动量与 Adam
为什么需要改进?
标准梯度下降的收敛路径在某些方向上振荡大、收敛慢。动量法和 Adam 等自适应方法通过改进更新规则,加速收敛。
Momentum(动量法)
引入"速度"概念,累积历史梯度方向,减少振荡:
v_t = β v_t-1 + (1-β) ∇_θ J(θ)
θ = θ - α v_t
其中 β ∈ [0.9, 0.999] 是动量系数。
def gradient_descent_with_momentum(X, y, theta, alpha, beta, n_iterations):
"""
带动量的梯度下降
"""
m = len(y)
v = np.zeros_like(theta) # 速度向量
for i in range(n_iterations):
predictions = X @ theta
gradients = (1/m) * X.T @ (predictions - y)
# 更新速度
v = beta * v + (1 - beta) * gradients
# 使用速度更新参数
theta = theta - alpha * v
if i % 100 == 0:
cost = (1/(2*m)) * np.sum((predictions - y) ** 2)
print(f"Iteration {i}: Cost = {cost:.6f}")
return theta
Adam(Adaptive Moment Estimation)
Adam 结合了动量和 RMSProp 的思想,使用自适应学习率:
m_t = β_1 m_t-1 + (1-β_1_g_t (一阶矩估计:类似动量))
v_t = β_2 v_t-1 + (1-β_2_g_t^2 (二阶矩估计:类似 RMSProp))
m_t^corrected = (m_t)/(1-β_1^t_v_t^corrected = (v_t)/(1-β_2^t)
θ = θ - α (m_t^corrected)/(√v_t^corrected) + ε)
def adam_optimizer(theta, gradients, t, m, v,
alpha=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8):
"""
Adam 优化器
参数:
theta: 当前参数
gradients: 当前梯度
t: 当前时间步
m: 一阶矩估计(动量)
v: 二阶矩估计(RMSProp)
alpha: 学习率
beta1, beta2: 衰减系数
epsilon: 防止除零
"""
# 更新一阶矩估计
m = beta1 * m + (1 - beta1) * gradients
# 更新二阶矩估计
v = beta2 * v + (1 - beta2) * (gradients ** 2)
# 偏差校正
m_hat = m / (1 - beta1 ** t)
v_hat = v / (1 - beta2 ** t)
# 更新参数
theta = theta - alpha * m_hat / (np.sqrt(v_hat) + epsilon)
return theta, m, v
def adam_linear_regression(X, y, alpha=0.1, n_iterations=1000):
"""使用 Adam 的线性回归"""
m, n = X.shape
theta = np.zeros((n, 1))
# Adam 状态
t = 0
m_moment = np.zeros((n, 1))
v_moment = np.zeros((n, 1))
for iteration in range(n_iterations):
predictions = X @ theta
gradients = (1/m) * X.T @ (predictions - y)
t += 1
theta, m_moment, v_moment = adam_optimizer(
theta, gradients, t, m_moment, v_moment, alpha
)
if iteration % 100 == 0:
cost = (1/(2*m)) * np.sum((predictions - y) ** 2)
print(f"Iteration {iteration}: Cost = {cost:.6f}")
return theta
优化算法选择建议
- SGD + Momentum:计算机视觉任务,效果稳定
- Adam:NLP、强化学习、推荐系统,默认好用的选择
- AdamW:带权重衰减的 Adam,正则化效果更好
- Lion:2023 年新提出的简化版优化器,只用动量
FAQ 常见问题解答
Q1. 梯度下降一定能收敛到全局最优吗?
不一定。对于凸函数,梯度下降收敛到全局最优。对于非凸函数(如神经网络),只能保证收敛到局部最优或鞍点。但通过合适的初始化和超参数,可以找到足够好的局部最优。
Q2. 学习率太大或太小会怎样?
太大:参数在最优解附近振荡,甚至越过最优点导致发散。太小:收敛速度极慢,需要很多次迭代才能接近最优解,浪费计算资源。
Q3. 批量梯度下降和随机梯度下降哪个更好?
取决于场景。小数据集用批量梯度下降,大数据集用小批量梯度下降。随机梯度下降适合在线学习,但收敛振荡大。深度学习标配是小批量梯度下降(batch_size=32/64/128)。
Q4. 什么是鞍点?为什么梯度下降会在鞍点卡住?
鞍点是梯度为零但不是局部极值的点(如马鞍的形状)。在鞍点,梯度在各方向都接近零,参数更新变慢。随机梯度下降的噪声可以帮助逃离鞍点。
Q5. 为什么需要学习率衰减?
前期用较大学习率快速接近最优点,后期用较小学习率精细调整。开始时离最优点远,大学习率加速收敛;接近最优点时,大学习率会导致振荡,需要衰减。
Q6. 动量法和 Adam 的区别是什么?
动量法只使用历史梯度的指数加权平均(方向),Adam同时使用一阶矩(方向)和二阶矩(梯度大小)来自适应学习率。Adam 通常比纯动量法收敛更快更稳定。
Q7. 梯度消失和梯度爆炸的根本原因是什么?
链式法则的连乘效应。深层网络中,梯度通过每层的偏导数连乘。如果偏导数持续小于 1(梯度消失)或大于 1(梯度爆炸),多层的连乘会导致梯度极小或极大。
Q8. 如何选择 batch_size?
常见选择 32/64/128/256。小 batch_size 梯度噪声大,有助于探索但收敛不稳定;大 batch_size 梯度准确但需要更多内存。实践中常用 2 的幂次方以利用 GPU 并行计算。
Q9. 什么是 early stopping?为什么用它?
Early stopping是在验证集损失开始上升时停止训练,防止过拟合。当训练损失继续下降但验证损失开始上升,说明模型开始过拟合训练数据,此时停止训练可以保留最佳模型。
Q10. 梯度下降和正规方程有什么区别?
正规方程一步求出解析解 θ = (X^TX)^-1X^Ty,但需要矩阵求逆(O(p^3)),且不适用于非线性问题。梯度下降是迭代求解,适合大规模数据和非线性问题,但可能只能找到近似解。
Q11. 什么是二阶优化方法?为什么不用?
二阶方法使用二阶导数(Hessian矩阵)信息,如牛顿法、拟牛顿法。收敛更快,但计算 Hessian 矩阵及其逆的复杂度是 O(p^2),内存消耗大。深度学习场景基本不用。
Q12. 如何判断梯度下降是否收敛?
两种方法:① 观察损失函数曲线,当损失变化小于阈值时停止;② 设置最大迭代次数。实践中常用第二种,简单有效。
Q13. 什么是学习率 finder?
Learning Rate Finder是 Leslie Smith 提出的找最优学习率的方法。从极小学习率开始,每步指数增加,记录损失,绘制学习率 vs 损失曲线。找到损失下降最快的区间,选择该区间偏小的值。
Q14. 随机梯度下降的期望等于批量梯度吗?
是。随机梯度是对真实梯度的无偏估计:E[∇_θ L^(i)(θ)] = ∇_θ L(θ)。因此理论上 SGD 可以收敛到同一点,只是路径更曲折。
Q15. 什么是 Nesterov 动量?
Nesterov Accelerated Gradient(NAG)是一种改进的动量法。先按历史动量方向更新,再计算梯度并修正。比起标准动量,NAG 在碰到陡坡时能更早减速,更快收敛。
Q16. 梯度为 0 一定是最优点吗?
不一定。梯度为 0 的点可能是:① 局部最小值;② 局部最大值;③ 鞍点。需要检查 Hessian 矩阵或使用二阶信息来区分。
Q17. 为什么要对特征做归一化/标准化?
加速收敛。不同特征尺度差异大时,损失函数的等高线是椭圆形,梯度下降路径曲折。归一化后等高线接近圆形,梯度下降可以沿直线更快到达圆心。
Q18. Adam 为什么需要偏差校正?
因为初始化时一阶、二阶矩估计为零。在训练初期(t 很小),m_t = (1-β_1^t_m_true 远小于真实值,需要除以 (1-β_1^t) 来校正。后期(t 大时)β^t ≈ 0,校正效果可以忽略。
Q19. 什么是 Learning Rate Schedule?
Learning Rate Schedule是预先定义的学习率衰减策略,如 step decay、cosine annealing、warmup。与自适应方法(Adam)不同,schedule 是全局统一调整,不针对每个参数。
Q20. 深度学习框架默认用什么优化器?
PyTorch/TensorFlow 默认通常是 SGD + Momentum。但社区广泛使用 Adam 作为默认选择,因为它收敛快、调参少。实际项目中,CV 任务常用 SGD+Momentum,NLP 任务常用 Adam/AdamW。
本文核心知识点回顾
- 1 个核心公式:θ_k+1 = θ_k - α ∇ f(θ_k)
- 2 个问题:梯度消失 + 梯度爆炸
- 3 种变体:BGD(批量)、SGD(随机)、MBGD(小批量)
- 4 个关键超参数:学习率 α、batch_size、动量 β、衰减策略
- 5 个常用优化器:SGD、Momentum、AdaGrad、RMSProp、Adam
Roadmap 后续预告
在理解了梯度下降算法之后,第三篇我们将学习最小二乘法的梯度下降算法及 Python 实现。这篇将深入探讨:
- 如何用梯度下降法求解最小二乘问题
- 从正规方程到迭代优化的桥梁
- 大规模最小二乘问题的分布式求解
- 实战:用 NumPy/PyTorch 实现完整的最小二乘梯度下降

浙公网安备 33010602011771号