数学分析深度指南

目录

  1. 引言与核心地位
  2. 实数体系的公理化构建
  3. 极限理论
  4. 连续性与可微性
  5. 积分理论
  6. 级数理论
  7. 多元函数分析
  8. 测度论初步
  9. 函数空间与泛函分析基础
  10. 数学分析在人工智能中的应用

引言与核心地位

数学分析在人工智能时代的复兴

数学分析作为现代数学的基石,其理论体系在21世纪的人工智能革命中焕发出前所未有的生命力。从深度学习的梯度下降算法到强化学习的价值函数逼近,从计算机视觉的卷积神经网络到自然语言处理的注意力机制,数学分析的基本概念——极限、连续、可微、积分——构成了这些算法理论分析的核心工具。

本指南旨在为人工智能研究者和工程师提供一份系统、深入、实用的数学分析参考文档。我们不仅讲解理论本身,更关注这些理论如何支撑现代机器学习算法的设计与分析,以及如何在实践中应用这些数学工具。

数学分析与其他数学分支的关系

数学分析并非孤立的学科,它是连接代数、几何、概率论的枢纽。在人工智能的语境下:

  • 线性代数 提供向量空间和矩阵运算的语言,数学分析在此基础上处理函数空间
  • 概率论 中的期望、方差等概念需要数学分析的极限工具进行严格化
  • 优化理论 本质上是数学分析中极值问题的延续和发展
  • 拓扑学 提供了研究连续性和收敛性的更一般框架

理解这些联系,对于构建完整的数学知识体系至关重要。


实数体系的公理化构建

为什么需要严格的实数理论

在人工智能的算法实现中,我们通常使用浮点数近似实数。然而,要理解梯度下降的收敛性、分析神经网络的表达能力、证明某些算法的正确性,必须建立在严格的实数理论基础之上。

浮点数系统虽然模拟了实数的主要性质,但存在精度误差、溢出、下溢等问题。理解实数体系的公理化结构,有助于我们在算法设计中规避这些数值陷阱。

实数的公理化定义

实数体系 可以通过以下公理系统唯一确定( up to isomorphism):

域公理(Field Axioms)

对加法和乘法构成域:

  1. 加法封闭性
  2. 加法交换律
  3. 加法结合律
  4. 加法单位元
  5. 加法逆元
  6. 乘法封闭性
  7. 乘法交换律
  8. 乘法结合律
  9. 乘法单位元
  10. 乘法逆元
  11. 分配律

序公理(Order Axioms)

在实数上定义全序关系

  1. 自反性
  2. 反对称性
  3. 传递性
  4. 完全性
  5. 与运算的协调性
  6. 正数乘法

完备性公理(Completeness Axiom)

这是实数区别于有理数的关键:

戴德金完备性:若 满足:

等价的叙述方式是上确界性质 的每个非空有上界子集都有上确界。

完备性公理的重要性

完备性公理是实数系分析性质的源头。它确保了:

  • 极限运算的合法性(收敛序列必有极限)
  • 连续函数的中介值性质
  • 积分的存在性

在算法分析中,完备性保证了我们在实数空间中进行极限运算时不会遇到”洞”。

重要不等式

实数理论中的一些关键不等式在机器学习算法分析中频繁出现:

三角不等式

更一般地:

柯西-施瓦茨不等式

对于内积空间中的向量:

中:

算术-几何平均不等式

当且仅当 时取等。

杨氏不等式

,则:


极限理论

数列的极限

ε-N 定义

数列 收敛于

这个定义是整个数学分析的基础。理解 论证是掌握严格数学推理的关键。

证明示例:

目标:证明

证明:给定 ,取 。则对所有

证毕。

证明示例:

证明:给定

需要 ,即

即可。

数列极限的性质

四则运算

,则:

夹逼定理

,则

应用:求

,取对数:

利用洛必达法则:

因此

收敛准则

单调有界收敛定理

单调递增且有上界的数列必收敛。

这是深度学习中许多迭代算法收敛性证明的基础。

柯西收敛准则

数列 收敛,当且仅当:

柯西准则的优势在于:证明收敛时不需要预先知道极限值。

函数极限

ε-δ 定义

单侧极限

  • 左极限:
  • 右极限:

函数极限存在的充要条件是左右极限存在且相等。

海涅定理(归结原则)

当且仅当对任何收敛于 的数列 ),都有

这个定理建立了数列极限与函数极限之间的桥梁,在机器学习中常用于证明神经网络函数序列的收敛性。


连续性与可微性

连续性的严格定义

点连续

在点 处连续:

等价于:

区间连续

在区间 上连续,记作 ,当且仅当 的每一点都连续。

连续函数的基本性质

最值定理

,则 上必能达到最大值和最小值。

机器学习含义:连续损失函数在紧集上必有极值点,保证全局最优或全局最差的存在性。

介值定理

,则

应用:二分搜索算法的理论基础。

一致连续性

上一致连续:

区别:普通连续性中 可能依赖于点 ;一致连续性中 是全局的,只依赖于

重要定理:康托尔定理:若 ,则 上一致连续。

可微性与导数

导数的定义

若极限存在,则 处可微。

几何意义:导数是切线斜率。

物理意义:导数是瞬时变化率。

可微与连续的关系

定理:若 处可微,则 处连续。

逆命题不成立 处连续但不可微。

导数的计算法则

  1. 线性法则
  2. 加法法则
  3. 乘法法则(莱布尼茨公式)
  4. 除法法则
  5. 链式法则

链式法则的严格证明

,且 处可微, 处可微。

定义:

取极限

因此

(可能发生但不影响结论),可类似证明。

高阶导数

表示 阶导数。

莱布尼茨公式

这与二项式定理结构相同。

微分中值定理

罗尔定理

满足:

  1. 上连续
  2. 内可导

拉格朗日中值定理

上连续,在 内可导,则

推论:若 ,则 单调递增。

柯西中值定理

上连续,在 内可导,且 ,则

泰勒公式

泰勒多项式

处的 阶泰勒多项式:

泰勒定理

在含 的开区间内有 阶连续导数,则:

其中拉格朗日余项:

常见函数的泰勒展开

指数函数

正弦函数

余弦函数

对数函数(在 处):

泰勒公式在机器学习中的应用

  1. 牛顿法:使用二阶泰勒展开近似目标函数
  2. 自然语言处理中的 softmax:使用指数函数的泰勒展开进行数值近似
  3. 激活函数的近似:如 sigmoid 的泰勒展开用于硬件实现

洛必达法则

0/0 型

,且 ,则:

前提是右侧极限存在(可以是有限值或 )。

∞/∞ 型

,则:

注意事项

  • 洛必达法则可以多次使用
  • 必须确保分子分母同时趋于 0 或无穷
  • 极限必须存在(不包括振荡情形)

反例

分子分母都趋于无穷,可以使用洛必达:


积分理论

定积分的定义

黎曼和

上有界。将 分成 个小区间:

取介点 ,定义黎曼和:

其中

达布定理

上积分: 下积分:

其中 分别是达布上和与达布下和。

可积的充要条件:上积分等于下积分。

可积函数类

以下函数类在闭区间上可积:

  1. 连续函数
  2. 单调有界函数
  3. 有有限个间断点的有界函数

定积分的性质

线性性

区间可加性

保序性

,则:

绝对值不等式

微积分基本定理

第一基本定理

上连续,则:

上可导,且

第二基本定理(牛顿-莱布尼茨公式)

的原函数,则:

这是计算定积分的核心公式。

不定积分

原函数与不定积分

,则 称为 的原函数。

的全体原函数称为不定积分:

其中 是常数。

换元积分法

第一换元法(凑微分)

的原函数,则:

第二换元法

单调可导,则:

分部积分法

典型应用场景:

定积分的计算技巧

偶函数与奇函数

是偶函数,则:

是奇函数,则:

周期函数

的周期为 ,则:

广义积分

无穷限积分

若极限存在,则广义积分收敛。

p-积分判别法

  • 时收敛, 时发散

瑕积分

处无界:

p-积分判别法

  • 时收敛, 时发散

积分在机器学习中的应用

概率密度函数的积分

连续型随机变量 的概率:

期望值的计算

信息熵

神经网络中的积分变换

卷积操作本质上是一种积分变换:


级数理论

数项级数

级数收敛的定义

若极限存在(有限值),则级数收敛;否则发散。

正项级数判别法

比较判别法:若

  • 收敛,则 收敛
  • 发散,则 发散

比值判别法(达朗贝尔判别法)

  • :收敛
  • :发散
  • :不确定

根值判别法(柯西判别法)

  • :收敛
  • :发散
  • :不确定

积分判别法:若 单调递减且非负,则 同敛散。

交错级数

莱布尼茨判别法:若 单调递减趋于 ,则 收敛。

绝对收敛与条件收敛

  • 绝对收敛 收敛
  • 条件收敛 收敛但 发散

重要性质

  • 绝对收敛的级数必收敛
  • 绝对收敛的级数可以重排,重排后仍收敛且和不变
  • 条件收敛的级数可以通过重排收敛到任意值(黎曼重排定理)

函数项级数

一致收敛

上一致收敛于

与逐点收敛的区别:一致收敛要求 不依赖于

魏尔斯特拉斯 M 判别法

若有 收敛且 ,则 一致收敛。

一致收敛的性质

  1. 连续性:若 连续且一致收敛于 ,则 连续
  2. 可积性:若 可积且一致收敛于 ,则 可积且积分可以逐项积分
  3. 可微性:若 可导, 一致收敛,且 至少一点收敛,则 一致收敛于 ,且

幂级数

幂级数的定义

收敛半径

由柯西-阿达马公式:

幂级数的性质

  1. 内绝对收敛
  2. 和函数连续、可导、可积
  3. 逐项求导、逐项积分不改变收敛半径

傅里叶级数

傅里叶级数的定义

周期为 的函数 的傅里叶级数:

其中:

狄利克雷定理

上分段光滑,则傅里叶级数在每一点收敛到 的左右极限的平均值。

帕塞瓦尔恒等式

傅里叶级数在机器学习中的应用

  1. 信号处理:频域分析的基础
  2. 卷积神经网络:傅里叶变换是理解卷积运算频域特性的工具
  3. 数据压缩:傅里叶级数的高频截断实现有损压缩

多元函数分析

多元函数的极限与连续

二重极限

定义为:

累次极限

  • 先对 取极限:
  • 先对 取极限:

注意:两者不一定相等,即使都存在。

反例

累次极限存在且都等于 ,但二重极限不存在。

偏导数

偏导数的定义

偏导数表示函数沿坐标轴方向的变化率。

高阶偏导数

施瓦茨定理:若 在点 连续,则

全微分

全微分的定义

若全微分存在,则函数在该点可微。

可微的条件

必要条件:若 可微,则偏导数存在。

充分条件:若偏导数在 的邻域内存在且连续,则 可微。

全微分在近似计算中的应用

方向导数与梯度

方向导数

方向的方向导数:

其中 是单位向量。

梯度

梯度与方向导数的关系

方向导数可以表示为梯度与方向向量的点积:

其中 是梯度方向与 方向的夹角。

重要推论

  • 梯度方向是函数值增加最快的方向
  • 梯度的模是方向导数的最大值

机器学习含义:在梯度下降算法中,我们沿着梯度的负方向更新参数,因为那是函数值下降最快的方向。

链式法则(多元情形)

,则:

更一般地,若 ,则:

隐函数定理

单个方程的情形

,且 ,则在 附近唯一确定 ,且:

多个方程的情形

方程组:

在一定条件下可确定

多元函数的极值

无条件极值

必要条件:若 处取得极值且偏导数存在,则

充分条件:设 ,记:

则:

  • :极小值
  • :极大值
  • :鞍点
  • :需进一步分析

条件极值(拉格朗日乘数法)

在约束条件 下求 的极值:

构造拉格朗日函数:

解方程组:

拉格朗日乘数法在机器学习中的应用

支持向量机的最大间隔优化:

主成分分析:在正交约束下最大化方差。

雅可比矩阵与海森矩阵

雅可比矩阵

对于向量值函数

海森矩阵

标量函数 的二阶偏导数矩阵:

在优化中的角色:海森矩阵决定了目标函数的局部曲率,是牛顿法收敛性的关键。

多元泰勒展开

处的二阶泰勒展开:


测度论初步

测度的直观背景

为什么要引入测度

黎曼积分在处理不连续函数、极限与积分交换等问题时存在局限。勒贝格测度提供了一种更一般的积分理论,解决了这些问题。

外测度

对任意集合 ,定义外测度:

其中 是区间, 是区间长度。

可测集

集合 是勒贝格可测的,当且仅当对任意集合

勒贝格测度的性质

  1. 非负性
  2. 空集测度为零
  3. 可数可加性:若 两两不相交,则
  4. 平移不变性

可测函数

可测函数的定义

是可测的,当且仅当对任意

是可测集。

简单函数

简单函数是可测函数的”基本构件”:

其中 是集合 的特征函数。

可测函数的性质

  1. 可测函数列的极限是可测的
  2. 可测函数与连续函数的乘积是可测的

勒贝格积分

简单函数的积分

对非负简单函数:

非负可测函数的积分

一般可测函数的积分

分解为正部与负部:

若至少一个无穷,则积分可能无定义。

勒贝格积分与黎曼积分的比较

特性黎曼积分勒贝格积分
可积函数类有界且间断点少的函数更广泛的可测函数
极限交换需一致收敛等强条件只需一致有界收敛等弱条件
计算方法分区间求和分值域求和

概率论中的测度论

概率空间 是测度空间的特例:

  • :样本空间
  • -代数(事件域)
  • :概率测度

随机变量是到 的可测映射。


函数空间与泛函分析基础

赋范线性空间

范数的定义

满足:

  1. 正定性,且
  2. 齐次性
  3. 三角不等式

常见范数

中:

  • 范数
  • 范数(欧几里得范数)
  • 范数
  • 范数

范数与距离

范数诱导的距离(度量):

巴拿赫空间与希尔伯特空间

巴拿赫空间

完备的赋范线性空间称为巴拿赫空间。

完备性:所有柯西序列都收敛到空间内。

上的任何范数都诱导完备空间。

希尔伯特空间

完备的内积空间称为希尔伯特空间。

内积 满足:

  1. 共轭对称性:
  2. 线性性:
  3. 正定性:,且

内积空间自动是赋范空间:

勒贝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())}")

延伸阅读与参考文献

经典教材

  1. 《数学分析原理》(Principles of Mathematical Analysis)- Walter Rudin
  2. 《数学分析》(Mathematical Analysis)- Tom M. Apostol
  3. 《实分析与复分析》(Real and Complex Analysis)- Walter Rudin
  4. 《陶哲轩实分析》(Analysis I, II)- Terence Tao

机器学习相关数学

  1. 《深度学习》(Deep Learning)- Ian Goodfellow, Yoshua Bengio, Aaron Courville
  2. 《统计学习方法》- 李航
  3. 《机器学习的数学》- 石溪

在线资源

  • 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 条件给出最优解的必要条件:

  1. 原始可行性:
  2. 对偶可行性:
  3. 互补松弛:
  4. 稳定点条件:

变分法的基本框架

泛函与变分

泛函:从函数空间到实数的映射

变分

欧拉-拉格朗日方程

泛函 的极值满足:

应用

  • 最短路径(直线)
  • 最速降线(摆线)
  • 测地线

蒙特卡洛方法的数学基础

大数定律的应用

是独立同分布的随机变量,,则:

蒙特卡洛积分

其中

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