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/ 构建缓存
This commit is contained in:
2026-05-03 10:23:20 +08:00
commit 2536c937e3
400 changed files with 49040 additions and 0 deletions
@@ -0,0 +1,219 @@
# 多元微积分
*多元微积分将导数和积分扩展到多变量函数,这对于机器学习模型拥有数百万参数的情形至关重要。本章涵盖偏导数、梯度、雅可比矩阵、海森矩阵以及使反向传播成为可能的多变量链式法则。*
- 到目前为止,我们的函数都只接受单个输入 $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
```