Skip to content

线性回归与梯度下降

线性回归是最简单的机器学习算法,但包含了所有核心概念:模型、损失、优化。

假设目标值 yy 是特征 xx 的线性组合:

y^=w0+w1x1+w2x2++wnxn=Xw\hat{y} = w_0 + w_1x_1 + w_2x_2 + \cdots + w_nx_n = Xw

衡量预测值与真实值的差距:

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

令梯度为零,直接求解(适合小数据集):

w=(XTX)1XTyw = (X^TX)^{-1}X^Ty
import numpy as np
np.random.seed(42)
X = np.random.rand(100, 1) * 10
y = 3 * X.ravel() + 2 + np.random.randn(100) * 2
X_b = np.c_[np.ones((len(X), 1)), X]
w = np.linalg.inv(X_b.T @ X_b) @ X_b.T @ y
print(f"w0(偏置) = {w[0]:.2f}, w1(斜率) = {w[1]:.2f}")

当特征很多时,逐步更新参数:

w:=wαJ(w),J(w)=2mXT(Xwy)w := w - \alpha \nabla J(w), \quad \nabla J(w) = \frac{2}{m}X^T(Xw - y)
flowchart LR
A[初始化 w] --> B[计算梯度 J]
B --> C[更新 w -= α×▽J]
C --> D{收敛?}
D -->|| B
D -->|| E[完成]
def gradient_descent(X, y, lr=0.01, epochs=1000):
m, n = X.shape
w = np.zeros(n)
for epoch in range(epochs):
y_pred = X @ w
grad = (2 / m) * X.T @ (y_pred - y)
w -= lr * grad
if epoch % 200 == 0:
loss = np.mean((y_pred - y) ** 2)
print(f"Epoch {epoch:4d}: loss = {loss:.4f}")
return w
X_std = (X - X.mean()) / X.std()
X_b_std = np.c_[np.ones((len(X_std), 1)), X_std]
w_gd = gradient_descent(X_b_std, y, lr=0.1, epochs=1000)
import matplotlib.pyplot as plt
for lr in [0.001, 0.01, 0.1, 0.5]:
w = np.zeros(2)
losses = []
for _ in range(100):
y_pred = X_b_std @ w
grad = (2/len(X)) * X_b_std.T @ (y_pred - y)
w -= lr * grad
losses.append(np.mean((y_pred - y)**2))
plt.plot(losses, label=f'lr={lr}')
plt.xlabel('Epoch'); plt.ylabel('Loss')
plt.legend(); plt.yscale('log')
plt.show()
学习率效果
太大跳过最优点,震荡甚至发散
太小收敛太慢
适中快速稳定收敛
类型每步数据量特点
批量全部数据最稳定,但每步都慢
随机 (SGD)1 条最快,但振荡
小批量32-256 条折中最优,实际最常用