梯度下降算法原理详解与实战优化指南

1次阅读
没有评论

共计 2130 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

数学原理:理解梯度下降的核心

梯度下降是机器学习中用来最小化代价函数的迭代优化算法。它的核心思想可以概括为: 沿着代价函数梯度的反方向,逐步调整参数 ,直到找到最小值点。

梯度下降算法原理详解与实战优化指南

代价函数与梯度

假设我们有代价函数 $J(\theta)$,其中 $\theta$ 是模型参数。梯度下降的更新规则为:

$$\theta_{t+1} = \theta_t – \eta \cdot \nabla_\theta J(\theta_t)$$

其中:

  • $\eta$ 是学习率,控制每次更新的步长
  • $\nabla_\theta J(\theta_t)$ 是代价函数在当前参数处的梯度

梯度实际上是一个向量,指向函数值增长最快的方向。因此,沿着梯度的反方向更新参数,可以确保代价函数值逐渐减小。

标准梯度下降的三大痛点

虽然理论上简单,标准梯度下降(Batch Gradient Descent)在实践中面临几个主要挑战:

  1. 计算开销大 :每次迭代需要计算整个数据集的梯度,当数据量大时计算成本高昂

  2. 易陷入局部最优 :特别是在非凸函数中,算法可能收敛到局部最小值而非全局最优

  3. 学习率敏感 :学习率设置不当会导致收敛缓慢(太小)或震荡(太大)

改进方案:从 SGD 到带动量的优化

随机梯度下降(SGD)

SGD 每次只用一个样本来估计梯度:

$$\theta_{t+1} = \theta_t – \eta \cdot \nabla_\theta J(\theta_t; x_i, y_i)$$

优点

  • 计算速度快,适合大数据集
  • 随机性有助于跳出局部最优

缺点

  • 更新方向噪声大,收敛路径曲折
  • 可能最终在最小值附近震荡

带动量的优化方法

动量法通过引入速度变量 $v$ 来平滑更新方向:

$$v_{t+1} = \gamma v_t + \eta \nabla_\theta J(\theta_t)$$

$$\theta_{t+1} = \theta_t – v_{t+1}$$

其中 $\gamma$ 是动量系数(通常 0.9)。这种方法能:

  • 加速在平坦方向的收敛
  • 减少震荡

Python 实现:带学习率衰减的线性回归

import numpy as np
import matplotlib.pyplot as plt

# 生成模拟数据
np.random.seed(42)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)

# 添加偏置项
X_b = np.c_[np.ones((100, 1)), X]

# 初始化参数
theta = np.random.randn(2, 1)

# 梯度下降参数
eta = 0.1  # 初始学习率
n_iterations = 1000
m = len(X)

def learning_rate_schedule(t):
    """学习率衰减函数"""
    return eta / (1 + 0.1 * t)

# 存储损失历史
loss_history = []

for iteration in range(n_iterations):
    gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y)
    current_eta = learning_rate_schedule(iteration)
    theta = theta - current_eta * gradients
    loss = np.mean((X_b.dot(theta) - y)**2)
    loss_history.append(loss)

# 可视化损失曲线
plt.plot(range(n_iterations), loss_history)
plt.xlabel('Iterations')
plt.ylabel('Loss')
plt.title('Loss during Gradient Descent')
plt.show()

print("Final parameters:", theta.ravel())

生产环境建议

学习率选择

  1. 初始学习率 :可以先尝试 0.1,然后根据表现调整。常用策略:
  2. 从大到小尝试(如 0.1, 0.01, 0.001)
  3. 使用学习率扫描(Learning Rate Finder)

  4. 学习率衰减

  5. 时间衰减:$\eta_t = \eta_0 / (1 + decay_rate \times t)$
  6. 指数衰减:$\eta_t = \eta_0 \times 0.1^{t/N}$

批量大小

  • 小批量(32-256)通常表现最好
  • 太大:收敛慢,内存需求高
  • 太小:更新噪声大

早停法实现

best_loss = np.inf
patience = 10  # 连续多少次不改进就停止
no_improve = 0

for iteration in range(n_iterations):
    # ... 训练代码...

    if loss < best_loss:
        best_loss = loss
        no_improve = 0
    else:
        no_improve += 1

    if no_improve >= patience:
        print(f"Early stopping at iteration {iteration}")
        break

思考题

当特征尺度差异大时,梯度下降会出现什么问题?如何解决?

问题 :不同特征的梯度幅度差异大,导致收敛路径曲折,需要更小的学习率来避免震荡。

解决方案

  1. 特征标准化(如 Z -score 标准化)
  2. 使用自适应优化算法(如 Adam、RMSprop)
  3. 为不同参数设置不同的学习率

这些方法的本质都是让不同特征的更新步长更加均衡。

正文完
 0
评论(没有评论)