深度学习理论:从神经网络到Transformer—前馈网络、反向传播、注意力机制与训练

目录

  • 第一部分:神经网络基础
    • 第一章:绪论------深度学习的理论框架
    • 第二章:前馈神经网络
    • 第三章:反向传播与自动微分
  • 第二部分:现代架构
    • 第四章:卷积神经网络(CNN)
    • 第五章:循环神经网络与序列建模
    • 第六章:Transformer 与注意力机制
  • 第三部分:训练理论
    • 第七章:损失函数与优化目标
    • 第八章:梯度下降与训练动力学
    • 第九章:正则化与泛化
  • 第四部分:理论分析
    • 第十章:神经网络的表达能力
    • 第十一章:优化景观与收敛性
    • 第十二章:信息论视角
  • 第五部分:前沿与代码
    • 第十三章:生成模型
    • 第十四章:自监督学习
    • 第十五章:SSM 与深度学习
    • 第十六章:完整可运行代码实现
  • 附录

第一部分:神经网络基础


第一章:绪论------深度学习的理论框架

1.1 深度学习的核心问题

深度学习研究的核心问题是:

如何设计和训练多层非线性变换,使得机器能够从数据中自动学习有用的表示?

这个问题可以分解为三个子问题:

  1. 表示:用什么数学结构表示学习到的映射?
  2. 优化:如何高效地找到好的参数?
  3. 泛化:为什么学到的模型能在未见过的数据上工作?

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 本文的组织

本文从神经网络的基本理论出发,逐步构建出现代深度学习的完整理论体系。我们特别关注:

  1. 反向传播的数学推导:梯度是如何计算的?
  2. Transformer 的理论基础:注意力机制的本质是什么?
  3. 训练动力学:为什么深度网络能被训练?
  4. 泛化理论:为什么过参数化的网络不过拟合?

第二章:前馈神经网络

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−tanh⁡2(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,使得:

sup⁡x∈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=max⁡m,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=1nyilog⁡y\^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=1Kyiklog⁡y^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)γyilog⁡y^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=−log⁡exp⁡(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)

使得 sup⁡x∣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 信息瓶颈原理

深度网络的每一层都在做信息压缩:

min⁡TI(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 两个阶段

  1. 拟合阶段 :I(T;Y)I(T; Y)I(T;Y) 增加
  2. 压缩阶段 :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 原理

好的模型应该同时:

  1. 拟合数据(小的误差)
  2. 简单(短的描述长度)

MDL=L(θ)+12log⁡n⋅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(证据下界)

log⁡p(x)≥Eqϕ(z∣x)log⁡pθ(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 博弈目标

min⁡Gmax⁡DV(D,G)=Ex∼pdatalog⁡D(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 纳什均衡

在最优判别器下,最小化:

min⁡GL(G)=2JS(pdata∥pg)−log⁡4\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=−log⁡exp⁡(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=−∑kyklog⁡y^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

相关推荐
chsmiao2 小时前
张量(Tensor)
深度学习·ai编程
A_Sinon2 小时前
卷积神经网络
人工智能·神经网络·cnn
chsmiao3 小时前
深度学习之线性代数
人工智能·深度学习·线性代数
HyperAI超神经4 小时前
MiniCPM5-1B采用RL+OPD训练,多项复杂任务达SOTA;面向复杂医疗业务自动化:医疗智能体评测数据集 CHI-Bench
人工智能·深度学习·ai·计算化学
一个王同学4 小时前
从零到一 | CV转多模态大模型 | week12 | 整理 MiniLLaVA 工程与文档
人工智能·深度学习·算法·机器学习·计算机视觉
chsmiao5 小时前
深度学习之微积分
人工智能·深度学习
阳明山水5 小时前
LightGBM为何胜过Prophet做销量预测
人工智能·深度学习·机器学习·微信公众平台·微信开放平台
JeJe同学5 小时前
LabelImg报错:IndexError: list index out of range 解决方法
深度学习·目标检测
zhangfeng11336 小时前
2021-2026 年全球 传统厂家AI 算力卡 GPU 前沿技术研究报告
人工智能·深度学习·语言模型·gpu算力·芯片