TTiti的学习笔记
首页 / 专业知识 / 05-Courses/人工智能/MIT_6S191_Introduction_to_Deep_Learning/03-数学与代码最小可运行例子.md

03-数学与代码最小可运行例子

专业知识 · 05-Courses/人工智能/MIT_6S191_Introduction_to_Deep_Learning/03-数学与代码最小可运行例子.md

# MIT 6.S191 数学与代码最小可运行例子

目标:把课前必须会的数学概念转成能运行、能解释、能写进笔记的最小代码。你不需要在第一轮掌握复杂推导,但必须能把公式和代码对应起来。

1. 从线性模型开始

深度学习的第一块积木是线性变换:


Y = XW + b

直觉解释:X 是输入数据,W 是模型学到的权重,b 是偏置,Y 是输出。权重决定每个输入特征对输出的影响。


import numpy as np



X = np.array([

    [1.0, 2.0, 3.0],

    [2.0, 0.0, 1.0],

    [0.0, 1.0, 2.0],

    [1.0, 1.0, 1.0],

])



W = np.array([

    [0.2, -0.1],

    [0.5,  0.3],

    [0.1,  0.7],

])



b = np.array([0.1, -0.2])



Y = X @ W + b

print(Y)

print("shape:", Y.shape)

你要能解释:4 个样本,每个 3 个特征,经过 W 后变成每个样本 2 个输出。因此 Y.shape(4, 2)

2. 激活函数为什么必要

如果模型只有线性变换,多层线性层叠加仍然是线性的,表达能力有限。激活函数让模型能表示弯曲边界和复杂关系。


def relu(x):

    return np.maximum(0, x)



z = np.array([-2.0, -0.5, 0.0, 1.0, 3.0])

print(relu(z))

ReLU 的直觉是:负数信号被关掉,正数信号保留。它简单、计算快、在深度网络中常用。

3. Loss 的最小例子

回归任务常用 MSE:


MSE = mean((y_pred - y_true)^2)


y_true = np.array([3.0, 5.0, 7.0])

y_pred = np.array([2.5, 5.5, 8.0])

loss = np.mean((y_pred - y_true) ** 2)

print(loss)

分类任务常用 cross entropy。直觉是:正确类别概率越低,惩罚越大。


probs = np.array([0.1, 0.7, 0.2])  # 三个类别的预测概率

true_class = 1

loss = -np.log(probs[true_class])

print(loss)

如果正确类别概率从 0.7 降到 0.1,loss 会显著变大。

4. 梯度下降手算版

假设模型是:


y_pred = w * x

loss = (y_pred - y_true)^2

w 的梯度是:


d loss / d w = 2 * (w*x - y_true) * x

代码:


w = 1.0

x = 2.0

y_true = 5.0

lr = 0.1



for step in range(8):

    y_pred = w * x

    loss = (y_pred - y_true) ** 2

    grad_w = 2 * (y_pred - y_true) * x

    w = w - lr * grad_w

    print(f"step={step}, w={w:.3f}, y_pred={y_pred:.3f}, loss={loss:.3f}")

你要观察三件事:

  1. loss 是否整体下降。
  2. w 是否朝合适方向改变。
  3. 学习率如果过大会发生什么。

可以把 lr 改成 1.0 看看训练是否震荡。

5. PyTorch 中的自动求导

真实深度学习不会手写所有梯度,而是用自动求导。


import torch



w = torch.tensor(1.0, requires_grad=True)

x = torch.tensor(2.0)

y_true = torch.tensor(5.0)



y_pred = w * x

loss = (y_pred - y_true) ** 2

loss.backward()



print("loss:", loss.item())

print("grad:", w.grad.item())

requires_grad=True 表示 PyTorch 要追踪这个变量上的计算。loss.backward() 会自动计算梯度。你要知道:这就是 backpropagation 在代码中的表现。

6. 一个最小神经网络


import torch

import torch.nn as nn



X = torch.randn(16, 4)              # 16 个样本,每个 4 维

y = torch.randint(0, 3, (16,))      # 3 分类标签



model = nn.Sequential(

    nn.Linear(4, 8),

    nn.ReLU(),

    nn.Linear(8, 3)

)



criterion = nn.CrossEntropyLoss()

optimizer = torch.optim.Adam(model.parameters(), lr=0.01)



for step in range(20):

    logits = model(X)

    loss = criterion(logits, y)

    

    optimizer.zero_grad()

    loss.backward()

    optimizer.step()

    

    if step % 5 == 0:

        print(step, loss.item(), logits.shape)

解释:

  • X.shape = (16, 4):16 个样本,每个 4 个特征。
  • 第一层 Linear(4, 8):把 4 维输入变成 8 维隐藏表示。
  • 第二层 Linear(8, 3):输出 3 个类别的 logits。
  • CrossEntropyLoss:内部会处理 softmax 和 negative log likelihood。
  • optimizer.zero_grad():清空上一轮梯度。
  • loss.backward():计算梯度。
  • optimizer.step():更新参数。

7. Shape 检查表

任务输入 shape输出 shape常见 loss
表格二分类(batch, features)(batch, 2)(batch, 1)cross entropy / BCE
图像分类(batch, channels, height, width)(batch, classes)cross entropy
语言模型(batch, seq_len)(batch, seq_len, vocab)token cross entropy
回归(batch, features)(batch, 1)MSE
去噪生成noisy samplepredicted noiseMSE

当代码报错时,先打印 shape:


print("X", X.shape)

print("logits", logits.shape)

print("y", y.shape)

8. 训练循环流程


flowchart TD

    A["准备 batch 数据"] --> B["model(X) 得到 logits 或预测"]

    B --> C["计算 loss"]

    C --> D["optimizer.zero_grad()"]

    D --> E["loss.backward()"]

    E --> F["optimizer.step()"]

    F --> G["记录 loss/metric"]

    G --> A

这段流程是你看任何 lab 时都要找的结构。如果 notebook 很长,你先找到这几行,就能理解训练主线。

9. 常见错误

报错现象可能原因检查方式
matrix shape mismatch线性层输入维度不对打印 X.shapeLinear(in_features, ...)
expected Long but got Float分类标签 dtype 错y.dtype
CUDA not available本机没有 GPU 或环境没配好先用 CPU 跑小样本
loss 不下降学习率、标签、模型、数据有问题先用很小数据过拟合测试
accuracy 很高但不可信数据泄漏或样本太少检查 train/test split

10. 写进报告的表达

我先用一个最小神经网络确认训练流程。输入张量形状为 (batch, features),模型输出为 (batch, classes) 的 logits。训练时使用 cross entropy 作为分类损失,通过 backpropagation 计算梯度,并由 Adam optimizer 更新参数。这个例子不能证明模型在真实数据上有效,但可以验证我理解了 forward、loss、gradient 和 optimizer 的基本关系。