数学分析深度指南
目录
引言与核心地位
数学分析在人工智能时代的复兴
数学分析作为现代数学的基石,其理论体系在21世纪的人工智能革命中焕发出前所未有的生命力。从深度学习的梯度下降算法到强化学习的价值函数逼近,从计算机视觉的卷积神经网络到自然语言处理的注意力机制,数学分析的基本概念——极限、连续、可微、积分——构成了这些算法理论分析的核心工具。
本指南旨在为人工智能研究者和工程师提供一份系统、深入、实用的数学分析参考文档。我们不仅讲解理论本身,更关注这些理论如何支撑现代机器学习算法的设计与分析,以及如何在实践中应用这些数学工具。
数学分析与其他数学分支的关系
数学分析并非孤立的学科,它是连接代数、几何、概率论的枢纽。在人工智能的语境下:
- 线性代数 提供向量空间和矩阵运算的语言,数学分析在此基础上处理函数空间
- 概率论 中的期望、方差等概念需要数学分析的极限工具进行严格化
- 优化理论 本质上是数学分析中极值问题的延续和发展
- 拓扑学 提供了研究连续性和收敛性的更一般框架
理解这些联系,对于构建完整的数学知识体系至关重要。
实数体系的公理化构建
为什么需要严格的实数理论
在人工智能的算法实现中,我们通常使用浮点数近似实数。然而,要理解梯度下降的收敛性、分析神经网络的表达能力、证明某些算法的正确性,必须建立在严格的实数理论基础之上。
浮点数系统虽然模拟了实数的主要性质,但存在精度误差、溢出、下溢等问题。理解实数体系的公理化结构,有助于我们在算法设计中规避这些数值陷阱。
实数的公理化定义
实数体系 可以通过以下公理系统唯一确定( up to isomorphism):
域公理(Field Axioms)
对加法和乘法构成域:
- 加法封闭性:
- 加法交换律:
- 加法结合律:
- 加法单位元:
- 加法逆元:
- 乘法封闭性:
- 乘法交换律:
- 乘法结合律:
- 乘法单位元:
- 乘法逆元:
- 分配律:
序公理(Order Axioms)
在实数上定义全序关系 :
- 自反性:
- 反对称性:
- 传递性:
- 完全性:
- 与运算的协调性:
- 正数乘法:
完备性公理(Completeness Axiom)
这是实数区别于有理数的关键:
戴德金完备性:若 满足:
则
等价的叙述方式是上确界性质: 的每个非空有上界子集都有上确界。
完备性公理的重要性
完备性公理是实数系分析性质的源头。它确保了:
- 极限运算的合法性(收敛序列必有极限)
- 连续函数的中介值性质
- 积分的存在性
在算法分析中,完备性保证了我们在实数空间中进行极限运算时不会遇到”洞”。
重要不等式
实数理论中的一些关键不等式在机器学习算法分析中频繁出现:
三角不等式
更一般地:
柯西-施瓦茨不等式
对于内积空间中的向量:
在 中:
算术-几何平均不等式
当且仅当 时取等。
杨氏不等式
若 且 ,则:
极限理论
数列的极限
ε-N 定义
数列 收敛于 :
这个定义是整个数学分析的基础。理解 论证是掌握严格数学推理的关键。
证明示例:
目标:证明
证明:给定 ,取 。则对所有 :
证毕。
证明示例:
证明:给定 :
需要 ,即 。
取 即可。
数列极限的性质
四则运算
若 ,则:
- 若 ,
夹逼定理
若 且 ,则 。
应用:求
设 ,取对数:
利用洛必达法则:
因此 。
收敛准则
单调有界收敛定理
单调递增且有上界的数列必收敛。
这是深度学习中许多迭代算法收敛性证明的基础。
柯西收敛准则
数列 收敛,当且仅当:
柯西准则的优势在于:证明收敛时不需要预先知道极限值。
函数极限
ε-δ 定义
单侧极限
- 左极限:
- 右极限:
函数极限存在的充要条件是左右极限存在且相等。
海涅定理(归结原则)
当且仅当对任何收敛于 的数列 (),都有 。
这个定理建立了数列极限与函数极限之间的桥梁,在机器学习中常用于证明神经网络函数序列的收敛性。
连续性与可微性
连续性的严格定义
点连续
在点 处连续:
等价于:
区间连续
在区间 上连续,记作 ,当且仅当 在 的每一点都连续。
连续函数的基本性质
最值定理
若 ,则 在 上必能达到最大值和最小值。
机器学习含义:连续损失函数在紧集上必有极值点,保证全局最优或全局最差的存在性。
介值定理
若 且 ,则 。
应用:二分搜索算法的理论基础。
一致连续性
在 上一致连续:
区别:普通连续性中 可能依赖于点 ;一致连续性中 是全局的,只依赖于 。
重要定理:康托尔定理:若 ,则 在 上一致连续。
可微性与导数
导数的定义
若极限存在,则 在 处可微。
几何意义:导数是切线斜率。
物理意义:导数是瞬时变化率。
可微与连续的关系
定理:若 在 处可微,则 在 处连续。
逆命题不成立: 在 处连续但不可微。
导数的计算法则
- 线性法则:
- 加法法则:
- 乘法法则(莱布尼茨公式):
- 除法法则:()
- 链式法则:
链式法则的严格证明
设 ,且 在 处可微, 在 处可微。
定义:
若 :
取极限 :
因此 。
若 (可能发生但不影响结论),可类似证明。
高阶导数
表示 阶导数。
莱布尼茨公式
这与二项式定理结构相同。
微分中值定理
罗尔定理
若 满足:
- 在 上连续
- 在 内可导
则 。
拉格朗日中值定理
若 在 上连续,在 内可导,则 :
推论:若 ,则 单调递增。
柯西中值定理
若 在 上连续,在 内可导,且 ,则 :
泰勒公式
泰勒多项式
在 处的 阶泰勒多项式:
泰勒定理
若 在含 的开区间内有 阶连续导数,则:
其中拉格朗日余项:
常见函数的泰勒展开
指数函数:
正弦函数:
余弦函数:
对数函数(在 处):
泰勒公式在机器学习中的应用
- 牛顿法:使用二阶泰勒展开近似目标函数
- 自然语言处理中的 softmax:使用指数函数的泰勒展开进行数值近似
- 激活函数的近似:如 sigmoid 的泰勒展开用于硬件实现
洛必达法则
0/0 型
若 ,且 ,则:
前提是右侧极限存在(可以是有限值或 )。
∞/∞ 型
若 ,则:
注意事项:
- 洛必达法则可以多次使用
- 必须确保分子分母同时趋于 0 或无穷
- 极限必须存在(不包括振荡情形)
反例:
分子分母都趋于无穷,可以使用洛必达:
积分理论
定积分的定义
黎曼和
设 在 上有界。将 分成 个小区间:
取介点 ,定义黎曼和:
其中 。
达布定理
上积分: 下积分:
其中 和 分别是达布上和与达布下和。
可积的充要条件:上积分等于下积分。
可积函数类
以下函数类在闭区间上可积:
- 连续函数
- 单调有界函数
- 有有限个间断点的有界函数
定积分的性质
线性性
区间可加性
保序性
若 ,则:
绝对值不等式
微积分基本定理
第一基本定理
若 在 上连续,则:
在 上可导,且 。
第二基本定理(牛顿-莱布尼茨公式)
若 是 的原函数,则:
这是计算定积分的核心公式。
不定积分
原函数与不定积分
若 ,则 称为 的原函数。
的全体原函数称为不定积分:
其中 是常数。
换元积分法
第一换元法(凑微分):
若 是 的原函数,则:
第二换元法:
设 , 单调可导,则:
分部积分法
典型应用场景:
定积分的计算技巧
偶函数与奇函数
若 是偶函数,则:
若 是奇函数,则:
周期函数
若 的周期为 ,则:
广义积分
无穷限积分
若极限存在,则广义积分收敛。
p-积分判别法:
- 当 时收敛, 时发散
瑕积分
若 在 处无界:
p-积分判别法:
- 当 时收敛, 时发散
积分在机器学习中的应用
概率密度函数的积分
连续型随机变量 的概率:
期望值的计算
信息熵
神经网络中的积分变换
卷积操作本质上是一种积分变换:
级数理论
数项级数
级数收敛的定义
若极限存在(有限值),则级数收敛;否则发散。
正项级数判别法
比较判别法:若 :
- 若 收敛,则 收敛
- 若 发散,则 发散
比值判别法(达朗贝尔判别法):
- :收敛
- :发散
- :不确定
根值判别法(柯西判别法):
- :收敛
- :发散
- :不确定
积分判别法:若 单调递减且非负,则 与 同敛散。
交错级数
莱布尼茨判别法:若 单调递减趋于 ,则 收敛。
绝对收敛与条件收敛
- 绝对收敛: 收敛
- 条件收敛: 收敛但 发散
重要性质:
- 绝对收敛的级数必收敛
- 绝对收敛的级数可以重排,重排后仍收敛且和不变
- 条件收敛的级数可以通过重排收敛到任意值(黎曼重排定理)
函数项级数
一致收敛
在 上一致收敛于 :
与逐点收敛的区别:一致收敛要求 不依赖于 。
魏尔斯特拉斯 M 判别法
若有 收敛且 ,则 一致收敛。
一致收敛的性质
- 连续性:若 连续且一致收敛于 ,则 连续
- 可积性:若 可积且一致收敛于 ,则 可积且积分可以逐项积分
- 可微性:若 可导, 一致收敛,且 至少一点收敛,则 一致收敛于 ,且
幂级数
幂级数的定义
收敛半径
由柯西-阿达马公式:
幂级数的性质
- 在 内绝对收敛
- 和函数连续、可导、可积
- 逐项求导、逐项积分不改变收敛半径
傅里叶级数
傅里叶级数的定义
周期为 的函数 的傅里叶级数:
其中:
狄利克雷定理
若 在 上分段光滑,则傅里叶级数在每一点收敛到 的左右极限的平均值。
帕塞瓦尔恒等式
傅里叶级数在机器学习中的应用
- 信号处理:频域分析的基础
- 卷积神经网络:傅里叶变换是理解卷积运算频域特性的工具
- 数据压缩:傅里叶级数的高频截断实现有损压缩
多元函数分析
多元函数的极限与连续
二重极限
定义为:
累次极限
- 先对 取极限:
- 先对 取极限:
注意:两者不一定相等,即使都存在。
反例:
累次极限存在且都等于 ,但二重极限不存在。
偏导数
偏导数的定义
偏导数表示函数沿坐标轴方向的变化率。
高阶偏导数
施瓦茨定理:若 和 在点 连续,则 。
全微分
全微分的定义
若全微分存在,则函数在该点可微。
可微的条件
必要条件:若 在 可微,则偏导数存在。
充分条件:若偏导数在 的邻域内存在且连续,则 在 可微。
全微分在近似计算中的应用
方向导数与梯度
方向导数
方向的方向导数:
其中 是单位向量。
梯度
梯度与方向导数的关系
方向导数可以表示为梯度与方向向量的点积:
其中 是梯度方向与 方向的夹角。
重要推论:
- 梯度方向是函数值增加最快的方向
- 梯度的模是方向导数的最大值
机器学习含义:在梯度下降算法中,我们沿着梯度的负方向更新参数,因为那是函数值下降最快的方向。
链式法则(多元情形)
若 ,,,则:
更一般地,若 ,,则:
隐函数定理
单个方程的情形
若 ,且 ,则在 附近唯一确定 ,且:
多个方程的情形
方程组:
在一定条件下可确定 ,。
多元函数的极值
无条件极值
必要条件:若 在 处取得极值且偏导数存在,则 。
充分条件:设 ,记:
则:
- :极小值
- :极大值
- :鞍点
- :需进一步分析
条件极值(拉格朗日乘数法)
在约束条件 下求 的极值:
构造拉格朗日函数:
解方程组:
拉格朗日乘数法在机器学习中的应用
支持向量机的最大间隔优化:
主成分分析:在正交约束下最大化方差。
雅可比矩阵与海森矩阵
雅可比矩阵
对于向量值函数 :
海森矩阵
标量函数 的二阶偏导数矩阵:
在优化中的角色:海森矩阵决定了目标函数的局部曲率,是牛顿法收敛性的关键。
多元泰勒展开
在 处的二阶泰勒展开:
测度论初步
测度的直观背景
为什么要引入测度
黎曼积分在处理不连续函数、极限与积分交换等问题时存在局限。勒贝格测度提供了一种更一般的积分理论,解决了这些问题。
外测度
对任意集合 ,定义外测度:
其中 是区间, 是区间长度。
可测集
集合 是勒贝格可测的,当且仅当对任意集合 :
勒贝格测度的性质
- 非负性:
- 空集测度为零:
- 可数可加性:若 两两不相交,则
- 平移不变性:
可测函数
可测函数的定义
是可测的,当且仅当对任意 :
是可测集。
简单函数
简单函数是可测函数的”基本构件”:
其中 是集合 的特征函数。
可测函数的性质
- 可测函数列的极限是可测的
- 可测函数与连续函数的乘积是可测的
勒贝格积分
简单函数的积分
对非负简单函数:
非负可测函数的积分
一般可测函数的积分
将 分解为正部与负部:
若至少一个无穷,则积分可能无定义。
勒贝格积分与黎曼积分的比较
| 特性 | 黎曼积分 | 勒贝格积分 |
|---|---|---|
| 可积函数类 | 有界且间断点少的函数 | 更广泛的可测函数 |
| 极限交换 | 需一致收敛等强条件 | 只需一致有界收敛等弱条件 |
| 计算方法 | 分区间求和 | 分值域求和 |
概率论中的测度论
概率空间 是测度空间的特例:
- :样本空间
- :-代数(事件域)
- :概率测度
随机变量是到 的可测映射。
函数空间与泛函分析基础
赋范线性空间
范数的定义
满足:
- 正定性:,且
- 齐次性:
- 三角不等式:
常见范数
在 中:
- 范数:
- 范数(欧几里得范数):
- 范数:
- 范数:
范数与距离
范数诱导的距离(度量):
巴拿赫空间与希尔伯特空间
巴拿赫空间
完备的赋范线性空间称为巴拿赫空间。
完备性:所有柯西序列都收敛到空间内。
上的任何范数都诱导完备空间。
希尔伯特空间
完备的内积空间称为希尔伯特空间。
内积 满足:
- 共轭对称性:
- 线性性:
- 正定性:,且
内积空间自动是赋范空间:
勒贝esgue 空间
空间的定义
范数定义为:
重要不等式
赫尔德不等式:若 且 ,则:
明可夫斯基不等式:
空间
是希尔伯特空间,内积为:
在信号处理和量子力学中, 空间是基本框架。
算子范数
有界线性算子
是有界线性算子:
算子范数的计算
对于矩阵 :
- 诱导的 范数:(最大奇异值)
- 诱导的 范数:(列范数)
- 诱导的 范数:(行范数)
巴拿赫不动点定理(压缩映射定理)
定理陈述
设 是完备度量空间, 是压缩映射,即 ,使得:
则 有唯一不动点。
在机器学习中的应用
梯度下降法的收敛性分析:在某些条件下,梯度下降可以视为在参数空间上的压缩映射,从而保证收敛到全局最优。
神经网络训练:在适当的假设下,神经网络的训练过程可以映射到参数空间上的压缩映射,保证了解的收敛性。
数学分析在人工智能中的应用
深度学习中的优化理论
梯度下降法
参数更新规则:
其中 是损失函数, 是学习率。
收敛性分析:对于凸函数,梯度下降法在适当条件下收敛到全局最优。
随机梯度下降(SGD)
使用随机近似:
其中 是随机采样的样本。
数学分析工具:
- 鞅收敛定理
- 随机过程的大数定律
- 随机微分方程的渐近分析
动量法
物理含义:参数更新带有惯性,加速收敛。
信息论基础
熵的定义
离散随机变量 的香农熵:
连续随机变量的微分熵:
KL 散度
两个分布 和 之间的 KL 散度:
非负性:,当且仅当 时取等。
吉布斯不等式:,当且仅当 时取等。
互信息
互信息衡量两个变量之间的相关性。
变分推断
变分法的基本思想
在贝叶斯推断中,我们希望最小化真实后验 与近似分布 之间的 KL 散度。
ELBO(证据下界)
其中:
由于 KL 散度非负,,因此称为下界。
变分推断的目标是最大化 ELBO。
代码实现:梯度下降
import numpy as np
def gradient_descent(gradient_fn, x_init, learning_rate=0.01,
max_iterations=1000, tolerance=1e-6):
"""
梯度下降优化算法
Parameters:
-----------
gradient_fn : callable
梯度函数,接受当前参数值,返回梯度
x_init : array-like
初始参数
learning_rate : float
学习率
max_iterations : int
最大迭代次数
tolerance : float
收敛阈值(梯度范数小于此值时停止)
Returns:
--------
x : array
优化后的参数
history : list
迭代历史记录
"""
x = np.array(x_init, dtype=np.float64)
history = [x.copy()]
for i in range(max_iterations):
grad = gradient_fn(x)
grad_norm = np.linalg.norm(grad)
if grad_norm < tolerance:
print(f"Converged at iteration {i}")
break
x = x - learning_rate * grad
history.append(x.copy())
return x, history
def stochastic_gradient_descent(gradient_fn, x_init, data,
learning_rate=0.01, batch_size=32,
max_epochs=100, tolerance=1e-6):
"""
随机梯度下降算法
Parameters:
-----------
gradient_fn : callable
随机梯度函数,接受参数和数据批次
x_init : array-like
初始参数
data : tuple
(X, y) 训练数据
learning_rate : callable
学习率函数或常数,如果是函数,接受当前epoch返回学习率
batch_size : int
批次大小
max_epochs : int
最大epoch数
tolerance : float
收敛阈值
"""
X, y = data
n_samples = len(X)
x = np.array(x_init, dtype=np.float64)
history = []
for epoch in range(max_epochs):
indices = np.random.permutation(n_samples)
for i in range(0, n_samples, batch_size):
batch_idx = indices[i:i + batch_size]
X_batch = X[batch_idx]
y_batch = y[batch_idx]
grad = gradient_fn(x, X_batch, y_batch)
lr = learning_rate(epoch) if callable(learning_rate) else learning_rate
x = x - lr * grad
history.append(x.copy())
if len(history) >= 2:
param_change = np.linalg.norm(history[-1] - history[-2])
if param_change < tolerance:
print(f"Converged at epoch {epoch}")
break
return x, history
def momentum_gradient_descent(gradient_fn, x_init, learning_rate=0.01,
momentum=0.9, max_iterations=1000,
tolerance=1e-6):
"""
带动量的梯度下降
Parameters:
-----------
gradient_fn : callable
梯度函数
x_init : array-like
初始参数
learning_rate : float
学习率
momentum : float
动量系数
"""
x = np.array(x_init, dtype=np.float64)
v = np.zeros_like(x)
history = []
for i in range(max_iterations):
grad = gradient_fn(x)
grad_norm = np.linalg.norm(grad)
if grad_norm < tolerance:
print(f"Converged at iteration {i}")
break
v = momentum * v + learning_rate * grad
x = x - v
history.append({
'x': x.copy(),
'v': v.copy(),
'grad_norm': grad_norm
})
return x, history
def adam_optimizer(gradient_fn, x_init, learning_rate=0.001,
beta1=0.9, beta2=0.999, epsilon=1e-8,
max_iterations=1000, tolerance=1e-6):
"""
Adam 优化器实现
Adam 结合了动量法和 RMSProp 的优点,
使用梯度的一阶矩估计和二阶矩估计来自适应调整学习率
Parameters:
-----------
gradient_fn : callable
梯度函数
x_init : array-like
初始参数
learning_rate : float
步长
beta1, beta2 : float
矩估计的指数衰减率
epsilon : float
数值稳定项
"""
x = np.array(x_init, dtype=np.float64)
m = np.zeros_like(x) # 一阶矩估计(动量)
v = np.zeros_like(x) # 二阶矩估计(RMSProp)
history = []
for t in range(1, max_iterations + 1):
grad = gradient_fn(x)
grad_norm = np.linalg.norm(grad)
if grad_norm < tolerance:
print(f"Converged at iteration {t}")
break
# 更新一阶矩估计
m = beta1 * m + (1 - beta1) * grad
# 更新二阶矩估计
v = beta2 * v + (1 - beta2) * (grad ** 2)
# 偏差校正
m_hat = m / (1 - beta1 ** t)
v_hat = v / (1 - beta2 ** t)
# 参数更新
x = x - learning_rate * m_hat / (np.sqrt(v_hat) + epsilon)
history.append({
'x': x.copy(),
'm': m.copy(),
'v': v.copy(),
'grad_norm': grad_norm
})
return x, history
# 示例:优化 Rosenbrock 函数
def rosenbrock(x):
"""Rosenbrock 函数:非凸优化基准函数"""
return sum(100 * (x[1:] - x[:-1]**2)**2 + (1 - x[:-1])**2)
def rosenbrock_gradient(x):
"""Rosenbrock 函数的梯度"""
grad = np.zeros_like(x)
grad[0] = -400 * x[0] * (x[1] - x[0]**2) + 2 * (x[0] - 1)
grad[-1] = 200 * (x[-1] - x[-2]**2)
grad[1:-1] = (200 * (x[1:-1] - x[:-2]**2) -
400 * x[1:-1] * (x[2:] - x[1:-1]**2) +
2 * (x[1:-1] - 1))
return grad
if __name__ == "__main__":
# 测试梯度下降
x_init = np.array([-1.0, 1.0])
print("Testing Gradient Descent...")
x_opt, history_gd = gradient_descent(
rosenbrock_gradient, x_init,
learning_rate=0.001, max_iterations=10000
)
print(f"GD Result: x = {x_opt}, f(x) = {rosenbrock(x_opt):.6f}")
print("\nTesting Momentum GD...")
x_opt, history_mom = momentum_gradient_descent(
rosenbrock_gradient, x_init,
learning_rate=0.001, momentum=0.9, max_iterations=10000
)
print(f"Momentum Result: x = {x_opt}, f(x) = {rosenbrock(x_opt):.6f}")
print("\nTesting Adam...")
x_opt, history_adam = adam_optimizer(
rosenbrock_gradient, x_init,
learning_rate=0.001, max_iterations=10000
)
print(f"Adam Result: x = {x_opt}, f(x) = {rosenbrock(x_opt):.6f}")代码实现:自动微分框架
import numpy as np
from typing import List, Tuple, Callable
class Value:
"""
自动微分中的标量变量
支持前向模式和反向模式自动微分
"""
def __init__(self, data: float, children: Tuple['Value', ...] = (),
op: str = '', label: str = ''):
self.data = float(data)
self.grad = 0.0
self._backward = lambda: None
self._prev = set(children)
self._op = op
self.label = label
def __repr__(self):
return f"Value(data={self.data:.4f}, grad={self.grad:.4f})"
def __add__(self, other):
other = other if isinstance(other, Value) else Value(other)
out = Value(self.data + other.data, (self, other), '+')
def _backward():
self.grad += out.grad
other.grad += out.grad
out._backward = _backward
return out
def __radd__(self, other):
return self.__add__(other)
def __mul__(self, other):
other = other if isinstance(other, Value) else Value(other)
out = Value(self.data * other.data, (self, other), '*')
def _backward():
self.grad += other.data * out.grad
other.grad += self.data * out.grad
out._backward = _backward
return out
def __rmul__(self, other):
return self.__mul__(other)
def __pow__(self, other):
assert isinstance(other, (int, float))
out = Value(self.data ** other, (self,), f'**{other}')
def _backward():
self.grad += (other * self.data ** (other - 1)) * out.grad
out._backward = _backward
return out
def relu(self):
out = Value(0 if self.data < 0 else self.data, (self,), 'ReLU')
def _backward():
self.grad += (out.data > 0) * out.grad
out._backward = _backward
return out
def backward(self):
"""反向传播算法"""
topo = []
visited = set()
def build_topo(v):
if v not in visited:
visited.add(v)
for child in v._prev:
build_topo(child)
topo.append(v)
build_topo(self)
self.grad = 1.0
for v in reversed(topo):
v._backward()
def zero_grad(self):
"""清零梯度"""
self.grad = 0.0
for child in self._prev:
child.zero_grad()
class Tensor:
"""
多维张量的自动微分实现
"""
def __init__(self, data: np.ndarray, requires_grad: bool = False):
self.data = np.array(data, dtype=np.float64)
self.requires_grad = requires_grad
self.grad = None
self._backward_fn = None
if requires_grad:
self.grad = np.zeros_like(self.data)
@property
def shape(self):
return self.data.shape
@property
def ndim(self):
return self.data.ndim
def __repr__(self):
return f"Tensor({self.data}, requires_grad={self.requires_grad})"
def backward(self):
if not self.requires_grad:
raise RuntimeError("Tensor does not require grad")
if self.grad is None:
self.grad = np.ones_like(self.data)
# 拓扑排序
topo = []
visited = set()
def build_topo(t):
if id(t) not in visited:
visited.add(id(t))
if t._backward_fn:
for child in t._backward_fn.children:
build_topo(child)
topo.append(t)
build_topo(self)
for t in reversed(topo):
if t._backward_fn:
t._backward_fn.apply()
def zero_grad(self):
if self.grad is not None:
self.grad.fill(0)
if self._backward_fn:
for child in self._backward_fn.children:
child.zero_grad()
class MulBackward:
def __init__(self, children: List[Tensor], other_data: np.ndarray, axis=None):
self.children = children
self.other_data = other_data
self.axis = axis
def apply(self):
for child in self.children:
if child.requires_grad:
if self.axis is None:
child.grad += self.other_data * child.grad
else:
child.grad += self.other_data * child.grad
def matmul_backward_fn(x: Tensor, y: Tensor, out: Tensor):
"""矩阵乘法的反向传播"""
def backward():
if x.requires_grad:
x.grad += out.grad @ y.data.T
if y.requires_grad:
y.grad += x.data.T @ out.grad
return backward
class TensorOps:
"""张量运算"""
@staticmethod
def matmul(a: Tensor, b: Tensor) -> Tensor:
out = Tensor(a.data @ b.data, requires_grad=a.requires_grad or b.requires_grad)
out._backward_fn = matmul_backward_fn(a, b, out)
return out
@staticmethod
def add(a: Tensor, b: Tensor) -> Tensor:
out = Tensor(a.data + b.data, requires_grad=a.requires_grad or b.requires_grad)
def backward():
if a.requires_grad:
a.grad += out.grad
if b.requires_grad:
b.grad += out.grad
out._backward_fn = type('Backward', (), {'apply': backward, 'children': [a, b]})()
return out
@staticmethod
def relu(x: Tensor) -> Tensor:
out = Tensor(np.maximum(0, x.data), requires_grad=x.requires_grad)
def backward():
if x.requires_grad:
x.grad += (x.data > 0).astype(np.float64) * out.grad
out._backward_fn = type('Backward', (), {'apply': backward, 'children': [x]})()
return out
@staticmethod
def sigmoid(x: Tensor) -> Tensor:
out = Tensor(1 / (1 + np.exp(-x.data)), requires_grad=x.requires_grad)
def backward():
if x.requires_grad:
x.grad += out.data * (1 - out.data) * out.grad
out._backward_fn = type('Backward', (), {'apply': backward, 'children': [x]})()
return out
# 示例:使用自动微分实现简单的神经网络层
class LinearLayer:
"""线性(全连接)层"""
def __init__(self, input_dim: int, output_dim: int):
scale = np.sqrt(2.0 / input_dim)
self.W = Tensor(np.random.randn(input_dim, output_dim) * scale, requires_grad=True)
self.b = Tensor(np.zeros(output_dim), requires_grad=True)
def forward(self, x: Tensor) -> Tensor:
out = TensorOps.matmul(x, self.W)
out = TensorOps.add(out, self.b)
return out
def parameters(self) -> List[Tensor]:
return [self.W, self.b]
class MLP:
"""多层感知机"""
def __init__(self, input_dim: int, hidden_dims: List[int], output_dim: int):
dims = [input_dim] + hidden_dims + [output_dim]
self.layers = []
for i in range(len(dims) - 1):
self.layers.append(LinearLayer(dims[i], dims[i+1]))
def forward(self, x: Tensor) -> Tensor:
for i, layer in enumerate(self.layers):
x = layer.forward(x)
if i < len(self.layers) - 1:
x = TensorOps.relu(x)
return x
def parameters(self) -> List[Tensor]:
params = []
for layer in self.layers:
params.extend(layer.parameters())
return params
if __name__ == "__main__":
# 测试 Value 的自动微分
print("=== Testing Value Auto-Diff ===")
a = Value(2.0, label='a')
b = Value(3.0, label='b')
c = a * b + a ** 2
c.backward()
print(f"a = {a.data}, da/dc = {a.grad}")
print(f"b = {b.data}, db/dc = {b.grad}")
print(f"c = {c.data}")
# 测试 Tensor 的自动微分
print("\n=== Testing Tensor Auto-Diff ===")
x = Tensor(np.array([1.0, 2.0, 3.0]), requires_grad=True)
w = Tensor(np.array([0.5, -0.5, 0.25]), requires_grad=True)
y = TensorOps.matmul(x.reshape(1, 3), w.reshape(3, 1))
y.backward()
print(f"x.grad = {x.grad}")
print(f"w.grad = {w.grad}")
# 测试 MLP
print("\n=== Testing MLP ===")
mlp = MLP(input_dim=4, hidden_dims=[8, 8], output_dim=2)
x = Tensor(np.random.randn(1, 4), requires_grad=True)
y = mlp.forward(x)
print(f"Input shape: {x.shape}")
print(f"Output: {y.data}")
print(f"Number of parameters: {len(mlp.parameters())}")延伸阅读与参考文献
经典教材
- 《数学分析原理》(Principles of Mathematical Analysis)- Walter Rudin
- 《数学分析》(Mathematical Analysis)- Tom M. Apostol
- 《实分析与复分析》(Real and Complex Analysis)- Walter Rudin
- 《陶哲轩实分析》(Analysis I, II)- Terence Tao
机器学习相关数学
- 《深度学习》(Deep Learning)- Ian Goodfellow, Yoshua Bengio, Aaron Courville
- 《统计学习方法》- 李航
- 《机器学习的数学》- 石溪
在线资源
- MIT OpenCourseWare: Single Variable Calculus
- MIT OpenCourseWare: Multivariable Calculus
- Khan Academy: Calculus
附录:补充专题
A. 非标准分析简介
为什么要了解非标准分析
非标准分析提供了处理无穷小量的严格工具,可以简化许多分析中的证明。在机器学习语境下,它可以帮助我们更直观地理解收敛性、连续性等概念。
超实数系
超实数系 包含:
- 所有实数
- 无穷小数(严格小于所有正实数的数)
- 无穷大数(严格大于所有实数的数)
转移原理
在 中成立的命题,在 中同样成立(适当解释)。
B. 凸分析的扩展
凸函数的深刻性质
定理: 凸 其 epigraph 是凸集
其中 epigraph 定义为
次微分
在 处的次梯度 满足:
次微分 是 处所有次梯度的集合。
在优化中的应用:次梯度法处理不可微凸函数。
C. 测度论进阶
博雷尔 -代数
上的博雷尔 -代数 是包含所有开集的最小 -代数。
性质: 由所有开区间生成,包含所有开集、闭集、可数集等。
拉东-尼科迪姆定理
若 是 -有限测度, 是 的绝对连续符号测度,则存在 使得:
称为拉东-尼科迪姆导数,记作 。
D. 分布理论初步
测试函数
: 上无穷阶连续且紧支撑的函数空间。
分布
上的连续线性泛函称为分布。
例子:
- Dirac 分布 :
- 分布的导数:分布 的导数定义为
E. 傅里叶分析进阶
傅里叶变换
逆变换
帕塞瓦尔恒等式
F. 小波分析入门
小波基
不同于傅里叶基,小波基同时提供时域和频域信息:
多分辨率分析
通过尺度函数 和小波函数 构建函数空间的嵌套序列。
附录:习题与解答
证明题精选
题目1:证明
证明:使用斯特林公式的粗略版本或比值判别法。
题目2:证明 上的任何范数都等价于欧几里得范数
证明:在有限维空间中,所有范数等价。
题目3:设 在 上可微,证明 在 上不一定连续。
反例: 当 ,。
计算题精选
题目1:求
解答:使用泰勒展开或洛必达法则(多次)。
梯度下降法的收敛性分析
凸函数情形
定理:设 是凸函数且 是 -Lipschitz 连续的(),则使用固定步长 的梯度下降满足:
这称为梯度下降的下降引理。
收敛速率
对于凸函数:
- 非强凸: 收敛到最优值附近
- 强凸(): 线性收敛
随机梯度下降的收敛性
对于随机梯度下降(SGD),在适当条件下有:
- 凸函数: 收敛
- 强凸函数: 收敛
自适应学习率方法
AdaGrad:
Adam 结合了动量法和 RMSProp 的思想。
拉格朗日乘数法的扩展
Karush-Kuhn-Tucker 条件
对于约束优化问题:
KKT 条件给出最优解的必要条件:
- 原始可行性:
- 对偶可行性:
- 互补松弛:
- 稳定点条件:
变分法的基本框架
泛函与变分
泛函:从函数空间到实数的映射
变分:
欧拉-拉格朗日方程
泛函 的极值满足:
应用:
- 最短路径(直线)
- 最速降线(摆线)
- 测地线
蒙特卡洛方法的数学基础
大数定律的应用
设 是独立同分布的随机变量,,则:
蒙特卡洛积分:
其中
Metropolis-Hastings 算法
马尔可夫链理论
Metropolis-Hastings 算法构造一个马尔可夫链,使其平稳分布为目标分布 。
细致平衡条件:
收敛性分析
在适当条件下,马尔可夫链的分布收敛到平稳分布:
这为 MCMC 方法提供了理论基础。
代码实现:高级优化算法
import numpy as np
from scipy.linalg import lu_solve, lu_factor
class NewtonOptimizer:
"""
牛顿优化器
使用二阶信息(海森矩阵)加速收敛
"""
def __init__(self, function, gradient, hessian,
line_search='backtracking', max_iterations=100,
tolerance=1e-6):
self.function = function
self.gradient = gradient
self.hessian = hessian
self.line_search = line_search
self.max_iterations = max_iterations
self.tolerance = tolerance
def optimize(self, x_init):
x = x_init.copy()
history = []
for k in range(self.max_iterations):
grad = self.gradient(x)
grad_norm = np.linalg.norm(grad)
if grad_norm < self.tolerance:
print(f"Converged at iteration {k}")
break
H = self.hessian(x)
# 使用 Cholesky 分解(如果 H 正定)
try:
L = np.linalg.cholesky(H)
p = lu_solve(lu_factor(H.T), -grad)
except np.linalg.LinAlgError:
# 如果不正定,使用阻尼牛顿法
damping = 0.001
H_reg = H + damping * np.eye(len(x))
p = -np.linalg.solve(H_reg, grad)
# 线搜索
alpha = self._line_search(x, p, grad)
x = x + alpha * p
history.append({
'iteration': k,
'x': x.copy(),
'f': self.function(x),
'grad_norm': grad_norm
})
return x, history
def _line_search(self, x, p, grad, c1=1e-4, rho=0.9):
"""回溯线搜索(Armijo 条件)"""
alpha = 1.0
f0 = self.function(x)
while self.function(x + alpha * p) > f0 + c1 * alpha * np.dot(grad, p):
alpha *= rho
return alpha
class ConjugateGradient:
"""
共轭梯度法
适用于大规模稀疏线性系统和优化问题
"""
def __init__(self, function, gradient, max_iterations=1000,
tolerance=1e-6):
self.function = function
self.gradient = gradient
self.max_iterations = max_iterations
self.tolerance = tolerance
def optimize(self, x_init):
x = x_init.copy()
g = self.gradient(x)
d = -g # 初始搜索方向
for k in range(self.max_iterations):
grad_norm = np.linalg.norm(g)
if grad_norm < self.tolerance:
print(f"Converged at iteration {k}")
break
# 线搜索步长
alpha = self._line_search(x, d)
x_new = x + alpha * d
g_new = self.gradient(x_new)
# β 参数(FR, PR, HS 等不同公式)
beta = np.dot(g_new, g_new) / np.dot(g, g) # Fletcher-Reeves
# PR 公式(Polak-Ribiere)
# beta = np.dot(g_new, g_new - g) / np.dot(g, g)
d = -g_new + beta * d
x = x_new
g = g_new
return x, {'iterations': k, 'final_grad_norm': grad_norm}
def _line_search(self, x, d, c1=1e-4, rho=0.9):
"""简化线搜索"""
alpha = 1.0
f0 = self.function(x)
g0 = np.dot(self.gradient(x), d)
while self.function(x + alpha * d) > f0 + c1 * alpha * g0:
alpha *= rho
return alpha
class BFGSOptimizer:
"""
BFGS 拟牛顿法
用海森矩阵的近似来加速优化
"""
def __init__(self, function, gradient, max_iterations=1000,
tolerance=1e-6):
self.function = function
self.gradient = gradient
self.max_iterations = max_iterations
self.tolerance = tolerance
def optimize(self, x_init):
n = len(x_init)
x = x_init.copy()
H = np.eye(n) # 初始海森近似
g = self.gradient(x)
for k in range(self.max_iterations):
grad_norm = np.linalg.norm(g)
if grad_norm < self.tolerance:
print(f"Converged at iteration {k}")
break
# 搜索方向
d = -H @ g
# 线搜索
alpha = self._line_search(x, d, g)
# 更新
x_new = x + alpha * d
g_new = self.gradient(x_new)
s = x_new - x
y = g_new - g
# BFGS 更新公式
if np.dot(y, s) > 0: # 确保正定性
rho = 1.0 / np.dot(y, s)
I = np.eye(n)
H = (I - rho * np.outer(s, y)) @ H @ (I - rho * np.outer(y, s)) + rho * np.outer(s, s)
x = x_new
g = g_new
return x, {'iterations': k}
def _line_search(self, x, d, g, c1=1e-4, rho=0.9):
"""Armijo 线搜索"""
alpha = 1.0
f0 = self.function(x)
g0 = np.dot(g, d)
for _ in range(20):
if self.function(x + alpha * d) <= f0 + c1 * alpha * g0:
break
alpha *= rho
return alpha
# 测试函数
if __name__ == "__main__":
# Rosenbrock 函数
def rosenbrock(x):
return sum(100 * (x[1:] - x[:-1]**2)**2 + (1 - x[:-1])**2)
def rosenbrock_grad(x):
grad = np.zeros_like(x)
grad[0] = -400 * x[0] * (x[1] - x[0]**2) + 2 * (x[0] - 1)
grad[-1] = 200 * (x[-1] - x[-2]**2)
grad[1:-1] = (200 * (x[1:-1] - x[:-2]**2) -
400 * x[1:-1] * (x[2:] - x[1:-1]**2) +
2 * (x[1:-1] - 1))
return grad
def rosenbrock_hess(x):
n = len(x)
H = np.zeros((n, n))
H[0, 0] = -400 * (x[1] - x[0]**2) + 800 * x[0]**2 + 2
H[0, 1] = -400 * x[0]
for i in range(1, n-1):
H[i, i-1] = -400 * x[i-1]
H[i, i] = 200 + 1200 * x[i]**2 - 400 * x[i+1] + 2
H[i, i+1] = -400 * x[i]
H[-1, -2] = -400 * x[-2]
H[-1, -1] = 200
return H
x_init = np.array([-1.0, 1.0])
print("Testing Newton Optimizer...")
newton = NewtonOptimizer(rosenbrock, rosenbrock_grad, rosenbrock_hess)
x_opt, _ = newton.optimize(x_init.copy())
print(f"Newton: f(x) = {rosenbrock(x_opt):.6f}")
print("\nTesting BFGS...")
bfgs = BFGSOptimizer(rosenbrock, rosenbrock_grad)
x_opt, _ = bfgs.optimize(x_init.copy())
print(f"BFGS: f(x) = {rosenbrock(x_opt):.6f}")
print("\nTesting CG...")
cg = ConjugateGradient(rosenbrock, rosenbrock_grad)
x_opt, _ = cg.optimize(x_init.copy())
print(f"CG: f(x) = {rosenbrock(x_opt):.6f}")代码实现:自适应积分
import numpy as np
from typing import Callable
class AdaptiveIntegrator:
"""
自适应积分(Simpson 法则)
根据函数行为自动调整采样点密度
"""
def __init__(self, tol=1e-6, max_depth=50):
self.tol = tol
self.max_depth = max_depth
def integrate(self, f: Callable, a: float, b: float) -> float:
"""自适应的 Simpson 积分"""
return self._adaptive_simpson(f, a, b, self.tol, 0)
def _simpson(self, f: Callable, a: float, b: float) -> float:
"""Simpson 公式"""
c = (a + b) / 2
return (b - a) / 6 * (f(a) + 4 * f(c) + f(b))
def _adaptive_simpson(self, f: Callable, a: float, b: float,
tol: float, depth: int) -> float:
"""自适应 Simpson 法则的递归实现"""
if depth > self.max_depth:
return self._simpson(f, a, b)
c = (a + b) / 2
left = self._simpson(f, a, c)
right = self._simpson(f, c, b)
whole = self._simpson(f, a, b)
if abs(left + right - whole) < 15 * tol:
return left + right + (left + right - whole) / 15
return (self._adaptive_simpson(f, a, c, tol / 2, depth + 1) +
self._adaptive_simpson(f, c, b, tol / 2, depth + 1))
class MonteCarloIntegrator:
"""
蒙特卡洛积分
高维积分的有效方法
"""
def __init__(self, seed=None):
if seed is not None:
np.random.seed(seed)
def integrate(self, f: Callable, bounds: list, n_samples: int = 10000) -> tuple:
"""
多维蒙特卡洛积分
Parameters:
-----------
f : callable
被积函数
bounds : list of (min, max) tuples
每个维度的积分边界
n_samples : int
采样点数
Returns:
--------
integral : float
积分估计值
variance : float
估计的方差
"""
dim = len(bounds)
# 在超立方体内均匀采样
samples = np.zeros((n_samples, dim))
for i, (lo, hi) in enumerate(bounds):
samples[:, i] = np.random.uniform(lo, hi, n_samples)
# 计算函数值
f_values = np.array([f(s) for s in samples])
# 计算体积
volume = 1.0
for lo, hi in bounds:
volume *= (hi - lo)
# 积分估计
integral = volume * np.mean(f_values)
# 方差估计
variance = volume**2 * np.var(f_values) / n_samples
return integral, variance
def stratified_sampling(self, f: Callable, bounds: list,
n_samples: int = 10000) -> float:
"""
分层采样蒙特卡洛
通过分层采样减少方差
"""
dim = len(bounds)
# 每层一个采样点
n_strata = int(np.sqrt(n_samples))
samples_per_stratum = n_samples // (n_strata ** dim)
samples = []
f_values = []
# 递归生成分层采样点
def generate_samples(dim_idx, samples_so_far, samples_per_stratum):
if dim_idx == dim:
# 在当前超矩形中采样
for _ in range(samples_per_stratum):
point = np.array(samples_so_far)
for d in range(dim):
lo, hi = bounds[d]
point[d] = np.random.uniform(lo, hi)
samples.append(point)
else:
lo, hi = bounds[dim_idx]
n_sub = n_strata
sub_size = (hi - lo) / n_sub
for i in range(n_sub):
generate_samples(dim_idx + 1,
samples_so_far + [lo + i * sub_size],
samples_per_stratum)
generate_samples(0, [], 1)
samples = np.array(samples)
f_values = np.array([f(s) for s in samples])
volume = 1.0
for lo, hi in bounds:
volume *= (hi - lo)
return volume * np.mean(f_values)
class GaussianQuadrature:
"""
高斯求积
使用最优节点实现高精度积分
"""
def __init__(self, n_points):
self.n_points = n_points
self._compute_nodes_weights()
def _compute_nodes_weights(self):
"""计算 Gauss-Legendre 节点和权重"""
from scipy.special import roots_legendre
self.nodes, self.weights = roots_legendre(self.n_points)
def integrate(self, f: Callable) -> float:
"""积分 [-1, 1] 区间"""
f_values = f(self.nodes)
return np.sum(self.weights * f_values)
def integrate_interval(self, f: Callable, a: float, b: float) -> float:
"""积分 [a, b] 区间"""
# 变量替换
midpoint = (b + a) / 2
half_width = (b - a) / 2
def transformed_f(t):
return f(midpoint + half_width * t)
return half_width * self.integrate(transformed_f)
# 示例
if __name__ == "__main__":
print("=== Numerical Integration Demo ===")
# 测试函数
def f1(x):
return np.exp(-x**2)
# 自适应 Simpson
integrator = AdaptiveIntegrator(tol=1e-10)
result = integrator.integrate(f1, -10, 10)
print(f"Adaptive Simpson: ∫exp(-x²)dx from -10 to 10 ≈ {result:.10f}")
print(f"Exact (error function): ≈ {np.sqrt(np.pi):.10f}")
# 蒙特卡洛
print("\nMonte Carlo Integration:")
mc = MonteCarloIntegrator(seed=42)
# 2D 积分
def f2(x):
return np.exp(-np.sum(x**2))
bounds = [(-2, 2), (-2, 2)]
result, var = mc.integrate(f2, bounds, n_samples=100000)
print(f"2D integral: ≈ {result:.6f} ± {np.sqrt(var):.6f}")
print(f"Exact: ≈ {np.pi:.6f}")
# 高斯求积
print("\nGaussian Quadrature:")
gq = GaussianQuadrature(n_points=10)
result = gq.integrate_interval(f1, -10, 10)
print(f"Gauss-Legendre (10 points): ≈ {result:.10f}")符号表
| 符号 | 含义 |
|---|---|
| 自然数集 | |
| 整数集 | |
| 有理数集 | |
| 实数集 | |
| 复数集 | |
| 极限 | |
| 上确界 | |
| 下确界 | |
| 梯度算子 | |
| 偏导数 | |
| 积分 | |
| 求和 | |
| 求积 |
名词索引
- 一致收敛:第3章
- 泰勒公式:第4章
- 傅里叶级数:第6章
- 雅可比矩阵:第7章
- 测度论:第8章
- 巴拿赫空间:第9章
- 压缩映射:第9章
本指南最后更新于 2026-04-19