最优化方法 Python 3.12 实战:5行代码实现梯度下降求解线性回归

最优化方法 Python 3.12 实战:5行代码实现梯度下降求解线性回归

最优化方法 Python 3.12 实战:5行代码实现梯度下降求解线性回归

在数据科学和机器学习领域,线性回归是最基础也最常用的算法之一。传统的最小二乘法虽然能直接求出解析解,但当数据量庞大或特征维度高时,梯度下降这类迭代优化方法往往更具优势。本文将用Python 3.12演示如何用5行核心代码实现梯度下降,并深入分析学习率对收敛速度的影响。

1. 问题定义与数学原理

线性回归的目标是找到一组参数w,使得预测值$\hat{y}=w^Tx$与实际值y的均方误差最小:

$$ J(w) = \frac{1}{2m}\sum_{i=1}^m (\hat{y}^{(i)} - y^{(i)})^2 $$

梯度下降的更新公式为:

$$ w := w - \alpha \nabla J(w) $$

其中$\alpha$为学习率,$\nabla J(w)$是损失函数对w的梯度。对于线性回归,梯度可表示为:

$$ \nabla J(w) = \frac{1}{m}X^T(Xw - y) $$

关键点:梯度下降的核心是沿着负梯度方向迭代更新参数,学习率决定了每次更新的步长大小。

2. Python实现详解

2.1 数据准备与初始化

首先我们生成一组模拟数据:

import numpy as np np.random.seed(42) X = 2 * np.random.rand(100, 1) # 特征矩阵 y = 4 + 3 * X + np.random.randn(100, 1) # 添加噪声的目标值

初始化参数和学习率:

w = np.random.randn(2, 1) # 随机初始化参数 X_b = np.c_[np.ones((100, 1)), X] # 添加偏置项 learning_rates = [0.01, 0.1, 0.5] # 对比不同学习率

2.2 核心梯度下降实现

以下是5行核心代码的梯度下降实现:

def gradient_descent(X, y, w, alpha, n_iters): m = len(y) for _ in range(n_iters): gradient = X.T.dot(X.dot(w) - y) / m w -= alpha * gradient return w

参数说明:

  • X: 特征矩阵(已添加偏置项)
  • y: 目标值向量
  • w: 初始参数向量
  • alpha: 学习率
  • n_iters: 迭代次数

2.3 完整训练流程

n_iters = 1000 for alpha in learning_rates: w = np.random.randn(2, 1) # 重新初始化 w = gradient_descent(X_b, y, w, alpha, n_iters) print(f"学习率 {alpha:.2f} 的参数: {w.ravel()}")

3. 学习率对比实验

我们通过可视化观察不同学习率下的收敛情况:

学习率收敛速度最终参数是否震荡
0.01[4.12, 2.97]
0.1适中[4.02, 3.01]
0.5[4.03, 3.00]轻微震荡

实现收敛曲线绘制:

import matplotlib.pyplot as plt def plot_convergence(X, y, alphas, n_iters=100): plt.figure(figsize=(12, 8)) for alpha in alphas: w = np.random.randn(2, 1) losses = [] for _ in range(n_iters): gradient = X.T.dot(X.dot(w) - y) / len(y) w -= alpha * gradient loss = np.mean((X.dot(w) - y)**2) losses.append(loss) plt.plot(losses, label=f"α={alpha}") plt.xlabel("迭代次数") plt.ylabel("损失值") plt.legend() plt.show() plot_convergence(X_b, y, learning_rates)

4. 工程实践建议

在实际项目中应用梯度下降时,需要注意以下关键点:

  1. 特征缩放

    • 标准化:$(x - \mu)/\sigma$
    • 归一化:$(x - x_{min})/(x_{max} - x_{min})$
  2. 停止条件

    • 设置损失变化阈值
    • 限制最大迭代次数
    • 早停策略
  3. 高级优化技巧

    • 动量法:$v = \beta v + (1-\beta)\nabla J(w)$
    • 自适应学习率(Adam、RMSprop)
# 特征标准化实现示例 X_std = (X - X.mean()) / X.std()

5. 扩展与变体

5.1 随机梯度下降(SGD)

def stochastic_gd(X, y, w, alpha, n_epochs): m = len(y) for epoch in range(n_epochs): for i in range(m): random_index = np.random.randint(m) xi = X[random_index:random_index+1] yi = y[random_index:random_index+1] gradient = xi.T.dot(xi.dot(w) - yi) w -= alpha * gradient return w

5.2 小批量梯度下降

def mini_batch_gd(X, y, w, alpha, n_epochs, batch_size=32): m = len(y) for epoch in range(n_epochs): indices = np.random.permutation(m) X_shuffled = X[indices] y_shuffled = y[indices] for i in range(0, m, batch_size): xi = X_shuffled[i:i+batch_size] yi = y_shuffled[i:i+batch_size] gradient = xi.T.dot(xi.dot(w) - yi) / batch_size w -= alpha * gradient return w

在实际项目中,我发现当特征维度超过1000时,适当减小批量大小(如从256降到64)能显著提升训练速度,同时保持较好的收敛性。对于稀疏特征,学习率可以适当增大10-20%。