深度学习中梯度下降优化算法全解

发布于:2025-07-08 ⋅ 阅读:(19) ⋅ 点赞:(0)

梯度下降基础与挑战

梯度下降是深度学习的核心优化算法,通过迭代调整参数最小化损失函数:

θ=θ−α∇θJ(θ) \theta = \theta - \alpha \nabla_\theta J(\theta) θ=θαθJ(θ)

其中 α\alphaα 是学习率,∇θJ(θ)\nabla_\theta J(\theta)θJ(θ) 是损失函数梯度。

梯度下降面临的主要问题

梯度下降问题
梯度消失
梯度爆炸
局部最优
鞍点
震荡
1. 梯度消失/爆炸:

在梯度函数上出现的以指数级递增或者递减的情况分别称为梯度爆炸或者梯度消失

假设g(z)=z,b[l]=0g(z)=z,b^{[l]}=0g(z)=z,b[l]=0,对于目标输出有:y^=W[L]W[L−1]...W2W1X\hat{y}=W^{[L]}W^{[L-1]}...W^{2}W^{1}Xy^=W[L]W[L1]...W2W1X

  • 对于W[l]W^{[l]}W[l]的值大于 1 的情况,激活函数的值将以指数级递增;
  • 对于W[l]W^{[l]}W[l]的值小于 1 的情况,激活函数的值将以指数级递减。

在计算梯度时,根据不同情况梯度函数也会以指数级递增或递减,导致训练导数难度上升,梯度下降算法的步长会变得非常小,需要训练的时间将会非常长。

3. 局部最优与鞍点:
单一全局最优
多个局部最优
高维鞍点
凸函数
简单优化
非凸函数
优化困难
梯度接近0
局部最优原理图
局部最优原理图
  • 鞍点是函数上导数为零,但不是轴上局部极值的点。通常梯度为零的点 。通常梯度为零的点是下图所示的鞍点,而非局部最小值。减少损失的难度也来自误差曲面中的鞍点,而不是局部最低点。
    鞍点示意图
    鞍点示意图
  • 鞍点附近的平稳段会使学习非常缓慢,而这也需要后面的优化算法加速学习的原因,它们能帮助尽早走出平稳段
4. 震荡问题:
  • 在陡峭方向更新过大,平缓方向更新不足
  • 导致优化路径曲折,收敛缓慢

梯度下降变体算法

1. 批梯度下降 (Batch Gradient Descent)

原理:使用整个训练集计算梯度
更新公式
θ=θ−α∇θJ(θ)\theta = \theta - \alpha \nabla_\theta J(\theta)θ=θαθJ(θ)

特点

  • 每次迭代计算整个数据集
  • 收敛稳定但计算成本高
  • 不适合大数据集
def batch_gradient_descent(X, y, theta, alpha, num_iters):
    m = len(y)
    cost_history = []
    
    for i in range(num_iters):
        # 计算梯度
        gradient = (1/m) * X.T.dot(X.dot(theta) - y)
        
        # 更新参数
        theta = theta - alpha * gradient
        
        # 记录损失
        cost = np.mean((X.dot(theta) - y)**2)
        cost_history.append(cost)
    
    return theta, cost_history

2. Mini-Batch 梯度下降

原理:将数据集分成小批量进行更新
更新公式
θ=θ−α∇θJ(θ;Xi:i+n;yi:i+n)\theta = \theta - \alpha \nabla_\theta J(\theta; X^{{i:i+n}}; y^{{i:i+n}})θ=θαθJ(θ;Xi:i+n;yi:i+n)

特点

  • 平衡计算效率和收敛稳定性
  • 常用批量大小:32, 64, 128
  • 默认推荐算法
  • 当 mini-batch 的大小为 1 ,即是随机梯度下降法(stochastic gradient descent)
def minibatch_gd(X, y, theta, alpha, num_iters, batch_size=32):
    m = len(y)
    cost_history = []
    
    for i in range(num_iters):
        # 随机打乱数据
        permutation = np.random.permutation(m)
        X_shuffled = X[permutation]
        y_shuffled = y[permutation]
        
        for j in range(0, m, batch_size):
            # 获取当前batch
            X_batch = X_shuffled[j:j+batch_size]
            y_batch = y_shuffled[j:j+batch_size]
            
            # 计算梯度
            gradient = (1/batch_size) * X_batch.T.dot(X_batch.dot(theta) - y_batch)
            
            # 更新参数
            theta = theta - alpha * gradient
        
        # 记录损失
        cost = np.mean((X.dot(theta) - y)**2)
        cost_history.append(cost)
    
    return theta, cost_history

3.批梯度下降与 Mini-Batch梯度下降的区别

批梯度下降法与 Mini-Batch梯度下降法代价函数的变化趋势如下:


批梯度下降代价函数的变化图



批梯度下降代价函数的变化图

Mini-Batch梯度下降代价函数的变化图
Mini-Batch梯度下降代价函数的变化图
  • 如果训练样本的大小比较小,如m<=2000时,选择 batch 梯度下降法
  • 如果训练样本的大小比较大, 选择 Mini-Batch梯度下降法。为了和计算机的存储方式相适应,代码在 Mini-batch 大小为 2 的幂次时运行要快一些。

高级优化算法

3. 指数加权平均 (Exponentially Weighted Averages)

指数加权平均是一种常用的序列数据处理方式。通常用在序列场景如金融分析,温度变化序列分析。

假定给定一个序列,例如某地一年中每天的气温值,下图中蓝色的点代表真实数据。

某地一年气温变化图
某地一年气温变化图
  • 那么这样的气温值变化可以理解成优化的过程波动较大,异常较多。那么怎么平缓一些呢,这时候就要用到加权平均了。

    平缓气温变化图1
    平缓气温变化图1

这条红线通过指数加权的公式计算得出:
St={Y1t=1βSt−1+(1−β)Ytt>1S_t=\begin{cases} Y_1 & t=1 \\ \beta S_{t-1}+(1-\beta)Y_t & t>1 \end{cases}St={Y1βSt1+(1β)Ytt=1t>1
其中YtY_tYtttt下的实际值,StS_tStttt下加权平均后的值,β\betaβ为权重值。
上图红线中,β\betaβ为0.9。下图中,当取权重值β=0.98\beta=0.98β=0.98时,可以得到图中更为平滑的绿色曲线。β\betaβ越大相当于求取平均利用的天数越多,曲线自然也就越平滑而且越滞后

平缓气温变化图2
平缓气温变化图2

公式
vt=βvt−1+(1−β)θtv_t = \beta v_{t-1} + (1-\beta)\theta_tvt=βvt1+(1β)θt

加权
衰减
当前值
平均
历史值

特点

  • β\betaβ 控制平均范围(通常0.9)
  • 偏差校正:vtcorrected=vt1−βtv_t^{corrected} = \frac{v_t}{1-\beta^t}vtcorrected=1βtvt

4. 动量梯度下降 (Momentum)

原理:引入速度变量,积累历史梯度 ,是计算梯度的指数加权平均数数值
更新公式
vt=βvt−1+(1−β)∇θJ(θ)θ=θ−αvt \begin{align*} v_t &= \beta v_{t-1} + (1-\beta)\nabla_\theta J(\theta) \\ \theta &= \theta - \alpha v_t \end{align*} vtθ=βvt1+(1β)θJ(θ)=θαvt

效果

  • 当前后梯度方向一致时,动量梯度下降能够加速学习
  • 而前后梯度方向不一致时,能够减少震荡
  • 帮助跨越局部最优
def momentum_gd(X, y, theta, alpha, beta, num_iters):
    m = len(y)
    v = np.zeros_like(theta)
    cost_history = []
    
    for i in range(num_iters):
        # 计算梯度
        gradient = (1/m) * X.T.dot(X.dot(theta) - y)
        
        # 更新速度
        v = beta * v + (1 - beta) * gradient
        
        # 更新参数
        theta = theta - alpha * v
        
        # 记录损失
        cost = np.mean((X.dot(theta) - y)**2)
        cost_history.append(cost)
    
    return theta, cost_history

5. RMSProp (Root Mean Square Propagation)

原理:在对梯度进行指数加权平均基础上,引入平方和平方根
更新公式
st=βst−1+(1−β)(∇θJ(θ))2θ=θ−α∇θJ(θ)st+ϵ \begin{align*} s_t &= \beta s_{t-1} + (1-\beta)(\nabla_\theta J(\theta))^2 \\ \theta &= \theta - \alpha \frac{\nabla_\theta J(\theta)}{\sqrt{s_t} + \epsilon} \end{align*} stθ=βst1+(1β)(θJ(θ))2=θαst +ϵθJ(θ)
其中ϵ\epsilonϵ时一个非常小的数,防止分母太小导致不稳定。

特点

  • 在陡峭方向减小步长
  • 在平缓方向增大步长
  • 解决学习率敏感问题
def rmsprop(X, y, theta, alpha, beta, epsilon, num_iters):
    m = len(y)
    s = np.zeros_like(theta)
    cost_history = []
    
    for i in range(num_iters):
        # 计算梯度
        grad = (1/m) * X.T.dot(X.dot(theta) - y)
        
        # 更新累积平方梯度
        s = beta * s + (1 - beta) * grad**2
        
        # 更新参数
        theta = theta - alpha * grad / (np.sqrt(s) + epsilon)
        
        # 记录损失
        cost = np.mean((X.dot(theta) - y)**2)
        cost_history.append(cost)
    
    return theta, cost_history

6. Adam (Adaptive Moment Estimation)

原理:结合动量和RMSProp
更新公式
mt=β1mt−1+(1−β1)∇θJ(θ)vt=β2vt−1+(1−β2)(∇θJ(θ))2m^t=mt1−β1tv^t=vt1−β2tθ=θ−αm^tv^t+ϵ \begin{align*} m_t &= \beta_1 m_{t-1} + (1-\beta_1)\nabla_\theta J(\theta) \\ v_t &= \beta_2 v_{t-1} + (1-\beta_2)(\nabla_\theta J(\theta))^2 \\ \hat{m}_t &= \frac{m_t}{1-\beta_1^t} \\ \hat{v}_t &= \frac{v_t}{1-\beta_2^t} \\ \theta &= \theta - \alpha \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} \end{align*} mtvtm^tv^tθ=β1mt1+(1β1)θJ(θ)=β2vt1+(1β2)(θJ(θ))2=1β1tmt=1β2tvt=θαv^t +ϵm^t

特点

  • 目前最常用的优化算法
  • 自适应学习率
  • 内置偏差校正
def adam(X, y, theta, alpha, beta1, beta2, epsilon, num_iters):
    m = len(y)
    mt = np.zeros_like(theta)
    vt = np.zeros_like(theta)
    cost_history = []
    
    for t in range(1, num_iters+1):
        # 计算梯度
        grad = (1/m) * X.T.dot(X.dot(theta) - y)
        
        # 更新一阶矩估计
        mt = beta1 * mt + (1 - beta1) * grad
        
        # 更新二阶矩估计
        vt = beta2 * vt + (1 - beta2) * grad**2
        
        # 偏差校正
        mt_hat = mt / (1 - beta1**t)
        vt_hat = vt / (1 - beta2**t)
        
        # 更新参数
        theta = theta - alpha * mt_hat / (np.sqrt(vt_hat) + epsilon)
        
        # 记录损失
        cost = np.mean((X.dot(theta) - y)**2)
        cost_history.append(cost)
    
    return theta, cost_history

优化技巧

7. 学习率衰减

原理:随训练过程降低学习率
常用策略

  • 时间衰减:α=α01+decay_rate×epoch_num\alpha = \frac{\alpha_0}{1 + \text{decay\_rate} \times \text{epoch\_num}}α=1+decay_rate×epoch_numα0,其中decay_rate\text{decay\_rate}decay_rate为衰减率,epoch_num\text{epoch\_num}epoch_num为将所以样本完整过一遍的次数
  • 指数衰减:α=α0×e−decay_rate×epoch_num\alpha = \alpha_0 \times e^{-\text{decay\_rate} \times \text{epoch\_num}}α=α0×edecay_rate×epoch_num
  • 阶梯衰减:每N个epoch减半
def learning_rate_decay(initial_lr, epoch, decay_type='time', decay_rate=0.1):
    if decay_type == 'time':
        return initial_lr / (1 + decay_rate * epoch)
    elif decay_type == 'exponential':
        return initial_lr * np.exp(-decay_rate * epoch)
    elif decay_type == 'step':
        return initial_lr * (0.5 ** (epoch // 10))
    else:
        return initial_lr

8. 输入标准化

原理:使特征具有零均值和单位方差
公式
x′=x−μσx' = \frac{x - \mu}{\sigma}x=σxμ

效果

  • 加速收敛
  • 减少震荡
  • 提高优化稳定性
def normalize_input(X):
    mu = np.mean(X, axis=0)
    sigma = np.std(X, axis=0)
    X_norm = (X - mu) / (sigma + 1e-8)
    return X_norm, mu, sigma

优化算法对比分析

优化算法
标准梯度下降
动量GD
RMSProp
Adam
简单但效率低
减少震荡
自适应学习率
综合最优
算法 收敛速度 内存需求 超参数敏感性 适用场景
Batch GD 小数据集
Mini-Batch GD 中等 中等 中等 通用
Momentum 中等 有噪声梯度
RMSProp 非平稳目标
Adam 很快 深度学习通用
梯度优化算法效果对比图
梯度优化算法效果对比图

优化算法选择指南

小数据集
大数据集
稀疏数据
RNN/LSTM
GAN
有限内存
充足资源
选择优化算法
数据规模
批梯度下降
Adam或RMSProp
问题类型
自适应方法
Adam或RMSProp
Adam
计算资源
小批量Adam
大批量SGD

实际应用建议

  1. 默认选择:Adam优化器
  2. 学习率设置
    • 初始值:0.001(Adam),0.01(SGD)
    • 配合学习率衰减
  3. 批大小
    • 小数据集:32-128
    • 大数据集:256-1024
  4. 输入处理
    • 必须标准化输入
    • 考虑批归一化层
  5. 监控训练
    • 绘制损失曲线
    • 跟踪验证集性能
    • 使用早停策略

总结

梯度下降优化是深度学习成功的关键:

  1. 基础算法:BGD、SGD、Mini-batch GD
  2. 高级优化:Momentum、RMSProp、Adam
  3. 关键技巧
    • 学习率衰减
    • 输入标准化
    • 批归一化
  4. 实践准则
    • Adam作为默认选择
    • 配合学习率衰减
    • 标准化输入数据

理解这些优化算法的原理和实现,对于构建高效、稳定的深度学习模型至关重要。