Files
flykhan 2536c937e3 feat: 完整中文翻译 maths-cs-ai-compendium(数学·计算机科学·AI 知识大全)
翻译自英文原版 maths-cs-ai-compendium,共 20 章全部完成。

第01章 向量 | 第02章 矩阵 | 第03章 微积分
第04章 统计学 | 第05章 概率论 | 第06章 机器学习
第07章 计算语言学 | 第08章 计算机视觉 | 第09章 音频与语音
第10章 多模态学习 | 第11章 自主系统 | 第12章 图神经网络
第13章 计算与操作系统 | 第14章 数据结构与算法
第15章 生产级软件工程 | 第16章 SIMD与GPU编程
第17章 AI推理 | 第18章 ML系统设计
第19章 应用人工智能 | 第20章 前沿人工智能

翻译说明:
- 所有数学公式 $...$ / $$...$$、代码块、图片引用完整保留
- mkdocs.yml 配置中文导航 + language: zh
- README.md 已翻译为中文(兼 docs/index.md)
- docs/ 目录包含指向各章文件的 symlink
- 约 29,000 行中文内容,排除 .cache/ 构建缓存
2026-05-03 10:23:20 +08:00

220 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 多元微积分
*多元微积分将导数和积分扩展到多变量函数,这对于机器学习模型拥有数百万参数的情形至关重要。本章涵盖偏导数、梯度、雅可比矩阵、海森矩阵以及使反向传播成为可能的多变量链式法则。*
- 到目前为止,我们的函数都只接受单个输入 $x$ 并产生单个输出 $f(x)$。但在机器学习中,我们几乎从不只处理一个变量。
- 考虑一个双变量函数,例如 $f(x, y) = x^2 + y^2$。它在三维空间中定义了一个曲面,形状像一个碗。我们想知道:如果我们在保持 $y$ 固定的同时稍微调整 $x$,$f$ 会如何变化?这就是**偏导数**。
- $f$ 对 $x$ 的**偏导数**,记作 $\frac{\partial f}{\partial x}$,将其他所有变量视为常数,然后对 $x$ 正常求导。
- 对于 $f(x, y) = x^2y + 3x - 2y$
$$\frac{\partial f}{\partial x} = 2xy + 3 \qquad \frac{\partial f}{\partial y} = x^2 - 2$$
- 计算 $\frac{\partial f}{\partial x}$ 时,我们将 $y$ 视为常数,因此 $x^2y$ 求导得 $2xy$$3x$ 求导得 $3$$-2y$ 求导得 $0$。
- 计算 $\frac{\partial f}{\partial y}$ 时,我们将 $x$ 视为常数,因此 $x^2y$ 求导得 $x^2$$3x$ 求导得 $0$$-2y$ 求导得 $-2$。
- 从几何上看,对 $x$ 求偏导数就像用一个平行于 $xz$ 平面的平面(在固定的 $y$ 值处)切割三维曲面,然后求所得曲线的斜率。
![偏导数:固定一个变量来切割曲面](../images/partial_derivative.svg)
- **梯度**将所有偏导数收集到一个向量中:
$$\nabla f = \left(\frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, \ldots, \frac{\partial f}{\partial x_n}\right)$$
- 对于 $f(x, y) = x^2 + y^2$$\nabla f(x, y) = (2x, 2y)$。在点 $(1, 2)$ 处:$\nabla f(1, 2) = (2, 4)$。
- 梯度有两个关键性质:
- **方向**:它指向上升最陡的方向。想象一位登山者在山上。他们所在位置的梯度指向正上方,沿着最陡的路径。
- **大小**$\|\nabla f\|$ 给出了最陡方向上的变化率。梯度大意味着地形陡峭;梯度小意味着地形近乎平坦。
![梯度向量指向山坡上方,垂直于等高线](../images/gradient_contour.svg)
- 由于梯度指向上坡,沿相反方向($-\nabla f$)移动就是下坡,走向更低的值。这个简单的想法是**梯度下降**的基础,我们将在后续章节中详细探讨这种优化技术。现在,关键要点是:梯度告诉你哪个方向是"上坡",以及攀登的陡峭程度。
- **方向导数**推广了偏导数。它不问"$f$ 沿 $x$ 轴如何变化?",而是问"$f$ 沿任意方向 $\mathbf{u}$ 如何变化?"它通过梯度与单位向量的点积来计算:
$$D_{\mathbf{u}} f = \nabla f \cdot \mathbf{u}$$
- 对于 $f(x, y) = x^2 + y^2$ 在点 $(1, 2)$ 处,沿方向 $\mathbf{v} = (3, 4)$:首先归一化得到 $\mathbf{u} = (3/5, 4/5)$,然后 $D_{\mathbf{u}} f = (2, 4) \cdot (3/5, 4/5) = 6/5 + 16/5 = 22/5$。
- 偏导数是方向导数的特例,其中方向沿着坐标轴。如果方向导数在某个方向上为零,则函数在该点沿该方向是平坦的。
- **等高线**(或水平曲线)连接函数值相等的点。对于 $f(x, y) = x^2 + y^2$,等高线是以原点为中心的圆:对应不同 $c$ 值的 $x^2 + y^2 = c$。
- 等高线永不相交(一个点不可能有两个不同的函数值)。
- 梯度始终垂直于等高线,从低值指向高值。
- 等高线密集表示地形陡峭;等高线稀疏表示坡度平缓。
- 到目前为止,我们的函数都只产生单个输出。但许多函数会产生多个输出。函数 $\mathbf{F}: \mathbb{R}^n \to \mathbb{R}^m$ 接收 $n$ 个输入并产生 $m$ 个输出。**雅可比矩阵**组织了这样一个向量值函数的所有偏导数:
```math
J = \begin{bmatrix} \frac{\partial f_1}{\partial x_1} & \cdots & \frac{\partial f_1}{\partial x_n} \\ \vdots & \ddots & \vdots \\ \frac{\partial f_m}{\partial x_1} & \cdots & \frac{\partial f_m}{\partial x_n} \end{bmatrix}
```
- 雅可比矩阵的每一行是一个输出分量的梯度。对于一个有 3 个输入和 2 个输出的函数,雅可比矩阵是一个 $2 \times 3$ 矩阵。
- 雅可比矩阵将导数推广到向量值函数。
- 就像标量函数的导数告诉你每单位输入变化对应的输出变化量一样,雅可比矩阵告诉你每个输出相对于每个输入的变化情况。
- **雅可比行列式**衡量一个变换局部拉伸或压缩空间的程度。
- 如果行列式为 2,小区域的面积加倍。如果行列式为 0,该变换将空间压缩到更低维度(回想我们在矩阵章节中学到的:行列式为零意味着奇异变换,不可逆)。
- 当多个变换组合在一起(一个变换的输出作为下一个变换的输入)时,整体映射的雅可比矩阵是各个雅可比矩阵的乘积。我们将在后续章节中看到这个思想变得至关重要。
- 梯度捕获一阶信息(斜率),而**海森矩阵**捕获二阶信息(曲率)。
- 对于标量函数 $f(x_1, \ldots, x_n)$,海森矩阵是所有二阶偏导数的 $n \times n$ 矩阵:
```math
H = \begin{bmatrix} \frac{\partial^2 f}{\partial x_1^2} & \frac{\partial^2 f}{\partial x_1 \partial x_2} & \cdots \\ \frac{\partial^2 f}{\partial x_2 \partial x_1} & \frac{\partial^2 f}{\partial x_2^2} & \cdots \\ \vdots & \vdots & \ddots \end{bmatrix}
```
- 对于 $f(x, y) = x^3 + 2xy^2 - y^3$,梯度为 $(3x^2 + 2y^2,\; 4xy - 3y^2)$,海森矩阵为:
```math
H = \begin{bmatrix} 6x & 4y \\ 4y & 4x - 6y \end{bmatrix}
```
- 对角线元素($6x$ 和 $4x - 6y$)告诉你 $x$ 方向的斜率随 $x$ 移动如何变化,$y$ 方向同理。
- 非对角线元素($4y$)告诉你一个方向的斜率随另一个方向的移动如何变化。
- **克莱罗定理**保证:对于具有连续二阶导数的函数,混合偏导数相等:$\frac{\partial^2 f}{\partial x \partial y} = \frac{\partial^2 f}{\partial y \partial x}$。
- 这意味着海森矩阵是对称的,这(正如我们在矩阵章节中看到的)保证了实特征值和正交特征向量。
- 海森矩阵告诉我们临界点(梯度为零的点)附近函数的形状:
- 如果 $H$ 是正定的(所有特征值为正),则该点是**局部极小值点**,曲面像碗一样向各个方向向上弯曲。
- 如果 $H$ 是负定的(所有特征值为负),则该点是**局部极大值点**,曲面像倒扣的碗一样向各个方向向下弯曲。
- 如果 $H$ 同时具有正负特征值,则该点是**鞍点**,曲面在某些方向上向上弯曲,在另一些方向上向下弯曲,就像山坳一样。
- **多变量链式法则**将链式法则扩展到多变量函数。如果 $z = f(x, y)$,其中 $x = g(t)$ 且 $y = h(t)$,则:
$$\frac{dz}{dt} = \frac{\partial f}{\partial x}\frac{dx}{dt} + \frac{\partial f}{\partial y}\frac{dy}{dt}$$
- 从 $t$ 到 $z$ 的每条路径都贡献一项:沿该路径的偏导数乘以中间变量对 $t$ 的导数。
- 例如,如果 $z = x^2 y + 3x - y^2$$x = \cos(t)$$y = \sin(t)$
$$\frac{dz}{dt} = (2xy + 3)(-\sin t) + (x^2 - 2y)(\cos t)$$
- 除了手动计算导数,还有三种方法:
- **数值微分**:用 $f'(x) \approx \frac{f(x+h) - f(x-h)}{2h}$(取很小的 $h$)来近似。简单但有噪声且不精确。
- **符号微分**:通过代数地应用求导法则产生精确表达式。可能导致表达式呈指数级膨胀。
- **自动微分(autodiff)**:跟踪运算链并高效地计算精确导数。JAX、PyTorch 和 TensorFlow 都使用这种方法。它能给出精确的数值(而非近似值),且不会产生臃肿的符号表达式。
## 编程练习(使用 CoLab 或 notebook
1. 使用 `jax.grad` 计算函数 $f(x, y) = x^2 y + 3x - 2y$ 在点 $(1, 2)$ 处的梯度。由于 $f$ 接收向量输入,请使用带 `argnums` 参数的 `jax.grad`
```python
import jax
import jax.numpy as jnp
def f(x, y):
return x**2 * y + 3*x - 2*y
df_dx = jax.grad(f, argnums=0)
df_dy = jax.grad(f, argnums=1)
x, y = 1.0, 2.0
print(f"∂f/∂x = {df_dx(x, y):.4f} (期望: {2*x*y + 3:.4f})")
print(f"∂f/∂y = {df_dy(x, y):.4f} (期望: {x**2 - 2:.4f})")
```
2. 使用 `jax.jacobian` 计算向量值函数的雅可比矩阵,并与手动计算结果进行比较。
```python
import jax
import jax.numpy as jnp
def F(x):
return jnp.array([x[0]**2 + x[1], x[0] * x[1]**2])
J = jax.jacobian(F)
x = jnp.array([1.0, 2.0])
print(f"在 (1,2) 处的雅可比矩阵:\n{J(x)}")
# 期望: [[2*x[0], 1], [x[1]**2, 2*x[0]*x[1]]] = [[2, 1], [4, 4]]
```
3. 使用 `jax.hessian` 计算 $f(x, y) = x^3 + 2xy^2 - y^3$ 的海森矩阵,并验证其对称性。
```python
import jax
import jax.numpy as jnp
def f(xy):
x, y = xy[0], xy[1]
return x**3 + 2*x*y**2 - y**3
H = jax.hessian(f)
point = jnp.array([1.0, 2.0])
hess = H(point)
print(f"海森矩阵:\n{hess}")
print(f"是否对称: {jnp.allclose(hess, hess.T)}")
# 期望: [[6x, 4y], [4y, 4x-6y]] = [[6, 8], [8, -8]]
```
4. 从头构建一个极简的自动微分引擎。
- 每个 `Var` 追踪其值以及如何通过链式法则反向传播梯度。
- 尝试扩展更多运算(除法、幂运算等)。
- 这是 JAX、PyTorch 和 Numpy 的设计基础。
```python
class Var:
def __init__(self, val, children=(), backward_fn=None):
self.val = val
self.grad = 0.0
self.children = children
self.backward_fn = backward_fn
def __add__(self, other):
out = Var(self.val + other.val, children=(self, other))
def _backward():
self.grad += out.grad # d(a+b)/da = 1
other.grad += out.grad # d(a+b)/db = 1
out.backward_fn = _backward
return out
def __mul__(self, other):
out = Var(self.val * other.val, children=(self, other))
def _backward():
self.grad += other.val * out.grad # d(a*b)/da = b
other.grad += self.val * out.grad # d(a*b)/db = a
out.backward_fn = _backward
return out
def backward(self):
# 拓扑排序,然后传播梯度
# 我们将在数据结构与算法章节中详细介绍
order, visited = [], set()
def topo(v):
if v not in visited:
visited.add(v)
for c in v.children:
topo(c)
order.append(v)
topo(self)
self.grad = 1.0
for v in reversed(order):
if v.backward_fn:
v.backward_fn()
# f(x, y) = x*x*y + x 在 (3, 2) 处
x = Var(3.0)
y = Var(2.0)
f = x * x * y + x # = 3*3*2 + 3 = 21
f.backward()
print(f"f = {f.val}") # 21.0
print(f"df/dx = {x.grad}") # 2*x*y + 1 = 13.0
print(f"df/dy = {y.grad}") # x*x = 9.0
```