第一阶段:数学与编程基础
1.1 线性代数 — 神经网络的"语言"
如果你只想记住一句话:神经网络的前向传播 = 矩阵乘法链 + 非线性激活函数。
标量、向量、矩阵、张量
| 概念 | 数学表示 | PyTorch 表示 | 示例 |
|---|---|---|---|
| 标量 (Scalar) | torch.tensor(3.14) | 温度 25.3°C | |
| 向量 (Vector) | torch.randn(100) | 100 维词向量 | |
| 矩阵 (Matrix) | torch.randn(32, 100) | 32 个样本的特征 | |
| 张量 (Tensor) | torch.randn(16, 32, 100) | 16 个 batch |
核心运算
1. 矩阵乘法 — 神经网络最基本的运算
一个简单的全连接层:
其中:
— 输入向量(d_in = 输入维度) — 权重矩阵 — 偏置向量 — 输出向量
python
import torch
# 一个简单的线性层
d_in, d_out = 784, 256
x = torch.randn(1, d_in) # 输入: (1, 784) — 例如一张 MNIST 图片
W = torch.randn(d_out, d_in) # 权重: (256, 784)
b = torch.randn(d_out) # 偏置: (256,)
# 前向传播:y = Wx + b
y = x @ W.T + b # (1, 784) @ (784, 256) + (256,) = (1, 256)
print(f"输入形状: {x.shape} → 输出形状: {y.shape}")2. 点积 — 注意力机制的基础
两个向量的点积衡量它们的"相似度":
当两个向量同方向时点积最大,正交时为 0,反向时为负。Transformer 的自注意力本质上就是大规摸的点积计算。
3. Softmax — 把任意向量变成概率分布
python
def softmax(x):
"""将任意实数向量转换为概率分布(所有元素之和为1)"""
exp_x = torch.exp(x - x.max()) # 减去最大值防止数值溢出
return exp_x / exp_x.sum(dim=-1, keepdim=True)
logits = torch.tensor([2.0, 1.0, 0.1])
probs = softmax(logits)
print(f"输入: {logits}")
print(f"Softmax 后: {probs} (和={probs.sum():.1f})")
# 输出: tensor([0.6590, 0.2424, 0.0986]) (和=1.0)Softmax 是 Transformer 的命脉,它把注意力分数转化为"每个位置应该关注多少"的概率分布。
1.2 微积分与优化基础 — 梯度下降为什么有效
深度学习 = 大规模梯度下降。理解微积分,才能真正理解"模型是怎么学会的"。
导数与偏导数
导数描述函数在某一点的变化率:
偏导数:对于多元函数
梯度 — 最陡上升方向
梯度是所有偏导数组成的向量,指向函数增长最快的方向:
梯度下降:沿着梯度的反方向走一小步,函数值会下降:
python
"""手工实现梯度下降:找到 y = x² 的最小值"""
import torch
x = torch.tensor([3.0], requires_grad=True) # 初始值:x=3
lr = 0.1 # 学习率
for step in range(20):
y = x ** 2 # 损失函数:y = x²,最小值在 x=0
y.backward() # dy/dx = 2x
with torch.no_grad():
x -= lr * x.grad # x = x - lr * 2x
x.grad.zero_() # 清零梯度
print(f"Step {step:2d}: x = {x.item():.6f}, y = {y.item():.6f}")
# 输出:x 从 3.0 逐渐收敛到 0(y 的最小值点)链式法则 — 反向传播的数学基础
对于复合函数
对于多层网络
这就是反向传播的数学本质:误差从输出层逐层传回输入层。
python
"""手工演示反向传播的链式法则"""
x = torch.tensor([2.0], requires_grad=True)
# 复合函数:y = (3x² + 2)³
# 分解:a = x², b = 3a + 2, y = b³
# 链式法则:dy/dx = dy/db · db/da · da/dx
# = 3b² · 3 · 2x
y = (3 * x**2 + 2) ** 3
y.backward()
# 验证
a = x.item() ** 2
b = 3 * a + 2
expected = 3 * b**2 * 3 * 2 * x.item()
print(f"PyTorch 计算: {x.grad.item():.2f}")
print(f"手工链式法则: {expected:.2f}")Jacobian 与 Hessian — 进阶优化
| 概念 | 定义 | 作用 | 何时关心 |
|---|---|---|---|
| 梯度 (Gradient) | 表明"往哪走最快下降" | 所有训练 | |
| Jacobian | 层间误差传播 | 理解 autograd 原理 | |
| Hessian | 曲率信息,判断是鞍点还是最小值 | 理解优化器选择(Adam vs SGD) |
python
"""Hessian 的直观示例:为什么 Adam 比 SGD 好"""
# 鞍点问题:SGD 在鞍点处梯度 ≈ 0,会卡住不动
# Adam 利用了历史梯度信息(动量+自适应学习率),能冲过鞍点
# 但对程序员来说,只需记住:默认用 AdamW 就行了1.3 线性代数进阶 — 理解 Embedding 空间
特征值与特征向量
对于方阵
则
直觉:特征向量是矩阵作用于其上"只放缩不转向"的方向。
在大模型中的意义
python
"""特征值分解在 NLP 中的直观应用"""
# 词向量矩阵 W ∈ R^(vocab_size × embed_dim)
# PCA(主成分分析)= 对协方差矩阵做特征值分解
# 场景:把 768 维词向量降到 2 维可视化
import torch
# 模拟 1000 个词的 768 维词向量
embeddings = torch.randn(1000, 768)
embeddings = embeddings / embeddings.norm(dim=1, keepdim=True)
# 协方差矩阵
cov = embeddings.T @ embeddings / embeddings.size(0) # (768, 768)
# 特征值分解
eigenvalues, eigenvectors = torch.linalg.eigh(cov)
# 特征值排序(降序)
sorted_idx = eigenvalues.argsort(descending=True)
top_eigenvectors = eigenvectors[:, sorted_idx[:2]] # 取前 2 个主成分
# 降维到 2D
embeddings_2d = embeddings @ top_eigenvectors
print(f"词向量: {embeddings.shape} → 2D: {embeddings_2d.shape}")
# 前 2 个特征值的方差解释率
print(f"Top-2 特征值占比: {eigenvalues[sorted_idx[:2]].sum() / eigenvalues.sum():.1%}")SVD (奇异值分解) — 任意矩阵的分解
:左奇异向量(行空间的正交基) :奇异值(降序排列) :右奇异向量(列空间的正交基)
在 Attention 中的应用:低秩分解降低计算量(如 Linformer 用 SVD 将
Embedding 空间的几何直觉
python
# 经典的词向量类比
# king - man + woman ≈ queen
# 说明:词向量的方向编码了语义关系
# 在向量空间中:
# king_vec + (woman_vec - man_vec) ≈ queen_vec
# 即:国王 + 性别方向 = 女王
# 余弦相似度衡量语义相关性
def cosine_sim(a, b):
"""两个向量的余弦相似度"""
return (a @ b) / (a.norm() * b.norm())
# 高相似方向 → 词义相近
# 正交方向 → 词义无关
# 相反方向 → 词义对立1.4 概率论与统计学习基础
为什么深度学习需要概率?
现实世界充满不确定性。概率论给深度学习提供了:
- 损失函数的理论基础(交叉熵为什么有效?)
- 不确定性量化(模型有多确定?)
- 生成模型的理论框架(GAN/VAE/Diffusion)
熵 (Entropy) — 信息量的度量
熵衡量一个随机变量的不确定性:
- 均匀分布:熵最大(最不确定)
- 确定性分布(某个事件概率为 1):熵 = 0(完全确定)
交叉熵 (Cross-Entropy) — 实际 vs 预测的差异
交叉熵衡量用预测分布
python
import torch.nn.functional as F
# 真实标签:类别 2(one-hot: [0, 0, 1, 0, 0])
# 模型预测:logits 转换为概率
logits = torch.tensor([[0.1, 0.2, 3.0, 0.4, 0.1]]) # 第三个最高
labels = torch.tensor([2]) # 真实类别
# 交叉熵损失 = -log(预测概率[真实类别])
loss = F.cross_entropy(logits, labels)
print(f"交叉熵损失: {loss.item():.4f}")
# 损失越小 → 模型对正确类别的置信度越高核心直觉:训练就是在最小化交叉熵——让模型对正确答案越来越"确定"。
KL 散度 (KL Divergence)
KL 散度衡量两个分布之间的"距离"。训练时最小化 KL 散度等价于最小化交叉熵(因为
最大似然估计 (MLE) — 训练的本质
深度学习训练的本质就是最大似然估计。给定数据
取对数后等价于最小化负对数似然(Negative Log-Likelihood, NLL):
关键联系:当模型输出高斯分布时,NLL = MSE;当模型输出分类分布时,NLL = 交叉熵。所以你在 PyTorch 里写的
nn.CrossEntropyLoss()本质上就是在做最大似然估计。
最大后验估计 (MAP) — 引入先验知识
MAP 在 MLE 基础上加入了参数的先验分布
取对数:
关键联系:当
是高斯先验时, 等价于 L2 正则化项(Weight Decay)。所以 AdamW 的 weight_decay 本质上就是贝叶斯先验。
python
# MLE vs MAP 的代码等价性
# MLE(不加正则化):
loss_mle = F.cross_entropy(outputs, targets)
# MAP with L2 prior(等价于 Weight Decay):
loss_map = F.cross_entropy(outputs, targets) + weight_decay * sum(p.pow(2).sum() for p in model.parameters())
# 实际上 AdamW 的 weight_decay 在 optimizer 里自动处理了偏差-方差权衡 — 理解过拟合与欠拟合
| 概念 | 定义 | 表现 | 对应 |
|---|---|---|---|
| 偏差 (Bias) | 模型预测的期望与真实值之间的差距 | 欠拟合:训练集和测试集表现都差 | 模型太简单 |
| 方差 (Variance) | 模型对不同训练集的敏感程度 | 过拟合:训练集很好,测试集很差 | 模型太复杂 |
| 不可约误差 | 数据本身的噪声 | 无论多好的模型都无法避免 | 数据质量问题 |
mermaid
graph LR
UNDER["🔵 高偏差 (欠拟合)<br/>- 训练 loss 高<br/>- 验证 loss 也高<br/>- 原因:模型太简单"] --> BALANCED["🟢 平衡点<br/>- 训练 loss 低<br/>- 验证 loss 低<br/>- 原因:模型恰好"]
BALANCED --> OVER["🔴 高方差 (过拟合)<br/>- 训练 loss 很低<br/>- 验证 loss 很高<br/>- 原因:模型太复杂"]
style UNDER fill:#3498db,color:#fff
style BALANCED fill:#2ecc71,color:#fff
style OVER fill:#e74c3c,color:#fff如何判断:训练 loss 低但验证 loss 高 → 过拟合 → 加正则化/更多数据/减少参数。训练 loss 和验证 loss 都高 → 欠拟合 → 加大模型/减少正则化/更多 epoch。
泛化误差 — 模型真正的"考试成绩"
- 训练误差:在训练数据上的错误率(平时作业成绩)
- 泛化误差:在未见过的数据上的错误率(高考成绩)
- 泛化间隙:两者之差(越大说明过拟合越严重)
python
"""监控泛化间隙的代码框架"""
def check_generalization_gap(model, train_loader, val_loader):
model.eval()
with torch.no_grad():
train_loss = evaluate(model, train_loader)
val_loss = evaluate(model, val_loader)
gap = val_loss - train_loss
if gap > 0.1: # 间隙过大
print(f"⚠️ 泛化间隙 {gap:.4f} 过大,可能过拟合")
print(f" 建议:加 Dropout / Weight Decay / 更多数据")
else:
print(f"✅ 泛化间隙 {gap:.4f} 正常")1.5 Python 与 PyTorch 速成
PyTorch 的核心三要素
| 概念 | 说明 | 关键代码 |
|---|---|---|
| Tensor | 多维数组,可在 GPU 上运算 | torch.tensor([1,2,3]) |
| Autograd | 自动微分,自动计算梯度 | x.requires_grad_() |
| nn.Module | 神经网络层的基类 | class MyNet(nn.Module) |
python
import torch
import torch.nn as nn
# === 自动微分示例 ===
x = torch.tensor([2.0], requires_grad=True) # 需要计算梯度
y = x ** 3 + 2 * x ** 2 + 1 # y = x³ + 2x² + 1
y.backward() # 自动计算 dy/dx
print(f"x=2 时, dy/dx = {x.grad.item()}") # 理论上 3*4+4*2 = 20
# === 构建一个简单的网络 ===
class TinyNet(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(10, 5) # 10 → 5
self.fc2 = nn.Linear(5, 1) # 5 → 1
def forward(self, x):
x = torch.relu(self.fc1(x)) # 激活函数
return self.fc2(x)
model = TinyNet()
print(f"模型参数总数: {sum(p.numel() for p in model.parameters())}")
# 输出: 10*5 + 5(偏置) + 5*1 + 1(偏置) = 61🧭 学习导航
← 上一阶段:math-foundations | 返回总览 | 下一阶段:classic-neural-networks →
登录后即可发表评论 👇