一、梯度下降:从基础到变种

梯度下降是机器学习中最基础的优化算法,它的核心思想是通过迭代调整参数,逐步逼近损失函数的最小值。想象一下你在山上蒙着眼睛找下山的路,每次只能试探周围一小步,选择最陡的方向迈出一步——这就是梯度下降的直观比喻。

1.1 标准梯度下降(Batch GD)

标准的梯度下降在每次迭代时使用全部训练数据计算梯度,虽然方向准确,但计算量大。例如,用Python实现线性回归的梯度下降:

# 技术栈:Python + NumPy
import numpy as np

def batch_gradient_descent(X, y, learning_rate=0.01, epochs=1000):
    m, n = X.shape
    theta = np.zeros(n)  # 初始化参数
    for _ in range(epochs):
        gradient = (1/m) * X.T @ (X @ theta - y)  # 计算梯度(全部数据)
        theta -= learning_rate * gradient  # 更新参数
    return theta

1.2 随机梯度下降(SGD)

SGD每次随机选一个样本计算梯度,速度快但波动大。适合大规模数据:

def stochastic_gradient_descent(X, y, learning_rate=0.01, epochs=100):
    m, n = X.shape
    theta = np.zeros(n)
    for _ in range(epochs):
        for i in range(m):
            random_idx = np.random.randint(m)
            xi, yi = X[random_idx], y[random_idx]
            gradient = xi * (xi @ theta - yi)  # 单样本梯度
            theta -= learning_rate * gradient
    return theta

1.3 小批量梯度下降(Mini-batch GD)

折中方案:每次用一小批数据。例如批量大小为32:

def mini_batch_gradient_descent(X, y, batch_size=32, learning_rate=0.01, epochs=100):
    m, n = X.shape
    theta = np.zeros(n)
    for _ in range(epochs):
        indices = np.random.permutation(m)
        X_shuffled, y_shuffled = X[indices], y[indices]
        for i in range(0, m, batch_size):
            X_batch = X_shuffled[i:i+batch_size]
            y_batch = y_shuffled[i:i+batch_size]
            gradient = (1/batch_size) * X_batch.T @ (X_batch @ theta - y_batch)
            theta -= learning_rate * gradient
    return theta

优缺点对比

  • Batch GD:稳定但慢,适合小数据。
  • SGD:快但噪声大,需动态调整学习率。
  • Mini-batch GD:平衡效率与稳定性,最常用。

二、反向传播:神经网络的引擎

反向传播是训练神经网络的核心算法,通过链式法则将误差从输出层反向传递到每一层。以简单的3层网络为例:

# 技术栈:Python + NumPy
class NeuralNetwork:
    def __init__(self, input_size, hidden_size, output_size):
        self.W1 = np.random.randn(input_size, hidden_size) * 0.01
        self.W2 = np.random.randn(hidden_size, output_size) * 0.01

    def forward(self, X):
        self.z1 = X @ self.W1
        self.a1 = np.tanh(self.z1)  # 隐藏层激活函数
        self.z2 = self.a1 @ self.W2
        return self.z2  # 输出层(未激活)

    def backward(self, X, y, learning_rate):
        m = X.shape[0]
        # 输出层误差
        dz2 = (self.z2 - y) / m
        dW2 = self.a1.T @ dz2
        # 隐藏层误差
        dz1 = (dz2 @ self.W2.T) * (1 - np.tanh(self.z1)**2)  # tanh导数
        dW1 = X.T @ dz1
        # 更新权重
        self.W1 -= learning_rate * dW1
        self.W2 -= learning_rate * dW2

关键点

  1. 前向传播计算预测值。
  2. 反向传播计算梯度时,需注意激活函数的导数(如tanh的导数为1 - tanh²)。

三、神经网络的优化策略

3.1 动量法(Momentum)

模拟物理中的动量,加速收敛并减少震荡:

def momentum_update(gradient, velocity, beta=0.9):
    velocity = beta * velocity + (1 - beta) * gradient
    return velocity

3.2 Adam优化器

结合动量和自适应学习率,以下是简化实现:

def adam_update(gradient, m, v, t, lr=0.001, beta1=0.9, beta2=0.999, eps=1e-8):
    m = beta1 * m + (1 - beta1) * gradient  # 一阶矩
    v = beta2 * v + (1 - beta2) * (gradient ** 2)  # 二阶矩
    m_hat = m / (1 - beta1**t)  # 偏差修正
    v_hat = v / (1 - beta2**t)
    return m_hat / (np.sqrt(v_hat) + eps)

应用场景

  • 动量法:适用于损失函数存在局部最优或鞍点。
  • Adam:默认首选,尤其适合稀疏数据(如自然语言处理)。

四、实战注意事项

  1. 学习率选择:过大导致震荡,过小收敛慢。可用学习率衰减策略:
    learning_rate = initial_lr / (1 + decay_rate * epoch)
    
  2. 梯度消失/爆炸:用Batch Normalization或残差连接(ResNet)解决。
  3. 过拟合:Dropout层或L2正则化。

总结
梯度下降变种、反向传播和优化策略是训练神经网络的三大支柱。理解其原理后,灵活选择工具(如PyTorch已内置所有优化器),才能在实践中游刃有余。