00 - 深度学习数学基础¶
重要性: ⭐⭐⭐⭐⭐ 实用度: ⭐⭐⭐⭐⭐ 学习时间: 15-20小时 必须掌握: 是
为什么需要学习数学?¶
深度学习不是魔法,而是建立在严谨的数学基础之上的工程技术。掌握数学能让你:
- 真正理解算法为什么有效,而不是死记硬背
- 调试问题时知道从哪里入手
- 设计新模型时有理论指导
- 阅读论文时能理解推导过程
- 与他人交流时使用准确的语言
好消息:你不需要成为数学家,只需要掌握深度学习常用的数学工具。
学习路线图¶
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 深度学习数学基础学习路线图 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 第一阶段:线性代数(核心中的核心) │
│ ├── 向量与向量空间 [2小时] │
│ ├── 矩阵与矩阵运算 [2小时] │
│ ├── 特征分解与SVD [2小时] │
│ └── 在深度学习中的应用 [1小时] │
│ │
│ 第二阶段:微积分(优化的基础) │
│ ├── 导数与梯度 [2小时] │
│ ├── 偏导数与方向导数 [2小时] │
│ ├── 链式法则 [1小时] │
│ └── 泰勒展开 [1小时] │
│ │
│ 第三阶段:概率论(不确定性的语言) │
│ ├── 概率基础 [2小时] │
│ ├── 常见分布 [1小时] │
│ ├── 期望与方差 [1小时] │
│ └── 信息论 [2小时] │
│ │
│ 第四阶段:优化理论(训练的本质) │
│ ├── 凸优化基础 [1小时] │
│ ├── 梯度下降理论 [2小时] │
│ └── 约束优化 [1小时] │
│ │
└─────────────────────────────────────────────────────────────────────┘
第一部分:线性代数¶
1. 向量与向量空间¶
1.1 什么是向量?¶
直观理解:向量是有方向的量,可以表示为空间中从一个点指向另一个点的箭头。
数学定义:向量是向量空间中的元素,满足加法和数乘的封闭性。
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 向量的表示 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 几何表示: 代数表示: 物理意义: │
│ │
│ ↑y │
│ │ •(3,2) v = [3] 位移、速度、力 │
│ │ / [2] │
│ │ / 或 v = (3, 2) │
│ │ / │
│ └────────→ x │
│ │
│ 向量的维度: │
│ • 2维向量:平面上的点 [x, y] │
│ • 3维向量:空间中的点 [x, y, z] │
│ • n维向量:n维空间中的点 [x₁, x₂, ..., xₙ] │
│ │
│ 在深度学习中: │
│ • 一张28×28的灰度图像 = 784维向量 │
│ • 一个词嵌入 = 通常128或256维向量 │
│ • 一个batch的64张图像 = 64×784矩阵 │
│ │
└─────────────────────────────────────────────────────────────────────┘
1.2 向量运算¶
Python
import numpy as np
# 向量定义
v1 = np.array([1, 2, 3])
v2 = np.array([4, 5, 6])
# 1. 向量加法(对应元素相加)
# 几何意义:平行四边形法则
v_add = v1 + v2 # [5, 7, 9]
# 2. 数乘(每个元素乘以标量)
# 几何意义:长度的缩放
v_scale = 2 * v1 # [2, 4, 6]
# 3. 点积(内积)- 结果是一个标量
# 公式:v₁·v₂ = Σ(v₁[i] × v₂[i])
# 几何意义:v₁在v₂方向上的投影长度 × |v₂|
dot_product = np.dot(v1, v2) # 1×4 + 2×5 + 3×6 = 32
# 4. 范数(长度)
# L2范数(欧几里得范数):||v|| = √(Σv[i]²)
norm = np.linalg.norm(v1) # √(1+4+9) = √14 ≈ 3.74
# 5. 向量夹角
# cos(θ) = (v₁·v₂) / (||v₁|| × ||v₂||)
cos_theta = np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))
print(f"v1 + v2 = {v_add}")
print(f"2 * v1 = {v_scale}")
print(f"v1 · v2 = {dot_product}")
print(f"||v1|| = {norm:.2f}")
print(f"cos(θ) = {cos_theta:.4f}")
1.3 向量空间与基¶
直观理解:向量空间是一个集合,其中的元素(向量)可以进行加法和数乘运算。
基(Basis):向量空间中的一组特殊向量,空间中的任何向量都可以表示为这组基的线性组合。
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 基与坐标 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 标准基: │
│ 在2维空间中:e₁ = [1, 0], e₂ = [0, 1] │
│ 任何向量 v = [3, 2] = 3×e₁ + 2×e₂ │
│ │
│ 非标准基: │
│ b₁ = [1, 1], b₂ = [1, -1] │
│ 同样 v = [3, 2] 可以表示为: │
│ v = 2.5×b₁ + 0.5×b₂ │
│ │
│ 在深度学习中的应用: │
│ • 主成分分析(PCA):找到数据最重要的基(主成分) │
│ • 嵌入空间:词嵌入就是学习到的语义基 │
│ • 特征提取:CNN学习的是图像的特征基 │
│ │
└─────────────────────────────────────────────────────────────────────┘
2. 矩阵与矩阵运算¶
2.1 什么是矩阵?¶
直观理解:矩阵是向量的集合,可以看作是一个二维表格或线性变换。
数学定义:m×n矩阵是由m行n列数排列成的矩形阵列。
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 矩阵的直观理解 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 矩阵作为数据表格: │
│ ┌─────────────────────────────────────┐ │
│ │ 身高 体重 年龄 | 样本1 │ │
│ │ 170 65 25 | 样本2 │ │
│ │ 160 55 30 | 样本3 │ │
│ └─────────────────────────────────────┘ │
│ │
│ 矩阵作为线性变换: │
│ │
│ 输入向量 x ──────→ 矩阵 A ──────→ 输出向量 y = Ax │
│ │
│ 几何意义: │
│ • 旋转:A = [[cosθ, -sinθ], [sinθ, cosθ]] │
│ • 缩放:A = [[2, 0], [0, 3]] (x方向2倍,y方向3倍) │
│ • 投影:A = [[1, 0], [0, 0]] (投影到x轴) │
│ │
│ 在深度学习中: │
│ • 权重矩阵:W 将输入特征映射到输出特征 │
│ • 批量数据:X 是batch_size × feature_dim 的矩阵 │
│ • 图像数据:28×28图像是784维向量,batch是矩阵 │
│ │
└─────────────────────────────────────────────────────────────────────┘
2.2 矩阵运算¶
Python
import numpy as np
# 矩阵定义
A = np.array([[1, 2], [3, 4], [5, 6]]) # 3×2矩阵
B = np.array([[7, 8], [9, 10]]) # 2×2矩阵
print(f"A的形状: {A.shape}") # (3, 2)
print(f"B的形状: {B.shape}") # (2, 2)
# 1. 矩阵加法(对应元素相加,形状必须相同)
C = np.array([[1, 2], [3, 4]])
D = np.array([[5, 6], [7, 8]])
print(f"C + D = \n{C + D}")
# 2. 数乘
print(f"2 * A = \n{2 * A}")
# 3. 矩阵乘法(最重要的运算!)
# 规则:A(m×n) @ B(n×p) = C(m×p)
# A的列数必须等于B的行数
E = A @ B # 3×2 @ 2×2 = 3×2
print(f"A @ B = \n{E}")
# 矩阵乘法的元素计算:
# C[i,j] = Σ(A[i,k] × B[k,j])
# 即:A的第i行与B的第j列的点积
# 4. 转置(行列互换)
print(f"A的转置: \n{A.T}") # 2×3
# 5. 单位矩阵(对角线为1,其余为0)
I = np.eye(3)
print(f"3×3单位矩阵: \n{I}")
# 性质:A @ I = I @ A = A
# 6. 逆矩阵(只对方阵存在,且行列式不为0)
F = np.array([[4, 7], [2, 6]])
F_inv = np.linalg.inv(F)
print(f"F的逆矩阵: \n{F_inv}")
print(f"F @ F_inv = \n{F @ F_inv}") # 接近单位矩阵
2.3 矩阵在深度学习中的应用¶
Python
import numpy as np
# 场景1:全连接层的前向传播
# y = x @ W + b
batch_size = 64
input_dim = 784
output_dim = 256
# 随机初始化
X = np.random.randn(batch_size, input_dim) # 输入:64张784维的图像
W = np.random.randn(input_dim, output_dim) * 0.01 # 权重
b = np.zeros(output_dim) # 偏置
# 前向传播
Y = X @ W + b # 输出:64×256
print(f"输入形状: {X.shape}")
print(f"权重形状: {W.shape}")
print(f"输出形状: {Y.shape}")
# 场景2:批量处理多个样本
# 矩阵乘法天然支持批量运算
# 场景3:注意力机制中的矩阵运算
# Attention(Q, K, V) = softmax(Q @ K.T / √d) @ V
seq_len = 10
d_k = 64
Q = np.random.randn(seq_len, d_k)
K = np.random.randn(seq_len, d_k)
V = np.random.randn(seq_len, d_k)
# 计算注意力分数
scores = Q @ K.T / np.sqrt(d_k) # (10, 10)
print(f"\n注意力分数形状: {scores.shape}")
# softmax(简化版)
def softmax(x):
exp_x = np.exp(x - np.max(x, axis=-1, keepdims=True))
return exp_x / np.sum(exp_x, axis=-1, keepdims=True)
attention_weights = softmax(scores)
output = attention_weights @ V
print(f"注意力输出形状: {output.shape}")
3. 特征分解与奇异值分解¶
3.1 特征值与特征向量¶
核心问题:矩阵A作用在向量v上,什么时候v只是被拉伸,而不改变方向?
答案:当v是A的特征向量时!
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 特征值与特征向量 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 定义:如果 Av = λv,则: │
│ • v 是A的特征向量(非零) │
│ • λ 是对应的特征值(标量) │
│ │
│ 几何意义: │
│ │
│ 变换前 矩阵A 变换后 │
│ ↘ ↗ │
│ v ─────────────────→ λv │
│ ↗ ↘ │
│ 方向不变,只是长度变为λ倍 │
│ │
│ 计算方法: │
│ Av = λv ⟹ Av - λv = 0 ⟹ (A - λI)v = 0 │
│ 要有非零解,需要 det(A - λI) = 0(特征方程) │
│ │
│ 在深度学习中的应用: │
│ • PCA降维:用最大的k个特征值对应的特征向量作为新基 │
│ • 谱归一化:用特征值控制Lipschitz常数 │
│ • PageRank:特征向量表示网页重要性 │
│ │
└─────────────────────────────────────────────────────────────────────┘
Python
import numpy as np
# 定义矩阵
A = np.array([[4, 2], [1, 3]])
# 计算特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
print("特征值:", eigenvalues)
print("特征向量:\n", eigenvectors)
# 验证:Av = λv
for i in range(len(eigenvalues)):
v = eigenvectors[:, i]
lambda_v = eigenvalues[i]
Av = A @ v
lambda_v_v = lambda_v * v
print(f"\n特征向量 {i+1}: {v}")
print(f"Av = {Av}")
print(f"λv = {lambda_v_v}")
print(f"是否相等: {np.allclose(Av, lambda_v_v)}")
# 特征分解:A = V @ diag(λ) @ V^(-1)
V = eigenvectors
Lambda = np.diag(eigenvalues)
V_inv = np.linalg.inv(V)
A_reconstructed = V @ Lambda @ V_inv
print(f"\n重构的A:\n{A_reconstructed}")
print(f"与原A相等: {np.allclose(A, A_reconstructed)}")
3.2 奇异值分解(SVD)¶
重要性:SVD是线性代数中最强大的工具之一,任何矩阵都可以做SVD!
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 奇异值分解(SVD) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 定理:任何m×n矩阵A都可以分解为: │
│ │
│ A = U @ Σ @ V^T │
│ │
│ 其中: │
│ • U:m×m正交矩阵(左奇异向量) │
│ • Σ:m×n对角矩阵(奇异值,非负,从大到小排列) │
│ • V^T:n×n正交矩阵的转置(右奇异向量) │
│ │
│ 几何意义: │
│ │
│ 输入x ──→ V^T ──→ Σ ──→ U ──→ 输出Ax │
│ 旋转 缩放 旋转 │
│ │
│ 任何线性变换都可以分解为:旋转→缩放→旋转 │
│ │
│ 在深度学习中的应用: │
│ • 降维:取前k个奇异值,实现最优低秩近似 │
│ • 压缩:存储U_k, Σ_k, V_k代替原矩阵 │
│ • 去噪:小奇异值通常对应噪声 │
│ • 推荐系统:矩阵补全 │
│ │
└─────────────────────────────────────────────────────────────────────┘
Python
import numpy as np
# 创建矩阵
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) # 4×3
print(f"原矩阵形状: {A.shape}")
# SVD分解
U, s, Vt = np.linalg.svd(A, full_matrices=False)
print(f"U形状: {U.shape}") # (4, 3)
print(f"奇异值: {s}") # (3,)
print(f"Vt形状: {Vt.shape}") # (3, 3)
# 重构Sigma矩阵
Sigma = np.diag(s)
# 重构原矩阵
A_reconstructed = U @ Sigma @ Vt
print(f"\n重构误差: {np.linalg.norm(A - A_reconstructed):.10f}")
# 应用:降维(取前2个奇异值)
k = 2
U_k = U[:, :k]
Sigma_k = np.diag(s[:k])
Vt_k = Vt[:k, :]
A_approx = U_k @ Sigma_k @ Vt_k
print(f"\n用{k}个奇异值近似,误差: {np.linalg.norm(A - A_approx):.4f}")
# 压缩率计算
original_size = A.size
compressed_size = U_k.size + s[:k].size + Vt_k.size
print(f"原矩阵大小: {original_size}")
print(f"压缩后大小: {compressed_size}")
print(f"压缩率: {compressed_size/original_size:.2%}")
第二部分:微积分¶
4. 导数与梯度¶
4.1 导数的本质¶
直观理解:导数是变化率,描述函数在某一点的"陡峭程度"。
数学定义:f'(x) = lim(h→0) [f(x+h) - f(x)] / h
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 导数的几何意义 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ y │
│ │ ╱ │
│ │ ╱ f(x) = x² │
│ │ ╱ │
│ │ ╱ 在x=1处,切线斜率=2 │
│ │╱──────┐ │
│ │ ╱ │ 切线 │
│ │ ╱ │ │
│ └──┼────┼────────────────→ x │
│ 0 1 │
│ │
│ 导数告诉我们: │
│ • 函数在某点的瞬时变化率 │
│ • 函数图像在该点的切线斜率 │
│ • 函数在该点的局部线性近似 │
│ │
│ 在深度学习中: │
│ • 损失函数对参数的导数 = 梯度 │
│ • 梯度告诉我们如何调整参数以减少损失 │
│ │
└─────────────────────────────────────────────────────────────────────┘
4.2 常见函数的导数¶
Python
import numpy as np
import matplotlib.pyplot as plt
# 常见函数及其导数
def f_and_df():
"""
函数 导数
─────────────────────────
c (常数) 0
x 1
x² 2x
xⁿ n·x^(n-1)
e^x e^x
ln(x) 1/x
sin(x) cos(x)
cos(x) -sin(x)
sigmoid(x) sigmoid(x)·(1-sigmoid(x))
"""
pass
# 数值导数(用于验证)
def numerical_derivative(f, x, h=1e-5):
"""
计算函数f在点x处的数值导数
参数:
f: 函数
x: 标量或数组,求导点
h: 步长
返回:
数值导数
"""
if np.isscalar(x):
return (f(x + h) - f(x - h)) / (2 * h)
else:
# 处理数组输入
x = np.asarray(x)
grad = np.zeros_like(x)
for i in range(x.size):
x_plus = x.copy()
x_minus = x.copy()
x_plus.flat[i] += h
x_minus.flat[i] -= h
grad.flat[i] = (f(x_plus) - f(x_minus)) / (2 * h)
return grad
# 测试:f(x) = x² 的导数
def f(x):
return x**2
def df_analytical(x):
return 2*x
x = 3.0
df_numerical = numerical_derivative(f, x)
df_exact = df_analytical(x)
print(f"f(x) = x² 在 x={x} 处:")
print(f"数值导数: {df_numerical}")
print(f"解析导数: {df_exact}")
print(f"误差: {abs(df_numerical - df_exact):.10f}")
# 可视化函数和导数
x = np.linspace(-3, 3, 100)
y = x**2
dy = 2*x
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.plot(x, y, 'b-', label='f(x) = x²')
plt.plot(x, dy, 'r--', label="f'(x) = 2x")
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.grid(True, alpha=0.3)
plt.title('Function and Derivative')
plt.subplot(1, 2, 2)
# 绘制某点的切线
x0 = 1.5
y0 = x0**2
slope = 2*x0
x_tangent = np.linspace(x0-1, x0+1, 10)
y_tangent = slope * (x_tangent - x0) + y0
plt.plot(x, y, 'b-', label='f(x) = x²')
plt.plot(x_tangent, y_tangent, 'r-', label=f'Tangent at x={x0}')
plt.plot(x0, y0, 'ro', markersize=8)
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.grid(True, alpha=0.3)
plt.title('Tangent Line')
plt.tight_layout()
plt.savefig('derivative_visualization.png', dpi=150)
plt.show()
4.3 梯度(多元函数的导数)¶
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 梯度:多元函数的变化率 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 定义:对于函数 f(x₁, x₂, ..., xₙ),其梯度为: │
│ │
│ ∇f = [∂f/∂x₁, ∂f/∂x₂, ..., ∂f/∂xₙ]ᵀ │
│ │
│ 几何意义: │
│ • 梯度是一个向量,指向函数增长最快的方向 │
│ • 梯度的模长表示增长的速度 │
│ • 负梯度指向函数下降最快的方向(这就是为什么梯度下降有效) │
│ │
│ 示例:f(x, y) = x² + y² │
│ ∇f = [2x, 2y]ᵀ │
│ │
│ 在点(1, 1):∇f = [2, 2]ᵀ │
│ 在点(1, 1)沿梯度方向移动,函数增长最快 │
│ │
│ 在深度学习中的应用: │
│ • 损失函数 L(θ) 对参数 θ 的梯度告诉我们如何更新参数 │
│ • θ_new = θ_old - η·∇L(θ) │
│ │
└─────────────────────────────────────────────────────────────────────┘
Python
import numpy as np
# 多元函数示例:f(x, y) = x² + 2y²
def f(x, y):
return x**2 + 2*y**2
def gradient_f(x, y):
"""计算梯度 [∂f/∂x, ∂f/∂y]"""
df_dx = 2*x # x的偏导数
df_dy = 4*y # y的偏导数
return np.array([df_dx, df_dy])
# 在点(1, 2)处
point = np.array([1.0, 2.0])
grad = gradient_f(point[0], point[1])
print(f"在点 {point}:")
print(f"函数值: {f(point[0], point[1])}")
print(f"梯度: {grad}")
print(f"梯度方向(单位向量): {grad / np.linalg.norm(grad)}")
# 验证:沿梯度方向移动,函数值增加
step = 0.1
direction = grad / np.linalg.norm(grad) # 单位方向
new_point = point + step * direction
print(f"\n沿梯度方向移动 {step}:")
print(f"新位置: {new_point}")
print(f"原函数值: {f(point[0], point[1]):.4f}")
print(f"新函数值: {f(new_point[0], new_point[1]):.4f}")
print(f"变化: {f(new_point[0], new_point[1]) - f(point[0], point[1]):.4f}")
# 梯度下降演示
print("\n" + "="*50)
print("梯度下降优化演示")
print("="*50)
current_point = np.array([3.0, 3.0])
learning_rate = 0.1
for i in range(10):
grad = gradient_f(current_point[0], current_point[1])
loss = f(current_point[0], current_point[1])
print(f"Step {i}: 位置={current_point}, 损失={loss:.4f}, 梯度={grad}")
# 梯度下降更新
current_point = current_point - learning_rate * grad
5. 链式法则¶
5.1 链式法则的本质¶
核心思想:复合函数的导数 = 外层函数导数 × 内层函数导数
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 链式法则:复合函数的求导 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 单变量链式法则: │
│ 如果 y = f(g(x)),则 dy/dx = f'(g(x)) · g'(x) │
│ │
│ 直观理解: │
│ x的变化 → 引起g的变化 → 引起f的变化 │
│ 总变化 = 第一步变化 × 第二步变化 │
│ │
│ 示例:y = (x + 1)² │
│ 令 u = x + 1,则 y = u² │
│ dy/dx = dy/du · du/dx = 2u · 1 = 2(x + 1) │
│ │
│ ───────────────────────────────────────────────────────────────── │
│ │
│ 多变量链式法则(深度学习核心): │
│ │
│ 如果 z = f(x, y),x = g(t),y = h(t) │
│ 则 dz/dt = ∂z/∂x · dx/dt + ∂z/∂y · dy/dt │
│ │
│ 向量形式(更常用): │
│ 如果 y = f(g(x)),则 ∂y/∂x = ∂y/∂g · ∂g/∂x │
│ │
│ 在神经网络中的应用: │
│ 损失L → 输出层 → 隐藏层 → 输入 │
│ ∂L/∂W₁ = ∂L/∂h₂ · ∂h₂/∂h₁ · ∂h₁/∂W₁ │
│ │
└─────────────────────────────────────────────────────────────────────┘
5.2 链式法则在反向传播中的应用¶
Python
import numpy as np
# 链式法则验证示例
# 函数: y = sigmoid(w·x + b)
# 我们想计算 ∂y/∂w, ∂y/∂b, ∂y/∂x
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def sigmoid_derivative(z):
s = sigmoid(z)
return s * (1 - s)
# 前向传播
x = 2.0
w = 3.0
b = 1.0
z = w * x + b # 线性变换
y = sigmoid(z) # 激活函数
print(f"前向传播:")
print(f"z = w·x + b = {w}·{x} + {b} = {z}")
print(f"y = sigmoid({z}) = {y}")
# 反向传播(假设损失对y的梯度为1)
dy = 1.0
# 链式法则: ∂L/∂z = ∂L/∂y · ∂y/∂z
dz = dy * sigmoid_derivative(z)
print(f"\n反向传播:")
print(f"∂y/∂z = sigmoid'(z) = {sigmoid_derivative(z):.4f}")
print(f"∂L/∂z = {dz:.4f}")
# 继续传播
dw = dz * x # ∂L/∂w = ∂L/∂z · ∂z/∂w = ∂L/∂z · x
db = dz * 1 # ∂L/∂b = ∂L/∂z · ∂z/∂b = ∂L/∂z · 1
dx = dz * w # ∂L/∂x = ∂L/∂z · ∂z/∂x = ∂L/∂z · w
print(f"\n各参数的梯度:")
print(f"∂L/∂w = {dw:.4f}")
print(f"∂L/∂b = {db:.4f}")
print(f"∂L/∂x = {dx:.4f}")
# 数值验证
epsilon = 1e-5
def compute_loss(w, b, x):
z = w * x + b
return sigmoid(z)
dw_numerical = (compute_loss(w+epsilon, b, x) - compute_loss(w-epsilon, b, x)) / (2*epsilon)
db_numerical = (compute_loss(w, b+epsilon, x) - compute_loss(w, b-epsilon, x)) / (2*epsilon)
print(f"\n数值验证:")
print(f"∂L/∂w 解析: {dw:.6f}, 数值: {dw_numerical:.6f}")
print(f"∂L/∂b 解析: {db:.6f}, 数值: {db_numerical:.6f}")
第三部分:概率论与信息论¶
6. 概率基础¶
6.1 概率与随机变量¶
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 概率基础概念 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 概率的定义: │
│ P(A) 表示事件A发生的可能性,取值在[0, 1]之间 │
│ │
│ 随机变量:将随机事件映射为数值 │
│ • 离散随机变量:取值为有限或可数无限个(如掷骰子的点数) │
│ • 连续随机变量:取值为连续区间(如身高、体重) │
│ │
│ 概率分布: │
│ • 离散:概率质量函数(PMF)P(X=x) │
│ • 连续:概率密度函数(PDF)f(x),P(a≤X≤b) = ∫f(x)dx │
│ │
│ 在深度学习中的应用: │
│ • 数据增强的随机性 │
│ • Dropout的随机失活 │
│ • 生成模型学习数据分布 │
│ • 贝叶斯神经网络 │
│ │
└─────────────────────────────────────────────────────────────────────┘
6.2 常见概率分布¶
Python
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# 1. 均匀分布 Uniform(a, b)
# 在[a, b]区间内概率密度相同
x = np.linspace(0, 1, 100)
y_uniform = stats.uniform.pdf(x, 0, 1)
# 2. 正态分布(高斯分布)Normal(μ, σ²)
# 钟形曲线,自然界最常见
# 概率密度:f(x) = (1/√(2πσ²)) · exp(-(x-μ)²/(2σ²))
x = np.linspace(-5, 5, 100)
y_normal = stats.norm.pdf(x, 0, 1)
# 3. 伯努利分布 Bernoulli(p)
# 二值随机变量,取1的概率为p,取0的概率为1-p
# 应用:二分类问题的标签
# 4. 二项分布 Binomial(n, p)
# n次独立伯努利试验中成功的次数
# 5. 多项分布 Multinomial(n, p)
# 多分类问题的推广
# 6. 分类分布 Categorical(p)
# 一次试验的多项分布,用于多分类
# 可视化
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
# 均匀分布
axes[0, 0].plot(x, stats.uniform.pdf(x, -2, 4), 'b-', linewidth=2)
axes[0, 0].set_title('Uniform Distribution')
axes[0, 0].set_xlabel('x')
axes[0, 0].set_ylabel('PDF')
axes[0, 0].grid(True, alpha=0.3)
# 正态分布
axes[0, 1].plot(x, stats.norm.pdf(x, 0, 1), 'r-', linewidth=2, label='μ=0, σ=1')
axes[0, 1].plot(x, stats.norm.pdf(x, 0, 2), 'g--', linewidth=2, label='μ=0, σ=2')
axes[0, 1].plot(x, stats.norm.pdf(x, 2, 1), 'b:', linewidth=2, label='μ=2, σ=1')
axes[0, 1].set_title('Normal Distribution')
axes[0, 1].legend()
axes[0, 1].grid(True, alpha=0.3)
# 二项分布
n, p = 10, 0.5
x_binom = np.arange(0, n+1)
y_binom = stats.binom.pmf(x_binom, n, p)
axes[1, 0].bar(x_binom, y_binom, alpha=0.7)
axes[1, 0].set_title(f'Binomial Distribution (n={n}, p={p})')
axes[1, 0].set_xlabel('k')
axes[1, 0].set_ylabel('PMF')
axes[1, 0].grid(True, alpha=0.3)
# 指数分布
x_exp = np.linspace(0, 5, 100)
y_exp = stats.expon.pdf(x_exp, scale=1)
axes[1, 1].plot(x_exp, y_exp, 'm-', linewidth=2)
axes[1, 1].set_title('Exponential Distribution')
axes[1, 1].set_xlabel('x')
axes[1, 1].set_ylabel('PDF')
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('probability_distributions.png', dpi=150)
plt.show()
print("概率分布可视化完成!")
6.3 期望、方差与协方差¶
Python
import numpy as np
# 期望(均值):E[X] = Σx·P(X=x) 或 ∫x·f(x)dx
# 表示随机变量的平均值
# 方差:Var(X) = E[(X - E[X])²] = E[X²] - E[X]²
# 表示随机变量的离散程度
# 标准差:σ = √Var(X)
# 协方差:Cov(X, Y) = E[(X - E[X])(Y - E[Y])]
# 表示两个随机变量的线性相关性
# 相关系数:ρ = Cov(X, Y) / (σ_X · σ_Y)
# 标准化后的协方差,取值[-1, 1]
# 示例:计算数据集的统计量
data = np.random.randn(1000, 3) # 1000个样本,3个特征
# 均值
mean = np.mean(data, axis=0)
print(f"均值: {mean}")
# 方差
variance = np.var(data, axis=0)
print(f"方差: {variance}")
# 标准差
std = np.std(data, axis=0)
print(f"标准差: {std}")
# 协方差矩阵
cov_matrix = np.cov(data.T)
print(f"\n协方差矩阵:\n{cov_matrix}")
# 相关系数矩阵
corr_matrix = np.corrcoef(data.T)
print(f"\n相关系数矩阵:\n{corr_matrix}")
# 在深度学习中的应用:
# 1. Batch Normalization使用均值和方差
# 2. 权重初始化考虑方差:
# - Xavier初始化:适用于Sigmoid/Tanh激活,W ~ N(0, 2/(n_in+n_out))
# - He初始化:适用于ReLU激活,W ~ N(0, 2/n_in)
# 3. 梯度裁剪使用标准差
# 4. 特征相关性分析
7. 信息论基础¶
7.1 熵(Entropy)¶
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 熵:不确定性的度量 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 定义:H(X) = -Σ P(x) · log(P(x)) │
│ │
│ 直观理解: │
│ • 熵越大,不确定性越大,信息量越大 │
│ • 熵越小,不确定性越小,信息量越小 │
│ │
│ 示例: │
│ 硬币A:P(正面)=0.5, P(反面)=0.5 │
│ H(A) = -(0.5·log(0.5) + 0.5·log(0.5)) = 1 bit │
│ │
│ 硬币B:P(正面)=0.9, P(反面)=0.1 │
│ H(B) = -(0.9·log(0.9) + 0.1·log(0.1)) ≈ 0.47 bit │
│ │
│ 结论:硬币A的不确定性更大(熵更大) │
│ │
│ 在深度学习中的应用: │
│ • 交叉熵损失函数 │
│ • 决策树的划分准则 │
│ • 模型压缩(信息瓶颈) │
│ │
└─────────────────────────────────────────────────────────────────────┘
7.2 KL散度与交叉熵¶
Python
import numpy as np
# KL散度(Kullback-Leibler Divergence)
# 衡量两个概率分布的差异
# D_KL(P||Q) = Σ P(x) · log(P(x)/Q(x))
# 性质:非负,不对称
def kl_divergence(p, q):
"""计算KL散度 D_KL(p||q)"""
# 避免log(0)
p = np.clip(p, 1e-10, 1)
q = np.clip(q, 1e-10, 1)
return np.sum(p * np.log(p / q))
# 交叉熵 H(P, Q) = -Σ P(x) · log(Q(x))
# 与KL散度的关系:H(P, Q) = H(P) + D_KL(P||Q)
def cross_entropy(p, q):
"""计算交叉熵"""
q = np.clip(q, 1e-10, 1)
return -np.sum(p * np.log(q))
# 示例
p = np.array([0.1, 0.2, 0.7]) # 真实分布
q1 = np.array([0.1, 0.2, 0.7]) # 与p相同
q2 = np.array([0.3, 0.3, 0.4]) # 与p不同
print("真实分布 P:", p)
print("预测分布 Q1:", q1)
print("预测分布 Q2:", q2)
print()
print(f"H(P, Q1) = {cross_entropy(p, q1):.4f}")
print(f"H(P, Q2) = {cross_entropy(p, q2):.4f}")
print(f"D_KL(P||Q2) = {kl_divergence(p, q2):.4f}")
# 在分类问题中的应用
# 真实标签(one-hot): y = [0, 0, 1, 0]
# 预测概率: ŷ = [0.1, 0.2, 0.6, 0.1]
# 损失 = -Σ y[i] · log(ŷ[i]) = -log(0.6)
y_true = np.array([0, 0, 1, 0])
y_pred = np.array([0.1, 0.2, 0.6, 0.1])
loss = -np.sum(y_true * np.log(y_pred + 1e-10))
print(f"\n分类损失: {loss:.4f}")
第四部分:优化理论¶
8. 梯度下降理论¶
8.1 优化问题定义¶
Text Only
┌─────────────────────────────────────────────────────────────────────┐
│ 优化问题:最小化损失函数 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 目标:找到参数 θ*,使得 L(θ*) 最小 │
│ │
│ θ* = argmin L(θ) │
│ │
│ 梯度下降算法: │
│ θ_{t+1} = θ_t - η · ∇L(θ_t) │
│ │
│ 其中: │
│ • η:学习率(步长) │
│ • ∇L(θ_t):损失函数在θ_t处的梯度 │
│ │
│ 为什么梯度下降有效? │
│ • 梯度指向函数增长最快的方向 │
│ • 负梯度指向函数下降最快的方向 │
│ • 沿负梯度移动,函数值减小 │
│ │
│ 学习率的选择: │
│ • 太大:震荡,甚至发散 │
│ • 太小:收敛慢 │
│ • 合适:稳定快速收敛 │
│ │
└─────────────────────────────────────────────────────────────────────┘
8.2 凸优化简介¶
Python
import numpy as np
import matplotlib.pyplot as plt
# 凸函数:任意两点连线在函数上方
# 性质:局部最小值就是全局最小值
# 凸函数示例:f(x) = x²
def convex_function(x):
return x**2
# 非凸函数示例:f(x) = x·sin(x)
def non_convex_function(x):
return x * np.sin(x)
x = np.linspace(-5, 5, 1000)
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(x, convex_function(x), 'b-', linewidth=2)
plt.title('Convex Function: f(x) = x²')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True, alpha=0.3)
# 标注全局最小值
plt.plot(0, 0, 'ro', markersize=10, label='Global Minimum')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(x, non_convex_function(x), 'r-', linewidth=2)
plt.title('Non-Convex Function: f(x) = x·sin(x)')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True, alpha=0.3)
# 标注多个局部最小值
local_mins = [-2.3, 2.3]
for xm in local_mins:
plt.plot(xm, non_convex_function(xm), 'bo', markersize=8)
plt.plot(0, 0, 'ro', markersize=10, label='Global Minimum')
plt.legend()
plt.tight_layout()
plt.savefig('convex_vs_nonconvex.png', dpi=150)
plt.show()
print("凸函数 vs 非凸函数可视化完成!")
# 深度学习的挑战:
# 神经网络的损失函数通常是非凸的
# 但实践中SGD通常能找到好的局部最小值
# 原因:高维空间中,鞍点比局部最小值更常见
总结与下一步¶
数学基础速查表¶
| 概念 | 公式 | 深度学习应用 |
|---|---|---|
| 向量点积 | a·b = Σaᵢbᵢ | 注意力机制 |
| 矩阵乘法 | C = AB | 全连接层、注意力 |
| 特征分解 | A = VΛV⁻¹ | PCA、谱分析 |
| SVD | A = UΣVᵀ | 降维、压缩 |
| 导数 | f'(x) = df/dx | 梯度计算 |
| 梯度 | ∇f = [∂f/∂x₁, ...] | 参数更新 |
| 链式法则 | ∂z/∂x = ∂z/∂y · ∂y/∂x | 反向传播 |
| 期望 | E[X] = Σx·P(x) | 损失函数 |
| 方差 | Var(X) = E[(X-μ)²] | 初始化、BatchNorm |
| 熵 | H(X) = -ΣP(x)logP(x) | 交叉熵损失 |
| KL散度 | D_KL(P||Q) = ΣP·log(P/Q) | 变分推断 |
学习建议¶
- 不要死记硬背:理解概念的本质和几何意义
- 动手计算:用笔和纸推导公式
- 代码验证:用Python验证数学结论
- 联系应用:思考每个概念在深度学习中的具体应用
- 循序渐进:先掌握核心概念,再深入细节
下一步¶
完成数学基础后,你可以: 1. 回到 01-深度学习概述 继续学习 2. 在学习理论章节时,随时回来查阅数学基础 3. 尝试用数学语言重新理解已学过的概念
记住:数学是工具,不是目的。掌握这些数学基础,是为了更深入地理解深度学习算法。祝学习愉快!🎉







