Skip to content

第一个模型:30 分钟跑通全流程 ​

目标:亲手走完「数据 → 模型 → 损失 → 优化 → 评估」这一圈。

这一页的意义不在结果(线性回归太简单了),而在于建立地图:之后学的所有模型,都是这五步的变体。

全流程只有五步 ​

1
准备数据(x, y) 成对样本
2
定义模型y = wx + b
3
定义损失MSE 衡量差距
4
优化参数沿梯度反方向走
5
评估在新数据上看误差

任务:用学习时长预测考试分数 ​

学习时长(h)12345678
分数4255587178839296

(理想情况接近「分数 ≈ 40 + 7 × 时长」,我们让模型自己找出来。)

版本一:NumPy 手写(推荐先跑这个) ​

不用框架,看清每一步在干什么。

python
import numpy as np

# ① 数据
x = np.array([1, 2, 3, 4, 5, 6, 7, 8], dtype=float)
y = np.array([42, 55, 58, 71, 78, 83, 92, 96], dtype=float)

# ② 模型:y_hat = w * x + b
w, b = 0.0, 0.0

# ③ 超参数
lr = 0.01          # 学习率
epochs = 2000      # 训练轮数
n = len(x)

for epoch in range(epochs):
    # 前向:预测
    y_hat = w * x + b

    # 损失:均方误差
    loss = np.mean((y_hat - y) ** 2)

    # 反向:对 w 和 b 求偏导(手推出来的,见下)
    dw = 2 * np.mean((y_hat - y) * x)
    db = 2 * np.mean(y_hat - y)

    # ④ 优化:沿梯度反方向走一小步
    w -= lr * dw
    b -= lr * db

    if epoch % 400 == 0:
        print(f"epoch={epoch:4d} loss={loss:8.3f} w={w:.3f} b={b:.3f}")

print(f"\n最终: y ≈ {w:.2f}x + {b:.2f}")
print(f"测试:学 10 小时 → 预测 {w*10+b:.1f} 分")

你应该看到:loss 从上千降到个位数,w 收敛到约 7.3,b 收敛到约 35。

那两行偏导是怎么来的? ​

损失 $L = \frac{1}{n}\sum(\hat y - y)^2$,而 $\hat y = wx + b$。对 $w$ 求导得 $\frac{2}{n}\sum(\hat y-y)x$,对 $b$ 求导得 $\frac{2}{n}\sum(\hat y-y)$。

看不懂没关系 —— PyTorch 会自动帮你算。但你要知道「这里确实是在求导」,不是魔法。数学细节见 L1 数学。

版本二:PyTorch 自动求导 ​

同样的任务,让框架算梯度。

python
import torch
import torch.nn as nn

x = torch.tensor([[1.], [2.], [3.], [4.], [5.], [6.], [7.], [8.]])
y = torch.tensor([[42.], [55.], [58.], [71.], [78.], [83.], [92.], [96.]])

# ② 模型
model = nn.Linear(in_features=1, out_features=1)

# ③ 损失 + ④ 优化器
loss_fn = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

for epoch in range(2000):
    pred = model(x)                 # 前向
    loss = loss_fn(pred, y)         # 算损失

    optimizer.zero_grad()           # 清空上轮梯度(漏了会累加!)
    loss.backward()                 # 反向传播,自动求导
    optimizer.step()                # 更新参数

    if epoch % 400 == 0:
        w = model.weight.item()
        b = model.bias.item()
        print(f"epoch={epoch:4d} loss={loss.item():8.3f} w={w:.3f} b={b:.3f}")

三个必踩的坑

  1. 忘了 zero_grad() → 梯度在上一轮基础上累加,模型乱飞
  2. 忘了 loss.backward() → 梯度是空的,参数永远不变
  3. loss 忘了 .item() → 把整个计算图存下来,内存爆掉

版本三:scikit-learn 三行版 ​

实际业务里,这类简单任务直接调库:

python
import numpy as np
from sklearn.linear_model import LinearRegression

X = np.array([1, 2, 3, 4, 5, 6, 7, 8]).reshape(-1, 1)
y = np.array([42, 55, 58, 71, 78, 83, 92, 96])

model = LinearRegression().fit(X, y)
print(f"y ≈ {model.coef_[0]:.2f}x + {model.intercept_:.2f}")
print(f"R² = {model.score(X, y):.3f}")

三行搞定,但你应该先跑版本一,否则永远不知道 fit 里发生了什么。

三个版本对照 ​

手写 NumPyPyTorchscikit-learn
需要理解的梯度怎么算、怎么更新计算图、反向传播几乎没有
代码量~20 行~12 行3 行
适用学习原理深度模型传统 ML 业务
换模型成本全部重写改一行改一行

加一步:看拟合效果 ​

模型好不好,画出来最直观。

python
import matplotlib.pyplot as plt

plt.figure(figsize=(6, 4))
plt.scatter(x, y, label="真实数据")
plt.plot(x, w * x + b, color="crimson", label=f"拟合: y={w:.1f}x+{b:.1f}")
plt.xlabel("学习时长 (h)")
plt.ylabel("分数")
plt.legend()
plt.title("线性回归拟合结果")
plt.grid(alpha=0.3)
plt.show()

看到点紧贴直线,就说明模型学到了规律。「画图检查」是 AI 工程里最便宜、最有效的验证手段,从今天开始养成。

从这一步能延伸出什么 ​

这个 30 行的例子,是所有模型的骨架:

你现在做的换成什么就成了…
w*x+b换成多层神经网络 → 深度学习
MSE 损失换成交叉熵 → 分类任务
全量数据算梯度每次取 32 条 → 小批量 SGD
8 条样本换成 1 万亿 token → 大模型预训练
手算梯度换成 loss.backward() → 自动微分

框架在变,骨架从没变过。

通过标准 ​

下一步 ​

L0 结束,进入 L1 数学与数据基础 —— 开始补「为什么」。

AI 学习路线 · 从入门到专家