线性回归是深度学习里最经典的“第一性模型”:
你会第一次把下面这套完整闭环跑通:

数据 → 模型 → 损失 → 梯度 → 更新参数 → 训练收敛

而且它非常贴近你前面学的两章:


1. 模型:( \hat{y} = Xw + b )

假设每个样本有 (d) 个特征:

  • (X \in \mathbb{R}^{n \times d})(n 个样本)

  • (w \in \mathbb{R}^{d \times 1})

  • (b \in \mathbb{R})

  • 输出:(\hat{y} \in \mathbb{R}^{n \times 1})

y_hat = X @ w + b

直觉:线性回归就是把特征加权求和(大量点积),再加一个偏置。


2. 损失函数:平方损失(MSE)

常用的是均方误差(MSE):

[
L(y, \hat{y}) = \frac{1}{n}\sum_{i=1}^n (y_i - \hat{y}_i)^2
]

实现时最常见写法:

loss = ((y_hat - y) ** 2).mean() / 2

除以 2 是为了求导后更简洁(李沐也经常这么写),不影响最优解位置。


3. 优化:小批量随机梯度下降(SGD)

梯度下降更新公式:

[
w \leftarrow w - \eta \frac{\partial L}{\partial w}, \quad b \leftarrow b - \eta \frac{\partial L}{\partial b}
]

其中:

  • (\eta) 是学习率(lr)

  • 梯度由 autograd 自动给你算出来


4. 从零实现:造数据 → 初始化参数 → 训练循环(可跑通)

下面代码完整复现“李沐线性回归训练闭环”:
(造一个有噪声的线性数据集,训练把参数学回来)

import torch

# 1) 造数据:y = Xw + b + noise
torch.manual_seed(0)
n, d = 1000, 2
true_w = torch.tensor([[2.0], [-3.4]])
true_b = 4.2

X = torch.randn(n, d)
noise = torch.randn(n, 1) * 0.01
y = X @ true_w + true_b + noise

# 2) 初始化参数(要学的)
w = torch.randn(d, 1, requires_grad=True)
b = torch.zeros(1, requires_grad=True)

# 3) 超参数
lr = 0.03
batch_size = 32
num_epochs = 5

def data_iter(batch_size, X, y):
    idx = torch.randperm(X.shape[0])
    for i in range(0, X.shape[0], batch_size):
        j = idx[i:i+batch_size]
        yield X[j], y[j]

# 4) 训练
for epoch in range(num_epochs):
    for X_batch, y_batch in data_iter(batch_size, X, y):
        y_hat = X_batch @ w + b
        loss = ((y_hat - y_batch) ** 2).mean() / 2

        loss.backward()

        # 手写 SGD 更新(注意:更新参数时不建图)
        with torch.no_grad():
            w -= lr * w.grad
            b -= lr * b.grad
            w.grad.zero_()
            b.grad.zero_()

    # 每个 epoch 打印一下全量 loss
    with torch.no_grad():
        train_loss = (((X @ w + b) - y) ** 2).mean().item() / 2
    print(f"epoch {epoch+1}, loss {train_loss:.6f}")

print("learned w:", w.reshape(-1).tolist())
print("learned b:", b.item())
print("true w:", true_w.reshape(-1).tolist())
print("true b:", true_b)

你跑完会看到:

  • loss 快速下降

  • 学到的 w, b 非常接近 true_w, true_b


5. 训练循环里最关键的 3 个细节(必考点)

5.1 loss.backward() 后梯度会累加 → 必须清零

w.grad.zero_()
b.grad.zero_()

5.2 参数更新要 no_grad(),否则会把更新步骤也记录进计算图

with torch.no_grad():
    w -= lr * w.grad

5.3 batch 的意义:更快、更稳、更泛化

  • 全量梯度下降:每步算 n 个样本,慢

  • SGD:每步只看 1 个样本,噪声大

  • mini-batch:折中(最常用)


6. 线性回归为什么是“深度学习入门第一模型”?

因为它把所有训练本质都展示出来了:

  • 前向:y_hat = X @ w + b

  • 损失:(y_hat - y)^2

  • 反向:loss.backward()

  • 更新:w -= lr * grad

你学会这一套,后面 softmax、MLP、CNN 都只是把“模型结构”换掉。

更多推荐