目录
- 第一部分:神经网络基础
- 第一章:绪论------深度学习的理论框架
- 第二章:前馈神经网络
- 第三章:反向传播与自动微分
- 第二部分:现代架构
- 第四章:卷积神经网络(CNN)
- 第五章:循环神经网络与序列建模
- 第六章:Transformer 与注意力机制
- 第三部分:训练理论
- 第七章:损失函数与优化目标
- 第八章:梯度下降与训练动力学
- 第九章:正则化与泛化
- 第四部分:理论分析
- 第十章:神经网络的表达能力
- 第十一章:优化景观与收敛性
- 第十二章:信息论视角
- 第五部分:前沿与代码
- 第十三章:生成模型
- 第十四章:自监督学习
- 第十五章:SSM 与深度学习
- 第十六章:完整可运行代码实现
- 附录
第一部分:神经网络基础
第一章:绪论------深度学习的理论框架
1.1 深度学习的核心问题
深度学习研究的核心问题是:
如何设计和训练多层非线性变换,使得机器能够从数据中自动学习有用的表示?
这个问题可以分解为三个子问题:
- 表示:用什么数学结构表示学习到的映射?
- 优化:如何高效地找到好的参数?
- 泛化:为什么学到的模型能在未见过的数据上工作?
1.2 深度学习的三大支柱
| 支柱 | 核心问题 | 理论工具 |
|---|---|---|
| 表示 | 网络架构设计 | 函数逼近论、微分几何 |
| 优化 | 参数学习 | 优化理论、动力系统 |
| 泛化 | 未见数据上的表现 | 统计学习理论、信息论 |
1.3 深度学习的历史脉络
| 年份 | 里程碑 | 贡献者 | 贡献 |
|---|---|---|---|
| 1943 | MCP 神经元 | McCulloch, Pitts | 第一个人工神经元模型 |
| 1958 | 感知机 | Rosenblatt | 单层神经网络 |
| 1969 | XOR 问题 | Minsky, Papert | 感知机的局限性 |
| 1986 | 反向传播 | Rumelhart, Hinton | 多层网络训练 |
| 1989 | CNN | LeCun | 卷积神经网络 |
| 1997 | LSTM | Hochreiter, Schmidhuber | 长短期记忆网络 |
| 2012 | AlexNet | Krizhevsky et al. | 深度 CNN 的突破 |
| 2014 | GAN | Goodfellow et al. | 生成对抗网络 |
| 2017 | Transformer | Vaswani et al. | 自注意力机制 |
| 2018 | BERT, GPT | Devlin et al., Radford et al. | 预训练语言模型 |
| 2020+ | 大语言模型 | OpenAI, Meta, Google | GPT-3, LLaMA, PaLM |
1.4 本文的组织
本文从神经网络的基本理论出发,逐步构建出现代深度学习的完整理论体系。我们特别关注:
- 反向传播的数学推导:梯度是如何计算的?
- Transformer 的理论基础:注意力机制的本质是什么?
- 训练动力学:为什么深度网络能被训练?
- 泛化理论:为什么过参数化的网络不过拟合?
第二章:前馈神经网络
2.1 单个神经元
2.1.1 线性模型
z=wTx+b=∑i=1dwixi+bz = w^T x + b = \sum_{i=1}^{d} w_i x_i + bz=wTx+b=i=1∑dwixi+b
其中 x∈Rdx \in \mathbb{R}^dx∈Rd 是输入,w∈Rdw \in \mathbb{R}^dw∈Rd 是权重,b∈Rb \in \mathbb{R}b∈R 是偏置。
2.1.2 激活函数
Sigmoid:
σ(z)=11+e−z\sigma(z) = \frac{1}{1 + e^{-z}}σ(z)=1+e−z1
σ′(z)=σ(z)(1−σ(z))\sigma'(z) = \sigma(z)(1 - \sigma(z))σ′(z)=σ(z)(1−σ(z))
Tanh:
tanh(z)=ez−e−zez+e−z\tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}}tanh(z)=ez+e−zez−e−z
tanh′(z)=1−tanh2(z)\tanh'(z) = 1 - \tanh^2(z)tanh′(z)=1−tanh2(z)
ReLU(Rectified Linear Unit):
ReLU(z)=max(0,z)\text{ReLU}(z) = \max(0, z)ReLU(z)=max(0,z)
ReLU′(z)={1z>00z<0\text{ReLU}'(z) = \begin{cases} 1 & z > 0 \\ 0 & z < 0 \end{cases}ReLU′(z)={10z>0z<0
Leaky ReLU:
LeakyReLU(z)={zz>0αzz≤0\text{LeakyReLU}(z) = \begin{cases} z & z > 0 \\ \alpha z & z \leq 0 \end{cases}LeakyReLU(z)={zαzz>0z≤0
GELU(Gaussian Error Linear Unit):
GELU(z)=z⋅Φ(z)≈z⋅σ(1.702z)\text{GELU}(z) = z \cdot \Phi(z) \approx z \cdot \sigma(1.702z)GELU(z)=z⋅Φ(z)≈z⋅σ(1.702z)
其中 Φ\PhiΦ 是标准正态分布的 CDF。
Swish:
Swish(z)=z⋅σ(βz)\text{Swish}(z) = z \cdot \sigma(\beta z)Swish(z)=z⋅σ(βz)
2.1.3 激活函数的选择
| 激活函数 | 优点 | 缺点 | 应用 |
|---|---|---|---|
| Sigmoid | 输出 (0,1),可解释为概率 | 梯度消失、非零中心 | 输出层(二分类) |
| Tanh | 零中心 | 梯度消失 | RNN |
| ReLU | 计算简单、缓解梯度消失 | 死亡 ReLU | CNN、MLP |
| GELU | 平滑、非单调 | 计算稍复杂 | Transformer |
2.2 多层感知机(MLP)
2.2.1 网络结构
LLL 层 MLP 的前向传播:
z(l)=W(l)a(l−1)+b(l)z^{(l)} = W^{(l)} a^{(l-1)} + b^{(l)}z(l)=W(l)a(l−1)+b(l)
a(l)=f(l)(z(l))a^{(l)} = f^{(l)}(z^{(l)})a(l)=f(l)(z(l))
其中 l=1,2,...,Ll = 1, 2, \dots, Ll=1,2,...,L,a(0)=xa^{(0)} = xa(0)=x 是输入。
2.2.2 万能逼近定理
定理 2.1(Cybenko, 1989; Hornik, 1991) :对于任意连续函数 g:0,1d→Rg: 0,1^d \to \mathbb{R}g:0,1d→R 和任意 ϵ>0\epsilon > 0ϵ>0,存在一个具有单个隐藏层的神经网络 fff,使得:
supx∈0,1d∣f(x)−g(x)∣<ϵ\sup_{x \in 0,1^d} |f(x) - g(x)| < \epsilonx∈0,1dsup∣f(x)−g(x)∣<ϵ
注意:这个定理只保证存在性,不保证网络大小或可训练性。
2.2.3 深度 vs 宽度
深度的优势:深度网络可以用指数级少的参数表示某些函数。
定理 2.2 :存在一类函数,深度为 kkk 的网络可以用 O(n)O(n)O(n) 个参数表示,但宽度为 1 的网络需要 O(nk)O(n^k)O(nk) 个参数。
2.3 参数初始化
2.3.1 为什么初始化很重要
- 太小的权重:信号逐层衰减(梯度消失)
- 太大的权重:信号逐层放大(梯度爆炸)
- 合适的初始化:保持信号的统计特性
2.3.2 Xavier/Glorot 初始化
动机:保持前向传播中激活值的方差稳定。
W∼N(0,2nin+nout)W \sim \mathcal{N}\left(0, \frac{2}{n_{\text{in}} + n_{\text{out}}}\right)W∼N(0,nin+nout2)
或均匀分布:
W∼U(−6nin+nout,6nin+nout)W \sim U\left(-\sqrt{\frac{6}{n_{\text{in}} + n_{\text{out}}}}, \sqrt{\frac{6}{n_{\text{in}} + n_{\text{out}}}}\right)W∼U(−nin+nout6 ,nin+nout6 )
2.3.3 He/Kaiming 初始化
动机:适用于 ReLU 激活函数。
W∼N(0,2nin)W \sim \mathcal{N}\left(0, \frac{2}{n_{\text{in}}}\right)W∼N(0,nin2)
2.3.4 正交初始化
WWW 是正交矩阵,保持梯度范数稳定。
第三章:反向传播与自动微分
3.1 计算图
3.1.1 定义
计算图是有向无环图(DAG),节点表示操作,边表示数据流。
例子 :f(x,y,z)=(x+y)⋅zf(x, y, z) = (x + y) \cdot zf(x,y,z)=(x+y)⋅z
x ---+
+--- q ---×--- f
y ---+ |
z
3.1.2 前向传播
沿着图的方向计算,从输入到输出。
3.1.3 反向传播
沿着图的反方向计算梯度,从输出到输入。
3.2 链式法则
3.2.1 单变量链式法则
dfdx=dfdu⋅dudx\frac{df}{dx} = \frac{df}{du} \cdot \frac{du}{dx}dxdf=dudf⋅dxdu
3.2.2 多变量链式法则
∂f∂xi=∑j∂f∂uj⋅∂uj∂xi\frac{\partial f}{\partial x_i} = \sum_j \frac{\partial f}{\partial u_j} \cdot \frac{\partial u_j}{\partial x_i}∂xi∂f=j∑∂uj∂f⋅∂xi∂uj
3.3 反向传播算法
3.3.1 符号定义
- z(l)z^{(l)}z(l):第 lll 层的线性输出
- a(l)a^{(l)}a(l):第 lll 层的激活输出
- δ(l)\delta^{(l)}δ(l):第 lll 层的误差项
3.3.2 前向传播
z(l)=W(l)a(l−1)+b(l)z^{(l)} = W^{(l)} a^{(l-1)} + b^{(l)}z(l)=W(l)a(l−1)+b(l)
a(l)=f(z(l))a^{(l)} = f(z^{(l)})a(l)=f(z(l))
3.3.3 反向传播
输出层误差:
δ(L)=∇aL⊙f′(z(L))\delta^{(L)} = \nabla_a \mathcal{L} \odot f'(z^{(L)})δ(L)=∇aL⊙f′(z(L))
隐藏层误差:
δ(l)=(W(l+1))Tδ(l+1)⊙f′(z(l))\delta^{(l)} = (W^{(l+1)})^T \delta^{(l+1)} \odot f'(z^{(l)})δ(l)=(W(l+1))Tδ(l+1)⊙f′(z(l))
梯度计算:
∂L∂W(l)=δ(l)(a(l−1))T\frac{\partial \mathcal{L}}{\partial W^{(l)}} = \delta^{(l)} (a^{(l-1)})^T∂W(l)∂L=δ(l)(a(l−1))T
∂L∂b(l)=δ(l)\frac{\partial \mathcal{L}}{\partial b^{(l)}} = \delta^{(l)}∂b(l)∂L=δ(l)
3.3.4 矩阵形式
对于整个 batch(mmm 个样本):
∂L∂W(l)=1mΔ(l)(A(l−1))T\frac{\partial \mathcal{L}}{\partial W^{(l)}} = \frac{1}{m} \Delta^{(l)} (A^{(l-1)})^T∂W(l)∂L=m1Δ(l)(A(l−1))T
∂L∂b(l)=1m∑i=1mδi(l)\frac{\partial \mathcal{L}}{\partial b^{(l)}} = \frac{1}{m} \sum_{i=1}^{m} \delta_i^{(l)}∂b(l)∂L=m1i=1∑mδi(l)
3.4 自动微分
3.4.1 前向模式
从输入到输出,逐个计算导数。
复杂度:O(n)O(n)O(n) 次前向传播(nnn 是输入维度)
3.4.2 反向模式
从输出到输入,一次性计算所有梯度。
复杂度:O(1)O(1)O(1) 次反向传播(与输入维度无关)
反向传播是反向模式自动微分的特例。
3.4.3 复杂度比较
| 模式 | 计算量 | 适用场景 |
|---|---|---|
| 前向模式 | O(n)O(n)O(n) 前向传播 | 输入维度小,输出维度大 |
| 反向模式 | O(1)O(1)O(1) 反向传播 | 输入维度大,输出维度小(如损失函数) |
深度学习中,参数维度很大(百万级),损失是标量,因此反向模式是最优选择。
第二部分:现代架构
第四章:卷积神经网络(CNN)
4.1 卷积操作
4.1.1 一维卷积
(x∗w)n=∑kxn+kwk(x * w)n = \sum_{k} xn+k wk(x∗w)n=k∑xn+kwk
4.1.2 二维卷积
(x∗w)i,j=∑m∑nxi+m,j+nwm,n(x * w)i,j = \sum_{m} \sum_{n} xi+m, j+n wm,n(x∗w)i,j=m∑n∑xi+m,j+nwm,n
4.1.3 卷积的性质
- 局部性:输出只依赖于输入的局部区域
- 平移等变性:输入平移,输出也平移
- 参数共享:同一个卷积核在整个输入上滑动
4.2 卷积层
4.2.1 多通道卷积
输入:X∈RCin×H×WX \in \mathbb{R}^{C_{\text{in}} \times H \times W}X∈RCin×H×W
卷积核:W∈RCout×Cin×KH×KWW \in \mathbb{R}^{C_{\text{out}} \times C_{\text{in}} \times K_H \times K_W}W∈RCout×Cin×KH×KW
输出:Y∈RCout×H′×W′Y \in \mathbb{R}^{C_{\text{out}} \times H' \times W'}Y∈RCout×H′×W′
Ycout,i,j=∑cin∑m,nXcin,i+m,j+nWcout,cin,m,n+bcoutYc_{\\text{out}}, i, j = \sum_{c_{\text{in}}} \sum_{m,n} Xc_{\\text{in}}, i+m, j+n Wc_{\\text{out}}, c_{\\text{in}}, m, n + bc_{\\text{out}}Ycout,i,j=cin∑m,n∑Xcin,i+m,j+nWcout,cin,m,n+bcout
4.2.2 输出尺寸计算
H′=H−KH+2PS+1H' = \frac{H - K_H + 2P}{S} + 1H′=SH−KH+2P+1
其中 KKK 是卷积核大小,PPP 是填充(padding),SSS 是步长(stride)。
4.2.3 感受野
感受野是输出特征图上一个点对应输入区域的大小。
第 lll 层的感受野:
RFl=RFl−1+(Kl−1)∏i=1l−1SiRF_l = RF_{l-1} + (K_l - 1) \prod_{i=1}^{l-1} S_iRFl=RFl−1+(Kl−1)i=1∏l−1Si
4.3 池化层
4.3.1 最大池化
Yi,j=maxm,nXi⋅S+m,j⋅S+nYi,j = \max_{m,n} Xi \\cdot S + m, j \\cdot S + nYi,j=m,nmaxXi⋅S+m,j⋅S+n
4.3.2 平均池化
Yi,j=1K2∑m,nXi⋅S+m,j⋅S+nYi,j = \frac{1}{K^2} \sum_{m,n} Xi \\cdot S + m, j \\cdot S + nYi,j=K21m,n∑Xi⋅S+m,j⋅S+n
4.3.3 全局平均池化
Yc=1H×W∑i,jXc,i,jYc = \frac{1}{H \times W} \sum_{i,j} Xc, i, jYc=H×W1i,j∑Xc,i,j
4.4 经典 CNN 架构
4.4.1 LeNet-5
输入(32×32) → Conv(6@5×5) → Pool → Conv(16@5×5) → Pool → FC(120) → FC(84) → FC(10)
4.4.2 AlexNet
- ReLU 激活函数
- Dropout 正则化
- 数据增强
- GPU 训练
4.4.3 VGGNet
- 使用 3×3 小卷积核
- 网络更深(16-19 层)
4.4.4 ResNet
残差连接:
y=F(x)+xy = F(x) + xy=F(x)+x
为什么有效:
- 缓解梯度消失
- 恒等映射容易学习
- 集成效果
第五章:循环神经网络与序列建模
5.1 基本 RNN
5.1.1 递推公式
ht=σ(Whht−1+Wxxt+b)h_t = \sigma(W_h h_{t-1} + W_x x_t + b)ht=σ(Whht−1+Wxxt+b)
yt=Wyht+byy_t = W_y h_t + b_yyt=Wyht+by
5.1.2 梯度消失/爆炸
∂hT∂h0=∏t=1T∂ht∂ht−1=∏t=1Tdiag(σ′(zt))Wh\frac{\partial h_T}{\partial h_0} = \prod_{t=1}^{T} \frac{\partial h_t}{\partial h_{t-1}} = \prod_{t=1}^{T} \text{diag}(\sigma'(z_t)) W_h∂h0∂hT=t=1∏T∂ht−1∂ht=t=1∏Tdiag(σ′(zt))Wh
当 ∥Wh∥>1\|W_h\| > 1∥Wh∥>1 时梯度爆炸,∥Wh∥<1\|W_h\| < 1∥Wh∥<1 时梯度消失。
5.2 LSTM
5.2.1 门控机制
ft=σ(Wfht−1,xt+bf)(遗忘门)f_t = \sigma(W_f h_{t-1}, x_t + b_f) \quad \text{(遗忘门)}ft=σ(Wfht−1,xt+bf)(遗忘门)
it=σ(Wiht−1,xt+bi)(输入门)i_t = \sigma(W_i h_{t-1}, x_t + b_i) \quad \text{(输入门)}it=σ(Wiht−1,xt+bi)(输入门)
c~t=tanh(Wcht−1,xt+bc)(候选)\tilde{c}_t = \tanh(W_c h_{t-1}, x_t + b_c) \quad \text{(候选)}c~t=tanh(Wcht−1,xt+bc)(候选)
ct=ft⊙ct−1+it⊙c~t(细胞状态)c_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t \quad \text{(细胞状态)}ct=ft⊙ct−1+it⊙c~t(细胞状态)
ot=σ(Woht−1,xt+bo)(输出门)o_t = \sigma(W_o h_{t-1}, x_t + b_o) \quad \text{(输出门)}ot=σ(Woht−1,xt+bo)(输出门)
ht=ot⊙tanh(ct)h_t = o_t \odot \tanh(c_t)ht=ot⊙tanh(ct)
5.2.2 为什么 LSTM 缓解梯度消失
细胞状态 ctc_tct 的递推是线性的:
ct=ft⊙ct−1+it⊙c~tc_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_tct=ft⊙ct−1+it⊙c~t
当 ft≈1f_t \approx 1ft≈1 时,梯度可以无损传递。
5.3 GRU
zt=σ(Wzht−1,xt)(更新门)z_t = \sigma(W_z h_{t-1}, x_t) \quad \text{(更新门)}zt=σ(Wzht−1,xt)(更新门)
rt=σ(Wrht−1,xt)(重置门)r_t = \sigma(W_r h_{t-1}, x_t) \quad \text{(重置门)}rt=σ(Wrht−1,xt)(重置门)
h~t=tanh(Wrt⊙ht−1,xt)\tilde{h}_t = \tanh(W r_t \\odot h_{t-1}, x_t)h~t=tanh(Wrt⊙ht−1,xt)
ht=(1−zt)⊙ht−1+zt⊙h~th_t = (1 - z_t) \odot h_{t-1} + z_t \odot \tilde{h}_tht=(1−zt)⊙ht−1+zt⊙h~t
5.4 双向 RNN
h→t=f(h→t−1,xt)\overrightarrow{h}t = f(\overrightarrow{h}{t-1}, x_t)h t=f(h t−1,xt)
h←t=f(h←t+1,xt)\overleftarrow{h}t = f(\overleftarrow{h}{t+1}, x_t)h t=f(h t+1,xt)
ht=h→t;h←th_t = \\overrightarrow{h}_t; \\overleftarrow{h}_tht=h t;h t
第六章:Transformer 与注意力机制
6.1 自注意力机制
6.1.1 缩放点积注意力
Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)VAttention(Q,K,V)=softmax(dk QKT)V
其中:
- Q=XWQQ = XW^QQ=XWQ:查询矩阵
- K=XWKK = XW^KK=XWK:键矩阵
- V=XWVV = XW^VV=XWV:值矩阵
6.1.2 为什么要缩放
假设 q,kq, kq,k 的元素独立,均值为 0,方差为 1,则 qTkq^T kqTk 的方差为 dkd_kdk。
当 dkd_kdk 很大时,qTkq^T kqTk 的值很大,softmax 会变得很尖锐(梯度很小)。
除以 dk\sqrt{d_k}dk 使得方差保持为 1。
6.1.3 多头注意力
MultiHead(Q,K,V)=Concat(head1,...,headh)WO\text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \dots, \text{head}_h) W^OMultiHead(Q,K,V)=Concat(head1,...,headh)WO
headi=Attention(QWiQ,KWiK,VWiV)\text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)headi=Attention(QWiQ,KWiK,VWiV)
优势:不同的头可以关注不同类型的信息。
6.2 位置编码
6.2.1 为什么需要位置编码
自注意力是置换等变的------打乱输入顺序,输出也相应打乱。
位置编码打破这种对称性,注入位置信息。
6.2.2 正弦位置编码
PE(pos,2i)=sin(pos/100002i/d)PE_{(pos, 2i)} = \sin(pos / 10000^{2i/d})PE(pos,2i)=sin(pos/100002i/d)
PE(pos,2i+1)=cos(pos/100002i/d)PE_{(pos, 2i+1)} = \cos(pos / 10000^{2i/d})PE(pos,2i+1)=cos(pos/100002i/d)
性质:
- PEpos+kPE_{pos+k}PEpos+k 可以表示为 PEposPE_{pos}PEpos 的线性函数
- 不同位置的内积只依赖于相对距离
6.2.3 可学习位置编码
PE=Embedding(pos)PE = \text{Embedding}(pos)PE=Embedding(pos)
直接学习每个位置的嵌入向量。
6.2.4 RoPE(旋转位置编码)
qm=Rmq,kn=Rnkq_m = R_m q, \quad k_n = R_n kqm=Rmq,kn=Rnk
qmTkn=qTRmTRnk=qTRn−mkq_m^T k_n = q^T R_m^T R_n k = q^T R_{n-m} kqmTkn=qTRmTRnk=qTRn−mk
其中 RmR_mRm 是旋转矩阵。内积只依赖于相对位置 n−mn-mn−m。
6.3 Transformer 架构
6.3.1 编码器层
FFN(x)=ReLU(xW1+b1)W2+b2\text{FFN}(x) = \text{ReLU}(xW_1 + b_1)W_2 + b_2FFN(x)=ReLU(xW1+b1)W2+b2
EncoderLayer(x)=LayerNorm(x+FFN(LayerNorm(x+MultiHead(x,x,x))))\text{EncoderLayer}(x) = \text{LayerNorm}(x + \text{FFN}(\text{LayerNorm}(x + \text{MultiHead}(x, x, x))))EncoderLayer(x)=LayerNorm(x+FFN(LayerNorm(x+MultiHead(x,x,x))))
6.3.2 解码器层
解码器额外包含:
- 掩码自注意力(防止看到未来)
- 交叉注意力(关注编码器输出)
6.3.3 层归一化
LayerNorm(x)=γ⊙x−μσ2+ϵ+β\text{LayerNorm}(x) = \gamma \odot \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} + \betaLayerNorm(x)=γ⊙σ2+ϵ x−μ+β
其中 μ,σ2\mu, \sigma^2μ,σ2 是在特征维度上计算的均值和方差。
6.4 Transformer 的理论分析
6.4.1 计算复杂度
自注意力:O(n2d)O(n^2 d)O(n2d)(时间和空间)
6.4.2 表达能力
定理 6.1:Transformer 是通用逼近器------足够多层的 Transformer 可以逼近任何序列到序列的连续映射。
6.4.3 位置信息的编码
Transformer 本身不包含位置信息,需要通过位置编码注入。
第三部分:训练理论
第七章:损失函数与优化目标
7.1 回归损失
7.1.1 均方误差(MSE)
LMSE=1n∑i=1n(yi−y^i)2\mathcal{L}{MSE} = \frac{1}{n} \sum{i=1}^{n} (y_i - \hat{y}_i)^2LMSE=n1i=1∑n(yi−y^i)2
概率解释 :假设 y∼N(y^,σ2)y \sim \mathcal{N}(\hat{y}, \sigma^2)y∼N(y^,σ2),MSE 等价于负对数似然。
7.1.2 平均绝对误差(MAE)
LMAE=1n∑i=1n∣yi−y^i∣\mathcal{L}{MAE} = \frac{1}{n} \sum{i=1}^{n} |y_i - \hat{y}_i|LMAE=n1i=1∑n∣yi−y^i∣
概率解释 :假设 yyy 服从 Laplace 分布。
7.1.3 Huber 损失
LHuber={12(y−y^)2∣y−y^∣≤δδ∣y−y^∣−12δ2∣y−y^∣>δ\mathcal{L}_{Huber} = \begin{cases} \frac{1}{2}(y - \hat{y})^2 & |y - \hat{y}| \leq \delta \\ \delta|y - \hat{y}| - \frac{1}{2}\delta^2 & |y - \hat{y}| > \delta \end{cases}LHuber={21(y−y^)2δ∣y−y^∣−21δ2∣y−y^∣≤δ∣y−y^∣>δ
结合 MSE 和 MAE 的优点。
7.2 分类损失
7.2.1 二元交叉熵
LBCE=−1n∑i=1nyilogy\^i+(1−yi)log(1−y\^i)\mathcal{L}{BCE} = -\frac{1}{n} \sum{i=1}^{n} y_i \\log \\hat{y}_i + (1-y_i) \\log(1-\\hat{y}_i)LBCE=−n1i=1∑nyilogy\^i+(1−yi)log(1−y\^i)
概率解释 :假设 y∼Bernoulli(y^)y \sim \text{Bernoulli}(\hat{y})y∼Bernoulli(y^)。
7.2.2 多类交叉熵
LCE=−1n∑i=1n∑k=1Kyiklogy^ik\mathcal{L}{CE} = -\frac{1}{n} \sum{i=1}^{n} \sum_{k=1}^{K} y_{ik} \log \hat{y}_{ik}LCE=−n1i=1∑nk=1∑Kyiklogy^ik
其中 yiky_{ik}yik 是 one-hot 编码。
概率解释 :假设 y∼Categorical(y^)y \sim \text{Categorical}(\hat{y})y∼Categorical(y^)。
7.2.3 Softmax
y^k=ezk∑jezj\hat{y}_k = \frac{e^{z_k}}{\sum_j e^{z_j}}y^k=∑jezjezk
数值稳定版本:
y^k=ezk−max(z)∑jezj−max(z)\hat{y}_k = \frac{e^{z_k - \max(z)}}{\sum_j e^{z_j - \max(z)}}y^k=∑jezj−max(z)ezk−max(z)
7.2.4 Focal Loss
LFocal=−1n∑i=1n(1−y^i)γyilogy^i\mathcal{L}{Focal} = -\frac{1}{n} \sum{i=1}^{n} (1 - \hat{y}_i)^\gamma y_i \log \hat{y}_iLFocal=−n1i=1∑n(1−y^i)γyilogy^i
用于处理类别不平衡问题。
7.3 对比损失
7.3.1 InfoNCE
LInfoNCE=−logexp(sim(zi,zj)/τ)∑k=1Nexp(sim(zi,zk)/τ)\mathcal{L}{InfoNCE} = -\log \frac{\exp(\text{sim}(z_i, z_j)/\tau)}{\sum{k=1}^{N} \exp(\text{sim}(z_i, z_k)/\tau)}LInfoNCE=−log∑k=1Nexp(sim(zi,zk)/τ)exp(sim(zi,zj)/τ)
用于自监督学习中的对比学习。
第八章:梯度下降与训练动力学
8.1 随机梯度下降(SGD)
θt+1=θt−η∇θL(θt;xi)\theta_{t+1} = \theta_t - \eta \nabla_\theta \mathcal{L}(\theta_t; x_i)θt+1=θt−η∇θL(θt;xi)
8.1.1 小批量 SGD
θt+1=θt−η1∣B∣∑i∈B∇θL(θt;xi)\theta_{t+1} = \theta_t - \eta \frac{1}{|B|} \sum_{i \in B} \nabla_\theta \mathcal{L}(\theta_t; x_i)θt+1=θt−η∣B∣1i∈B∑∇θL(θt;xi)
8.1.2 收敛性
凸函数 :O(1/T)O(1/\sqrt{T})O(1/T ) 收敛速度
强凸函数 :O(1/T)O(1/T)O(1/T) 收敛速度
8.2 动量方法
8.2.1 Polyak 动量
vt+1=μvt+∇θL(θt)v_{t+1} = \mu v_t + \nabla_\theta \mathcal{L}(\theta_t)vt+1=μvt+∇θL(θt)
θt+1=θt−ηvt+1\theta_{t+1} = \theta_t - \eta v_{t+1}θt+1=θt−ηvt+1
8.2.2 Nesterov 动量
vt+1=μvt+∇θL(θt−ημvt)v_{t+1} = \mu v_t + \nabla_\theta \mathcal{L}(\theta_t - \eta \mu v_t)vt+1=μvt+∇θL(θt−ημvt)
θt+1=θt−ηvt+1\theta_{t+1} = \theta_t - \eta v_{t+1}θt+1=θt−ηvt+1
8.3 自适应学习率
8.3.1 Adam
mt=β1mt−1+(1−β1)gtm_t = \beta_1 m_{t-1} + (1-\beta_1) g_tmt=β1mt−1+(1−β1)gt
vt=β2vt−1+(1−β2)gt2v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2vt=β2vt−1+(1−β2)gt2
m^t=mt1−β1t,v^t=vt1−β2t\hat{m}_t = \frac{m_t}{1-\beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1-\beta_2^t}m^t=1−β1tmt,v^t=1−β2tvt
θt+1=θt−ηv^t+ϵm^t\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_tθt+1=θt−v^t +ϵηm^t
8.3.2 AdamW
θt+1=θt−η(m^tv^t+ϵ+λθt)\theta_{t+1} = \theta_t - \eta \left(\frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} + \lambda \theta_t\right)θt+1=θt−η(v^t +ϵm^t+λθt)
权重衰减与梯度更新解耦。
8.4 学习率调度
8.4.1 余弦退火
ηt=ηmin+ηmax−ηmin2(1+cos(πtT))\eta_t = \eta_{min} + \frac{\eta_{max} - \eta_{min}}{2} \left(1 + \cos\left(\frac{\pi t}{T}\right)\right)ηt=ηmin+2ηmax−ηmin(1+cos(Tπt))
8.4.2 预热
ηt=ηmax⋅tTwarmup,t≤Twarmup\eta_t = \eta_{max} \cdot \frac{t}{T_{warmup}}, \quad t \leq T_{warmup}ηt=ηmax⋅Twarmupt,t≤Twarmup
8.5 梯度裁剪
8.5.1 按范数裁剪
g←{g∥g∥≤ττg∥g∥∥g∥>τg \leftarrow \begin{cases} g & \|g\| \leq \tau \\ \tau \frac{g}{\|g\|} & \|g\| > \tau \end{cases}g←{gτ∥g∥g∥g∥≤τ∥g∥>τ
8.5.2 按值裁剪
gi←clip(gi,−τ,τ)g_i \leftarrow \text{clip}(g_i, -\tau, \tau)gi←clip(gi,−τ,τ)
第九章:正则化与泛化
9.1 权重衰减(ℓ2\ell_2ℓ2 正则化)
Lreg=L+λ2∥θ∥22\mathcal{L}_{reg} = \mathcal{L} + \frac{\lambda}{2} \|\theta\|_2^2Lreg=L+2λ∥θ∥22
效果:
- 限制参数大小
- 隐式地减小学习率
- 偏好"平坦"的最小值
9.2 Dropout
9.2.1 训练时
a^=a⊙m,mi∼Bernoulli(1−p)\hat{a} = a \odot m, \quad m_i \sim \text{Bernoulli}(1-p)a^=a⊙m,mi∼Bernoulli(1−p)
9.2.2 推理时
a^=(1−p)⋅a\hat{a} = (1-p) \cdot aa^=(1−p)⋅a
9.2.3 为什么 Dropout 有效
- 集成效果:等价于训练 2n2^n2n 个子网络
- 减少神经元之间的共适应
- 噪声注入的正则化效果
9.3 数据增强
9.3.1 图像增强
- 随机裁剪
- 水平翻转
- 颜色抖动
- 随机擦除
9.3.2 Mixup
x~=λxi+(1−λ)xj\tilde{x} = \lambda x_i + (1-\lambda) x_jx~=λxi+(1−λ)xj
y~=λyi+(1−λ)yj\tilde{y} = \lambda y_i + (1-\lambda) y_jy~=λyi+(1−λ)yj
其中 λ∼Beta(α,α)\lambda \sim \text{Beta}(\alpha, \alpha)λ∼Beta(α,α)。
9.4 批归一化(Batch Normalization)
9.4.1 训练时
x^i=xi−μBσB2+ϵ\hat{x}_i = \frac{x_i - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}}x^i=σB2+ϵ xi−μB
yi=γx^i+βy_i = \gamma \hat{x}_i + \betayi=γx^i+β
9.4.2 推理时
使用训练时的移动平均:
x^=x−ExVarx+ϵ\hat{x} = \frac{x - \mathbb{E}x}{\sqrt{\text{Var}x + \epsilon}}x^=Varx+ϵ x−Ex
9.4.3 为什么 BatchNorm 有效
- 减少内部协变量偏移
- 允许使用更大的学习率
- 具有正则化效果
第四部分:理论分析
第十章:神经网络的表达能力
10.1 万能逼近定理
10.1.1 Cybenko 定理(1989)
定理 10.1 :对于任意连续函数 f:0,1d→Rf: 0,1^d \to \mathbb{R}f:0,1d→R 和任意 ϵ>0\epsilon > 0ϵ>0,存在一个具有单个隐藏层的神经网络:
g(x)=∑i=1Nαiσ(wiTx+bi)g(x) = \sum_{i=1}^{N} \alpha_i \sigma(w_i^T x + b_i)g(x)=i=1∑Nαiσ(wiTx+bi)
使得 supx∣f(x)−g(x)∣<ϵ\sup_x |f(x) - g(x)| < \epsilonsupx∣f(x)−g(x)∣<ϵ。
10.1.2 定理的局限
- 只保证存在性,不保证 NNN 的大小
- 不保证可以通过梯度下降找到
- 不保证泛化能力
10.2 深度网络的优势
10.2.1 指数级效率
定理 10.2 :存在一类函数,深度为 O(k)O(k)O(k) 的网络可以用 O(n)O(n)O(n) 个参数表示,但深度为 O(1)O(1)O(1) 的网络需要 O(nk)O(n^k)O(nk) 个参数。
10.2.2 层次化特征
深度网络自然地学习层次化表示:
- 底层:边缘、纹理
- 中层:部件、模式
- 高层:语义、概念
10.3 神经正切核(NTK)
10.3.1 定义
神经正切核定义为:
K(x,x′)=⟨∇θf(x;θ),∇θf(x′;θ)⟩K(x, x') = \langle \nabla_\theta f(x; \theta), \nabla_\theta f(x'; \theta) \rangleK(x,x′)=⟨∇θf(x;θ),∇θf(x′;θ)⟩
10.3.2 无限宽度极限
当网络宽度趋于无穷时,NTK 在训练过程中保持不变:
K(x,x′)=K0(x,x′)K(x, x') = K_0(x, x')K(x,x′)=K0(x,x′)
这使得训练动力学变为线性:
f(x;θt)=f(x;θ0)+K(x,X)(K(X,X)+λI)−1(y−f(X;θ0))f(x; \theta_t) = f(x; \theta_0) + K(x, X) (K(X, X) + \lambda I)^{-1} (y - f(X; \theta_0))f(x;θt)=f(x;θ0)+K(x,X)(K(X,X)+λI)−1(y−f(X;θ0))
第十一章:优化景观与收敛性
11.1 损失景观
11.1.1 非凸性
深度网络的损失函数是高度非凸的,存在大量局部最小值和鞍点。
11.1.2 鞍点问题
在高维空间中,鞍点比局部最小值更常见。
逃离鞍点:SGD 的噪声天然帮助逃离鞍点。
11.2 线性化分析
12.2.1 动力学均场理论
在无限宽度极限下,网络的动力学可以用动力学均场理论(DMFT)描述。
11.2.2 信号传播
前向信号传播:
Varz(l)=σw2Vara(l−1)\text{Var}z\^{(l)} = \sigma_w^2 \text{Var}a\^{(l-1)}Varz(l)=σw2Vara(l−1)
反向信号传播:
Varδ(l)=σw2Varδ(l+1)\text{Var}\\delta\^{(l)} = \sigma_w^2 \text{Var}\\delta\^{(l+1)}Varδ(l)=σw2Varδ(l+1)
11.3 梯度下降的收敛性
11.3.1 NTK regime
在过参数化 regime 中,梯度下降收敛到全局最优:
L(θt)≤(1−ηλmin2)tL(θ0)\mathcal{L}(\theta_t) \leq \left(1 - \frac{\eta \lambda_{min}}{2}\right)^t \mathcal{L}(\theta_0)L(θt)≤(1−2ηλmin)tL(θ0)
11.3.2 收敛速度
收敛速度取决于 NTK 的最小特征值 λmin\lambda_{min}λmin。
第十二章:信息论视角
12.1 信息瓶颈
12.1.1 信息瓶颈原理
深度网络的每一层都在做信息压缩:
minTI(X;T)−βI(T;Y)\min_{T} I(X; T) - \beta I(T; Y)TminI(X;T)−βI(T;Y)
其中 TTT 是中间表示,III 是互信息。
12.1.2 两个阶段
- 拟合阶段 :I(T;Y)I(T; Y)I(T;Y) 增加
- 压缩阶段 :I(X;T)I(X; T)I(X;T) 减少
12.2 PAC-Bayes 界
12.2.1 基本形式
Eθ∼QL(θ)≤Eθ∼QL\^(θ)+KL(Q∥P)+ln(n/δ)2n\mathbb{E}{\theta \sim Q}\\mathcal{L}(\\theta) \leq \mathbb{E}{\theta \sim Q}\\hat{\\mathcal{L}}(\\theta) + \sqrt{\frac{KL(Q \| P) + \ln(n/\delta)}{2n}}Eθ∼QL(θ)≤Eθ∼QL\^(θ)+2nKL(Q∥P)+ln(n/δ)
12.2.2 应用到深度学习
- PPP:先验分布(如初始化分布)
- QQQ:后验分布(如训练后的参数分布)
- KL(Q∥P)KL(Q \| P)KL(Q∥P):复杂度惩罚
12.3 最小描述长度(MDL)
12.3.1 原理
好的模型应该同时:
- 拟合数据(小的误差)
- 简单(短的描述长度)
MDL=L(θ)+12logn⋅dof\text{MDL} = \mathcal{L}(\theta) + \frac{1}{2} \log n \cdot \text{dof}MDL=L(θ)+21logn⋅dof
第五部分:前沿与代码
第十三章:生成模型
13.1 变分自编码器(VAE)
13.1.1 模型结构
编码器 :qϕ(z∣x)q_\phi(z|x)qϕ(z∣x)(近似后验)
解码器 :pθ(x∣z)p_\theta(x|z)pθ(x∣z)(生成模型)
13.1.2 ELBO(证据下界)
logp(x)≥Eqϕ(z∣x)logpθ(x∣z)−KL(qϕ(z∣x)∥p(z))\log p(x) \geq \mathbb{E}{q\phi(z|x)}\\log p_\\theta(x\|z) - KL(q_\phi(z|x) \| p(z))logp(x)≥Eqϕ(z∣x)logpθ(x∣z)−KL(qϕ(z∣x)∥p(z))
13.1.3 重参数化技巧
z=μ+σ⊙ϵ,ϵ∼N(0,I)z = \mu + \sigma \odot \epsilon, \quad \epsilon \sim \mathcal{N}(0, I)z=μ+σ⊙ϵ,ϵ∼N(0,I)
使得采样操作可微。
13.2 生成对抗网络(GAN)
13.2.1 博弈目标
minGmaxDV(D,G)=Ex∼pdatalogD(x)+Ez∼pzlog(1−D(G(z)))\min_G \max_D V(D, G) = \mathbb{E}{x \sim p{data}}\\log D(x) + \mathbb{E}_{z \sim p_z}\\log(1 - D(G(z)))GminDmaxV(D,G)=Ex∼pdatalogD(x)+Ez∼pzlog(1−D(G(z)))
13.2.2 纳什均衡
在最优判别器下,最小化:
minGL(G)=2JS(pdata∥pg)−log4\min_G \mathcal{L}(G) = 2 JS(p_{data} \| p_g) - \log 4GminL(G)=2JS(pdata∥pg)−log4
13.2.3 训练不稳定性
- 模式崩溃
- 梯度消失
- 训练不稳定
解决方案:WGAN、Spectral Normalization、Progressive Training
13.3 扩散模型
13.3.1 前向过程
q(xt∣xt−1)=N(xt;1−βtxt−1,βtI)q(x_t | x_{t-1}) = \mathcal{N}(x_t; \sqrt{1-\beta_t} x_{t-1}, \beta_t I)q(xt∣xt−1)=N(xt;1−βt xt−1,βtI)
13.3.2 反向过程
pθ(xt−1∣xt)=N(xt−1;μθ(xt,t),σt2I)p_\theta(x_{t-1} | x_t) = \mathcal{N}(x_{t-1}; \mu_\theta(x_t, t), \sigma_t^2 I)pθ(xt−1∣xt)=N(xt−1;μθ(xt,t),σt2I)
13.3.3 训练目标
L=Et,x0,ϵ∥ϵ−ϵθ(xt,t)∥2\mathcal{L} = \mathbb{E}_{t, x_0, \epsilon} \left\\\|\\epsilon - \\epsilon_\\theta(x_t, t)\\\|\^2\\rightL=Et,x0,ϵ∥ϵ−ϵθ(xt,t)∥2
第十四章:自监督学习
14.1 对比学习
14.1.1 SimCLR
L=−logexp(sim(zi,zj)/τ)∑k=12N1k≠iexp(sim(zi,zk)/τ)\mathcal{L} = -\log \frac{\exp(\text{sim}(z_i, z_j)/\tau)}{\sum_{k=1}^{2N} \mathbb{1}_{k \neq i} \exp(\text{sim}(z_i, z_k)/\tau)}L=−log∑k=12N1k=iexp(sim(zi,zk)/τ)exp(sim(zi,zj)/τ)
14.1.2 MoCo
使用动量编码器和队列维护负样本。
14.2 掩码预测
14.2.1 BERT
随机遮盖 15% 的 token,预测被遮盖的 token。
14.2.2 MAE(Masked Autoencoder)
随机遮盖 75% 的图像 patches,重建被遮盖的 patches。
14.3 自蒸馏
14.3.1 BYOL
不需要负样本的自监督学习。
14.3.2 DINO
使用自蒸馏进行视觉表示学习。
第十五章:SSM 与深度学习
15.1 SSM 的深度学习视角
15.1.1 SSM 作为 RNN
ht=Aˉht−1+Bˉxth_t = \bar{A} h_{t-1} + \bar{B} x_tht=Aˉht−1+Bˉxt
yt=Chty_t = C h_tyt=Cht
SSM 可以看作一种特殊的 RNN,其中:
- 状态转移是线性的(没有非线性激活)
- 参数在时间上共享
15.1.2 SSM 作为 CNN
y=K∗xy = K * xy=K∗x
其中 Kn=CAˉnBˉK_n = C \bar{A}^n \bar{B}Kn=CAˉnBˉ 是卷积核。
SSM 在训练时可以表示为卷积操作。
15.1.3 SSM 与 Transformer 的对偶性
Mamba-2 发现了 SSM 与注意力机制之间的对偶性。
15.2 SSM 的优势
15.2.1 线性复杂度
SSM 的计算复杂度是 O(n)O(n)O(n),而 Transformer 是 O(n2)O(n^2)O(n2)。
15.2.2 长程依赖
HiPPO 理论保证了 SSM 可以有效地建模长程依赖。
15.2.3 流式处理
SSM 的递推模式天然支持流式处理。
15.3 SSM 的局限
15.3.1 固定衰减
LTI-SSM 的衰减模式是固定的,不依赖于输入内容。
15.3.2 选择性机制
Mamba 通过选择性机制(输入依赖的 Δ\DeltaΔ, BBB, CCC)解决了这个问题。
第十六章:完整可运行代码实现
16.1 前馈神经网络
python
"""
前馈神经网络的完整实现。
包含: 前向传播、反向传播、训练循环。
"""
import numpy as np
class Layer:
"""神经网络层的基类。"""
def forward(self, x):
raise NotImplementedError
def backward(self, grad_output):
raise NotImplementedError
class Linear(Layer):
"""线性层 (全连接层)。"""
def __init__(self, in_features, out_features):
self.W = np.random.randn(in_features, out_features) * np.sqrt(2.0 / in_features)
self.b = np.zeros(out_features)
self.x = None
self.dW = None
self.db = None
def forward(self, x):
self.x = x
return x @ self.W + self.b
def backward(self, grad_output):
self.dW = self.x.T @ grad_output / len(self.x)
self.db = np.mean(grad_output, axis=0)
return grad_output @ self.W.T
class ReLU(Layer):
"""ReLU 激活函数。"""
def __init__(self):
self.mask = None
def forward(self, x):
self.mask = (x > 0).astype(float)
return x * self.mask
def backward(self, grad_output):
return grad_output * self.mask
class Sigmoid(Layer):
"""Sigmoid 激活函数。"""
def __init__(self):
self.out = None
def forward(self, x):
self.out = 1 / (1 + np.exp(-np.clip(x, -500, 500)))
return self.out
def backward(self, grad_output):
return grad_output * self.out * (1 - self.out)
class MSELoss:
"""均方误差损失。"""
def forward(self, y_pred, y_true):
self.y_pred = y_pred
self.y_true = y_true
return np.mean((y_pred - y_true)**2)
def backward(self):
return 2 * (self.y_pred - self.y_true) / len(self.y_true)
class CrossEntropyLoss:
"""交叉熵损失。"""
def forward(self, logits, targets):
self.targets = targets
# Softmax
exp_logits = np.exp(logits - np.max(logits, axis=1, keepdims=True))
self.probs = exp_logits / np.sum(exp_logits, axis=1, keepdims=True)
# 交叉熵
n = len(targets)
log_probs = np.log(self.probs + 1e-10)
loss = -np.sum(log_probs[np.arange(n), targets]) / n
return loss
def backward(self):
n = len(self.targets)
grad = self.probs.copy()
grad[np.arange(n), self.targets] -= 1
return grad / n
class MLP:
"""多层感知机。"""
def __init__(self, layer_sizes):
self.layers = []
for i in range(len(layer_sizes) - 1):
self.layers.append(Linear(layer_sizes[i], layer_sizes[i+1]))
if i < len(layer_sizes) - 2: # 最后一层不加激活函数
self.layers.append(ReLU())
def forward(self, x):
for layer in self.layers:
x = layer.forward(x)
return x
def backward(self, grad):
for layer in reversed(self.layers):
grad = layer.backward(grad)
def update(self, lr):
for layer in self.layers:
if hasattr(layer, 'W'):
layer.W -= lr * layer.dW
layer.b -= lr * layer.db
def demonstrate_mlp():
"""演示 MLP 训练。"""
print("=" * 60)
print("多层感知机演示")
print("=" * 60)
np.random.seed(42)
# 生成数据 (XOR 问题)
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([0, 1, 1, 0])
# 创建模型
model = MLP([2, 8, 8, 2])
criterion = CrossEntropyLoss()
print(f"\n模型结构: 2 -> 8 -> 8 -> 2")
print(f"训练样本: {len(X)}")
# 训练
lr = 0.1
for epoch in range(1000):
# 前向传播
logits = model.forward(X)
loss = criterion.forward(logits, y)
# 反向传播
grad = criterion.backward()
model.backward(grad)
# 更新
model.update(lr)
if (epoch + 1) % 200 == 0:
print(f" Epoch {epoch+1}: loss = {loss:.4f}")
# 测试
logits = model.forward(X)
preds = np.argmax(logits, axis=1)
accuracy = np.mean(preds == y)
print(f"\n测试结果:")
print(f" 预测: {preds}")
print(f" 真实: {y}")
print(f" 准确率: {accuracy:.2%}")
if __name__ == "__main__":
demonstrate_mlp()
16.2 Transformer 注意力
python
"""
Transformer 注意力机制的完整实现。
包含: 自注意力、多头注意力、位置编码。
"""
import numpy as np
def softmax(x, axis=-1):
"""数值稳定的 softmax。"""
exp_x = np.exp(x - np.max(x, axis=axis, keepdims=True))
return exp_x / np.sum(exp_x, axis=axis, keepdims=True)
def scaled_dot_product_attention(Q, K, V, mask=None):
"""缩放点积注意力。
Args:
Q: (batch, n_q, d_k)
K: (batch, n_k, d_k)
V: (batch, n_k, d_v)
mask: (batch, n_q, n_k) 或 None
Returns:
output: (batch, n_q, d_v)
weights: (batch, n_q, n_k)
"""
d_k = Q.shape[-1]
scores = Q @ K.transpose(0, 2, 1) / np.sqrt(d_k)
if mask is not None:
scores = np.where(mask, scores, -1e9)
weights = softmax(scores, axis=-1)
output = weights @ V
return output, weights
class MultiHeadAttention:
"""多头注意力。"""
def __init__(self, d_model, num_heads):
self.d_model = d_model
self.num_heads = num_heads
self.d_k = d_model // num_heads
# 初始化权重
scale = np.sqrt(2.0 / d_model)
self.W_Q = np.random.randn(d_model, d_model) * scale
self.W_K = np.random.randn(d_model, d_model) * scale
self.W_V = np.random.randn(d_model, d_model) * scale
self.W_O = np.random.randn(d_model, d_model) * scale
def split_heads(self, x):
"""将最后一维分成多个头。"""
batch_size, seq_len, _ = x.shape
x = x.reshape(batch_size, seq_len, self.num_heads, self.d_k)
return x.transpose(0, 2, 1, 3) # (batch, heads, seq, d_k)
def combine_heads(self, x):
"""合并多个头。"""
batch_size, _, seq_len, _ = x.shape
x = x.transpose(0, 2, 1, 3) # (batch, seq, heads, d_k)
return x.reshape(batch_size, seq_len, self.d_model)
def forward(self, Q, K, V, mask=None):
"""
Args:
Q, K, V: (batch, seq_len, d_model)
mask: 掩码
Returns:
output: (batch, seq_len, d_model)
"""
# 线性变换
Q = Q @ self.W_Q
K = K @ self.W_K
V = V @ self.W_V
# 分头
Q = self.split_heads(Q)
K = self.split_heads(K)
V = self.split_heads(V)
# 注意力计算
output, weights = scaled_dot_product_attention(Q, K, V, mask)
# 合并头
output = self.combine_heads(output)
# 输出投影
output = output @ self.W_O
return output, weights
def sinusoidal_position_encoding(max_len, d_model):
"""正弦位置编码。"""
PE = np.zeros((max_len, d_model))
position = np.arange(max_len)[:, None]
div_term = np.exp(np.arange(0, d_model, 2) * -(np.log(10000.0) / d_model))
PE[:, 0::2] = np.sin(position * div_term)
PE[:, 1::2] = np.cos(position * div_term)
return PE
def demonstrate_attention():
"""演示注意力机制。"""
print("=" * 60)
print("Transformer 注意力演示")
print("=" * 60)
np.random.seed(42)
# 参数
batch_size = 2
seq_len = 10
d_model = 64
num_heads = 8
# 创建输入
x = np.random.randn(batch_size, seq_len, d_model)
# 位置编码
PE = sinusoidal_position_encoding(seq_len, d_model)
x = x + PE
# 多头注意力
mha = MultiHeadAttention(d_model, num_heads)
output, weights = mha.forward(x, x, x) # 自注意力
print(f"\n参数:")
print(f" 批量大小: {batch_size}")
print(f" 序列长度: {seq_len}")
print(f" 模型维度: {d_model}")
print(f" 注意力头数: {num_heads}")
print(f"\n结果:")
print(f" 输入形状: {x.shape}")
print(f" 输出形状: {output.shape}")
print(f" 注意力权重形状: {weights.shape}")
# 展示注意力权重
print(f"\n注意力权重 (第一个样本, 第一个头):")
print(f" 权重和 (应该为1): {weights[0, 0, 0, :].sum():.4f}")
return output, weights
if __name__ == "__main__":
demonstrate_attention()
16.3 训练循环
python
"""
完整训练循环的实现。
包含: 数据加载、训练、验证、学习率调度。
"""
import numpy as np
class DataLoader:
"""简单的数据加载器。"""
def __init__(self, X, y, batch_size=32, shuffle=True):
self.X = X
self.y = y
self.batch_size = batch_size
self.shuffle = shuffle
def __iter__(self):
indices = np.arange(len(self.X))
if self.shuffle:
np.random.shuffle(indices)
for start in range(0, len(self.X), self.batch_size):
end = min(start + self.batch_size, len(self.X))
batch_idx = indices[start:end]
yield self.X[batch_idx], self.y[batch_idx]
def __len__(self):
return (len(self.X) + self.batch_size - 1) // self.batch_size
class CosineAnnealingScheduler:
"""余弦退火学习率调度器。"""
def __init__(self, lr_max, lr_min, T_max):
self.lr_max = lr_max
self.lr_min = lr_min
self.T_max = T_max
def get_lr(self, epoch):
return self.lr_min + 0.5 * (self.lr_max - self.lr_min) * \
(1 + np.cos(np.pi * epoch / self.T_max))
class Trainer:
"""训练器。"""
def __init__(self, model, criterion, optimizer='adam', lr=0.001):
self.model = model
self.criterion = criterion
self.lr = lr
self.history = {'train_loss': [], 'val_loss': []}
def train_epoch(self, dataloader):
"""训练一个 epoch。"""
total_loss = 0
num_batches = 0
for X_batch, y_batch in dataloader:
# 前向传播
y_pred = self.model.forward(X_batch)
loss = self.criterion.forward(y_pred, y_batch)
# 反向传播
grad = self.criterion.backward()
self.model.backward(grad)
# 更新参数
self.model.update(self.lr)
total_loss += loss
num_batches += 1
return total_loss / num_batches
def evaluate(self, X, y):
"""评估模型。"""
y_pred = self.model.forward(X)
loss = self.criterion.forward(y_pred, y)
preds = np.argmax(y_pred, axis=1)
accuracy = np.mean(preds == y)
return loss, accuracy
def fit(self, X_train, y_train, X_val=None, y_val=None,
epochs=100, batch_size=32, verbose=True):
"""训练模型。"""
train_loader = DataLoader(X_train, y_train, batch_size)
for epoch in range(epochs):
# 训练
train_loss = self.train_epoch(train_loader)
self.history['train_loss'].append(train_loss)
# 验证
if X_val is not None:
val_loss, val_acc = self.evaluate(X_val, y_val)
self.history['val_loss'].append(val_loss)
# 打印
if verbose and (epoch + 1) % 10 == 0:
if X_val is not None:
print(f"Epoch {epoch+1}: train_loss={train_loss:.4f}, "
f"val_loss={val_loss:.4f}, val_acc={val_acc:.2%}")
else:
print(f"Epoch {epoch+1}: train_loss={train_loss:.4f}")
return self.history
def demonstrate_training():
"""演示完整训练流程。"""
print("=" * 60)
print("完整训练流程演示")
print("=" * 60)
np.random.seed(42)
# 生成数据
n_samples = 1000
n_features = 10
n_classes = 3
X = np.random.randn(n_samples, n_features)
w_true = np.random.randn(n_features, n_classes)
y = np.argmax(X @ w_true + np.random.randn(n_samples, n_classes) * 0.5, axis=1)
# 划分训练集和验证集
split = int(0.8 * n_samples)
X_train, X_val = X[:split], X[split:]
y_train, y_val = y[:split], y[split:]
print(f"\n数据集:")
print(f" 训练样本: {len(X_train)}")
print(f" 验证样本: {len(X_val)}")
print(f" 特征维度: {n_features}")
print(f" 类别数: {n_classes}")
# 创建模型和训练器
from functools import reduce
model = MLP([n_features, 32, 16, n_classes])
criterion = CrossEntropyLoss()
trainer = Trainer(model, criterion, lr=0.01)
# 训练
print(f"\n开始训练:")
history = trainer.fit(X_train, y_train, X_val, y_val,
epochs=50, batch_size=32, verbose=True)
# 最终评估
train_loss, train_acc = trainer.evaluate(X_train, y_train)
val_loss, val_acc = trainer.evaluate(X_val, y_val)
print(f"\n最终结果:")
print(f" 训练损失: {train_loss:.4f}, 训练准确率: {train_acc:.2%}")
print(f" 验证损失: {val_loss:.4f}, 验证准确率: {val_acc:.2%}")
return history
if __name__ == "__main__":
demonstrate_training()
附录
A. 数学符号表
| 符号 | 含义 | 维度 |
|---|---|---|
| xxx | 输入向量 | Rd\mathbb{R}^dRd |
| WWW | 权重矩阵 | Rm×n\mathbb{R}^{m \times n}Rm×n |
| bbb | 偏置向量 | Rn\mathbb{R}^nRn |
| zzz | 线性输出 | Rn\mathbb{R}^nRn |
| aaa | 激活输出 | Rn\mathbb{R}^nRn |
| δ\deltaδ | 误差项 | Rn\mathbb{R}^nRn |
| θ\thetaθ | 所有参数 | - |
| L\mathcal{L}L | 损失函数 | R\mathbb{R}R |
| η\etaη | 学习率 | R>0\mathbb{R}_{>0}R>0 |
| Q,K,VQ, K, VQ,K,V | 查询、键、值 | Rn×d\mathbb{R}^{n \times d}Rn×d |
B. 关键公式速查
前向传播 :
z(l)=W(l)a(l−1)+b(l),a(l)=f(z(l))z^{(l)} = W^{(l)} a^{(l-1)} + b^{(l)}, \quad a^{(l)} = f(z^{(l)})z(l)=W(l)a(l−1)+b(l),a(l)=f(z(l))
反向传播 :
δ(l)=(W(l+1))Tδ(l+1)⊙f′(z(l))\delta^{(l)} = (W^{(l+1)})^T \delta^{(l+1)} \odot f'(z^{(l)})δ(l)=(W(l+1))Tδ(l+1)⊙f′(z(l))
梯度 :
∂L∂W(l)=δ(l)(a(l−1))T\frac{\partial \mathcal{L}}{\partial W^{(l)}} = \delta^{(l)} (a^{(l-1)})^T∂W(l)∂L=δ(l)(a(l−1))T
Adam 更新 :
θt+1=θt−ηv^t+ϵm^t\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_tθt+1=θt−v^t +ϵηm^t
注意力 :
Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q,K,V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)VAttention(Q,K,V)=softmax(dk QKT)V
交叉熵 :
L=−∑kyklogy^k\mathcal{L} = -\sum_k y_k \log \hat{y}_kL=−k∑yklogy^k
Softmax :
y^k=ezk∑jezj\hat{y}_k = \frac{e^{z_k}}{\sum_j e^{z_j}}y^k=∑jezjezk