diff --git a/research/math/hermite_interpolation.md b/research/math/hermite_interpolation.md new file mode 100644 index 0000000..4b1a9c0 --- /dev/null +++ b/research/math/hermite_interpolation.md @@ -0,0 +1,612 @@ +--- +title: "Hermite 插值详解" +date: 2026-06-02 +draft: false +tags: ["数值分析", "插值", "Hermite插值", "多项式逼近"] +categories: ["research", "math"] +description: "从切触条件、构造方法到误差分析,系统讲解 Hermite 插值的理论与应用。" +--- + +# Hermite 插值详解 + +> 本文系统讲解数值分析中的 **Hermite 插值(Hermite Interpolation,埃尔米特插值)**。它是 Lagrange 插值的自然推广:不仅要求插值多项式在节点处与被插函数取相同的**函数值**,还要求取相同的**导数值(一阶乃至更高阶)**。这使得插值曲线在节点处不仅"经过"数据点,还与原曲线"相切",从而得到更光滑、更逼真的逼近。 + +--- + +## 一、引入与动机 + +### 1.1 从 Lagrange 插值说起 + +给定 $n+1$ 个互异节点 $x_0, x_1, \dots, x_n$ 及对应函数值 $f(x_i)$,Lagrange 插值给出唯一的次数 $\le n$ 多项式 $L_n(x)$,使得 + +$$ +L_n(x_i) = f(x_i), \qquad i = 0, 1, \dots, n. +$$ + +它只匹配**函数值**。然而在很多实际问题中,我们对曲线"形状"的要求更高,**仅匹配函数值是不够的**: + +- **光滑性不足**:Lagrange 插值在节点处的切线方向完全由全局多项式自动决定,可能与真实曲线的斜率相去甚远,导致曲线在节点附近"扭动"。 +- **物理意义缺失**:若数据点代表某质点的位置,那么我们往往同时知道该点的**速度**(即一阶导数)。只匹配位置而丢弃速度信息,是对已知信息的浪费。 +- **拼接不连续**:在分段插值中,若相邻段只匹配端点函数值而不匹配导数,则拼接处会出现折角(导数不连续)。 + +### 1.2 Hermite 插值的核心思想 + +**Hermite 插值**的思想是:在节点处同时匹配函数值与若干阶导数值。最常见的是同时匹配函数值与一阶导数值: + +$$ +H(x_i) = f(x_i), \qquad H'(x_i) = f'(x_i), \qquad i = 0, 1, \dots, n. +$$ + +### 1.3 几何直观:节点处"相切" + +考虑两条曲线 $y = f(x)$ 与 $y = H(x)$。如果它们在某点 $x_i$ 满足 + +$$ +H(x_i) = f(x_i) \quad (\text{过同一点}), \qquad H'(x_i) = f'(x_i) \quad (\text{斜率相同}), +$$ + +那么这两条曲线在 $x_i$ 处**相切**(一阶切触,order-1 contact)。如果进一步匹配到二阶导数 $H''(x_i)=f''(x_i)$,则它们在该点的**曲率**也一致(更高阶的切触)。 + +> 一句话概括:**Lagrange 插值让曲线"穿过"数据点;Hermite 插值让曲线"贴着"数据点走。** + +--- + +## 二、问题定义 + +### 2.1 一般 Hermite 插值问题 + +给定 $n+1$ 个互异节点 $x_0, x_1, \dots, x_n$。在每个节点 $x_i$ 处,给定函数值及从一阶到 $m_i$ 阶的导数值: + +$$ +f(x_i),\ f'(x_i),\ f''(x_i),\ \dots,\ f^{(m_i)}(x_i). +$$ + +也就是说,节点 $x_i$ 处提供了 $m_i + 1$ 个约束条件(称该节点的**重数(multiplicity)**为 $m_i + 1$)。我们称整数 $m_i$ 为节点 $x_i$ 的**切触阶(order of contact)**。 + +记总约束数(总自由度)为 + +$$ +N = \sum_{i=0}^{n} (m_i + 1). +$$ + +**目标**:求一个次数 $\le N-1$ 的多项式 $H(x)$,满足全部切触条件 + +$$ +H^{(k)}(x_i) = f^{(k)}(x_i), \qquad k = 0, 1, \dots, m_i, \quad i = 0, 1, \dots, n. +$$ + +### 2.2 存在唯一性定理 + +> **定理(Hermite 插值的存在唯一性)** +> 设节点 $x_0, \dots, x_n$ 互异,切触阶分别为 $m_0, \dots, m_n$,记 $N = \sum_{i=0}^{n}(m_i+1)$。则在给定上述 $N$ 个切触条件下,**存在且唯一**一个次数 $\le N-1$ 的多项式 $H(x)$ 满足所有条件。 + +**证明(唯一性,反证法)**: +次数 $\le N-1$ 的多项式构成一个 $N$ 维线性空间(基为 $1, x, \dots, x^{N-1}$),共有 $N$ 个待定系数。切触条件给出 $N$ 个线性方程,于是问题等价于一个 $N \times N$ 的线性方程组。要证明解存在且唯一,只需证明对应齐次问题只有零解。 + +设 $P(x)$ 是次数 $\le N-1$ 的多项式,且满足全部**齐次**条件 + +$$ +P^{(k)}(x_i) = 0, \qquad k = 0, 1, \dots, m_i, \quad i = 0, 1, \dots, n. +$$ + +则在每个节点 $x_i$ 处,$P$ 及其直到 $m_i$ 阶导数都为零,意味着 $x_i$ 是 $P$ 的至少 $m_i + 1$ 重根。因此 $P$ 的根(计重数)总数至少为 + +$$ +\sum_{i=0}^{n}(m_i + 1) = N. +$$ + +但 $P$ 的次数 $\le N-1$,一个非零的 $N-1$ 次多项式至多有 $N-1$ 个根(计重数)。矛盾。故 $P \equiv 0$。这证明齐次问题只有零解,从而线性方程组的系数矩阵非奇异,原问题存在唯一解。$\blacksquare$ + +**特例**:当所有 $m_i = 0$ 时,$N = n+1$,Hermite 插值退化为 **Lagrange 插值**;当 $n+1$ 个节点每个都匹配函数值与一阶导数($m_i = 1$)时,$N = 2(n+1) = 2n+2$,称为**标准 Hermite 插值**,其多项式次数 $\le 2n+1$。 + +--- + +## 三、两点三次 Hermite 插值(重点) + +这是工程与图形学中**最常用**的 Hermite 插值形式,必须重点掌握。 + +### 3.1 问题设定 + +取两个节点 $x_0, x_1$,每个节点匹配函数值与一阶导数: + +$$ +H(x_0) = f(x_0),\quad H'(x_0) = f'(x_0),\quad H(x_1) = f(x_1),\quad H'(x_1) = f'(x_1). +$$ + +共 $N = 4$ 个条件,故 $H(x)$ 是唯一的次数 $\le 3$ 的多项式(**三次多项式**)。 + +### 3.2 标准区间 $[0,1]$ 上的四个基函数 + +为简化推导,先把区间映射到 $[0,1]$。令 + +$$ +t = \frac{x - x_0}{x_1 - x_0} \in [0, 1], \qquad h = x_1 - x_0. +$$ + +我们寻找一组三次基函数 $H_{00}(t), H_{10}(t), H_{01}(t), H_{11}(t)$,使得 + +$$ +H(t) = H_{00}(t)\, p_0 + H_{10}(t)\, m_0 + H_{01}(t)\, p_1 + H_{11}(t)\, m_1, +$$ + +其中 $p_0 = f(x_0)$,$p_1 = f(x_1)$ 是端点值,$m_0 = h f'(x_0)$,$m_1 = h f'(x_1)$ 是按区间长度缩放后的端点导数(因为对 $t$ 求导带来因子 $h$,详见 3.4 节)。 + +每个基函数在 $t=0,1$ 两端的"值/导数"特征如下表(这正是它们的**定义性质**): + +| 基函数 | $值(0)$ | $导数(0)$ | $值(1)$ | $导数(1)$ | 作用 | +|---|---|---|---|---|---| +| $H_{00}$ | $1$ | $0$ | $0$ | $0$ | 携带左端点值 $p_0$ | +| $H_{10}$ | $0$ | $1$ | $0$ | $0$ | 携带左端点切线 $m_0$ | +| $H_{01}$ | $0$ | $0$ | $1$ | $0$ | 携带右端点值 $p_1$ | +| $H_{11}$ | $0$ | $0$ | $0$ | $1$ | 携带右端点切线 $m_1$ | + +### 3.3 基函数的推导 + +每个基函数是 $t$ 的三次多项式,写作 $H(t) = a t^3 + b t^2 + c t + d$,由上表的 4 个条件唯一确定。注意 $H'(t) = 3a t^2 + 2b t + c$。 + +**推导 $H_{00}$**:要求 $H_{00}(0)=1, H_{00}'(0)=0, H_{00}(1)=0, H_{00}'(1)=0$。 +- $H_{00}(0)=d=1$。 +- $H_{00}'(0)=c=0$。 +- $H_{00}(1)=a+b+c+d=a+b+1=0 \Rightarrow a+b=-1$。 +- $H_{00}'(1)=3a+2b+c=3a+2b=0 \Rightarrow b=-\tfrac{3}{2}a$。 +- 代入 $a+b=-1$:$a-\tfrac{3}{2}a=-1 \Rightarrow -\tfrac{1}{2}a=-1 \Rightarrow a=2$,于是 $b=-3$。 + +$$ +\boxed{H_{00}(t) = 2t^3 - 3t^2 + 1.} +$$ + +**推导 $H_{10}$**:要求 $H_{10}(0)=0, H_{10}'(0)=1, H_{10}(1)=0, H_{10}'(1)=0$。 +- $d=0$;$c=1$。 +- $a+b+c+d=a+b+1=0 \Rightarrow a+b=-1$。 +- $3a+2b+c=3a+2b+1=0 \Rightarrow 3a+2b=-1$。 +- 由 $a+b=-1$ 得 $b=-1-a$,代入:$3a+2(-1-a)=-1 \Rightarrow a-2=-1 \Rightarrow a=1$,$b=-2$。 + +$$ +\boxed{H_{10}(t) = t^3 - 2t^2 + t.} +$$ + +**推导 $H_{01}$**:要求 $H_{01}(0)=0, H_{01}'(0)=0, H_{01}(1)=1, H_{01}'(1)=0$。 +- $d=0$;$c=0$。 +- $a+b=1$;$3a+2b=0 \Rightarrow b=-\tfrac{3}{2}a$。 +- $a-\tfrac{3}{2}a=1 \Rightarrow -\tfrac12 a=1 \Rightarrow a=-2$,$b=3$。 + +$$ +\boxed{H_{01}(t) = -2t^3 + 3t^2.} +$$ + +**推导 $H_{11}$**:要求 $H_{11}(0)=0, H_{11}'(0)=0, H_{11}(1)=0, H_{11}'(1)=1$。 +- $d=0$;$c=0$。 +- $a+b=0$;$3a+2b=1$。 +- 由 $b=-a$:$3a-2a=1 \Rightarrow a=1$,$b=-1$。 + +$$ +\boxed{H_{11}(t) = t^3 - t^2.} +$$ + +**验证(单位分解性质)**:注意 $H_{00}(t) + H_{01}(t) = (2t^3-3t^2+1) + (-2t^3+3t^2) = 1$。这保证了对常值函数 $f\equiv c$(其导数为 $0$)的插值结果恒为 $c$,符合预期。 + +### 3.4 完整公式(一般区间 $[x_0, x_1]$) + +把 $t = (x-x_0)/h$ 代回,并注意链式法则 $\frac{\mathrm d}{\mathrm dx} = \frac{1}{h}\frac{\mathrm d}{\mathrm dt}$,对 $x$ 的导数与对 $t$ 的导数相差因子 $1/h$。因此端点导数 $f'(x_i)$ 与对 $t$ 的导数关系为 $\frac{\mathrm dH}{\mathrm dt}\big|_{t=0} = h f'(x_0)$,这解释了 3.2 节中为何令 $m_0 = h f'(x_0)$、$m_1 = h f'(x_1)$。最终插值多项式为 + +$$ +\boxed{ +H(x) = H_{00}(t)\,f(x_0) + H_{10}(t)\,h\,f'(x_0) + H_{01}(t)\,f(x_1) + H_{11}(t)\,h\,f'(x_1), +\qquad t=\frac{x-x_0}{h},\ h=x_1-x_0. +} +$$ + +展开为 + +$$ +\begin{aligned} +H(x) ={}& (2t^3-3t^2+1)\,f(x_0) + (t^3-2t^2+t)\,h\,f'(x_0) \\ +&+ (-2t^3+3t^2)\,f(x_1) + (t^3-t^2)\,h\,f'(x_1). +\end{aligned} +$$ + +### 3.5 数值算例 + +设 $f(x) = \sin x$,节点 $x_0 = 0$,$x_1 = \tfrac{\pi}{2}$。则 + +$$ +\begin{aligned} +&f(x_0) = \sin 0 = 0, & &f'(x_0) = \cos 0 = 1, \\ +&f(x_1) = \sin\tfrac{\pi}{2} = 1, & &f'(x_1) = \cos\tfrac{\pi}{2} = 0, +\end{aligned} +$$ + +且 $h = \tfrac{\pi}{2} \approx 1.5708$。代入完整公式(仅 $f(x_0)=0$、$f'(x_1)=0$ 两项消失): + +$$ +H(x) = H_{10}(t)\,h\cdot 1 + H_{01}(t)\cdot 1 += h(t^3 - 2t^2 + t) + (-2t^3 + 3t^2), +$$ + +其中 $t = x / h = \dfrac{2x}{\pi}$。 + +**在区间中点 $x = \tfrac{\pi}{4}$ 处检验**(此时 $t = 0.5$): + +$$ +\begin{aligned} +H_{10}(0.5) &= 0.125 - 0.5 + 0.5 = 0.125, \\ +H_{01}(0.5) &= -0.25 + 0.75 = 0.5, \\ +H(\tfrac{\pi}{4}) &= 1.5708 \times 0.125 + 1 \times 0.5 = 0.19635 + 0.5 = 0.69635. +\end{aligned} +$$ + +真实值 $\sin\tfrac{\pi}{4} = \tfrac{\sqrt2}{2} \approx 0.70711$。误差约为 $0.0108$,对仅用两个节点的三次插值而言已相当精确。作为对比,仅用相同两节点的线性 Lagrange 插值在中点给出 $0.5$,误差高达 $0.207$,可见匹配导数信息带来的显著改进。 + +--- + +## 四、一般 Hermite 插值的构造方法 + +### 4.1 方法一:基函数法(广义 Lagrange 基) + +对**标准 Hermite 插值**(每个节点匹配 $f(x_i)$ 与 $f'(x_i)$,$i=0,\dots,n$),插值多项式次数 $\le 2n+1$,可写成 + +$$ +H_{2n+1}(x) = \sum_{i=0}^{n} f(x_i)\, h_i(x) + \sum_{i=0}^{n} f'(x_i)\, \hat h_i(x), +$$ + +其中 $h_i(x)$ 与 $\hat h_i(x)$ 是满足下列"选择性"条件的基函数($\delta_{ij}$ 为 Kronecker 符号): + +$$ +\begin{aligned} +h_i(x_j) = \delta_{ij}, &\qquad h_i'(x_j) = 0, \\ +\hat h_i(x_j) = 0, &\qquad \hat h_i'(x_j) = \delta_{ij}. +\end{aligned} +$$ + +**构造公式**:借助 Lagrange 基函数 + +$$ +\ell_i(x) = \prod_{\substack{j=0 \\ j\ne i}}^{n} \frac{x - x_j}{x_i - x_j}, +$$ + +可以证明 + +$$ +\boxed{ +\begin{aligned} +h_i(x) &= \big[\,1 - 2(x - x_i)\,\ell_i'(x_i)\,\big]\,\ell_i^2(x), \\ +\hat h_i(x) &= (x - x_i)\,\ell_i^2(x). +\end{aligned} +} +$$ + +**验证思路**:因 $\ell_i(x_j) = \delta_{ij}$,故 $\ell_i^2(x_j) = \delta_{ij}$,于是 $\hat h_i(x_j) = (x_j-x_i)\delta_{ij} = 0$ 对一切 $j$ 成立;又 $\hat h_i'(x) = \ell_i^2(x) + (x-x_i)\cdot 2\ell_i\ell_i'$,在 $x=x_j$ 处当 $j\ne i$ 时 $\ell_i(x_j)=0$ 使两项皆为 $0$,当 $j=i$ 时第一项 $\ell_i^2(x_i)=1$、第二项含因子 $(x_i-x_i)=0$,故 $\hat h_i'(x_j)=\delta_{ij}$。$h_i$ 中的线性因子 $[1 - 2(x-x_i)\ell_i'(x_i)]$ 正是为抵消 $\ell_i^2$ 在 $x_i$ 处的导数而精心设计的。 + +基函数法概念清晰、利于理论分析,但当节点数较多或含高阶切触时,公式变得繁琐,**实际计算更推荐下面的差商法**。 + +### 4.2 方法二:重节点的差商法(Newton 形式,推荐) + +Newton 均差(divided differences,差商)插值可以**自然地推广**到 Hermite 情形:把每个节点按其重数 $m_i+1$ **重复列出**,对于重复的节点,差商表中无法用普通差商公式(会出现 $0/0$)的位置,**用导数值填充**。 + +#### 4.2.1 重节点差商的定义 + +普通差商递归定义为 + +$$ +f[x_i] = f(x_i), \qquad +f[x_i, \dots, x_{i+k}] = \frac{f[x_{i+1},\dots,x_{i+k}] - f[x_i,\dots,x_{i+k-1}]}{x_{i+k} - x_i}. +$$ + +当节点重合($x_{i+k} \to x_i$)时,分母为零。此时由微分中值定理的极限给出**重节点差商**: + +$$ +\boxed{\,\underbrace{f[x_i, x_i, \dots, x_i]}_{k+1 \text{ 个}} = \frac{f^{(k)}(x_i)}{k!}.\,} +$$ + +特别地: + +$$ +f[x_i, x_i] = f'(x_i), \qquad f[x_i, x_i, x_i] = \frac{f''(x_i)}{2}. +$$ + +#### 4.2.2 构造步骤 + +1. 建立**重复节点序列** $z_0, z_1, \dots, z_{N-1}$:把 $x_i$ 重复 $m_i+1$ 次依次排列。 +2. 建立差商表。**对角线(最高阶差商)**逐列计算: + - 若相邻两个 $z$ 不相等,用普通差商公式; + - 若相邻两个 $z$ 相等(对应同一节点),用上面的导数公式填充。 +3. 取**表的顶部对角线元素**作为 Newton 系数,写出多项式: + +$$ +\boxed{ +H(x) = \sum_{k=0}^{N-1} f[z_0, z_1, \dots, z_k] \prod_{j=0}^{k-1}(x - z_j). +} +$$ + +#### 4.2.3 算例:带重节点的差商表 + +求满足下列条件的多项式(即两点三次 Hermite,与第三节呼应,便于互相验证): + +$$ +f(0) = 1,\quad f'(0) = 0,\quad f(1) = 0,\quad f'(1) = -1. +$$ + +重复节点序列:$z_0 = z_1 = 0$,$z_2 = z_3 = 1$。差商表如下(左列为 $z$ 与 $f$,向右逐阶): + +$$ +\begin{array}{c|cccc} +z & f[\cdot] & f[\cdot,\cdot] & f[\cdot,\cdot,\cdot] & f[\cdot,\cdot,\cdot,\cdot] \\ \hline +0 & 1 & & & \\ + & & \mathbf{0} & & \\ +0 & 1 & & -1 & \\ + & & -1 & & \mathbf{1} \\ +1 & 0 & & 0 & \\ + & & -1 & & \\ +1 & 0 & & & \\ +\end{array} +$$ + +逐项说明: + +- 一阶差商列: + - $f[z_0,z_1] = f[0,0] = f'(0) = 0$(重节点,用导数)。 + - $f[z_1,z_2] = f[0,1] = \dfrac{0 - 1}{1 - 0} = -1$(普通差商)。 + - $f[z_2,z_3] = f[1,1] = f'(1) = -1$(重节点,用导数)。 +- 二阶差商列: + - $f[z_0,z_1,z_2] = \dfrac{f[z_1,z_2] - f[z_0,z_1]}{z_2 - z_0} = \dfrac{-1 - 0}{1 - 0} = -1$。 + - $f[z_1,z_2,z_3] = \dfrac{f[z_2,z_3] - f[z_1,z_2]}{z_3 - z_1} = \dfrac{-1 - (-1)}{1 - 0} = 0$。 +- 三阶差商(顶部): + - $f[z_0,z_1,z_2,z_3] = \dfrac{f[z_1,z_2,z_3] - f[z_0,z_1,z_2]}{z_3 - z_0} = \dfrac{0 - (-1)}{1 - 0} = 1$。 + +于是顶部对角线系数依次为 $1,\ 0,\ -1,\ 1$,Newton 形式为 + +$$ +\begin{aligned} +H(x) &= 1 + 0\cdot(x-0) + (-1)(x-0)(x-0) + 1\cdot(x-0)(x-0)(x-1) \\ +&= 1 - x^2 + x^2(x-1) \\ +&= 1 - x^2 + x^3 - x^2 \\ +&= x^3 - 2x^2 + 1. +\end{aligned} +$$ + +**验证**:$H(0)=1$ ✓;$H'(x)=3x^2-4x$,$H'(0)=0$ ✓;$H(1)=1-2+1=0$ ✓;$H'(1)=3-4=-1$ ✓。四个切触条件全部满足,构造正确。 + +> **说明**:差商法的最大优点是**统一处理任意阶切触**。无论某节点要匹配到几阶导数,只需把它重复相应次数、在重节点位置填入 $f^{(k)}(x_i)/k!$ 即可,无需为每种情形单独设计基函数。这也是教科书和数值库内部最常采用的实现思路。 + +--- + +## 五、误差分析 + +### 5.1 误差余项公式 + +> **定理(Hermite 插值余项)** +> 设 $f \in C^{N}[a,b]$,节点 $x_0,\dots,x_n \in [a,b]$ 互异,切触阶为 $m_0,\dots,m_n$,$N=\sum(m_i+1)$,$H(x)$ 为满足全部切触条件、次数 $\le N-1$ 的 Hermite 插值多项式。则对任意 $x\in[a,b]$,存在依赖于 $x$ 的 $\xi=\xi(x)\in(a,b)$,使得 +> $$ +> \boxed{\,f(x) - H(x) = \frac{f^{(N)}(\xi)}{N!}\,\prod_{i=0}^{n}(x - x_i)^{m_i+1}.\,} +> $$ + +**证明要点(Rolle 定理法)**:固定 $x\ne x_i$。令节点因子 $W(t)=\prod_i (t-x_i)^{m_i+1}$(次数为 $N$),并构造辅助函数 + +$$ +g(t) = f(t) - H(t) - \frac{f(x)-H(x)}{W(x)}\,W(t). +$$ + +则 $g$ 在 $t=x$ 处为零,且在每个 $x_i$ 处有 $m_i+1$ 重零点(因 $f-H$ 与 $W$ 在 $x_i$ 处都有相应阶的零)。于是 $g$(计重数)至少有 $N+1$ 个零点。反复使用 Rolle 定理,$g^{(N)}$ 至少有一个零点 $\xi$。由于 $H$ 次数 $\le N-1$ 故 $H^{(N)}\equiv 0$,而 $W^{(N)}=N!$,代入 $g^{(N)}(\xi)=0$ 解得 + +$$ +f^{(N)}(\xi) - \frac{f(x)-H(x)}{W(x)}\,N! = 0 +\;\Longrightarrow\; +f(x)-H(x) = \frac{f^{(N)}(\xi)}{N!}W(x). \qquad\blacksquare +$$ + +### 5.2 标准 Hermite(每点匹配值与一阶导)的余项 + +此时每个 $m_i=1$,$N=2n+2$,余项为 + +$$ +f(x) - H(x) = \frac{f^{(2n+2)}(\xi)}{(2n+2)!}\prod_{i=0}^{n}(x-x_i)^2. +$$ + +**两点三次情形**($n=1$,$N=4$): + +$$ +f(x) - H_3(x) = \frac{f^{(4)}(\xi)}{4!}(x-x_0)^2(x-x_1)^2 = \frac{f^{(4)}(\xi)}{24}(x-x_0)^2(x-x_1)^2. +$$ + +注意节点因子 $(x-x_i)^2 \ge 0$ 恒非负,这与 Lagrange 情形(节点因子可正可负)不同,反映了"相切"带来的更强约束。 + +### 5.3 与 Lagrange 插值误差的对比 + +| 对比项 | Lagrange 插值($n+1$ 点) | Hermite 插值(标准,$n+1$ 点) | +|---|---|---| +| 多项式次数 | $\le n$ | $\le 2n+1$ | +| 余项导数阶 | $f^{(n+1)}$ | $f^{(2n+2)}$ | +| 余项公式 | $\dfrac{f^{(n+1)}(\xi)}{(n+1)!}\prod (x-x_i)$ | $\dfrac{f^{(2n+2)}(\xi)}{(2n+2)!}\prod (x-x_i)^2$ | +| 节点因子符号 | 可正可负 | 恒 $\ge 0$ | +| 收敛阶(等距 $h$) | $O(h^{n+1})$ | $O(h^{2n+2})$ | + +**关键结论**:在使用相同节点数的前提下,Hermite 插值由于额外利用了导数信息,余项中出现**更高阶的导数**与**更高次的节点因子幂**,因而通常具有**更高的逼近精度(更高的收敛阶)**。代价是需要已知导数值,且多项式次数翻倍——次数过高时同样可能出现 Runge 现象,故实际更常用**分段**形式(见第六节)。 + +--- + +## 六、与样条的联系 + +### 6.1 分段三次 Hermite 插值 + +当节点很多时,直接构造高次 Hermite 多项式会引发振荡(Runge 现象)。实用做法是**分段**:在每个相邻区间 $[x_i, x_{i+1}]$ 上用第三节的两点三次 Hermite 公式构造一段三次多项式,再拼接起来。 + +由于每段都在端点匹配函数值与一阶导数,拼接处天然满足 + +$$ +H(x_i^-) = H(x_i^+) = f(x_i), \qquad H'(x_i^-) = H'(x_i^+) = f'(x_i), +$$ + +即整条曲线达到 **$C^1$ 连续**(函数与一阶导都连续)。这正是分段三次 Hermite 插值(Piecewise Cubic Hermite Interpolation)。其前提是**每个节点的导数 $f'(x_i)$ 已知或被估计出来**。 + +### 6.2 三次样条与 Hermite 形式的关系 + +**三次样条(cubic spline)**同样是分段三次、$C^1$ 连续,但它额外要求 + +$$ +H''(x_i^-) = H''(x_i^+), \qquad i=1,\dots,n-1, +$$ + +即**二阶导数也连续**,从而整体达到 **$C^2$ 连续**,曲线更光滑(曲率不突变)。 + +两者的本质区别在于"导数从何而来": + +- **分段 Hermite**:各节点的斜率 $f'(x_i)$ 是**给定或局部估计**的(局部方法,每段相互独立),只保证 $C^1$。 +- **三次样条**:斜率(或二阶导)是通过求解一个**全局三对角线性方程组**确定的,目的是让二阶导连续,因此是**全局方法**,达到 $C^2$,但任一数据点的改动会影响整条曲线。 + +事实上,任何三次样条都可以**改写成分段 Hermite 形式**:只要先解出样条在各节点的导数值 $s'(x_i)$,再把这些导数当作 Hermite 的输入即可。所以"三次样条"可视为"用全局光滑性条件自动确定斜率的分段三次 Hermite 插值"。 + +### 6.3 单调性保持(PCHIP) + +分段三次 Hermite 的一个重要变体是 **PCHIP(Piecewise Cubic Hermite Interpolating Polynomial)**。它不直接使用真实导数,而是用一套特殊规则**估计每个节点的斜率 $d_i$**,使得: + +- 在数据单调的区间内,插值曲线**保持单调**,不产生过冲(overshoot)/ 振荡; +- 在局部极值点处令斜率为 $0$,避免越过数据点。 + +具体地,PCHIP 在内部节点用相邻区间斜率的**加权调和平均**来估计 $d_i$:若相邻两段割线斜率 $\delta_{i-1}, \delta_i$ 同号,则 + +$$ +\frac{w_1+w_2}{d_i} = \frac{w_1}{\delta_{i-1}} + \frac{w_2}{\delta_i}, +\qquad w_1 = 2h_i + h_{i-1},\ w_2 = h_i + 2h_{i-1}, +$$ + +否则(异号或某段为零,即遇到局部极值)令 $d_i = 0$。这保证了形状保持性。与三次样条相比,PCHIP 牺牲了 $C^2$ 光滑(只保 $C^1$),换来**无过冲**的视觉与物理可靠性,非常适合插值带有尖锐变化或单调段的数据。 + +--- + +## 七、应用场景 + +### 7.1 计算机图形学:三次 Hermite 曲线 + +第三节的四基函数 $H_{00},H_{10},H_{01},H_{11}$ 正是图形学中**三次 Hermite 曲线(Cubic Hermite Spline)**的数学基础。给定两端点 $\mathbf P_0,\mathbf P_1$ 与两端切向量 $\mathbf T_0,\mathbf T_1$(这里把标量推广为向量,对每个坐标分量分别插值): + +$$ +\mathbf P(t) = H_{00}(t)\mathbf P_0 + H_{10}(t)\mathbf T_0 + H_{01}(t)\mathbf P_1 + H_{11}(t)\mathbf T_1,\quad t\in[0,1]. +$$ + +设计师通过拖动切向量即可直观地控制曲线的"出入方向"。 + +**Catmull-Rom 样条**是其著名特例:它自动地把每个控制点的切向量取为相邻两点连线方向 + +$$ +\mathbf T_i = \frac{1}{2}(\mathbf P_{i+1} - \mathbf P_{i-1}), +$$ + +从而只需给一串点就能生成一条**经过所有控制点、$C^1$ 连续**的光滑曲线,广泛用于路径与曲线设计。 + +### 7.2 动画关键帧插值与相机路径 + +在动画中,美术师设置若干**关键帧(keyframe)**:在某些时刻指定物体的位置、旋转、缩放等属性。系统需要在关键帧之间"补间(in-between)"。使用 Hermite 插值(指定每个关键帧的属性值**及其变化速率/切线**)可以让运动平滑、避免在关键帧处出现速度突变(折角)。相机沿预定轨迹平移、推拉时同样依赖 Hermite/样条曲线得到流畅运镜。 + +### 7.3 数值微分方程与轨迹规划 + +- **常微分方程数值解**:一些方法(如 Hermite–Obreschkoff、含导数信息的密集输出/dense output)利用解在网格点的函数值与导数值(导数恰由 ODE 右端 $f(t,y)$ 直接给出)做 Hermite 插值,得到任意时刻的高精度连续解。 +- **机器人/无人机轨迹规划**:要求轨迹在路点(waypoint)处同时满足位置与速度(甚至加速度)约束,正是高阶 Hermite 插值的典型用武之地——它能保证速度连续,使运动平稳、可执行。 + +--- + +## 八、Python 代码示例 + +下面用 `numpy` 从零实现两点三次 Hermite 插值,并用 SciPy 的 `CubicHermiteSpline` 与 `BPoly.from_derivatives` 进行对照验证。代码可直接运行。 + +```python +import numpy as np + +# ---------------------------------------------------------------------- +# 1) 基函数法:标准区间 [0,1] 上的四个三次 Hermite 基函数 +# ---------------------------------------------------------------------- +def hermite_basis(t): + """返回 (H00, H10, H01, H11) 在参数 t 处的值。t 可为标量或 numpy 数组。""" + H00 = 2 * t**3 - 3 * t**2 + 1 # 携带左端点值 + H10 = t**3 - 2 * t**2 + t # 携带左端点切线 + H01 = -2 * t**3 + 3 * t**2 # 携带右端点值 + H11 = t**3 - t**2 # 携带右端点切线 + return H00, H10, H01, H11 + + +def cubic_hermite(x, x0, x1, p0, p1, m0, m1): + """ + 两点三次 Hermite 插值。 + x0, x1 : 两个节点 + p0, p1 : 端点函数值 f(x0), f(x1) + m0, m1 : 端点一阶导数 f'(x0), f'(x1) + 返回 H(x)。 + """ + h = x1 - x0 + t = (x - x0) / h + H00, H10, H01, H11 = hermite_basis(t) + # 注意导数项需乘以区间长度 h(链式法则) + return H00 * p0 + H10 * (h * m0) + H01 * p1 + H11 * (h * m1) + + +# ---------------------------------------------------------------------- +# 2) 算例:用 f(x)=sin(x) 在 [0, pi/2] 上做两点三次 Hermite 插值 +# ---------------------------------------------------------------------- +x0, x1 = 0.0, np.pi / 2 +p0, p1 = np.sin(x0), np.sin(x1) # 函数值: 0, 1 +m0, m1 = np.cos(x0), np.cos(x1) # 导数值: 1, 0 + +xs = np.linspace(x0, x1, 9) +H_vals = cubic_hermite(xs, x0, x1, p0, p1, m0, m1) +true_vals = np.sin(xs) + +print("x Hermite sin(x) 误差") +for x, h, s in zip(xs, H_vals, true_vals): + print(f"{x:.4f} {h:.6f} {s:.6f} {abs(h - s):.2e}") + +# 在中点 pi/4 处单独检验(对应正文 3.5 节) +xm = np.pi / 4 +print(f"\n中点 H(pi/4) = {cubic_hermite(xm, x0, x1, p0, p1, m0, m1):.5f}, " + f"真值 = {np.sin(xm):.5f}") + +# ---------------------------------------------------------------------- +# 3) 与 SciPy 对照(若已安装 scipy) +# ---------------------------------------------------------------------- +try: + from scipy.interpolate import CubicHermiteSpline, BPoly + + # CubicHermiteSpline 直接接受节点、函数值、导数值 + nodes = np.array([x0, x1]) + vals = np.array([p0, p1]) + ders = np.array([m0, m1]) + chs = CubicHermiteSpline(nodes, vals, ders) + + # BPoly.from_derivatives: 每个节点给 [值, 一阶导] + bp = BPoly.from_derivatives(nodes, [[p0, m0], [p1, m1]]) + + max_err_chs = np.max(np.abs(chs(xs) - H_vals)) + max_err_bp = np.max(np.abs(bp(xs) - H_vals)) + print(f"\n与 CubicHermiteSpline 的最大偏差: {max_err_chs:.2e}") + print(f"与 BPoly.from_derivatives 的最大偏差: {max_err_bp:.2e}") + # 两者应与自实现完全一致(偏差约为机器精度 ~1e-16) +except ImportError: + print("\n未安装 scipy,跳过对照验证。") +``` + +**预期输出**(节选):自实现结果与 SciPy 两种方法的偏差均在机器精度量级(约 $10^{-16}$),中点处 $H(\pi/4)\approx 0.69635$,与正文 3.5 节手算一致。 + +--- + +## 九、小结表格 + +下表对比三种最常用的插值方案,帮助快速选型: + +| 对比维度 | Lagrange 插值 | Hermite 插值(标准) | 三次样条(cubic spline) | +|---|---|---|---| +| **匹配条件** | 仅节点函数值 $f(x_i)$ | 节点函数值 $f(x_i)$ **与导数值** $f'(x_i)$(可含更高阶) | 节点函数值;导数由全局光滑条件自动确定 | +| **多项式形态** | 单个次数 $\le n$ 的多项式 | 单个次数 $\le 2n+1$ 的多项式(或分段三次) | 分段三次多项式 | +| **连续性** | 自身光滑(单个多项式),分段拼接仅 $C^0$ | 节点处达 $C^1$(分段时);插值更"贴合" | $C^2$(二阶导连续,最光滑) | +| **是否需导数** | 否 | **是**(须已知或估计 $f'$) | 否(自动求解) | +| **误差余项** | $\dfrac{f^{(n+1)}(\xi)}{(n+1)!}\prod(x-x_i)$ | $\dfrac{f^{(2n+2)}(\xi)}{(2n+2)!}\prod(x-x_i)^2$ | 分段,$O(h^4)$ 量级 | +| **局部/全局** | 全局(改一点影响整体) | 局部(分段 Hermite 每段独立) | 全局(解三对角方程组) | +| **典型用途** | 理论分析、低阶插值、推导数值公式 | 图形学曲线、动画关键帧、轨迹规划、ODE 密集输出 | 数据光滑拟合、CAD 曲线、平滑插值 | +| **代表实现** | — | `CubicHermiteSpline`、`BPoly.from_derivatives`、PCHIP | `CubicSpline` | + +--- + +## 参考与延伸 + +- 经典数值分析教材(如 Burden & Faires《Numerical Analysis》、李庆扬《数值分析》)中关于 Hermite 插值与差商的章节。 +- SciPy 文档:[`CubicHermiteSpline`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.CubicHermiteSpline.html)、[`PchipInterpolator`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.PchipInterpolator.html)、`BPoly.from_derivatives`。 +- 计算机图形学中关于 Hermite 曲线、Bézier 曲线与 Catmull-Rom 样条相互转化的资料。 + +> **一句话总结**:Hermite 插值通过同时匹配函数值与导数值,让插值曲线在节点处"相切",以更高的收敛阶和更好的光滑性逼近原函数;其两点三次形式与分段推广(含 PCHIP、Catmull-Rom)是图形学、动画与轨迹规划的基石,实际构造首选**重节点差商法**。 \ No newline at end of file diff --git a/research/math/podcast/build_video.py b/research/math/podcast/build_video.py new file mode 100644 index 0000000..5b0da65 --- /dev/null +++ b/research/math/podcast/build_video.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +"""把 Hermite 幻灯片 + 已有播客音频合成为 MP4 视频(无需重新调 TTS)。 + +流程: + 1) 读已有完整音频时长;按每句文本字符数占比,把总时长分配到 11 页 + (字符数是中文 TTS 时长的良好代理;总时长严格等于真实音频)。 + 2) 用 Chrome headless 把 11 页各截一张 1920x1080 PNG(?page=N&clean=1)。 + 3) ffmpeg:每页图片按对应时长生成视频轨,叠加音频,输出 MP4。 + +用法:python3 build_video.py +""" +import json +import os +import subprocess +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +SCRIPT_JSON = os.path.join(HERE, "hermite_polynomials-script.json") +SLIDE_HTML = os.path.join(HERE, "slides", "Hermite 多项式.html") +OUT_DIR = os.path.join(HERE, "output") +SHOT_DIR = os.path.join(OUT_DIR, "shots") +AUDIO_IN = os.path.join(OUT_DIR, "hermite_polynomials-podcast.mp3") +VIDEO_OUT = os.path.join(OUT_DIR, "hermite_polynomials-video.mp4") + +CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" + +# 句(1-based) -> 页(1-based) 映射。共 43 句、11 页。 +LINE_TO_PAGE = { + 1: 1, 2: 1, + 3: 2, 4: 2, 5: 2, 6: 2, + 7: 3, 8: 3, + 9: 4, 10: 4, 11: 4, 12: 4, + 13: 5, 14: 5, 15: 5, 16: 5, 17: 5, + 18: 6, 19: 6, 20: 6, + 21: 7, 22: 7, 23: 7, 24: 7, 25: 7, 26: 7, + 27: 8, 28: 8, 29: 8, + 30: 9, 31: 9, 32: 9, 33: 9, + 34: 10, 35: 10, 36: 10, 37: 10, 38: 10, 39: 10, + 40: 11, 41: 11, 42: 11, 43: 11, +} +NUM_PAGES = 11 + + +def run(cmd): + subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + +def ffprobe_dur(path): + out = subprocess.check_output( + ["ffprobe", "-v", "error", "-show_entries", "format=duration", + "-of", "default=noprint_wrappers=1:nokey=1", path]) + return float(out.strip()) + + +def step1_page_durations(): + total = ffprobe_dur(AUDIO_IN) + with open(SCRIPT_JSON, encoding="utf-8") as f: + lines = json.load(f)["lines"] + # 每句字符数(去空白)作为时长权重 + page_chars = {p: 0 for p in range(1, NUM_PAGES + 1)} + for i, line in enumerate(lines, 1): + n = len(line["paragraph"].strip()) + page_chars[LINE_TO_PAGE.get(i, NUM_PAGES)] += n + grand = sum(page_chars.values()) + page_dur = {p: total * page_chars[p] / grand for p in page_chars} + # 修正累计误差,使最后一页吸收余量 + assigned = sum(page_dur.values()) + page_dur[NUM_PAGES] += (total - assigned) + print(f"音频总时长 {total:.2f}s,按字符占比分配到 {NUM_PAGES} 页:") + for p in range(1, NUM_PAGES + 1): + print(f" page {p:>2}: {page_dur[p]:6.2f}s ({page_chars[p]} 字)") + return page_dur, total + + +def step2_screenshots(): + os.makedirs(SHOT_DIR, exist_ok=True) + file_url = "file://" + SLIDE_HTML.replace(" ", "%20") + for p in range(1, NUM_PAGES + 1): + out = os.path.join(SHOT_DIR, f"page_{p:02d}.png") + url = f"{file_url}?page={p}&clean=1" + run([CHROME, "--headless=new", "--disable-gpu", "--hide-scrollbars", + "--force-device-scale-factor=1", "--window-size=1920,1080", + f"--screenshot={out}", "--virtual-time-budget=2800", url]) + if not os.path.exists(out): + raise RuntimeError(f"截图失败 page {p}") + print(f"截图 page {p:02d} ✓") + + +def step3_video(page_dur): + tmp_list = os.path.join(SHOT_DIR, "vlist.txt") + with open(tmp_list, "w") as lf: + for p in range(1, NUM_PAGES + 1): + img = os.path.join(SHOT_DIR, f"page_{p:02d}.png") + dur = max(page_dur[p], 0.8) + vid = os.path.join(SHOT_DIR, f"v_{p:02d}.mp4") + run(["ffmpeg", "-y", "-loop", "1", "-i", img, "-t", f"{dur:.3f}", + "-r", "30", "-pix_fmt", "yuv420p", + "-vf", "scale=1920:1080:force_original_aspect_ratio=decrease," + "pad=1920:1080:(ow-iw)/2:(oh-ih)/2", + "-c:v", "libx264", "-preset", "medium", "-crf", "20", vid]) + lf.write(f"file '{vid}'\n") + print(f"页视频 {p:02d} {dur:.2f}s ✓") + silent = os.path.join(SHOT_DIR, "silent.mp4") + run(["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", tmp_list, "-c", "copy", silent]) + run(["ffmpeg", "-y", "-i", silent, "-i", AUDIO_IN, + "-c:v", "copy", "-c:a", "aac", "-b:a", "192k", "-shortest", VIDEO_OUT]) + print(f"\n✅ 视频已输出:{VIDEO_OUT} ({ffprobe_dur(VIDEO_OUT):.1f}s)") + + +def main(): + if not os.path.exists(AUDIO_IN): + print(f"ERROR: 找不到音频 {AUDIO_IN}", file=sys.stderr) + sys.exit(1) + os.makedirs(OUT_DIR, exist_ok=True) + print("=== 步骤 1/3:按字符占比分配每页时长 ===") + page_dur, _ = step1_page_durations() + print("\n=== 步骤 2/3:截取 11 页幻灯片 ===") + step2_screenshots() + print("\n=== 步骤 3/3:ffmpeg 合成视频 ===") + step3_video(page_dur) + + +if __name__ == "__main__": + main() diff --git a/research/math/podcast/hermite_polynomials-script.json b/research/math/podcast/hermite_polynomials-script.json new file mode 100644 index 0000000..e0ae744 --- /dev/null +++ b/research/math/podcast/hermite_polynomials-script.json @@ -0,0 +1,49 @@ +{ + "title": "Hermite 多项式:高斯世界里的频率分解工具", + "locale": "zh", + "lines": [ + {"speaker": "male", "paragraph": "Hello Deer!欢迎回到我们的节目。今天我们要聊一个听起来很硬核、但其实特别优雅的数学工具——Hermite 多项式。"}, + {"speaker": "female", "paragraph": "对,很多人一听多项式就想躲。但今天我保证,我们用大白话把它讲明白。先说说,我们为什么要管它?"}, + {"speaker": "male", "paragraph": "好问题。这要从一个叫 LeJEPA 的自监督学习方法说起。它的核心证明里要回答一件事:编码器把数据映射成一个表示之后,这个表示里到底哪一部分,对所谓的正样本对的相关性贡献最大。"}, + {"speaker": "female", "paragraph": "正样本对,简单说就是同一个东西的两个不同视角,对吧?模型希望它们的表示尽量像。"}, + {"speaker": "male", "paragraph": "没错。而要回答哪部分贡献最大,你得先有一把刀,能把任意一个函数拆成一块一块。这就像傅里叶分析,把一段声音拆成不同频率的正弦波。"}, + {"speaker": "female", "paragraph": "啊,这个类比我喜欢。傅里叶是把周期信号拆成高音、低音。那 Hermite 是拆什么?"}, + {"speaker": "male", "paragraph": "Hermite 是专门为高斯分布、也就是我们常说的正态分布、钟形曲线,量身定做的拆分工具。当你的数据服从钟形曲线时,Hermite 多项式就是那套最自然的基本积木。"}, + {"speaker": "female", "paragraph": "所以可以理解成:傅里叶是周期世界的积木,Hermite 是高斯世界的积木。那这些积木长什么样?"}, + {"speaker": "male", "paragraph": "最前面几块特别简单。第零块就是常数一。第一块就是它本身,z。第二块是 z 的平方再减去一。第三块是 z 的三次方减去三倍的 z。越往后次数越高,但都有规律。"}, + {"speaker": "female", "paragraph": "有规律就好记。是不是有个递推的套路,能从前面两块推出下一块?"}, + {"speaker": "male", "paragraph": "正是。下一块等于 z 乘以当前这一块,再减去它的阶数乘以前一块。比如想要第二块,就拿 z 乘第一块的 z,得到 z 平方,再减去一倍的常数一,正好是 z 平方减一。"}, + {"speaker": "female", "paragraph": "漂亮,自己就能一层层搭上去。那这套积木最关键的本事是什么?"}, + {"speaker": "male", "paragraph": "最关键的叫正交性。意思是说,任意两块不同阶数的积木,在高斯分布下做平均,它们的乘积平均下来等于零。互不干扰。"}, + {"speaker": "female", "paragraph": "等一下,这个互不干扰,是不是又跟正弦波很像?不同频率的正弦波相乘积分也是零。"}, + {"speaker": "male", "paragraph": "完全一样的精神。不同频率的波互不打架;不同阶数的 Hermite 积木也互不打架。只有自己跟自己相乘,平均才不为零,而且那个值正好等于它的阶数的阶乘。"}, + {"speaker": "female", "paragraph": "能举个最小的例子验证一下吗?让我有点踏实感。"}, + {"speaker": "male", "paragraph": "当然。拿第一块 z 和第二块 z 平方减一相乘,展开就是 z 的三次方减去 z。在钟形曲线下,所有奇数次方的平均值都是零,所以整体就是零减零,等于零。它俩果然互不干扰。"}, + {"speaker": "female", "paragraph": "服气。那有了这套互不干扰的积木,是不是任何函数都能用它们拼出来?"}, + {"speaker": "male", "paragraph": "只要这个函数不太离谱,具体说是它的平方的平均值是有限的,那它就能写成这些积木的加权叠加。每一块前面配一个系数,系数大代表这个函数里那个阶数的成分多。"}, + {"speaker": "female", "paragraph": "就像把一个向量沿着一组坐标轴分解,每个轴上投影多少。这里的轴就是不同阶数的 Hermite 积木。"}, + {"speaker": "male", "paragraph": "比喻得非常准。好,现在重头戏来了:为什么这套工具对 LeJEPA 这么要命。"}, + {"speaker": "female", "paragraph": "我正想问。前面铺垫这么多,关键的转折在哪?"}, + {"speaker": "male", "paragraph": "关键在于那个生成正样本对的过程,数学上叫 OU 过程。你可以把它想象成:拿原始的表示,乘上一个介于零和一之间的系数,再掺进一点点随机噪声,得到第二个视角。"}, + {"speaker": "female", "paragraph": "那个介于零和一的系数,我们就叫它相关强度吧。它怎么影响不同阶数的积木?"}, + {"speaker": "male", "paragraph": "这就是最神奇的地方。线性成分,也就是第一阶,经过这个过程之后,两边的相关性正好等于那个系数本身。但二阶成分的相关性,是这个系数的平方。三阶是三次方。"}, + {"speaker": "female", "paragraph": "等等,因为这个系数小于一,所以平方会更小,三次方更更小。也就是阶数越高,相关性掉得越快?"}, + {"speaker": "male", "paragraph": "对,是指数级地掉。高阶的非线性成分,经过这个过程之后几乎就被冲淡没了。只有线性成分保留得最结实。"}, + {"speaker": "female", "paragraph": "我好像猜到结论了。如果模型的目标是让正样本对的相关性尽可能大……"}, + {"speaker": "male", "paragraph": "聪明。既然线性成分留下的相关性最高,非线性成分都被打了折扣,那最优策略自然就是:只保留线性成分,把所有非线性成分统统丢掉。"}, + {"speaker": "female", "paragraph": "所以模型被这个机制温柔地逼着,学成了一个本质上线性的表示。这就是他们那个核心定理的直觉来源。"}, + {"speaker": "male", "paragraph": "正是。研究者还给了一个很贴心的量,叫谱权重,专门衡量一个表示里每个阶数的成分占了多大比例。"}, + {"speaker": "female", "paragraph": "谱权重怎么理解?给我个画面感。"}, + {"speaker": "male", "paragraph": "你就想象一个饼图。整张饼是这个表示的总能量。线性成分切走一块,二阶切走一块,三阶再一块。每一块的占比就是那个阶数的谱权重,所有块加起来正好是百分之百。"}, + {"speaker": "female", "paragraph": "那如果一个表示是纯线性的,饼图就是线性那一块占满整张,对吧?"}, + {"speaker": "male", "paragraph": "完全正确。纯线性,线性那块就是百分之百。纯二次,二阶那块占满。混合的,就是好几块都有。而 LeJEPA 想要的理想状态,就是把整张饼都给线性那一块。"}, + {"speaker": "female", "paragraph": "我帮大家把今天的几个要点串一下。第一,Hermite 多项式是高斯世界里的频率分解工具,类比傅里叶。"}, + {"speaker": "male", "paragraph": "第二,它最核心的性质是正交性,不同阶数互不干扰,所以任意合理的函数都能干净地拆成这些积木的叠加。"}, + {"speaker": "female", "paragraph": "第三,那个生成正样本对的 OU 过程,对越高阶的成分削减得越狠,相关性按阶数指数衰减。"}, + {"speaker": "male", "paragraph": "第四,因此最大化相关性的最优解,就是只留线性成分,这就推出了所谓的线性可识别性,也是整套理论的基石。"}, + {"speaker": "female", "paragraph": "讲得太顺了。如果听众还想往下走,下一站是什么?"}, + {"speaker": "male", "paragraph": "下一站就是去看那个相关性按阶数衰减的公式到底从哪来,背后有个叫 Mehler 公式的东西,会把今天这个直觉彻底坐实。"}, + {"speaker": "female", "paragraph": "好,那我们下期接着聊。谢谢大家收听,记得,数学不可怕,可怕的是没人陪你拆积木。我们下次见!"}, + {"speaker": "male", "paragraph": "下次见,拜拜!"} + ] +} diff --git a/research/math/podcast/hermite_polynomials-transcript.md b/research/math/podcast/hermite_polynomials-transcript.md new file mode 100644 index 0000000..6d86580 --- /dev/null +++ b/research/math/podcast/hermite_polynomials-transcript.md @@ -0,0 +1,93 @@ +# Hermite 多项式:高斯世界里的频率分解工具(播客文字稿) + +> 来源文档:[`JEPA/math/01_hermite_polynomials.md`](../../../JEPA/math/01_hermite_polynomials.md) +> 形式:双主播(男 / 女)对话讲解,约 10 分钟 +> 配套脚本:[`hermite_polynomials-script.json`](hermite_polynomials-script.json) + +--- + +**男主播:** Hello Deer!欢迎回到我们的节目。今天我们要聊一个听起来很硬核、但其实特别优雅的数学工具——Hermite 多项式。 + +**女主播:** 对,很多人一听多项式就想躲。但今天我保证,我们用大白话把它讲明白。先说说,我们为什么要管它? + +**男主播:** 好问题。这要从一个叫 LeJEPA 的自监督学习方法说起。它的核心证明里要回答一件事:编码器把数据映射成一个表示之后,这个表示里到底哪一部分,对所谓的正样本对的相关性贡献最大。 + +**女主播:** 正样本对,简单说就是同一个东西的两个不同视角,对吧?模型希望它们的表示尽量像。 + +**男主播:** 没错。而要回答哪部分贡献最大,你得先有一把刀,能把任意一个函数拆成一块一块。这就像傅里叶分析,把一段声音拆成不同频率的正弦波。 + +**女主播:** 啊,这个类比我喜欢。傅里叶是把周期信号拆成高音、低音。那 Hermite 是拆什么? + +**男主播:** Hermite 是专门为高斯分布、也就是我们常说的正态分布、钟形曲线,量身定做的拆分工具。当你的数据服从钟形曲线时,Hermite 多项式就是那套最自然的基本积木。 + +**女主播:** 所以可以理解成:傅里叶是周期世界的积木,Hermite 是高斯世界的积木。那这些积木长什么样? + +**男主播:** 最前面几块特别简单。第零块就是常数一。第一块就是它本身,z。第二块是 z 的平方再减去一。第三块是 z 的三次方减去三倍的 z。越往后次数越高,但都有规律。 + +**女主播:** 有规律就好记。是不是有个递推的套路,能从前面两块推出下一块? + +**男主播:** 正是。下一块等于 z 乘以当前这一块,再减去它的阶数乘以前一块。比如想要第二块,就拿 z 乘第一块的 z,得到 z 平方,再减去一倍的常数一,正好是 z 平方减一。 + +**女主播:** 漂亮,自己就能一层层搭上去。那这套积木最关键的本事是什么? + +**男主播:** 最关键的叫正交性。意思是说,任意两块不同阶数的积木,在高斯分布下做平均,它们的乘积平均下来等于零。互不干扰。 + +**女主播:** 等一下,这个互不干扰,是不是又跟正弦波很像?不同频率的正弦波相乘积分也是零。 + +**男主播:** 完全一样的精神。不同频率的波互不打架;不同阶数的 Hermite 积木也互不打架。只有自己跟自己相乘,平均才不为零,而且那个值正好等于它的阶数的阶乘。 + +**女主播:** 能举个最小的例子验证一下吗?让我有点踏实感。 + +**男主播:** 当然。拿第一块 z 和第二块 z 平方减一相乘,展开就是 z 的三次方减去 z。在钟形曲线下,所有奇数次方的平均值都是零,所以整体就是零减零,等于零。它俩果然互不干扰。 + +**女主播:** 服气。那有了这套互不干扰的积木,是不是任何函数都能用它们拼出来? + +**男主播:** 只要这个函数不太离谱,具体说是它的平方的平均值是有限的,那它就能写成这些积木的加权叠加。每一块前面配一个系数,系数大代表这个函数里那个阶数的成分多。 + +**女主播:** 就像把一个向量沿着一组坐标轴分解,每个轴上投影多少。这里的轴就是不同阶数的 Hermite 积木。 + +**男主播:** 比喻得非常准。好,现在重头戏来了:为什么这套工具对 LeJEPA 这么要命。 + +**女主播:** 我正想问。前面铺垫这么多,关键的转折在哪? + +**男主播:** 关键在于那个生成正样本对的过程,数学上叫 OU 过程。你可以把它想象成:拿原始的表示,乘上一个介于零和一之间的系数,再掺进一点点随机噪声,得到第二个视角。 + +**女主播:** 那个介于零和一的系数,我们就叫它相关强度吧。它怎么影响不同阶数的积木? + +**男主播:** 这就是最神奇的地方。线性成分,也就是第一阶,经过这个过程之后,两边的相关性正好等于那个系数本身。但二阶成分的相关性,是这个系数的平方。三阶是三次方。 + +**女主播:** 等等,因为这个系数小于一,所以平方会更小,三次方更更小。也就是阶数越高,相关性掉得越快? + +**男主播:** 对,是指数级地掉。高阶的非线性成分,经过这个过程之后几乎就被冲淡没了。只有线性成分保留得最结实。 + +**女主播:** 我好像猜到结论了。如果模型的目标是让正样本对的相关性尽可能大…… + +**男主播:** 聪明。既然线性成分留下的相关性最高,非线性成分都被打了折扣,那最优策略自然就是:只保留线性成分,把所有非线性成分统统丢掉。 + +**女主播:** 所以模型被这个机制温柔地逼着,学成了一个本质上线性的表示。这就是他们那个核心定理的直觉来源。 + +**男主播:** 正是。研究者还给了一个很贴心的量,叫谱权重,专门衡量一个表示里每个阶数的成分占了多大比例。 + +**女主播:** 谱权重怎么理解?给我个画面感。 + +**男主播:** 你就想象一个饼图。整张饼是这个表示的总能量。线性成分切走一块,二阶切走一块,三阶再一块。每一块的占比就是那个阶数的谱权重,所有块加起来正好是百分之百。 + +**女主播:** 那如果一个表示是纯线性的,饼图就是线性那一块占满整张,对吧? + +**男主播:** 完全正确。纯线性,线性那块就是百分之百。纯二次,二阶那块占满。混合的,就是好几块都有。而 LeJEPA 想要的理想状态,就是把整张饼都给线性那一块。 + +**女主播:** 我帮大家把今天的几个要点串一下。第一,Hermite 多项式是高斯世界里的频率分解工具,类比傅里叶。 + +**男主播:** 第二,它最核心的性质是正交性,不同阶数互不干扰,所以任意合理的函数都能干净地拆成这些积木的叠加。 + +**女主播:** 第三,那个生成正样本对的 OU 过程,对越高阶的成分削减得越狠,相关性按阶数指数衰减。 + +**男主播:** 第四,因此最大化相关性的最优解,就是只留线性成分,这就推出了所谓的线性可识别性,也是整套理论的基石。 + +**女主播:** 讲得太顺了。如果听众还想往下走,下一站是什么? + +**男主播:** 下一站就是去看那个相关性按阶数衰减的公式到底从哪来,背后有个叫 Mehler 公式的东西,会把今天这个直觉彻底坐实。 + +**女主播:** 好,那我们下期接着聊。谢谢大家收听,记得,数学不可怕,可怕的是没人陪你拆积木。我们下次见! + +**男主播:** 下次见,拜拜! diff --git a/research/math/podcast/output/hermite_polynomials-podcast-transcript.md b/research/math/podcast/output/hermite_polynomials-podcast-transcript.md new file mode 100644 index 0000000..4aefd68 --- /dev/null +++ b/research/math/podcast/output/hermite_polynomials-podcast-transcript.md @@ -0,0 +1,87 @@ +# Hermite 多项式:高斯世界里的频率分解工具 + +**Host (Male)**: Hello Deer!欢迎回到我们的节目。今天我们要聊一个听起来很硬核、但其实特别优雅的数学工具——Hermite 多项式。 + +**Host (Female)**: 对,很多人一听多项式就想躲。但今天我保证,我们用大白话把它讲明白。先说说,我们为什么要管它? + +**Host (Male)**: 好问题。这要从一个叫 LeJEPA 的自监督学习方法说起。它的核心证明里要回答一件事:编码器把数据映射成一个表示之后,这个表示里到底哪一部分,对所谓的正样本对的相关性贡献最大。 + +**Host (Female)**: 正样本对,简单说就是同一个东西的两个不同视角,对吧?模型希望它们的表示尽量像。 + +**Host (Male)**: 没错。而要回答哪部分贡献最大,你得先有一把刀,能把任意一个函数拆成一块一块。这就像傅里叶分析,把一段声音拆成不同频率的正弦波。 + +**Host (Female)**: 啊,这个类比我喜欢。傅里叶是把周期信号拆成高音、低音。那 Hermite 是拆什么? + +**Host (Male)**: Hermite 是专门为高斯分布、也就是我们常说的正态分布、钟形曲线,量身定做的拆分工具。当你的数据服从钟形曲线时,Hermite 多项式就是那套最自然的基本积木。 + +**Host (Female)**: 所以可以理解成:傅里叶是周期世界的积木,Hermite 是高斯世界的积木。那这些积木长什么样? + +**Host (Male)**: 最前面几块特别简单。第零块就是常数一。第一块就是它本身,z。第二块是 z 的平方再减去一。第三块是 z 的三次方减去三倍的 z。越往后次数越高,但都有规律。 + +**Host (Female)**: 有规律就好记。是不是有个递推的套路,能从前面两块推出下一块? + +**Host (Male)**: 正是。下一块等于 z 乘以当前这一块,再减去它的阶数乘以前一块。比如想要第二块,就拿 z 乘第一块的 z,得到 z 平方,再减去一倍的常数一,正好是 z 平方减一。 + +**Host (Female)**: 漂亮,自己就能一层层搭上去。那这套积木最关键的本事是什么? + +**Host (Male)**: 最关键的叫正交性。意思是说,任意两块不同阶数的积木,在高斯分布下做平均,它们的乘积平均下来等于零。互不干扰。 + +**Host (Female)**: 等一下,这个互不干扰,是不是又跟正弦波很像?不同频率的正弦波相乘积分也是零。 + +**Host (Male)**: 完全一样的精神。不同频率的波互不打架;不同阶数的 Hermite 积木也互不打架。只有自己跟自己相乘,平均才不为零,而且那个值正好等于它的阶数的阶乘。 + +**Host (Female)**: 能举个最小的例子验证一下吗?让我有点踏实感。 + +**Host (Male)**: 当然。拿第一块 z 和第二块 z 平方减一相乘,展开就是 z 的三次方减去 z。在钟形曲线下,所有奇数次方的平均值都是零,所以整体就是零减零,等于零。它俩果然互不干扰。 + +**Host (Female)**: 服气。那有了这套互不干扰的积木,是不是任何函数都能用它们拼出来? + +**Host (Male)**: 只要这个函数不太离谱,具体说是它的平方的平均值是有限的,那它就能写成这些积木的加权叠加。每一块前面配一个系数,系数大代表这个函数里那个阶数的成分多。 + +**Host (Female)**: 就像把一个向量沿着一组坐标轴分解,每个轴上投影多少。这里的轴就是不同阶数的 Hermite 积木。 + +**Host (Male)**: 比喻得非常准。好,现在重头戏来了:为什么这套工具对 LeJEPA 这么要命。 + +**Host (Female)**: 我正想问。前面铺垫这么多,关键的转折在哪? + +**Host (Male)**: 关键在于那个生成正样本对的过程,数学上叫 OU 过程。你可以把它想象成:拿原始的表示,乘上一个介于零和一之间的系数,再掺进一点点随机噪声,得到第二个视角。 + +**Host (Female)**: 那个介于零和一的系数,我们就叫它相关强度吧。它怎么影响不同阶数的积木? + +**Host (Male)**: 这就是最神奇的地方。线性成分,也就是第一阶,经过这个过程之后,两边的相关性正好等于那个系数本身。但二阶成分的相关性,是这个系数的平方。三阶是三次方。 + +**Host (Female)**: 等等,因为这个系数小于一,所以平方会更小,三次方更更小。也就是阶数越高,相关性掉得越快? + +**Host (Male)**: 对,是指数级地掉。高阶的非线性成分,经过这个过程之后几乎就被冲淡没了。只有线性成分保留得最结实。 + +**Host (Female)**: 我好像猜到结论了。如果模型的目标是让正样本对的相关性尽可能大…… + +**Host (Male)**: 聪明。既然线性成分留下的相关性最高,非线性成分都被打了折扣,那最优策略自然就是:只保留线性成分,把所有非线性成分统统丢掉。 + +**Host (Female)**: 所以模型被这个机制温柔地逼着,学成了一个本质上线性的表示。这就是他们那个核心定理的直觉来源。 + +**Host (Male)**: 正是。研究者还给了一个很贴心的量,叫谱权重,专门衡量一个表示里每个阶数的成分占了多大比例。 + +**Host (Female)**: 谱权重怎么理解?给我个画面感。 + +**Host (Male)**: 你就想象一个饼图。整张饼是这个表示的总能量。线性成分切走一块,二阶切走一块,三阶再一块。每一块的占比就是那个阶数的谱权重,所有块加起来正好是百分之百。 + +**Host (Female)**: 那如果一个表示是纯线性的,饼图就是线性那一块占满整张,对吧? + +**Host (Male)**: 完全正确。纯线性,线性那块就是百分之百。纯二次,二阶那块占满。混合的,就是好几块都有。而 LeJEPA 想要的理想状态,就是把整张饼都给线性那一块。 + +**Host (Female)**: 我帮大家把今天的几个要点串一下。第一,Hermite 多项式是高斯世界里的频率分解工具,类比傅里叶。 + +**Host (Male)**: 第二,它最核心的性质是正交性,不同阶数互不干扰,所以任意合理的函数都能干净地拆成这些积木的叠加。 + +**Host (Female)**: 第三,那个生成正样本对的 OU 过程,对越高阶的成分削减得越狠,相关性按阶数指数衰减。 + +**Host (Male)**: 第四,因此最大化相关性的最优解,就是只留线性成分,这就推出了所谓的线性可识别性,也是整套理论的基石。 + +**Host (Female)**: 讲得太顺了。如果听众还想往下走,下一站是什么? + +**Host (Male)**: 下一站就是去看那个相关性按阶数衰减的公式到底从哪来,背后有个叫 Mehler 公式的东西,会把今天这个直觉彻底坐实。 + +**Host (Female)**: 好,那我们下期接着聊。谢谢大家收听,记得,数学不可怕,可怕的是没人陪你拆积木。我们下次见! + +**Host (Male)**: 下次见,拜拜! diff --git a/research/math/podcast/output/hermite_polynomials-podcast.mp3 b/research/math/podcast/output/hermite_polynomials-podcast.mp3 new file mode 100644 index 0000000..7d46154 Binary files /dev/null and b/research/math/podcast/output/hermite_polynomials-podcast.mp3 differ diff --git a/research/math/podcast/output/hermite_polynomials-video.mp4 b/research/math/podcast/output/hermite_polynomials-video.mp4 new file mode 100644 index 0000000..22eb8f4 Binary files /dev/null and b/research/math/podcast/output/hermite_polynomials-video.mp4 differ diff --git a/research/math/podcast/output/shots/page_01.png b/research/math/podcast/output/shots/page_01.png new file mode 100644 index 0000000..6d17845 Binary files /dev/null and b/research/math/podcast/output/shots/page_01.png differ diff --git a/research/math/podcast/output/shots/page_02.png b/research/math/podcast/output/shots/page_02.png new file mode 100644 index 0000000..3db4814 Binary files /dev/null and b/research/math/podcast/output/shots/page_02.png differ diff --git a/research/math/podcast/output/shots/page_03.png b/research/math/podcast/output/shots/page_03.png new file mode 100644 index 0000000..1f0ef57 Binary files /dev/null and b/research/math/podcast/output/shots/page_03.png differ diff --git a/research/math/podcast/output/shots/page_04.png b/research/math/podcast/output/shots/page_04.png new file mode 100644 index 0000000..393ad15 Binary files /dev/null and b/research/math/podcast/output/shots/page_04.png differ diff --git a/research/math/podcast/output/shots/page_05.png b/research/math/podcast/output/shots/page_05.png new file mode 100644 index 0000000..1313ef9 Binary files /dev/null and b/research/math/podcast/output/shots/page_05.png differ diff --git a/research/math/podcast/output/shots/page_06.png b/research/math/podcast/output/shots/page_06.png new file mode 100644 index 0000000..6dc231d Binary files /dev/null and b/research/math/podcast/output/shots/page_06.png differ diff --git a/research/math/podcast/output/shots/page_07.png b/research/math/podcast/output/shots/page_07.png new file mode 100644 index 0000000..5951c9d Binary files /dev/null and b/research/math/podcast/output/shots/page_07.png differ diff --git a/research/math/podcast/output/shots/page_08.png b/research/math/podcast/output/shots/page_08.png new file mode 100644 index 0000000..0aa41ab Binary files /dev/null and b/research/math/podcast/output/shots/page_08.png differ diff --git a/research/math/podcast/output/shots/page_09.png b/research/math/podcast/output/shots/page_09.png new file mode 100644 index 0000000..a143eb2 Binary files /dev/null and b/research/math/podcast/output/shots/page_09.png differ diff --git a/research/math/podcast/output/shots/page_10.png b/research/math/podcast/output/shots/page_10.png new file mode 100644 index 0000000..c67ec2f Binary files /dev/null and b/research/math/podcast/output/shots/page_10.png differ diff --git a/research/math/podcast/output/shots/page_11.png b/research/math/podcast/output/shots/page_11.png new file mode 100644 index 0000000..69974ed Binary files /dev/null and b/research/math/podcast/output/shots/page_11.png differ diff --git a/research/math/podcast/slides/Hermite 多项式 - 风格预览.html b/research/math/podcast/slides/Hermite 多项式 - 风格预览.html new file mode 100644 index 0000000..9582db7 --- /dev/null +++ b/research/math/podcast/slides/Hermite 多项式 - 风格预览.html @@ -0,0 +1,259 @@ + + + + + +Hermite 多项式 · 配套幻灯片 · 风格预览 + + + + + + + + + + + + + + + +
+ HERMITE · 风格预览 + + + + 每版=封面 + 典型内容页(OU 衰减)|选定后展开完整版 +
+ +
+
+ + +
+
+
+ 封面 +
+
+
SELF-SUPERVISED · 谱分解
+
Hermite
多项式
+
高斯世界里的「频率分解」工具——配套播客讲解
+
EP.01 · 时长 7:43 · LeJEPA 理论基石
+
+
+
+ 内容页 +

为什么线性成分最值钱

+
OU 过程让相关性按阶数指数衰减
+
+
+ $\mathbb{E}[He_n(z')\,He_n(z)] = \rho^{\,n} \cdot n!$ +
阶数越高 → 相关性掉得越快
+
+
+
1 阶
+
2 阶
+
3 阶
+
最优解:只保留线性成分 → 线性可识别性
+
+
+
+
+
+ + +
+
+
+ 封面 +
+
He
+
谱分解 / SPECTRALEP.01
+
埃尔米特多项式
+
高斯世界里的频率分解工具 —— 配套播客讲解 · 7 分 43 秒
+
+
+
+ 内容页 +
05 / OU 衰减ρⁿ
+

为什么线性成分最值钱

+
+
+ $\mathbb{E}[He_n(z')\,He_n(z)] = \rho^{\,n} n!$ +
阶数越高 → 衰减越快
+
+
+
ρ¹
+
ρ²
+
ρ³
+
→ 只留线性 = 线性可识别性
+
+
+
+
+
+ + +
+
+
+ 封面 +
+
SPECTRAL DECOMPOSITION · 第一讲
+
Hermite 多项式
+
高斯世界里的「频率分解」工具
配套播客讲解 · 全长 7 分 43 秒
+

分解
+
+
+
+
+ 内容页 +
05 · OU 过程与衰减
+

为什么线性成分最值钱

+
+
+ $\mathbb{E}[He_n(z')\,He_n(z)] = \rho^{\,n}\, n!$ +
阶数越高,相关性指数衰减
+
+
+
ρ¹
+
ρ²
+
ρ³
+
最优策略:只保留线性 → 线性可识别性
+
+
+
+
+
+ +
+
+ + + + diff --git a/research/math/podcast/slides/Hermite 多项式.html b/research/math/podcast/slides/Hermite 多项式.html new file mode 100644 index 0000000..b7c4d1f --- /dev/null +++ b/research/math/podcast/slides/Hermite 多项式.html @@ -0,0 +1,405 @@ + + + + + +Hermite 多项式 · 高斯世界里的频率分解工具 + + + + + + + + + + + + + + + +
← → 翻页 · F 全屏 · 刷新记忆当前页
+ +
+
+ + +
+
+
SELF-SUPERVISED · 谱分解 · EP.01
+

Hermite
多项式

+

高斯世界里的「频率分解」工具
—— 配套播客讲解,从直觉到 LeJEPA 的理论基石

+
配套音频 7:43 · 双主播对话 · 数学不可怕,可怕的是没人陪你拆积木
+
+ + +
+
+
01 · 动机
+

我们需要一把拆函数的刀

+
+
    +
  • LeJEPA 的证明要回答:编码器的表示里,哪一部分对「正样本对」的相关性贡献最大?
  • +
  • 正样本对 = 同一内容的两个视角,模型希望它们的表示尽量像。
  • +
  • 要回答这个问题,得先能把任意函数拆成一块块——就像傅里叶把声音拆成不同频率的波。
  • +
  • 在高斯(钟形)分布下,这套「积木」就是 Hermite 多项式
  • +
+
+
+ + +
+
+
02 · 类比
+

傅里叶之于周期,Hermite 之于高斯

+
+ + + + + + +
维度傅里叶级数Hermite 展开
适用场景周期函数高斯分布下的函数
基函数$\sin nx,\ \cos nx$$He_0,He_1,He_2,\dots$
正交性在区间上积分为 0在高斯期望下为 0
完备性任意周期函数可展开任意 $L^2(\gamma)$ 函数可展开
+
+
+ + +
+
+
03 · 定义
+

积木长什么样 & 递推搭出来

+
+
+ $He_0=1,\quad He_1=z$
+ $He_2=z^2-1$
+ $He_3=z^3-3z$
+ $He_4=z^4-6z^2+3$ +
+
+
+ $He_{n+1}(z)=z\,He_n(z)-n\,He_{n-1}(z)$ +
下一块 = z × 当前块 − 阶数 × 前一块
+
+

验证:$z\cdot z-1\cdot 1=z^2-1=He_2$ ✓

+
+
+
+ + +
+
+
04 · 核心性质
+

正交性:不同阶数互不干扰

+
+
+ $\mathbb{E}\big[He_m(z)\,He_n(z)\big]=\begin{cases}n! & m=n\\[4pt]0 & m\neq n\end{cases}$ +
$z\sim\mathcal N(0,1)$,期望对钟形曲线取
+
+
+
+
最小例子验证
+
+ $\mathbb{E}[He_1\cdot He_2]=\mathbb{E}[z^3-z]$
+ 高斯的奇数阶矩为 0 → $=0-0=0$ ✓ +
+
就像不同频率的正弦波互相正交
+
+
+
+
+ + +
+
+
05 · 完备性
+

任意函数都能拆开重组

+
+
+ $h(z)=\sum_{d=0}^{\infty}c_d\,He_d(z)$ +
$c_d=\dfrac{\mathbb{E}[h(z)\,He_d(z)]}{d!}$
+
+
+

只要 $\mathbb{E}[h(z)^2]<\infty$(有限能量),就能写成这些积木的加权叠加

+

就像把一个向量沿正交坐标轴分解——每个轴上投影多少,系数 $c_d$ 就有多大。

+
+
+
+ + +
+
+
06 · 关键转折
+

OU 过程让相关性按阶数指数衰减

+
+
+ $\mathbb{E}[He_n(z')He_n(z)]=\rho^{\,n}\cdot n!$ +
$z'=\rho z+\sqrt{1-\rho^2}\,\eta,\quad 0<\rho<1$
+
+
+
1 阶
ρ¹
+
2 阶
ρ²
+
3 阶
ρ³
+

阶数越高 → 相关性掉得越快 → 高阶非线性几乎被冲淡。

+
+
+
+ + +
+
+
07 · 结论
+

最优解:只保留线性成分

+
+
    +
  • 对齐损失要最大化正样本对的相关性。
  • +
  • 线性成分贡献 $\rho$;非线性成分贡献 $\rho^d<\rho\ (d\ge 2)$,被打了折扣。
  • +
  • 于是最优策略就是:留下线性,丢掉所有非线性
  • +
  • 模型被这个机制温柔地逼成一个本质线性的表示 —— 这就是线性可识别性,整套定理的直觉来源。
  • +
+
+
+ + +
+
+
08 · 度量工具
+

谱权重:一张能量饼图

+
+
+
+
线性 $w_1$ —— 我们想要的成分
+
二阶 $w_2$ —— 被 OU 衰减更多
+
更高阶 —— 衰减最狠
+
+ $w_d\ge 0,\quad w_0=0,\quad \textstyle\sum w_d=1$
+
理想状态:整张饼都给线性那一块。
+
+
+
+ + +
+
+
09 · 小结
+

四句话带走全场

+
+
+
01
Hermite 是高斯世界的频率分解工具,类比傅里叶。
+
02
正交性让任意合理函数都能干净地拆成这些积木叠加。
+
03
OU 过程使相关性按 ρᵈ 指数衰减,高阶削减更狠。
+
04
最大化相关性 → 只留线性 → 线性可识别性
+
+
+
+ + +
+
+
下一站
+

Mehler 公式
把直觉坐实

+

下一讲深入 $\rho^d$ 衰减的来源 —— 它来自 OU 过程的转移核在 Hermite 基下的展开。

+
谢谢收听 · 配套音频 hermite_polynomials-podcast.mp3 · 我们下次见
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/research/math/podcast/synth_volc_v3.py b/research/math/podcast/synth_volc_v3.py new file mode 100644 index 0000000..6d743af --- /dev/null +++ b/research/math/podcast/synth_volc_v3.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +"""用火山引擎 v3 单向流式 TTS(/api/v3/tts/unidirectional)把双人对话脚本合成为一个 MP3。 + +鉴权:请求头 x-api-key + X-Api-Resource-Id(新版方式,区别于旧版 Bearer;{token})。 +用法: + VOLC_API_KEY=<你的key> python3 synth_volc_v3.py \ + --script-file hermite_polynomials-script.json \ + --output-file output/hermite_polynomials-podcast.mp3 +""" +import argparse +import base64 +import json +import os +import sys +import time +import uuid + +import requests + +ENDPOINT = "https://openspeech.bytedance.com/api/v3/tts/unidirectional" +RESOURCE_ID = "volc.service_type.10029" + +# 男女两个大模型情感音色(v2 mars bigtts) +VOICE_MALE = "zh_male_beijingxiaoye_emo_v2_mars_bigtts" +VOICE_FEMALE = "zh_female_roumeinvyou_emo_v2_mars_bigtts" + +ADDITIONS = json.dumps( + { + "disable_markdown_filter": True, + "enable_language_detector": True, + "enable_latex_tn": True, + "disable_default_bit_rate": True, + "max_length_to_filter_parenthesis": 0, + } +) + + +def synth_line(api_key: str, text: str, speaker: str, retries: int = 3) -> bytes: + """合成一句,返回 mp3 字节。失败抛异常。""" + headers = { + "x-api-key": api_key, + "X-Api-Resource-Id": RESOURCE_ID, + "Connection": "keep-alive", + "Content-Type": "application/json", + } + payload = { + "req_params": { + "text": text, + "speaker": speaker, + "additions": ADDITIONS, + "audio_params": {"format": "mp3", "sample_rate": 24000}, + } + } + last_err = None + for attempt in range(retries): + try: + r = requests.post(ENDPOINT, headers=headers, json=payload, timeout=60) + if r.status_code != 200: + last_err = f"HTTP {r.status_code}: {r.text[:200]}" + time.sleep(1.0 + attempt) + continue + # 响应体可能是单个 JSON,也可能是多段(流式)。逐段解析 data 累积。 + audio = b"" + text_body = r.text.strip() + # 尝试按行分割的多 JSON(流式 unidirectional 常见) + chunks = [] + for line in text_body.splitlines(): + line = line.strip() + if not line: + continue + chunks.append(line) + if not chunks: + chunks = [text_body] + ok = False + for c in chunks: + try: + obj = json.loads(c) + except json.JSONDecodeError: + continue + if obj.get("code") not in (0, None): + last_err = f"code={obj.get('code')} msg={obj.get('message')}" + continue + d = obj.get("data") + if d: + audio += base64.b64decode(d) + ok = True + if ok and audio: + return audio + last_err = last_err or "no audio data in response" + time.sleep(1.0 + attempt) + except Exception as e: # noqa + last_err = str(e) + time.sleep(1.0 + attempt) + raise RuntimeError(f"合成失败: {last_err}") + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--script-file", required=True) + ap.add_argument("--output-file", required=True) + args = ap.parse_args() + + api_key = os.getenv("VOLC_API_KEY") + if not api_key: + print("ERROR: 需要环境变量 VOLC_API_KEY", file=sys.stderr) + sys.exit(2) + + with open(args.script_file, encoding="utf-8") as f: + script = json.load(f) + lines = script["lines"] + total = len(lines) + print(f"加载脚本:{script.get('title','')},共 {total} 句") + + os.makedirs(os.path.dirname(args.output_file) or ".", exist_ok=True) + + all_audio = b"" + ok_count = 0 + for i, line in enumerate(lines, 1): + speaker = VOICE_MALE if line["speaker"] == "male" else VOICE_FEMALE + text = line["paragraph"] + try: + audio = synth_line(api_key, text, speaker) + all_audio += audio + ok_count += 1 + print(f"[{i}/{total}] {line['speaker']:6s} ok ({len(audio)} bytes)") + except Exception as e: # noqa + print(f"[{i}/{total}] {line['speaker']:6s} FAIL: {e}") + time.sleep(0.15) # 轻微限速 + + if not all_audio: + print("ERROR: 没有任何一句合成成功", file=sys.stderr) + sys.exit(1) + + with open(args.output_file, "wb") as f: + f.write(all_audio) + print(f"\n完成:{ok_count}/{total} 句成功,已写出 {args.output_file}({len(all_audio)} bytes)") + + +if __name__ == "__main__": + main() diff --git a/research/math/podcast2/build_video2.py b/research/math/podcast2/build_video2.py new file mode 100644 index 0000000..8591eb2 --- /dev/null +++ b/research/math/podcast2/build_video2.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +"""把 OU/Mehler 幻灯片 + 已有播客音频合成为 MP4(复用第一篇流程)。 + +流程:读已有音频时长 → 按每句字符占比分配到 12 页 → Chrome 截 12 页 → ffmpeg 合成。 +用法:python3 build_video2.py +""" +import json +import os +import subprocess +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +SCRIPT_JSON = os.path.join(HERE, "ou_mehler-script.json") +SLIDE_HTML = os.path.join(HERE, "slides", "OU 过程与 Mehler 公式.html") +OUT_DIR = os.path.join(HERE, "output") +SHOT_DIR = os.path.join(OUT_DIR, "shots") +AUDIO_IN = os.path.join(OUT_DIR, "ou_mehler-podcast.mp3") +VIDEO_OUT = os.path.join(OUT_DIR, "ou_mehler-video.mp4") +CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" + +NUM_PAGES = 12 +# 句(1-based) -> 页(1-based)。共 44 句、12 页。 +# 1 封面 / 2 核心问题 / 3 OU直觉 / 4 离散定义 / 5 三性质 / 6 Mehler / 7 核心推论 +# 8 数值例子 / 9 对齐损失 / 10 衰减图 / 11 小结 / 12 尾页 +LINE_TO_PAGE = { + 1: 1, 2: 1, # 封面 + 3: 2, # 核心问题 + 4: 3, 5: 3, 6: 3, # OU 物理直觉 + 7: 4, 8: 4, 9: 4, # 离散定义 + 10: 5, 11: 5, 12: 5, 13: 5, 14: 5, 15: 5, # 三性质 + 16: 6, 17: 6, 18: 6, 19: 6, 20: 6, # Mehler 公式 + 21: 7, 22: 7, 23: 7, # 核心推论 + 24: 8, 25: 8, 26: 8, 27: 8, 28: 8, 29: 8, # 数值例子 + 30: 9, 31: 9, 32: 9, 33: 9, 34: 9, # 对齐损失 + 35: 10, 36: 10, # 衰减图示 + 37: 11, 38: 11, 39: 11, 40: 11, 41: 11, # 小结 + 42: 12, 43: 12, 44: 12, # 尾页 +} + + +def run(cmd): + subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + +def ffprobe_dur(path): + out = subprocess.check_output( + ["ffprobe", "-v", "error", "-show_entries", "format=duration", + "-of", "default=noprint_wrappers=1:nokey=1", path]) + return float(out.strip()) + + +def step1_page_durations(): + total = ffprobe_dur(AUDIO_IN) + lines = json.load(open(SCRIPT_JSON, encoding="utf-8"))["lines"] + page_chars = {p: 0 for p in range(1, NUM_PAGES + 1)} + for i, line in enumerate(lines, 1): + page_chars[LINE_TO_PAGE.get(i, NUM_PAGES)] += len(line["paragraph"].strip()) + grand = sum(page_chars.values()) + page_dur = {p: total * page_chars[p] / grand for p in page_chars} + page_dur[NUM_PAGES] += (total - sum(page_dur.values())) + print(f"音频总时长 {total:.2f}s,分配到 {NUM_PAGES} 页:") + for p in range(1, NUM_PAGES + 1): + print(f" page {p:>2}: {page_dur[p]:6.2f}s ({page_chars[p]} 字)") + return page_dur + + +def step2_screenshots(): + os.makedirs(SHOT_DIR, exist_ok=True) + file_url = "file://" + SLIDE_HTML.replace(" ", "%20") + for p in range(1, NUM_PAGES + 1): + out = os.path.join(SHOT_DIR, f"page_{p:02d}.png") + run([CHROME, "--headless=new", "--disable-gpu", "--hide-scrollbars", + "--force-device-scale-factor=1", "--window-size=1920,1080", + f"--screenshot={out}", "--virtual-time-budget=2800", + f"{file_url}?page={p}&clean=1"]) + if not os.path.exists(out): + raise RuntimeError(f"截图失败 page {p}") + print(f"截图 page {p:02d} ✓") + + +def step3_video(page_dur): + tmp_list = os.path.join(SHOT_DIR, "vlist.txt") + with open(tmp_list, "w") as lf: + for p in range(1, NUM_PAGES + 1): + img = os.path.join(SHOT_DIR, f"page_{p:02d}.png") + dur = max(page_dur[p], 0.8) + vid = os.path.join(SHOT_DIR, f"v_{p:02d}.mp4") + run(["ffmpeg", "-y", "-loop", "1", "-i", img, "-t", f"{dur:.3f}", + "-r", "30", "-pix_fmt", "yuv420p", + "-vf", "scale=1920:1080:force_original_aspect_ratio=decrease," + "pad=1920:1080:(ow-iw)/2:(oh-ih)/2", + "-c:v", "libx264", "-preset", "medium", "-crf", "20", vid]) + lf.write(f"file '{vid}'\n") + print(f"页视频 {p:02d} {dur:.2f}s ✓") + silent = os.path.join(SHOT_DIR, "silent.mp4") + run(["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", tmp_list, "-c", "copy", silent]) + run(["ffmpeg", "-y", "-i", silent, "-i", AUDIO_IN, + "-c:v", "copy", "-c:a", "aac", "-b:a", "192k", "-shortest", VIDEO_OUT]) + print(f"\n✅ 视频已输出:{VIDEO_OUT} ({ffprobe_dur(VIDEO_OUT):.1f}s)") + + +def main(): + if not os.path.exists(AUDIO_IN): + print(f"ERROR: 找不到音频 {AUDIO_IN}", file=sys.stderr); sys.exit(1) + print("=== 步骤 1/3:分配每页时长 ===") + page_dur = step1_page_durations() + print("\n=== 步骤 2/3:截取 12 页 ===") + step2_screenshots() + print("\n=== 步骤 3/3:ffmpeg 合成 ===") + step3_video(page_dur) + + +if __name__ == "__main__": + main() diff --git a/research/math/podcast2/ou_mehler-script.json b/research/math/podcast2/ou_mehler-script.json new file mode 100644 index 0000000..a851787 --- /dev/null +++ b/research/math/podcast2/ou_mehler-script.json @@ -0,0 +1,50 @@ +{ + "title": "OU 过程与 Mehler 公式:为什么高阶成分被罚得更狠", + "locale": "zh", + "lines": [ + {"speaker": "male", "paragraph": "Hello Deer!欢迎回来。上一期我们聊了 Hermite 多项式,留了个尾巴——相关性为什么会按阶数指数衰减。今天就来把这个坑填上。"}, + {"speaker": "female", "paragraph": "对,上次最后那个悬念我一直惦记着。今天的主角是两个名字,OU 过程和 Mehler 公式。先说说,它们是用来干嘛的?"}, + {"speaker": "male", "paragraph": "LeJEPA 训练时需要正样本对,也就是同一个内容的两个视角。问题是:这两个视角是怎么造出来的?为什么这种造法会让高阶的非线性成分被惩罚得更重?"}, + {"speaker": "female", "paragraph": "造正样本对的办法,就是 OU 过程,全名奥恩斯坦-乌伦贝克过程。这名字有点吓人,但物理图像其实很可爱对吧?"}, + {"speaker": "male", "paragraph": "非常可爱。你就想象一个小球,被一根弹簧拴在原点。弹簧一直想把它拉回中心,这叫均值回归;同时周围有随机的小扰动在推它,像布朗运动。"}, + {"speaker": "female", "paragraph": "所以小球既被往回拉、又被随机推。这一拉一推的拉扯,就是 OU 过程。那它在 LeJEPA 里具体长什么样?"}, + {"speaker": "male", "paragraph": "论文用的是离散版本,一步到位:新的视角 z 撇,等于 ρ 乘以原来的 z,再加上根号下一减 ρ 平方,乘一个全新的高斯噪声。"}, + {"speaker": "female", "paragraph": "这里的 ρ 是关键,介于零和一之间。它就是上一期我们叫的相关强度,对吧?"}, + {"speaker": "male", "paragraph": "正是。ρ 越接近一,新视角就越像原来的;ρ 越接近零,两个视角就越不相关。实践里一般取零点八到零点九五之间。"}, + {"speaker": "female", "paragraph": "明白。那这个造法有几个很妙的性质,我们一个个说。第一个是平稳性?"}, + {"speaker": "male", "paragraph": "对。如果原来的 z 服从标准高斯,那么造出来的 z 撇也服从同一个标准高斯。算一下就知道:均值还是零,方差还是一,因为 ρ 平方加上一减 ρ 平方正好等于一。"}, + {"speaker": "female", "paragraph": "漂亮,造完之后分布纹丝不动。这意味着两个视角是平起平坐的,没有谁更特殊。第二个性质呢?"}, + {"speaker": "male", "paragraph": "第二个是相关性可控。两个视角的协方差正好等于 ρ。所以 ρ 就像一个旋钮,你拧大它两个视角就更像,拧小就更不像,完全在你掌控之中。"}, + {"speaker": "female", "paragraph": "一个旋钮控制相似度,这设计真干净。第三个性质?"}, + {"speaker": "male", "paragraph": "第三个叫加性噪声。整个转移可以拆成两块:一块是线性漂移 ρ 乘 z,另一块是独立的噪声。干净的线性加噪声结构,正好满足论文要的假设。"}, + {"speaker": "female", "paragraph": "好,三个性质都很温和。那真正的硬核来了——Mehler 公式。它到底说了什么?"}, + {"speaker": "male", "paragraph": "Mehler 公式是 OU 过程的谱定理。一句话说:它把 OU 过程的转移规律,在 Hermite 这套积木的基底下展开了,而且每一阶积木前面的系数,正好是 ρ 的那一阶次方。"}, + {"speaker": "female", "paragraph": "等等,让我抓住重点:d 阶的 Hermite 成分,前面挂的系数是 ρ 的 d 次方?"}, + {"speaker": "male", "paragraph": "完全正确。这就是全部魔法的来源。把它用到编码器的某个分量上,就得到一个特别干净的式子:两个视角在这个分量上的相关性,等于各阶谱权重乘以 ρ 的对应次方,再全部加起来。"}, + {"speaker": "female", "paragraph": "谱权重我们上期讲过,就是那张能量饼图里每一阶占的比例。那现在把这个和数跟 ρ 比一比,会怎样?"}, + {"speaker": "male", "paragraph": "这就是核心推论。因为每一项里 ρ 的 d 次方都小于等于 ρ 本身——d 至少是一嘛——所以整个加权和一定小于等于 ρ。而所有权重加起来是一,所以上界恰好就是 ρ。"}, + {"speaker": "female", "paragraph": "所以相关性最多就是 ρ,封顶了。那什么时候能正好取到这个上限?"}, + {"speaker": "male", "paragraph": "只有一种情况:全部权重都压在一阶上,也就是编码器是纯线性的。只要有任何一个二阶或更高阶的权重大于零,那一项就会严格变小,整个和就够不到 ρ 了。"}, + {"speaker": "female", "paragraph": "所以等号成立,当且仅当纯线性。这个当且仅当太关键了。我们来点具体数字找找感觉?"}, + {"speaker": "male", "paragraph": "好。取 ρ 等于零点九。纯线性编码器,相关性就是零点九的一次方,等于零点九,完美顶到上限。"}, + {"speaker": "female", "paragraph": "纯二次的呢?"}, + {"speaker": "male", "paragraph": "纯二次,相关性是零点九的平方,等于零点八一,已经掉了零点零九。纯三次是零点九的三次方,约零点七三,掉得更多。"}, + {"speaker": "female", "paragraph": "那要是一半线性、一半二次的混合呢?"}, + {"speaker": "male", "paragraph": "混合的就是两者加权平均,零点五乘零点九加零点五乘零点八一,约等于零点八五五。介于两者之间,但仍然够不到零点九。结论很清楚:非线性成分越多,相关性越低。"}, + {"speaker": "female", "paragraph": "数字一摆,趋势一目了然。那这跟 LeJEPA 真正要优化的目标,是怎么挂上钩的?"}, + {"speaker": "male", "paragraph": "LeJEPA 的对齐损失,本质是让两个视角的表示尽量接近,写开之后就等于一个常数减去所有分量相关性的总和。所以最小化损失,就等价于最大化相关性总和。"}, + {"speaker": "female", "paragraph": "而我们刚证明了每个相关性最多是 ρ……"}, + {"speaker": "male", "paragraph": "对,所以对齐损失有一个下界,正比于一减 ρ。而这个最好的下界,当且仅当每一个编码器分量都是线性的时候才能达到。"}, + {"speaker": "female", "paragraph": "于是结论就水落石出了:最优编码器必须是线性的。这正是定理一的心脏。"}, + {"speaker": "male", "paragraph": "一点没错。我们再用一张画面感的图收一下尾:ρ 等于零点九时,一阶零点九、二阶零点八一、三阶零点七三、四阶零点六六、五阶零点五九,像一排越来越短的条。"}, + {"speaker": "female", "paragraph": "非线性成分的相关性随阶数指数往下掉,越高阶越吃亏。这画面我记住了。我们把今天五个要点串一下?"}, + {"speaker": "male", "paragraph": "第一,OU 过程用一拉一推的方式造正样本对,相似度由 ρ 这个旋钮控制。"}, + {"speaker": "female", "paragraph": "第二,平稳性保证两个视角分布相同;相关性恰好是 ρ;结构是线性漂移加独立噪声。"}, + {"speaker": "male", "paragraph": "第三,Mehler 公式说,d 阶 Hermite 成分的相关性是 ρ 的 d 次方。"}, + {"speaker": "female", "paragraph": "第四,核心不等式:相关性等于各阶权重乘 ρ 的对应次方之和,最多到 ρ,等号当且仅当纯线性。"}, + {"speaker": "male", "paragraph": "第五,因此最小化对齐损失就是最大化相关性,逼着编码器学成线性——这就是定理一。"}, + {"speaker": "female", "paragraph": "完美闭环。下一站去哪?"}, + {"speaker": "male", "paragraph": "下一讲我们把 Hermite 展开和今天的 OU 衰减正式拼起来,组装成定理一的完整证明,叫谱分解与线性可识别性。"}, + {"speaker": "female", "paragraph": "好,那我们下期见。谢谢大家收听,记得,弹簧拉小球,ρ 拧大小——我们下次接着拆。拜拜!"} + ] +} diff --git a/research/math/podcast2/ou_mehler-transcript.md b/research/math/podcast2/ou_mehler-transcript.md new file mode 100644 index 0000000..3c9feaa --- /dev/null +++ b/research/math/podcast2/ou_mehler-transcript.md @@ -0,0 +1,95 @@ +# OU 过程与 Mehler 公式:为什么高阶成分被罚得更狠(播客文字稿) + +> 来源文档:[`JEPA/math/02_ou_process_mehler.md`](../../../JEPA/math/02_ou_process_mehler.md) +> 形式:双主播(男 / 女)对话讲解,约 8 分钟 +> 配套脚本:[`ou_mehler-script.json`](ou_mehler-script.json) + +--- + +**男主播:** Hello Deer!欢迎回来。上一期我们聊了 Hermite 多项式,留了个尾巴——相关性为什么会按阶数指数衰减。今天就来把这个坑填上。 + +**女主播:** 对,上次最后那个悬念我一直惦记着。今天的主角是两个名字,OU 过程和 Mehler 公式。先说说,它们是用来干嘛的? + +**男主播:** LeJEPA 训练时需要正样本对,也就是同一个内容的两个视角。问题是:这两个视角是怎么造出来的?为什么这种造法会让高阶的非线性成分被惩罚得更重? + +**女主播:** 造正样本对的办法,就是 OU 过程,全名奥恩斯坦-乌伦贝克过程。这名字有点吓人,但物理图像其实很可爱对吧? + +**男主播:** 非常可爱。你就想象一个小球,被一根弹簧拴在原点。弹簧一直想把它拉回中心,这叫均值回归;同时周围有随机的小扰动在推它,像布朗运动。 + +**女主播:** 所以小球既被往回拉、又被随机推。这一拉一推的拉扯,就是 OU 过程。那它在 LeJEPA 里具体长什么样? + +**男主播:** 论文用的是离散版本,一步到位:新的视角 z 撇,等于 ρ 乘以原来的 z,再加上根号下一减 ρ 平方,乘一个全新的高斯噪声。 + +**女主播:** 这里的 ρ 是关键,介于零和一之间。它就是上一期我们叫的相关强度,对吧? + +**男主播:** 正是。ρ 越接近一,新视角就越像原来的;ρ 越接近零,两个视角就越不相关。实践里一般取零点八到零点九五之间。 + +**女主播:** 明白。那这个造法有几个很妙的性质,我们一个个说。第一个是平稳性? + +**男主播:** 对。如果原来的 z 服从标准高斯,那么造出来的 z 撇也服从同一个标准高斯。算一下就知道:均值还是零,方差还是一,因为 ρ 平方加上一减 ρ 平方正好等于一。 + +**女主播:** 漂亮,造完之后分布纹丝不动。这意味着两个视角是平起平坐的,没有谁更特殊。第二个性质呢? + +**男主播:** 第二个是相关性可控。两个视角的协方差正好等于 ρ。所以 ρ 就像一个旋钮,你拧大它两个视角就更像,拧小就更不像,完全在你掌控之中。 + +**女主播:** 一个旋钮控制相似度,这设计真干净。第三个性质? + +**男主播:** 第三个叫加性噪声。整个转移可以拆成两块:一块是线性漂移 ρ 乘 z,另一块是独立的噪声。干净的线性加噪声结构,正好满足论文要的假设。 + +**女主播:** 好,三个性质都很温和。那真正的硬核来了——Mehler 公式。它到底说了什么? + +**男主播:** Mehler 公式是 OU 过程的谱定理。一句话说:它把 OU 过程的转移规律,在 Hermite 这套积木的基底下展开了,而且每一阶积木前面的系数,正好是 ρ 的那一阶次方。 + +**女主播:** 等等,让我抓住重点:d 阶的 Hermite 成分,前面挂的系数是 ρ 的 d 次方? + +**男主播:** 完全正确。这就是全部魔法的来源。把它用到编码器的某个分量上,就得到一个特别干净的式子:两个视角在这个分量上的相关性,等于各阶谱权重乘以 ρ 的对应次方,再全部加起来。 + +**女主播:** 谱权重我们上期讲过,就是那张能量饼图里每一阶占的比例。那现在把这个和数跟 ρ 比一比,会怎样? + +**男主播:** 这就是核心推论。因为每一项里 ρ 的 d 次方都小于等于 ρ 本身——d 至少是一嘛——所以整个加权和一定小于等于 ρ。而所有权重加起来是一,所以上界恰好就是 ρ。 + +**女主播:** 所以相关性最多就是 ρ,封顶了。那什么时候能正好取到这个上限? + +**男主播:** 只有一种情况:全部权重都压在一阶上,也就是编码器是纯线性的。只要有任何一个二阶或更高阶的权重大于零,那一项就会严格变小,整个和就够不到 ρ 了。 + +**女主播:** 所以等号成立,当且仅当纯线性。这个当且仅当太关键了。我们来点具体数字找找感觉? + +**男主播:** 好。取 ρ 等于零点九。纯线性编码器,相关性就是零点九的一次方,等于零点九,完美顶到上限。 + +**女主播:** 纯二次的呢? + +**男主播:** 纯二次,相关性是零点九的平方,等于零点八一,已经掉了零点零九。纯三次是零点九的三次方,约零点七三,掉得更多。 + +**女主播:** 那要是一半线性、一半二次的混合呢? + +**男主播:** 混合的就是两者加权平均,零点五乘零点九加零点五乘零点八一,约等于零点八五五。介于两者之间,但仍然够不到零点九。结论很清楚:非线性成分越多,相关性越低。 + +**女主播:** 数字一摆,趋势一目了然。那这跟 LeJEPA 真正要优化的目标,是怎么挂上钩的? + +**男主播:** LeJEPA 的对齐损失,本质是让两个视角的表示尽量接近,写开之后就等于一个常数减去所有分量相关性的总和。所以最小化损失,就等价于最大化相关性总和。 + +**女主播:** 而我们刚证明了每个相关性最多是 ρ…… + +**男主播:** 对,所以对齐损失有一个下界,正比于一减 ρ。而这个最好的下界,当且仅当每一个编码器分量都是线性的时候才能达到。 + +**女主播:** 于是结论就水落石出了:最优编码器必须是线性的。这正是定理一的心脏。 + +**男主播:** 一点没错。我们再用一张画面感的图收一下尾:ρ 等于零点九时,一阶零点九、二阶零点八一、三阶零点七三、四阶零点六六、五阶零点五九,像一排越来越短的条。 + +**女主播:** 非线性成分的相关性随阶数指数往下掉,越高阶越吃亏。这画面我记住了。我们把今天五个要点串一下? + +**男主播:** 第一,OU 过程用一拉一推的方式造正样本对,相似度由 ρ 这个旋钮控制。 + +**女主播:** 第二,平稳性保证两个视角分布相同;相关性恰好是 ρ;结构是线性漂移加独立噪声。 + +**男主播:** 第三,Mehler 公式说,d 阶 Hermite 成分的相关性是 ρ 的 d 次方。 + +**女主播:** 第四,核心不等式:相关性等于各阶权重乘 ρ 的对应次方之和,最多到 ρ,等号当且仅当纯线性。 + +**男主播:** 第五,因此最小化对齐损失就是最大化相关性,逼着编码器学成线性——这就是定理一。 + +**女主播:** 完美闭环。下一站去哪? + +**男主播:** 下一讲我们把 Hermite 展开和今天的 OU 衰减正式拼起来,组装成定理一的完整证明,叫谱分解与线性可识别性。 + +**女主播:** 好,那我们下期见。谢谢大家收听,记得,弹簧拉小球,ρ 拧大小——我们下次接着拆。拜拜! diff --git a/research/math/podcast2/output/ou_mehler-podcast.mp3 b/research/math/podcast2/output/ou_mehler-podcast.mp3 new file mode 100644 index 0000000..626c63f Binary files /dev/null and b/research/math/podcast2/output/ou_mehler-podcast.mp3 differ diff --git a/research/math/podcast2/output/ou_mehler-video.mp4 b/research/math/podcast2/output/ou_mehler-video.mp4 new file mode 100644 index 0000000..a30a01a Binary files /dev/null and b/research/math/podcast2/output/ou_mehler-video.mp4 differ diff --git a/research/math/podcast2/output/shots/page_01.png b/research/math/podcast2/output/shots/page_01.png new file mode 100644 index 0000000..66eb8e2 Binary files /dev/null and b/research/math/podcast2/output/shots/page_01.png differ diff --git a/research/math/podcast2/output/shots/page_02.png b/research/math/podcast2/output/shots/page_02.png new file mode 100644 index 0000000..4abd8db Binary files /dev/null and b/research/math/podcast2/output/shots/page_02.png differ diff --git a/research/math/podcast2/output/shots/page_03.png b/research/math/podcast2/output/shots/page_03.png new file mode 100644 index 0000000..58b4b27 Binary files /dev/null and b/research/math/podcast2/output/shots/page_03.png differ diff --git a/research/math/podcast2/output/shots/page_04.png b/research/math/podcast2/output/shots/page_04.png new file mode 100644 index 0000000..8023e9b Binary files /dev/null and b/research/math/podcast2/output/shots/page_04.png differ diff --git a/research/math/podcast2/output/shots/page_05.png b/research/math/podcast2/output/shots/page_05.png new file mode 100644 index 0000000..5ab5e05 Binary files /dev/null and b/research/math/podcast2/output/shots/page_05.png differ diff --git a/research/math/podcast2/output/shots/page_06.png b/research/math/podcast2/output/shots/page_06.png new file mode 100644 index 0000000..5c03847 Binary files /dev/null and b/research/math/podcast2/output/shots/page_06.png differ diff --git a/research/math/podcast2/output/shots/page_07.png b/research/math/podcast2/output/shots/page_07.png new file mode 100644 index 0000000..56887ef Binary files /dev/null and b/research/math/podcast2/output/shots/page_07.png differ diff --git a/research/math/podcast2/output/shots/page_08.png b/research/math/podcast2/output/shots/page_08.png new file mode 100644 index 0000000..6a9f574 Binary files /dev/null and b/research/math/podcast2/output/shots/page_08.png differ diff --git a/research/math/podcast2/output/shots/page_09.png b/research/math/podcast2/output/shots/page_09.png new file mode 100644 index 0000000..fedb504 Binary files /dev/null and b/research/math/podcast2/output/shots/page_09.png differ diff --git a/research/math/podcast2/output/shots/page_10.png b/research/math/podcast2/output/shots/page_10.png new file mode 100644 index 0000000..5f39fb5 Binary files /dev/null and b/research/math/podcast2/output/shots/page_10.png differ diff --git a/research/math/podcast2/output/shots/page_11.png b/research/math/podcast2/output/shots/page_11.png new file mode 100644 index 0000000..3b1eab2 Binary files /dev/null and b/research/math/podcast2/output/shots/page_11.png differ diff --git a/research/math/podcast2/output/shots/page_12.png b/research/math/podcast2/output/shots/page_12.png new file mode 100644 index 0000000..e2aeff2 Binary files /dev/null and b/research/math/podcast2/output/shots/page_12.png differ diff --git a/research/math/podcast2/slides/OU 过程与 Mehler 公式.html b/research/math/podcast2/slides/OU 过程与 Mehler 公式.html new file mode 100644 index 0000000..136822b --- /dev/null +++ b/research/math/podcast2/slides/OU 过程与 Mehler 公式.html @@ -0,0 +1,357 @@ + + + + + +OU 过程与 Mehler 公式 · 为什么高阶成分被罚得更狠 + + + + + + + + + + + + +
← → 翻页 · F 全屏
+
+ + +
+
+
SELF-SUPERVISED · 谱分解 · EP.02
+

OU 过程
Mehler 公式

+

正样本对怎么造?为什么高阶非线性成分被罚得更狠?

+
配套播客 · 双主播对话 · 上接 Hermite 多项式,下启线性可识别性
+
+ + +
+
+
00 · 核心问题
+

正样本对从哪里来

+
+
    +
  • LeJEPA 训练需要「正样本对」——同一内容的两个视角 $(z, z')$。
  • +
  • 这对视角是怎么生成的?答案是 OU 过程
  • +
  • 为什么这种生成方式,会让高阶 Hermite 成分被更强地惩罚
  • +
  • 解开它的钥匙,是 Mehler 公式
  • +
+
+
+ + +
+
+
01 · 物理直觉
+

弹簧上的小球

+
+
+
弹簧力 · 均值回归
+
把小球持续拉回原点,不让它跑远。
+
+
+
随机扰动 · 布朗噪声
+
周围的随机推搡,让小球抖动。
+
+
+
一拉一推 = OU 过程
+
两股力量的拉扯,正是 Ornstein–Uhlenbeck 过程的图像。
+
+
+
+ + +
+
+
02 · 定义
+

LeJEPA 用的离散一步转移

+
+
+ $z' = \rho\,z + \sqrt{1-\rho^{2}}\;\eta$ +
$\eta\sim\mathcal N(0,I),\quad \rho\in(0,1)$
+
+
+

$\rho$ 是相关系数——两个视角的相似度旋钮。

+

$\rho\to1$:几乎相同视角;$\rho\to0$:相互独立。实践取 $\rho\in[0.8,0.95]$。

+
+
+
+ + +
+
+
03 · 三个性质
+

OU 过程的三块基石

+
+
+
① 平稳性
$z\sim\mathcal N(0,I)\Rightarrow z'\sim\mathcal N(0,I)$
均值 0、方差 $\rho^2+(1-\rho^2)=1$。两视角分布相同。
+
② 相关可控
$\mathrm{Cov}(z',z)=\rho\,I$
$\rho$ 直接 = 相似度,一个旋钮说了算。
+
③ 加性噪声
$z'=\rho z+\eta$:线性漂移 + 独立噪声。
满足论文的加性噪声假设。
+
+
+
+ + +
+
+
04 · 谱定理
+

Mehler 公式:每阶挂 ρᵈ

+
+
+ $p(z'\mid z)=\varphi(z')\displaystyle\sum_{d=0}^{\infty}\rho^{d}\,\frac{He_d(z)He_d(z')}{d!}$ +
OU 转移核在 Hermite 基下展开
+
+
+
+ $\mathbb{E}[h_i(z)\,h_i(z')]=\displaystyle\sum_{d=0}^{\infty}\rho^{d}\,w_d$ +
$w_d$=第 $i$ 分量在 $d$ 阶上的谱权重
+
+

关键:d 阶成分的系数 = ρ 的 d 次方

+
+
+
+ + +
+
+
05 · 核心推论
+

相关性封顶在 ρ

+
+
+ $\mathrm{corr}_i=\displaystyle\sum_{d\ge1}w_d\,\rho^{d}\le\sum_{d\ge1}w_d\,\rho=\rho$ +
因为 $\rho^d\le\rho\ (d\ge1)$,且 $\sum w_d=1$
+
+
+

等号成立 当且仅当 $w_1=1$——编码器纯线性。

+

只要有任何 $w_{d_0}>0\ (d_0\ge2)$,那一项就严格变小,和够不到 $\rho$。

+
+
+
+ + +
+
+
06 · 数值例子
+

ρ = 0.9 算给你看

+
+ + + + + + +
编码器谱权重相关性 corrᵢ与 0.9 的差距
纯线性 $h=z$$w_1=1$$0.9^1=0.900$0 | 最优
纯二次 $h=z^2-1$$w_2=1$$0.9^2=0.810$−0.090
纯三次 $h=z^3-3z$$w_3=1$$0.9^3=0.729$−0.171
混合 各半$w_1=w_2=0.5$$0.855$−0.045
+
+
+ + +
+
+
07 · 训练联系
+

对齐损失的下界

+
+
+ $\mathcal L_{\text{align}}=\mathbb{E}\|h(z')-h(z)\|^2$
+ $=2n-2\sum_i \mathrm{corr}_i\;\ge\;2(1-\rho)\,n$ +
最小化损失 ⟺ 最大化相关性之和
+
+
+

等号成立 当且仅当每个 $h_i$ 都是线性的

+

这就是定理一的心脏:最优编码器必须线性

+
+
+
+ + +
+
+
08 · 直觉图示
+

ρ = 0.9 时逐阶衰减

+
+
+
d=1 线性
ρ¹ = 0.900
+
d=2 二次
ρ² = 0.810
+
d=3 三次
ρ³ = 0.729
+
d=4 四次
ρ⁴ = 0.656
+
d=5 五次
ρ⁵ = 0.590
+

非线性成分的相关性随阶数指数衰减——越高阶越吃亏。

+
+
+
+ + +
+
+
09 · 小结
+

五句话带走全场

+
+
+
01
OU 过程「一拉一推」造正样本对,相似度由 ρ 控制。
+
02
平稳性 + 协方差 = ρ + 线性漂移加噪声,三性质齐备。
+
03
Mehler:d 阶 Hermite 成分相关性 = ρᵈ。
+
04
核心不等式 corrᵢ = Σ wᵈ ρᵈ ≤ ρ,等号 ⟺ 纯线性
+
05
最小化对齐损失 → 最大化相关性 → 编码器必须线性(定理一)。
+
+
+
+ + +
+
+
下一站
+

谱分解
与线性可识别性

+

下一讲把 Hermite 展开与 OU 衰减正式拼起来,组装成定理一的完整证明。

+
谢谢收听 · 配套音频 ou_mehler-podcast.mp3 · 弹簧拉小球,ρ 拧大小 · 我们下次见
+
+ +
+ + + + + +