Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

人工智能知识速查

6
Mar
2026

人工智能知识速查

By Alex
/ in AI,Algorithm,Math
0 Comments
基础数学
代数基础
运算律与代数式

代数式(Algebraic Expression)由常数、变量与运算构成;给定变量取值后即可求值。化简(Simplification)的目标是把表达式写成更可读、更便于推导/比较的等价形式:合并同类项(Like Terms)、提取公因子(Common Factor)、展开(Expansion)与因式分解(Factorization)是最常见的操作。

运算律(Algebraic Laws)本质上是在某个数系/代数结构(例如实数域)中成立的恒等式(Identity);它们允许在不改变值的前提下重排/重写表达式。需要区分:加法/乘法满足交换律与结合律,但减法/除法一般不满足。

性质 公式 备注
交换律(Commutativity) \(a+b=b+a\)
\(ab=ba\)
不适用于 \(a-b\)、\(a/b\)
结合律(Associativity) \((a+b)+c=a+(b+c)\)
\((ab)c=a(bc)\)
允许不改变括号结构地分组
分配律(Distributivity) \(a(b+c)=ab+ac\) 展开与提因式的核心
恒等元(Identity Element) \(a+0=a\)
\(a\cdot 1=a\)
0 与 1 在代数推导中常被隐式使用
逆元(Inverse) \(a+(-a)=0\)
\(a\cdot a^{-1}=1\)
第二式要求 \(a\ne 0\)
零乘积原则(Zero Product) \(ab=0\Rightarrow a=0\ \text{或}\ b=0\) 把方程从“乘积=0”转为“因子=0”
因式分解(Factorization)

因式分解(Factorization)把一个表达式改写成若干因子(Factor)的乘积。它的直接价值是:把“值为 0 / 符号变化 / 约束条件”转成对各因子的分析。与之对偶的是展开(Expansion):把乘积写成和式。

对多项式(Polynomial)\(p(x)\),根(Root/Zero)与线性因子之间存在精确对应:若 \(p(r)=0\),则 \((x-r)\) 是 \(p(x)\) 的因子(因子定理(Factor Theorem))。

套路/恒等式 形式 备注
提公因子(Common Factor) \(ax+ay=a(x+y)\) 先把最大公因子提出来
平方差(Difference of Squares) \(a^2-b^2=(a-b)(a+b)\) 常用于构造可约因子
完全平方(Perfect Square) \(a^2\pm 2ab+b^2=(a\pm b)^2\) 与配方(Completing the Square)等价
立方和/差(Sum/Difference of Cubes) \(a^3-b^3=(a-b)(a^2+ab+b^2)\)
\(a^3+b^3=(a+b)(a^2-ab+b^2)\)
二次因子在实数域可能不可再分
二次式按根分解 \(ax^2+bx+c=a(x-r_1)(x-r_2)\) \(r_1,r_2\) 可为复数
分组分解(Grouping) \(ax+ay+bx+by=(a+b)(x+y)\) 目标是制造共同因子
多项式(Polynomial)

一元多项式(Univariate Polynomial)是形如 \(p(x)=\sum_{k=0}^{n} a_k x^k\) 的函数,其中 \(a_k\) 是系数(Coefficient),\(n\) 是次数(Degree)。多项式在实数域上处处可导、可积;在局部逼近(例如 Taylor)与特征构造中非常常用。

多元多项式(Multivariate Polynomial)可写成对多重指数(Multi-index)求和:若 \(x\in\mathbb{R}^d\),则

\[p(x)=\sum_{\alpha\in\mathbb{N}^d} c_\alpha\,x^\alpha,\quad x^\alpha=\prod_{i=1}^{d} x_i^{\alpha_i}\]

补充:多元二次多项式(Quadratic Polynomial)的纯二次部分在线性代数里通常称为二次型(Quadratic Form),可写成矩阵形式 \(q(\mathbf{x})=\mathbf{x}^\top A\mathbf{x}\);其中 \(x_ix_j\)(例如 \(xy\))是交叉项(Cross Term)。

在机器学习里,多项式特征(Polynomial Features)把输入映射到包含高阶项的特征空间,等价于显式构造某些核函数(Kernel)的有限维版本。

概念 表述 用途
首项/首项系数(Leading Term/Coefficient) \(a_n x^n\) / \(a_n\) 决定远端增长阶与符号
余数定理(Remainder Theorem) \(p(x)=q(x)(x-a)+p(a)\) 快速计算 \(p(a)\)
因子定理(Factor Theorem) \(p(a)=0\Leftrightarrow (x-a)\mid p(x)\) 把“根”与“线性因子”连接起来
一元二次方程(Quadratic Equation)

一元二次方程(Quadratic Equation)标准形式为 \(ax^2+bx+c=0\)(\(a\ne 0\))。核心量是判别式(Discriminant)\(\Delta=b^2-4ac\):它决定解的个数与类型。

结论 公式 备注
求根公式(Quadratic Formula) \(x=\frac{-b\pm\sqrt{\Delta}}{2a}\) \(\Delta<0\) 时根为共轭复数
配方(Completing the Square) \(ax^2+bx+c=a\left(x+\frac{b}{2a}\right)^2-\frac{\Delta}{4a}\) 同时给出顶点与最值
顶点(Vertex) \(x_v=-\frac{b}{2a},\quad f(x_v)=-\frac{\Delta}{4a}\) \(a>0\) 时为全局最小;\(a<0\) 时为全局最大
韦达定理(Vieta) \(r_1+r_2=-\frac{b}{a},\quad r_1r_2=\frac{c}{a}\) 无需显式求根即可得到对称量
分式与有理式(Rational Expressions)

分式/有理式(Rational Expression)是两个多项式之比:\(\frac{p(x)}{q(x)}\),并要求 \(q(x)\ne 0\)。任何化简都必须保留定义域(Domain)约束:约分(Cancellation)只是在允许的点上重写表达式,不会“把不可取值点变得可取”。

典型例子: \(\frac{x^2-1}{x-1}=\frac{(x-1)(x+1)}{x-1}=x+1\),但仍需强调 \(x\ne 1\)。这里 \(x=1\) 是可去间断点(Removable Discontinuity):原式无定义,而约分后的表达式在该点有值。

操作 规则 要点
加减 \(\frac{a}{b}\pm\frac{c}{d}=\frac{ad\pm bc}{bd}\) 先通分(Common Denominator)
乘除 \(\frac{a}{b}\cdot\frac{c}{d}=\frac{ac}{bd}\)
\(\frac{a}{b}\div\frac{c}{d}=\frac{a}{b}\cdot\frac{d}{c}\)
除法要求 \(c\ne 0\)
约分 \(\frac{(x-r)u(x)}{(x-r)v(x)}=\frac{u(x)}{v(x)}\) 仍需保留 \(x\ne r\)
符号分析 把数轴按零点/极点分段 有理不等式常用“区间符号表”
绝对值与分段(Absolute Value & Piecewise)

绝对值(Absolute Value)\(|x|\) 表示到 0 的距离(Distance to Zero)。它把“正负”信息丢掉,只保留大小;因此绝对值相关方程/不等式通常要通过分段(Piecewise)把符号情况拆开讨论。

\[|x|=\begin{cases}x,& x\ge 0\\ -x,& x<0\end{cases}\]
形式 等价条件 前提
\(|x|=a\) \(x=a\ \text{或}\ x=-a\) \(a\ge 0\)
\(|x|<a\) \(-a<x<a\) \(a>0\)
\(|x|\le a\) \(-a\le x\le a\) \(a\ge 0\)
\(|x|\ge a\) \(x\le -a\ \text{或}\ x\ge a\) \(a\ge 0\)

三角不等式(Triangle Inequality)\(|x+y|\le |x|+|y|\) 是绝对值最重要的性质之一;它把“求和后的误差”上界化为“各自误差的和”,在误差分析与泛化界推导中高频出现。

深度学习里常见的 ReLU、hinge loss 等都是分段函数:分段点处通常不可导,但仍可用次梯度(Subgradient)做优化。

常用代数技巧:配方 / 换元 / 估计
配方(Completing the Square)

配方(Completing the Square)把二次式改写成“平方 + 常数”,从而直接读出最值、解的结构与可行区间:

\[ax^2+bx+c=a\left(x+\frac{b}{2a}\right)^2-\frac{b^2-4ac}{4a}\]

例如 \(x^2+6x+5=(x+3)^2-4\),因此方程 \(x^2+6x+5=0\) 等价于 \((x+3)^2=4\),解为 \(x=-1,-5\)。

换元(Substitution)

换元(Substitution)通过引入新变量,把原问题变成更低复杂度的标准形式,尤其适用于“重复结构”。例如:

\[x^4-5x^2+4=0,\ \text{令 }u=x^2\Rightarrow u^2-5u+4=0\]

解得 \(u=1,4\),再回代得到 \(x=\pm 1,\pm 2\)。

估计(Bounding / Estimation)

估计(Bounding/Estimation)常把表达式改写为“非负项 + 常数”,或利用单调性把复杂项夹逼到可控区间。最常见的来源是“平方非负”(\((\cdot)^2\ge 0\)):

\[(x-1)^2\ge 0\Rightarrow x^2+1\ge 2x,\quad (|x|-1)^2\ge 0\Rightarrow x^2+1\ge 2|x|\]

这类估计在证明最值、构造上界/下界、以及把损失函数改写成“凸的主项 + 可控余项”时很有效。

数系(Number Systems)

数系(Number Systems)描述“允许使用哪些数,以及这些数上哪些运算是封闭的”。常见链条是

\[\mathbb{N}\subset \mathbb{Z}\subset \mathbb{Q}\subset \mathbb{R}\subset \mathbb{C}\]

其中实数(Real Numbers)是有序(Ordered)且完备(Complete)的;复数(Complex Numbers)扩展了方程可解性(例如 \(x^2+1=0\) 在实数无解,但在复数有解)。

数系 记号 典型元素 结构要点
自然数(Natural Numbers) \(\mathbb{N}\) 0,1,2,…(是否含 0 取决于约定) 对加法/乘法封闭;一般不可做减法/除法
整数(Integers) \(\mathbb{Z}\) …,-2,-1,0,1,2,… 对加减乘封闭;除法不封闭
有理数(Rational Numbers) \(\mathbb{Q}\) \(p/q\)(\(p,q\in\mathbb{Z},q\ne 0\)) 域(Field):非零元素存在乘法逆元
实数(Real Numbers) \(\mathbb{R}\) 包含无理数(Irrational),如 \(\sqrt{2},\pi\) 有序完备域;极限/连续的基础
复数(Complex Numbers) \(\mathbb{C}\) \(a+bi\) 代数闭包(Algebraic Closure);不可定义全序
函数基础
定义域与值域

函数(Function)是映射:把输入集合中的每个元素映到一个输出。定义域(Domain)是允许的输入集合;值域(Range/Image)是实际能取到的输出集合(通常是陪域(Codomain)的子集)。常用记法:

\[f:D\to Y,\quad x\mapsto f(x)\]

从表达式读定义域的常见约束:

  • 分母不为 0: \(\frac{p(x)}{q(x)}\) 要求 \(q(x)\ne 0\)。
  • 偶次根非负: \(\sqrt{g(x)}\) 要求 \(g(x)\ge 0\)(实数域)。
  • 对数正数: \(\ln g(x)\) 要求 \(g(x)>0\)。

值域分析常用“解方程 + 约束”思路:令 \(y=f(x)\),把 \(x\) 表示成 \(y\) 并推导可行条件;若 \(f\) 在某区间单调,则可用反函数直接得到值域。

函数 定义域 值域
\(\sqrt{x}\) \(x\ge 0\) \(y\ge 0\)
\(\ln x\) \(x>0\) \(\mathbb{R}\)
sigmoid(\(\sigma(z)=\frac{1}{1+e^{-z}}\)) \(\mathbb{R}\) \((0,1)\)
\(\tanh z\) \(\mathbb{R}\) \((-1,1)\)
ReLU(\(\max(0,z)\)) \(\mathbb{R}\) \([0,+\infty)\)
复合函数

复合函数(Function Composition)把一个函数的输出作为另一个函数的输入:若 \(g:D\to E\)、\(f:E\to Y\),则

\[(f\circ g)(x)=f(g(x))\]

定义域必须同时满足两层约束: \(x\in\mathrm{dom}(g)\) 且 \(g(x)\in\mathrm{dom}(f)\)。例如 \(f(x)=\sqrt{x}\)、\(g(x)=x^2-1\),则 \((f\circ g)(x)=\sqrt{x^2-1}\) 的定义域是 \(|x|\ge 1\)。

复合满足结合律(Associativity):\((f\circ g)\circ h=f\circ(g\circ h)\),但一般不满足交换律: \(f\circ g\ne g\circ f\)。

反函数

反函数(Inverse Function)把映射“倒过来”。若 \(f:D\to Y\) 在 \(D\) 上是双射(Bijection),则存在 \(f^{-1}:\mathrm{range}(f)\to D\) 满足

\[f^{-1}(f(x))=x,\quad f(f^{-1}(y))=y\]

注意 \(f^{-1}\) 表示反函数,不是倒数 \(1/f\)。求反函数的常用步骤是:设 \(y=f(x)\),交换 \(x,y\) 并解出 \(y\)。

例:线性函数 \(y=ax+b\)(\(a\ne 0\))的反函数是 \(f^{-1}(y)=\frac{y-b}{a}\)。sigmoid 的反函数是 logit:若 \(p=\sigma(z)\),则 \(z=\log\frac{p}{1-p}\)(要求 \(p\in(0,1)\))。

若函数不单调或不可一一对应(如 \(f(x)=x^2\) 在 \(\mathbb{R}\) 上),则必须限制定义域(例如限制为 \(x\ge 0\))才能得到真正的反函数。

奇偶性与单调性

奇偶性(Parity)描述对称性:偶函数(Even Function)满足 \(f(-x)=f(x)\)(关于 y 轴对称),奇函数(Odd Function)满足 \(f(-x)=-f(x)\)(关于原点对称)。

单调性(Monotonicity)描述“随输入增加,输出是否不减/不增”。在区间 \(I\) 上:

  • 单调递增(Monotone Increasing):\(x_1<x_2\Rightarrow f(x_1)\le f(x_2)\)。
  • 严格递增(Strictly Increasing):\(x_1<x_2\Rightarrow f(x_1)<f(x_2)\)。
  • 单调递减/严格递减同理。

单调函数在区间上必为单射(Injective),因此在该区间上可定义反函数。这也是为什么很多“不可逆”的函数(如 \(x^2\))在限制到某个单调区间后就变得可逆。

凸性与凹性

凸性(Convexity)是优化与泛化分析的核心几何性质。函数 \(f\) 在区间/凸集上是凸函数(Convex Function),当且仅当对任意 \(x_1,x_2\) 与 \(\lambda\in[0,1]\) 都有

\[f(\lambda x_1+(1-\lambda)x_2)\le \lambda f(x_1)+(1-\lambda)f(x_2)\]

凹函数(Concave Function)则把不等号方向反过来。几何上:凸函数“弦在图像上方”,凹函数“弦在图像下方”。

若 \(f\) 二阶可导,则一维判别很简单: \(f''(x)\ge 0\) 则凸, \(f''(x)\le 0\) 则凹;多变量情形把 \(f''\) 替换为 Hessian,要求其半正定/半负定。

典型例子: \(x^2\) 与 \(e^x\) 是凸函数;\(\log x\)(\(x>0\))是凹函数。很多经典损失(如 MSE、logistic loss)对模型输出是凸的,但对深度网络参数整体通常非凸。

convex

方程与超平面
线性方程(Ax + By + C = 0)

二维平面中,线性方程(Linear Equation)\(Ax+By+C=0\)(\((A,B)\ne(0,0)\))表示一条直线(Line)。向量 \((A,B)\) 是法向量(Normal Vector):它与直线方向垂直;常数项 \(C\) 控制沿法向量方向的平移。

该形式与超平面形式 \(\mathbf{w}\cdot\mathbf{x}+b=0\) 完全一致:只需取 \(\mathbf{x}=(x,y)^\top\)、\(\mathbf{w}=(A,B)^\top\)、\(b=C\)。

等价形式 表达式 条件/说明
斜截式(Slope-Intercept) \(y=mx+b\) \(B\ne 0\) 时 \(m=-A/B,\ b=-C/B\)
截距(Intercepts) \(x\text{-截距}=-C/A\)
\(y\text{-截距}=-C/B\)
分别要求 \(A\ne 0\)、\(B\ne 0\)
点法式(Point-Normal) \(\mathbf{w}\cdot(\mathbf{x}-\mathbf{x}_0)=0\) \(\mathbf{x}_0\) 是直线上一点
点到直线距离 \(\mathrm{dist}=\frac{|Ax_0+By_0+C|}{\sqrt{A^2+B^2}}\) 来自把点沿法向量投影到直线

两条直线相交/平行可由法向量判断:若 \((A_1,B_1)\) 与 \((A_2,B_2)\) 共线,则两直线平行(或重合);否则相交,交点可由 2×2 线性方程组求解。

linear-equation-geometry

超平面(w·x + b = 0)

超平面(Hyperplane)是高维空间中的“线性边界”。在 \(\mathbb{R}^d\) 中,方程

\[\mathbf{w}\cdot \mathbf{x}+b=0\]

定义一个 \((d-1)\) 维的仿射子空间(Affine Subspace)。其中 \(\mathbf{w}\) 是法向量(Normal Vector),决定边界的朝向;\(b\) 是偏置(Bias),决定边界沿法向量方向的平移。

工程与论文里常写成 \(\mathbf{w}^\top \mathbf{x}+b\):这里的转置(Transpose)符号 \(^\top\) 只是为了把列向量 \(\mathbf{w}\) 变成行向量,从而与列向量 \(\mathbf{x}\) 做矩阵乘法;数值上它等价于点积:

\[\mathbf{w}^\top \mathbf{x}=\sum_{i=1}^{d} w_i x_i\]

例:令 \(\mathbf{w}=(2,3)^\top\)、\(\mathbf{x}=(4,5)^\top\),则 \(\mathbf{w}^\top \mathbf{x}=2\cdot4+3\cdot5=23\)。

在机器学习里,线性分类器(Linear Classifier)可写成 \(\hat y=\mathrm{sign}(\mathbf{w}^\top\mathbf{x}+b)\);逻辑回归(Logistic Regression)把它送入 sigmoid: \(p(y=1|\mathbf{x})=\sigma(\mathbf{w}^\top\mathbf{x}+b)\)。

法向量与半空间

超平面把空间划分成两个半空间(Half-space):

\[\mathbf{w}\cdot\mathbf{x}+b\ge 0,\quad \mathbf{w}\cdot\mathbf{x}+b\le 0\]

法向量 \(\mathbf{w}\) 指向“值更大”的一侧:沿 \(\mathbf{w}\) 方向移动会增大 \(\mathbf{w}\cdot\mathbf{x}+b\)。这也是为什么在线性分类里,得分的正负号自然对应类别划分。

点到超平面的距离

点 \(\mathbf{x}_0\) 到超平面 \(\mathbf{w}\cdot\mathbf{x}+b=0\) 的欧氏距离(Euclidean Distance)为:

\[\mathrm{dist}(\mathbf{x}_0,\ \mathbf{w}\cdot\mathbf{x}+b=0)=\frac{|\mathbf{w}\cdot\mathbf{x}_0+b|}{\|\mathbf{w}\|_2}\]

推导直觉:把 \(\mathbf{x}_0\) 沿法向量方向投影到超平面上;分子是“沿法向量方向的带符号位移”,除以 \(\|\mathbf{w}\|\) 把它变成真实距离。

约束函数、梯度与法向量

约束优化中的边界通常由一个定义在整个空间上的标量函数(Scalar Function)\(g(x)\) 给出,并通过等值方程 \(g(x)=0\) 表示边界本身。函数 \(g\) 是求导对象;边界则是满足该方程的点集。梯度(Gradient)算子 \(\nabla\) 作用在约束函数 \(g\) 上,由此把边界的法向几何信息编码为一个向量场。

线性超平面的情形最直接。边界写成

\[g(\mathbf{x})=\mathbf{w}^\top\mathbf{x}+b=0\]

其中 \(g\) 是定义在整个 \(\mathbb{R}^d\) 上的线性函数,而边界只是它的零等值面(Zero Level Set)。由于线性函数的一阶导数处处相同,立刻得到

\[\nabla g(\mathbf{x})=\mathbf{w}\]

因此,线性超平面的法向量是 \(\mathbf{w}\),本质上等价于“定义该超平面的约束函数 \(g\) 的梯度等于 \(\mathbf{w}\)”。

这一结论对一般光滑边界同样成立。设 \(x^*\) 是边界 \(g(x)=0\) 上一点,且 \(\nabla g(x^*)\ne 0\)。若 \(t\) 是该点处的切向量(Tangent Vector),则沿着 \(t\) 做无穷小移动仍停留在同一条边界上,因而 \(g\) 的一阶变化为 0:

\[\frac{d}{d\epsilon}g(x^*+\epsilon t)\Big|_{\epsilon=0}=0\]

应用链式法则(Chain Rule)得到

\[\nabla g(x^*)^\top t=0\]

这表示边界上的任意切向量都与 \(\nabla g(x^*)\) 正交。因此 \(\nabla g(x^*)\) 沿法向方向指向边界外侧或内侧,而不沿边界本身滑动;梯度正是边界法向量的解析表达。

KKT 条件中的 \(\nabla g(x^*)\) 正是以这种方式出现的。约束优化不是对“边界这个集合”求导,而是借助约束函数 \(g\) 的梯度,把边界的法向几何结构写入一阶最优性条件。驻点条件

\[\nabla f(x^*)+\lambda^*\nabla g(x^*)=0\]

表达的是:在活跃边界上,目标函数剩余的下降趋势完全落在约束边界的法向空间里,并与乘子加权后的法向量达到平衡。

基础几何(Basic Geometry)

解析几何(Analytic Geometry)、向量(Vector)、三角函数(Trigonometric Functions)以及很多 AI 中的空间直觉,都建立在更基础的几何概念上。这里先把最常用的几块地基补齐:距离、角度、弧度、比例与面积。

点、线、角与角度单位

平面几何最基本的对象是点(Point)、线段(Segment)、直线(Line)与角(Angle)。角度描述两条射线的张开程度;常见有两种单位:

\[360^\circ=2\pi\ \text{rad},\quad 180^\circ=\pi\ \text{rad},\quad 90^\circ=\frac{\pi}{2}\ \text{rad}\]

度数(Degree)更适合日常表达,弧度(Radian)更适合数学推导,因为它和圆弧长度、三角函数、导数公式天然兼容。后面遇到旋转矩阵(Rotation Matrix)、复数极坐标(Polar Form)、傅里叶分析(Fourier Analysis)时,默认几乎都使用弧度。

勾股定理与欧氏距离

勾股定理(Pythagorean Theorem)是平面距离公式的根源。对直角三角形,若两条直角边长为 \(a,b\),斜边长为 \(c\),则

\[a^2+b^2=c^2\]

把它应用到坐标平面,就得到两点之间的欧氏距离(Euclidean Distance):

\[\mathrm{dist}(P_1,P_2)=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}\]

在高维空间里,这个公式直接推广为 \(\|\mathbf{x}-\mathbf{y}\|_2\)。因此从二维几何到机器学习里的向量距离,本质上是一条连续的概念链。KNN、K-means、embedding 检索、对比学习(Contrastive Learning)都在反复使用这套“距离越小越相似”的几何直觉。

弧度、弧长与扇形

弧度的定义不是“人为约定一个新单位”,而是直接由圆弧长度导出的:若半径为 \(r\) 的圆上有一段弧长 \(s\),对应圆心角为 \(\theta\)(弧度),则

\[\theta=\frac{s}{r},\quad s=r\theta\]

对应扇形面积(Sector Area)是:

\[A=\frac{1}{2}r^2\theta\]

这正是弧度“自然”的原因:一旦用弧度记角,弧长与面积公式会变得非常干净。AI 里很多周期性表示都默认使用弧度输入,例如 \(\sin\theta\) / \(\cos\theta\) 的位置编码(Positional Encoding)、旋转位置编码(RoPE)以及频域特征(Fourier Features)。

相似、缩放与比例

相似(Similarity)指图形形状相同、大小可以不同;等价地说,对应角相等、对应边成比例。若把一个图形按比例 \(k\) 缩放,则长度变为原来的 \(k\) 倍,面积变为原来的 \(k^2\) 倍。

这个看似初等的事实,在 AI 图像处理中极其常见:图片 resize、本征尺度(Scale)、特征金字塔(Feature Pyramid)、多尺度检测(Multi-scale Detection)都在处理“同一对象在不同尺度下如何保持可识别性”的问题。若缩放时不保持纵横比(Aspect Ratio),就会引入几何畸变,进而影响分类、检测与分割结果。

面积、重叠与 IoU

基础几何里,面积(Area)衡量二维区域所占的大小。矩形面积是长乘宽,圆面积是

\[A=\pi r^2\]

在 AI 的目标检测(Object Detection)与实例分割(Instance Segmentation)中,一个高频几何量是交并比(Intersection over Union, IoU):

\[\mathrm{IoU}=\frac{\text{Intersection Area}}{\text{Union Area}}\]

它衡量预测框/预测区域与真实标注的重叠程度。这里用到的不是高深数学,而是最朴素的面积与重叠概念。

基础几何和AI

若把这些内容压缩成一句话,它们在 AI 中分别承担不同角色:

  • 距离(Distance):支撑近邻搜索、聚类、向量检索与损失函数中的相似度刻画。
  • 角度(Angle):支撑方向、夹角、余弦相似度(Cosine Similarity)与旋转直觉。
  • 弧度(Radian):支撑三角函数、周期建模、位置编码与频域表示。
  • 比例与缩放(Scale):支撑图像 resize、数据增强、特征金字塔与多尺度建模。
  • 面积与重叠(Area & Overlap):支撑 IoU、检测框评估与分割质量度量。
解析几何(Analytic Geometry)

解析几何(Analytic Geometry)的核心做法是:选定坐标系(Coordinate System),用代数方程描述几何对象。一个几何对象可以被理解为“满足某个方程(或方程组)的所有点”的集合。

高中阶段最常见的两类:

  • 一次方程:直线(Line)/平面(Plane)/超平面(Hyperplane)。
  • 二次方程:圆(Circle)与圆锥曲线(Conic Sections);在三维中推广为二次曲面(Quadric Surfaces)。
坐标、距离与圆

在直角坐标系(Cartesian Coordinate System)中,点 \(P\) 用坐标 \((x,y)\) 表示。两点 \(P_1(x_1,y_1)\) 与 \(P_2(x_2,y_2)\) 的欧氏距离(Euclidean Distance)是:

\[\mathrm{dist}(P_1,P_2)=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}\]

圆(Circle)是到某个固定点距离恒定的点集;这个固定点叫圆心(Center)。若圆心为 \((h,k)\)、半径(Radius)为 \(r\),则圆的方程是:

\[(x-h)^2+(y-k)^2=r^2\]

例:方程 \(x^2+y^2-4x+6y-12=0\) 通过配方(Completing the Square)可化为 \((x-2)^2+(y+3)^2=25\),因此它表示圆心 \((2,-3)\)、半径 \(5\) 的圆。

圆锥曲线(Conic Sections):二次方程的几何形状

圆锥曲线(Conic Sections)最初来自“平面截圆锥”的几何构造,但在解析几何里,它们等价于二维的二次方程曲线(Second-degree Plane Curves,方程里变量的最高次数为 2):

\[Ax^2+Bxy+Cy^2+Dx+Ey+F=0\]

其中 \(Bxy\) 是交叉项(Cross Term)。交叉项的存在通常意味着曲线的主轴(Principal Axes)与坐标轴不对齐;通过旋转坐标轴(Rotation of Axes)可以把交叉项消掉,从而得到更“标准”的形状表达。

而一次项 \(Dx+Ey\) 与常数项 \(F\) 扮演的是另一类角色:它们通常不改变主轴方向,而主要影响图形在平面中的位置与尺度。更具体地说,一次项往往意味着曲线的中心/顶点不在原点;在消去交叉项之后,再通过平移坐标(Translation of Axes)与配方(Completing the Square)可以把一次项吸收到平方项里。常数项则相当于改变“等号右边的阈值”,会影响曲线是否有实点、整体大小以及离原点的偏置。简言之:交叉项主要对应旋转,一次项主要对应平移,常数项主要对应整体偏移/尺度调整。

ellipse-term-effects

下面给出最常用的四类圆锥曲线的标准方程(Standard Form)与直观定义:

名称 标准方程 几何定义(直观) 形状关键词
圆(Circle) \(x^2+y^2=r^2\) 到圆心距离恒为 \(r\) 闭合;各向同性
椭圆(Ellipse) \(\frac{x^2}{a^2}+\frac{y^2}{b^2}=1\ (a\ge b>0)\) 到两个焦点(Focus)距离和为常数 闭合;主轴/次轴
抛物线(Parabola) \(y^2=4px\ (p>0)\) 到焦点(Focus)与准线(Directrix)距离相等 开口;无中心
双曲线(Hyperbola) \(\frac{x^2}{a^2}-\frac{y^2}{b^2}=1\) 到两个焦点(Focus)距离差的绝对值为常数 两支;有渐近线(Asymptotes)
椭圆(Ellipse):两焦点“距离和恒定”

椭圆(Ellipse)可以用一句话定义:平面内到两个固定点 \(F_1,F_2\) 的距离之和为常数的点的集合。若该常数为 \(2a\),则对椭圆上任意点 \(P\) 有:

\[\mathrm{dist}(P,F_1)+\mathrm{dist}(P,F_2)=2a\]

在以原点为中心、长轴沿 x 轴的标准位置下,椭圆方程是:

\[\frac{x^2}{a^2}+\frac{y^2}{b^2}=1,\quad a\ge b>0\]

这里 \(a\) 与 \(b\) 分别是半长轴(Semi-major Axis)与半短轴(Semi-minor Axis)。焦距参数 \(c\) 定义为焦点到中心的距离,满足

\[c^2=a^2-b^2\]

因此焦点坐标是 \((\pm c,0)\)。偏心率(Eccentricity)定义为 \(e=c/a\),它量化“椭圆有多扁”: \(e\in[0,1)\);当 \(a=b\) 时 \(e=0\),椭圆退化为圆。

例:若 \(a=5,b=3\),则 \(c=4\)、\(e=0.8\),椭圆为 \(\frac{x^2}{25}+\frac{y^2}{9}=1\),焦点为 \((\pm 4,0)\)。

三维推广:二次曲面(Quadric Surfaces)

在三维中,圆锥曲线推广为二次曲面(Quadric Surfaces):满足三元二次方程的点集。最一般的形式是:

\[Ax^2+By^2+Cz^2+Dxy+Exz+Fyz+Gx+Hy+Iz+J=0\]

其中 \(Dxy,Exz,Fyz\) 是交叉项(Cross Term),对应“坐标轴没有对齐到曲面的主轴方向”。通过平移(Translation)与旋转(Rotation)可以把它化为标准型(Standard Form):平移等价于把原点挪到合适的位置(通常是“中心”附近),旋转等价于把坐标轴转到主轴方向,从而一眼看出是“球/椭球/抛物面/双曲面”等哪一类。

名称 典型方程(标准型) 直观描述
球(Sphere) \(x^2+y^2+z^2=r^2\) 到中心距离恒定的点集(3D 的圆)
椭球(Ellipsoid) \(\frac{x^2}{a^2}+\frac{y^2}{b^2}+\frac{z^2}{c^2}=1\) 三个方向缩放不同的“球”;仍然闭合
椭圆抛物面(Elliptic Paraboloid) \(z=\frac{x^2}{a^2}+\frac{y^2}{b^2}\) “碗状”;水平截面是椭圆
双曲抛物面(Hyperbolic Paraboloid) \(z=\frac{x^2}{a^2}-\frac{y^2}{b^2}\) “马鞍形”;沿一个方向上凸、另一个方向下凹
单叶双曲面(Hyperboloid of One Sheet) \(\frac{x^2}{a^2}+\frac{y^2}{b^2}-\frac{z^2}{c^2}=1\) 连通的一张曲面;截面随方向变化
双叶双曲面(Hyperboloid of Two Sheets) \(-\frac{x^2}{a^2}-\frac{y^2}{b^2}+\frac{z^2}{c^2}=1\) 上下分离的两张曲面

二次曲面与优化中的“二次型/曲率”是同一套数学语言:把坐标轴旋到主轴方向后,表达式会变成各轴平方项的加权和/差,从而直接暴露“碗状(局部最小)”与“鞍形(Saddle)”的结构。

plot-quadric

指数函数

指数函数(Exponential Function)最常用的是自然指数 \(e^x\)。指数运算把“加法结构”映射为“乘法结构”,对数(Logarithm)作为反函数则把乘法结构拉平成加法结构。

性质/公式 表达式 备注
指数基本性质(Exponential Laws) \(e^{a+b}=e^a e^b\)
\(e^{a-b}=\frac{e^a}{e^b}\)
\(a,b\in\mathbb{R}\)
指数运算律(Exponent Rules) \(a^0=1\)
\(a^m a^n=a^{m+n}\)
\(\frac{a^m}{a^n}=a^{m-n}\)
\((a^m)^n=a^{mn}\)
\((ab)^n=a^n b^n\)
\(a>0,a\ne 1\);对整数指数最直接
自然常数(Euler's Number) \(e=\lim_{n\to\infty}\left(1+\frac{1}{n}\right)^n\) 极限刻画连续复利(Continuous Compounding)
微积分性质 \(\frac{d}{dx}e^x=e^x\)
\(\frac{d}{dx}\ln x=\frac{1}{x}\)
以 \(e\) 为底时形式最简
连续增长微分方程 \(y'(t)=y(t),\ y(0)=1\Rightarrow y(t)=e^t\) “增长率与当前值成正比”
与对数互逆 \(\ln(e^x)=x\)
\(e^{\ln x}=x\)
第二式要求 \(x>0\)

常用取值:

输入 \(e^x\) 备注
\(x=0\) \(e^0=1\) 基准点
\(x=1\) \(e^1=e\approx 2.71828\) 自然对数底
\(x=-1\) \(e^{-1}=\frac{1}{e}\approx 0.36788\) 常见衰减尺度
\(x=\ln 2\) \(e^{\ln 2}=2\) 对数域与线性域互换时常用
\(x=\ln 10\) \(e^{\ln 10}=10\) 与 \(\log_{10}\) 换底相关
对数函数

对数函数(Logarithm)\(\log x\) 在 \(x>0\) 上严格单调递增(Strictly Increasing),因此 \(-\log x\) 在 \(x>0\) 上严格单调递减(Strictly Decreasing)。

复合后的单调性由内层决定:若 \(f(x)\) 在某区间上单调递增且 \(f(x)>0\),则 \(-\log(f(x))\) 在该区间上单调递减;若 \(f(x)\) 不单调,则外层单调并不能推出整体单调。

在损失函数里常见的形式是 \(-\log\sigma(z)\)(\(\sigma\) 为 sigmoid)。因为 sigmoid 单调递增,所以该损失对 \(z\) 单调递减:增大 \(z\) 会降低损失。需要注意的是,这只说明“对中间量 z 的单调性”;对模型参数 \(\theta\) 的单调性一般不成立,因为 \(z=z(\theta)\) 是高维非线性函数。

性质/公式 表达式 备注
对数运算律(Logarithm Rules) \(\log(ab)=\log a+\log b\)
\(\log\!\left(\frac{a}{b}\right)=\log a-\log b\)
\(\log(a^k)=k\log a\)
同一底数;典型要求 \(a>0,b>0\)
换底公式(Change of Base) \(\log_a x=\frac{\ln x}{\ln a}\) \(a>0,a\ne 1,x>0\)
与指数互逆 \(a^{\log_a x}=x\)
\(\log_a(a^x)=x\)
\(x>0\)

常用取值:

表达式 值 备注
\(\ln 1\) \(0\) \(x=1\) 为基准点
\(\ln e\) \(1\) 自然对数的定义性质
\(\ln 2\) \(\approx 0.6931\) 二进制相关常数
\(\ln 10\) \(\approx 2.3026\) 十进制相关常数
\(\log_{10}2\) \(=\frac{\ln 2}{\ln 10}\approx 0.3010\) 工程里常用于数量级估算
\(\log_2 10\) \(=\frac{\ln 10}{\ln 2}\approx 3.3219\) bit 与十进制数量级换算
\(\log_2 e\) \(=\frac{1}{\ln 2}\approx 1.4427\) nats 与 bits 换算常数
\(\log_{10}e\) \(=\frac{1}{\ln 10}\approx 0.4343\) 自然对数与常用对数换算

在语言模型 softmax 中,logit 经过指数再归一化:\(\exp(\text{logit})\) 把分数映射为正数权重;取 log 则把乘法结构拉平成加法结构,便于用和式写出似然与损失。

幂函数

幂函数(Power Function)里常见的两个扩展是负指数(Negative Exponent)与分数指数(Rational Exponent)。

类型 公式 条件/备注
负指数(Negative Exponent) \(a^{-n}=\frac{1}{a^n}\) \(a\ne 0\);\(n\) 为正整数
分数指数(Rational Exponent) \(a^{p/q}=\sqrt[q]{a^p}\) \(q>0,\gcd(p,q)=1\);实数域通常要求 \(a>0\)
例 \(2^{-3}=\frac{1}{8}\)
\(9^{1/2}=3\)
\(8^{2/3}=4\)
偶次根要求被开方数非负

常用取值:

表达式 值 备注
\(2^{-3}\) \(=\frac{1}{8}=0.125\) 负指数转倒数
\(10^{-3}\) \(=0.001\) 毫(\(10^{-3}\))尺度
\(2^{1/2}=\sqrt{2}\) \(\approx 1.4142\) 最常见的无理数根
\(2^{-1/2}=\frac{1}{\sqrt{2}}\) \(\approx 0.7071\) 正交归一化、幅度缩放常用
\(10^{1/2}=\sqrt{10}\) \(\approx 3.1623\) 对数刻度下的“半个数量级”
\(10^{-1/2}=\frac{1}{\sqrt{10}}\) \(\approx 0.3162\) 与上式互为倒数
三角函数
基本三角恒等式

三角函数(Trigonometric Functions)可以用单位圆(Unit Circle)定义:在圆上角度为 \(\theta\) 的点坐标是 \((\cos\theta,\sin\theta)\)。由此得到最基本恒等式:

类别 公式 备注
基本恒等式 \(\sin^2\theta+\cos^2\theta=1\)
\(\tan\theta=\frac{\sin\theta}{\cos\theta}\)
\(\cos\theta\ne 0\) 时定义 \(\tan\theta\)
与 \(\tan,\cot\) 相关 \(1+\tan^2\theta=\sec^2\theta\)
\(1+\cot^2\theta=\csc^2\theta\)
定义域同 \(\tan,\cot\)
和差公式(Angle Addition) \(\sin(\alpha\pm\beta)=\sin\alpha\cos\beta\pm\cos\alpha\sin\beta\)
\(\cos(\alpha\pm\beta)=\cos\alpha\cos\beta\mp\sin\alpha\sin\beta\)
傅里叶分析、RoPE 等直觉常用
二倍角(Double-Angle) \(\sin 2\theta=2\sin\theta\cos\theta\)
\(\cos 2\theta=\cos^2\theta-\sin^2\theta=1-2\sin^2\theta=2\cos^2\theta-1\)
同一恒等式的不同等价写法
周期性(Periodicity) \(\sin(\theta+2\pi)=\sin\theta\)
\(\cos(\theta+2\pi)=\cos\theta\)
一个周期(Period)为 \(2\pi\)
常用极限(\(x\to 0\)) \(\lim_{x\to 0}\frac{\sin x}{x}=1\)
\(\lim_{x\to 0}\frac{\tan x}{x}=1\)
\(\lim_{x\to 0}\frac{1-\cos x}{x^2}=\frac{1}{2}\)
推导导数与近似时高频出现
常用特殊角(Special Angles)
\(\theta\)(弧度) 角度制 \(\sin\theta\) \(\cos\theta\) \(\tan\theta\)
\(0\) 0° \(0\) \(1\) \(0\)
\(\pi/6\) 30° \(\frac{1}{2}\) \(\frac{\sqrt{3}}{2}\) \(\frac{1}{\sqrt{3}}\)
\(\pi/4\) 45° \(\frac{\sqrt{2}}{2}\) \(\frac{\sqrt{2}}{2}\) \(1\)
\(\pi/3\) 60° \(\frac{\sqrt{3}}{2}\) \(\frac{1}{2}\) \(\sqrt{3}\)
\(\pi/2\) 90° \(1\) \(0\) 未定义(undefined)
\(\pi\) 180° \(0\) \(-1\) \(0\)
\(3\pi/2\) 270° \(-1\) \(0\) 未定义(undefined)
\(2\pi\) 360° \(0\) \(1\) \(0\)
欧拉公式

欧拉公式(Euler's Formula)把指数与三角函数在复数域(Complex Domain)里统一起来:

结论 公式 备注
欧拉公式(Euler's Formula) \(e^{i\theta}=\cos\theta+i\sin\theta\) 把“旋转”写成复指数
辐角相加对应指数相乘 \(e^{i\theta_1}e^{i\theta_2}=e^{i(\theta_1+\theta_2)}\) 复数乘法:模相乘、辐角相加
欧拉恒等式(Euler's Identity) \(e^{i\pi}+1=0\) 连接 \(e,i,\pi,1,0\)
基础函数图像

image-of-common-fns

复数

一个常见疑问是:既然 \(\mathbb{R}^2\) 里的二维向量已经能表示平面上的点 \((x,y)\),为什么还需要复数?表面上看,二维向量 \((a,b)\) 与复数 \(a+bi\) 确实对应同一个平面点;但它们的代数结构完全不同,关键差别在于“乘法”是否自然、闭合且可逆。

对二维向量而言,加法非常自然,但乘法并不形成一个像实数那样稳定的数系:点乘(Inner Product)会把两个向量变成标量,叉乘(Cross Product)又会把结果带到垂直方向;因此二维向量空间本身并没有一个同时兼顾封闭性(Closure)与可除性的内建乘法。复数则不同:两个复数相乘后仍是复数,非零复数还总能做除法。这使得复平面不只是“几何上的二维平面”,而是一个可自由做加减乘除的完整数系。

这带来两个二维向量本身不具备的优势。第一,复数把二维旋转直接写进了乘法:若 \(z=re^{i\theta}\),则乘以另一个复数时会自动实现“模相乘、角相加”。换句话说,复数乘法天然就是缩放 + 旋转;而若只用二维向量,通常还需要额外引入旋转矩阵。第二,复数让多项式方程的可解性闭合:例如 \(x^2+1=0\) 在实数域无解,但在复数域有解 \(\pm i\)。更深一层地,代数基本定理(Fundamental Theorem of Algebra)说明任意非常数多项式在复数域里都有根,因此复数成为代数方程的自然终点。

因此,二维向量更像是在描述“箭头、位移、速度、受力”的线性对象;复数则是在同一个平面上额外安装了一套兼容乘法、旋转与方程求解的代数机制。对于信号处理(Signal Processing)、交流电分析、傅里叶变换(Fourier Transform)、量子力学以及很多 AI 中的频域方法,复数都不是“二维向量的重复发明”,而是一个更强的二维代数系统。

复数的表示:直角坐标(Rectangular Form)

复数(Complex Number)写作 \(z=a+bi\),其中 \(a,b\in\mathbb{R}\),虚数单位(Imaginary Unit)满足 \(i^2=-1\)。把 \(z\) 视为二维平面上的点 \((a,b)\),就得到直角坐标(Rectangular Form)。

复数的表示:极坐标(Polar Form)

同一个点也可用极坐标(Polar Form)表示:令 \(r=|z|\) 为模(Modulus),\(\theta=\arg(z)\) 为辐角(Argument),则

\[z=r(\cos\theta+i\sin\theta)=re^{i\theta}\]

两种坐标之间的转换:

\[r=\sqrt{a^2+b^2},\quad a=r\cos\theta,\quad b=r\sin\theta\]

\(\theta\) 通常用 \(\mathrm{atan2}(b,a)\) 计算,并且 \(\arg(z)\) 不是唯一的:加上任意 \(2\pi k\)(\(k\in\mathbb{Z}\))表示同一个方向。

例:\(z=1+i\) 的模是 \(\sqrt{2}\),辐角是 \(\pi/4\),因此 \(z=\sqrt{2}\,e^{i\pi/4}\)。

棣莫弗公式(De Moivre's Formula)给出幂运算的快捷形式:

\[(\cos\theta+i\sin\theta)^n=\cos(n\theta)+i\sin(n\theta)\]
共轭与模

复数 \(z = a + bi\) 的模(Modulus)定义为 \(|z|=\sqrt{a^2+b^2}\),表示复平面(Complex Plane)中点 \((a,b)\) 到原点的欧氏距离(Euclidean Distance)。

共轭(Conjugate)记作 \(\bar z = a-bi\)。几何上,它把点 \((a,b)\) 关于实轴(Real Axis)镜像到 \((a,-b)\);数值上,它把“相位(Phase)”取反而保持“幅值(Magnitude)”不变。

共轭与模的核心关系是 \(z\bar z = |z|^2\),展开即可验证:

\[(a+bi)(a-bi)=a^2+b^2=|z|^2\]

这个恒等式的一个直接用途是复数除法:为了避免分母含有虚部,把分母乘以共轭进行“有理化(Rationalization)”。

\[\frac{a+bi}{c+di}=\frac{(a+bi)(c-di)}{(c+di)(c-di)}=\frac{(a+bi)(c-di)}{c^2+d^2}\]

例: \(\frac{1+2i}{3-4i}=\frac{(1+2i)(3+4i)}{3^2+4^2}=\frac{-5+10i}{25}=-\frac{1}{5}+\frac{2}{5}i\)。这里分母变成实数,是因为 \((3-4i)(3+4i)=3^2+4^2\)。

复数乘法与旋转

把复数写成极坐标(Polar Form):\(z=r(\cos\theta+i\sin\theta)=re^{i\theta}\)。此时复数乘法的几何意义非常直接:

\[z_1 z_2 = (r_1 e^{i\theta_1})(r_2 e^{i\theta_2}) = (r_1 r_2)e^{i(\theta_1+\theta_2)}\]

也就是说:模相乘、辐角相加。乘法同时完成缩放(Scaling)与旋转(Rotation)。

例:乘以 \(i=e^{i\pi/2}\) 会把任意复数逆时针旋转 90° 且不改变模;乘以 \(-1=e^{i\pi}\) 会旋转 180°。例如 \((1+2i)\cdot i=-2+i\),几何上就是把点 \((1,2)\) 旋到 \((-2,1)\)。

数列与级数

求和符号(Summation Symbol)\(\sum\) 与乘积符号(Product Symbol)\(\prod\) 是数列与级数推导里最常见的两个“聚合”记号:

\[\sum_{i=1}^{n} a_i=a_1+a_2+\cdots+a_n,\quad \prod_{i=1}^{n} a_i=a_1\cdot a_2\cdots a_n\]

英文里通常把 \(\sum\) 读作 “sigma” 或 “summation”,把 \(\prod\) 读作 “capital pi” 或 “product”。

等差数列 / 等比数列

数列(Sequence)是一列按整数下标排列的数 \(\{a_n\}_{n\ge 1}\)。最常见的两类是等差数列(Arithmetic Sequence)与等比数列(Geometric Sequence)。它们都可用“递推定义 + 通项公式 + 前 n 项和”三件套描述。

类型 递推定义 通项(\(a_n\)) 前 n 项和(\(S_n=\sum_{k=1}^{n} a_k\))
等差数列(Arithmetic) \(a_{n}=a_{n-1}+d\) \(a_n=a_1+(n-1)d\) \(S_n=\frac{n}{2}(a_1+a_n)=\frac{n}{2}\left(2a_1+(n-1)d\right)\)
等比数列(Geometric) \(a_{n}=ra_{n-1}\) \(a_n=a_1 r^{n-1}\) \(S_n=\begin{cases}\frac{a_1(1-r^n)}{1-r},& r\ne 1 \\ na_1,& r=1\end{cases}\)

例:若 \(a_1=1,d=2\),则 \(a_n=2n-1\) 且 \(S_n=n^2\)。若 \(a_1=1,r=\frac{1}{2}\),则 \(S_n=2\left(1-2^{-n}\right)\),并随 \(n\) 增大趋近于 2。

无穷级数与收敛

无穷级数(Infinite Series)\(\sum_{n=1}^{\infty} a_n\) 的核心对象是部分和(Partial Sum)序列 \(S_N=\sum_{n=1}^{N} a_n\)。若极限 \(\lim_{N\to\infty} S_N\) 存在且为有限值,则级数收敛(Convergence);否则发散(Divergence)。

必要条件:若 \(\sum_{n=1}^{\infty} a_n\) 收敛,则必有 \(\lim_{n\to\infty} a_n=0\)。反之不成立(例如调和级数 \(\sum 1/n\) 发散)。

绝对收敛(Absolute Convergence)指 \(\sum |a_n|\) 收敛;绝对收敛必推出原级数收敛。仅 \(\sum a_n\) 收敛但 \(\sum |a_n|\) 发散则为条件收敛(Conditional Convergence),此时项的重排可能改变和(甚至导致发散)。

infinite-series

判别法 条件/计算量 结论
几何级数(Geometric Series) \(\sum_{n=0}^{\infty} ar^n\) \(|r|<1\) 时收敛,且和为 \(\frac{a}{1-r}\);\(|r|\ge 1\) 时发散
p-级数(p-series) \(\sum_{n=1}^{\infty}\frac{1}{n^p}\) \(p>1\) 收敛;\(p\le 1\) 发散(调和级数为 \(p=1\))
比较判别(Comparison) \(0\le a_n\le b_n\)(充分大时) 若 \(\sum b_n\) 收敛,则 \(\sum a_n\) 收敛;若 \(\sum a_n\) 发散,则 \(\sum b_n\) 发散
比值判别(Ratio Test) \(L=\limsup_{n\to\infty}\left|\frac{a_{n+1}}{a_n}\right|\) \(L<1\) 绝对收敛;\(L>1\)(或无穷大)发散;\(L=1\) 不定
根值判别(Root Test) \(\rho=\limsup_{n\to\infty}\sqrt[n]{|a_n|}\) \(\rho<1\) 绝对收敛;\(\rho>1\) 发散;\(\rho=1\) 不定
交错级数(Alternating Series) \(\sum (-1)^{n-1}b_n\),其中 \(b_n\downarrow 0\) 收敛;截断误差满足 \(|S-S_N|\le b_{N+1}\)
调和级数与调和数(Harmonic Series / Harmonic Numbers)

调和级数(Harmonic Series)是 \(\sum_{n=1}^{\infty}\frac{1}{n}\)。它是最经典的“项趋于 0 但级数仍发散”的例子:虽然 \(\lim_{n\to\infty}\frac{1}{n}=0\),但部分和会无界增长。

其部分和称为调和数(Harmonic Number):

\[H_n=\sum_{k=1}^{n}\frac{1}{k}\]

调和数的渐近行为与对数紧密相关:\(H_n=\log n+\gamma+o(1)\),其中 \(\gamma\) 是欧拉-马歇罗尼常数(Euler–Mascheroni constant)。因此很多“累积量随步数缓慢增长”的分析最终都会出现 \(\log n\)。

在 AI/优化里,调和级数最常见的用途是解释与验证学习率(Learning Rate)衰减的收敛条件。经典随机逼近(Stochastic Approximation)的一个常用充分条件是:

\[\sum_{t=1}^{\infty}\eta_t=\infty,\quad \sum_{t=1}^{\infty}\eta_t^2<\infty\]

取 \(\eta_t=\frac{1}{t}\) 时,第一项对应调和级数发散(保证“走得足够远”),第二项对应 \(\sum 1/t^2\) 收敛(保证噪声的累计影响有限)。很多 SGD(Stochastic Gradient Descent)及在线学习(Online Learning)的理论推导,会用这组“一个发散、一个收敛”的对比来控制偏差与方差项。

Taylor 展开

Taylor 展开(Taylor Expansion)用多项式在局部逼近光滑函数。Taylor 定理(Taylor's Theorem)强调“有限阶近似 + 余项(Remainder)”,Taylor 级数(Taylor Series)强调“无限项级数在收敛时等于原函数”。

\[f(x)=\sum_{k=0}^{n}\frac{f^{(k)}(a)}{k!}(x-a)^k+R_{n+1}(x)\]

当余项在 \(n\to\infty\) 时收敛到 0,才有 \(f(x)=\sum_{k=0}^{\infty}\frac{f^{(k)}(a)}{k!}(x-a)^k\)。并非所有光滑函数都等于其 Taylor 级数。

例:在 \(a=0\) 展开,\(e^x\approx 1+x+\frac{x^2}{2}\);当 \(|x|\) 很小时,用低阶项就能得到高精度近似。

taylor-expansion

组合数学

组合数学(Combinatorics)研究离散结构的计数、构造与存在性。它的典型问题是“有多少种可能”:当选择空间巨大时,计数结果直接决定搜索/采样的复杂度;当把计数结果归一化为概率时,就得到二项分布、超几何分布等常见模型。

排列与组合

排列(Permutation)与组合(Combination)的区别只在一个点:是否区分顺序。把“先选哪些元素”与“再怎么排序”分开理解,可以避免大量记忆负担。

对象 记号 公式 直觉
阶乘(Factorial) \(n!\) \(n!=n(n-1)\cdots 2\cdot 1,\ 0!=1\) 把 \(n\) 个互异元素全部排列的方式数
排列(k-permutation) \(P(n,k)\) \(P(n,k)=\frac{n!}{(n-k)!}\) 从 \(n\) 个里选 \(k\) 个并排序:一步一步填位置
组合(k-combination) \({n \choose k}\) \({n \choose k}=\frac{n!}{k!(n-k)!}\) 从 \(n\) 个里选 \(k\) 个,不关心顺序:先选集合
排列与组合关系 \(P(n,k)\) \(P(n,k)={n \choose k}\,k!\) 先选 \(k\) 个元素,再把它们排序

例:从 5 个候选特征里挑 3 个做一个无序子集,有 \({5 \choose 3}=10\) 种;如果还要给这 3 个特征排“处理顺序”,则变为排列 \(P(5,3)=5\cdot4\cdot3=60\) 种。

二项式定理

二项式定理(Binomial Theorem)描述 \((a+b)^n\) 的展开结构:

\[(a+b)^n=\sum_{k=0}^{n}{n \choose k}a^{n-k}b^k\]

系数 \({n \choose k}\) 的组合解释非常直接:把 \((a+b)^n\) 看作 \(n\) 个括号相乘,每一项由“从每个括号里选 \(a\) 或 \(b\)”组成。若最终选了 \(k\) 次 \(b\),就需要从 \(n\) 个位置里挑出这 \(k\) 个位置,因此系数是 \({n \choose k}\)。

例:\((x+2)^4={4 \choose 0}x^4+{4 \choose 1}x^3\cdot2+{4 \choose 2}x^2\cdot2^2+{4 \choose 3}x\cdot2^3+{4 \choose 4}2^4=x^4+8x^3+24x^2+32x+16\)。

二项式系数还满足递推(Pascal's Rule):\({n \choose k}={n-1 \choose k-1}+{n-1 \choose k}\)。这等价于“选与不选某个固定元素”的分类讨论。

与概率的连接:若独立伯努利试验(Bernoulli Trial)成功概率为 \(p\),做 \(n\) 次恰好成功 \(k\) 次的概率是 \({n \choose k}p^k(1-p)^{n-k}\),其中 \({n \choose k}\) 计数的是“成功出现在哪些轮次”。

不等式

不等式(Inequality)是把“难算/难优化/难比较”的表达式替换为“可控的上界或下界”的工具。机器学习中的许多目标函数与泛化分析,本质上都在用不等式把复杂量压到可操作的形式(例如把非线性函数用线性或二次上界近似)。

基本不等式

基本不等式(Basic Inequalities)常见来源有两类:一类来自非负量(例如 \((\cdot)^2\ge 0\)),另一类来自范数(Norm)与凸性(Convexity)的结构性质。

不等式 形式 典型用途
平方非负 \((a-b)^2\ge 0\Rightarrow a^2+b^2\ge 2ab\) 把乘积项 \(ab\) 转成平方项,便于求界或优化(常见于“配方”)
三角不等式(Triangle Inequality) \(|x+y|\le |x|+|y|\) 把“相加后的绝对值”上界成“绝对值之和”;用于误差传播与残差界
均值不等式(AM-GM) \(\frac{a+b}{2}\ge \sqrt{ab}\quad (a,b\ge 0)\) 在“和固定时乘积最大”或“乘积/几何平均”相关问题里给出最紧的经典界

例(AM-GM 的“最大乘积”直觉):在 \(a,b\ge 0\) 且 \(a+b=10\) 的约束下,乘积满足 \(ab\le \left(\frac{a+b}{2}\right)^2=25\),并且当且仅当 \(a=b=5\) 取等号。

Jensen 不等式

Jensen 不等式(Jensen's Inequality)回答一个很具体的问题:“平均”与“非线性”交换顺序会发生什么。它是把抽象的凸性(Convexity)变成可用结论的最常用工具之一。

先把术语说清楚:

  • 加权平均(Weighted Average):给一组数 \(x_1,\dots,x_n\) 分配权重 \(\lambda_i\ge 0\) 且 \(\sum_i\lambda_i=1\),则加权平均是 \(\sum_i\lambda_i x_i\)(把 \(\lambda_i\) 视为“占比”即可)。
  • 凸函数(Convex Function):函数 \(\varphi\) 若满足对任意 \(x_1,x_2\) 与 \(\lambda\in[0,1]\) 都有 \(\varphi(\lambda x_1+(1-\lambda)x_2)\le \lambda\varphi(x_1)+(1-\lambda)\varphi(x_2)\),则称 \(\varphi\) 是凸的。直观上:它“向上弯”,因此对它做平均会被“惩罚”。
  • 随机变量(Random Variable):一个在不同试验/样本上会取不同值的量;把 \(X\) 视为“每次取到的数”。
  • 期望(Expectation)\(\mathbb{E}[\cdot]\):可把它理解为“按概率加权的平均”。

Jensen 的形式(离散加权平均):若 \(\varphi\) 凸,则

\[\varphi\!\left(\sum_i \lambda_i x_i\right)\le \sum_i \lambda_i \varphi(x_i)\]

等价的期望形式:对随机变量 \(X\)(且 \(\mathbb{E}[X]\) 与 \(\mathbb{E}[\varphi(X)]\) 存在),有

\[\varphi(\mathbb{E}[X])\le \mathbb{E}[\varphi(X)]\]

如果 \(\varphi\) 是凹函数(Concave Function),不等号方向会反过来。

场景 1:凸惩罚下,“波动”本身有代价。设某个系统的代价函数是 \(\varphi(t)=t^2\)(二次惩罚,Convex Penalty),比较两种延迟(Latency):

  • 稳定方案:每次都是 100ms,则平均代价是 \(100^2=10000\)。
  • 波动方案:一半时间 50ms、一半时间 150ms(平均同样是 100ms),则平均代价是 \(\frac{50^2+150^2}{2}=12500\)。

两者平均延迟一样,但二次代价更偏好稳定方案;这就是 Jensen 在 \(\varphi(t)=t^2\) 下的直接体现:\(\left(\frac{50+150}{2}\right)^2\le \frac{50^2+150^2}{2}\)。

场景 2:对数损失下,“偶尔很错”会被放大。分类里常用对数损失(Log Loss)\(\varphi(p)=-\log p\)(\(p\) 是正确类别的预测概率),它在 \((0,1]\) 上是凸函数。假设一个模型在同一个样本上两次输出 \(p=0.9\) 与 \(p=0.1\)(一次很自信、一次几乎反过来),则

\[-\log\!\left(\frac{0.9+0.1}{2}\right)=-\log 0.5\approx 0.693\le \frac{-\log 0.9-\log 0.1}{2}\approx 1.204\]

含义:在凸损失下,预测的波动会提高平均损失;这也是许多“用不等式构造上界/下界”方法(例如把难优化的期望目标变成可算的界)背后的数学原因。

何时取等号:当所有 \(x_i\) 相等(没有波动),或 \(\varphi\) 在相关区间上近似线性时,不等式可取等号。

Cauchy-Schwarz 不等式

Cauchy-Schwarz 不等式(Cauchy–Schwarz Inequality)回答另一个非常基础的问题:两组数“对齐相乘再求和”的结果,最多能有多大。它是内积(Inner Product)与范数(Norm)体系的核心约束。

把术语说清楚后,这个不等式就不神秘:

  • 向量(Vector):把一组数按顺序排成列表,例如 \(\mathbf{a}=(a_1,\dots,a_n)\)。
  • 点积/内积(Dot Product / Inner Product):\(\mathbf{a}^\top\mathbf{b}=\sum_i a_i b_i\),可理解为“两组数在同一位置上的重叠程度”。
  • L2 范数(\(\ell_2\) Norm):\(\|\mathbf{a}\|_2=\sqrt{\sum_i a_i^2}\),几何上是向量长度(Length)。

不等式本身是:

\[|\mathbf{a}^\top\mathbf{b}|\le \|\mathbf{a}\|_2\,\|\mathbf{b}\|_2\]

几何解释:把 \(\mathbf{a}^\top\mathbf{b}\) 写成 \(\|\mathbf{a}\|_2\|\mathbf{b}\|_2\cos\theta\),Cauchy-Schwarz 等价于 \(|\cos\theta|\le 1\)。当且仅当两向量同向或反向(线性相关(Linearly Dependent))时取等号。

场景 1:为什么检索里常用“余弦相似度(Cosine Similarity)”。在向量检索中,常用点积 \(\mathbf{q}^\top\mathbf{d}\) 衡量查询向量 \(\mathbf{q}\) 与文档向量 \(\mathbf{d}\) 的相似度。但点积同时受“方向”和“长度”影响:如果某个向量范数很大,即使方向一般,点积也可能很大。

一个最小例子:令查询 \(\mathbf{q}=(1,1)\),两篇候选文档向量为 \(\mathbf{d}_1=(100,0)\)、\(\mathbf{d}_2=(2,2)\)。点积分别是 \(\mathbf{q}^\top\mathbf{d}_1=100\)、\(\mathbf{q}^\top\mathbf{d}_2=4\),点积会更偏向 \(\mathbf{d}_1\)。但如果把向量归一化到单位范数(Unit Norm)再比较,则

\[\cos(\mathbf{q},\mathbf{d}_1)=\frac{\mathbf{q}^\top\mathbf{d}_1}{\|\mathbf{q}\|_2\|\mathbf{d}_1\|_2}=\frac{1}{\sqrt{2}},\quad \cos(\mathbf{q},\mathbf{d}_2)=\frac{\mathbf{q}^\top\mathbf{d}_2}{\|\mathbf{q}\|_2\|\mathbf{d}_2\|_2}=1\]

归一化后 \(\mathbf{d}_2\) 与 \(\mathbf{q}\) 方向完全一致,更符合“语义对齐”的直觉。Cauchy-Schwarz 保证余弦相似度一定落在 [-1,1],从而成为一个尺度稳定、可解释的相似度。

场景 2:为什么相关系数(Correlation Coefficient)不可能超过 1。把两组已中心化(Centered,均值为 0)的数据序列看成向量 \(\mathbf{x},\mathbf{y}\),它们的“协方差方向”可以写成点积 \(\mathbf{x}^\top\mathbf{y}\),而各自的尺度由 \(\|\mathbf{x}\|_2,\|\mathbf{y}\|_2\) 给出。Cauchy-Schwarz 直接推出

\[\left|\frac{\mathbf{x}^\top\mathbf{y}}{\|\mathbf{x}\|_2\|\mathbf{y}\|_2}\right|\le 1\]

这就是“线性相关强度最多 100%”的数学原因;取等号对应完全线性关系,即 \(\mathbf{y}=c\mathbf{x}\)。

集合论基础

集合论(Set Theory)是现代数学语言的底座:几乎所有“对象 + 结构”的定义都能归结为集合及其上的运算。工程语境里,把对象抽象为集合的好处是:边界清晰、可组合、可用代数规则推导。

集合运算(并 / 交 / 补)

集合(Set)是元素(Element)的无序聚合。记 \(x\in A\) 表示 \(x\) 属于集合 \(A\),记 \(A\subseteq B\) 表示子集(Subset)。常用的运算如下。

运算 记号 定义 例子
并(Union) \(A\cup B\) \(\{x\mid x\in A\ \text{或}\ x\in B\}\) \(\{1,2,3\}\cup\{3,4\}=\{1,2,3,4\}\)
交(Intersection) \(A\cap B\) \(\{x\mid x\in A\ \text{且}\ x\in B\}\) \(\{1,2,3\}\cap\{3,4\}=\{3\}\)
差(Difference) \(A\setminus B\) \(\{x\mid x\in A,\ x\notin B\}\) \(\{1,2,3\}\setminus\{3,4\}=\{1,2\}\)
补(Complement) \(A^c\) 相对于全集 \(U\): \(A^c=U\setminus A\) 若 \(U=\{1,2,3,4\}\),则 \(\{1,2,3\}^c=\{4\}\)

De Morgan 律(De Morgan's Laws)是“补运算”与“并/交”之间的互换规则:

\[(A\cup B)^c=A^c\cap B^c,\quad (A\cap B)^c=A^c\cup B^c\]

计数场景常用容斥原理(Inclusion–Exclusion):\(|A\cup B|=|A|+|B|-|A\cap B|\)。例:一个数据集里“命中规则 A”的样本有 120 个,“命中规则 B”的有 80 个,同时命中的有 30 个,则命中至少一个规则的样本数是 \(120+80-30=170\)。

映射与关系

映射(Mapping / Function)用来描述“从输入到输出”的确定性规则。写作 \(f:A\to B\),其中 \(A\) 是定义域(Domain),\(B\) 是陪域(Codomain)。对 \(x\in A\),输出写作 \(f(x)\in B\)。像集(Image / Range)为 \(f(A)=\{f(x)\mid x\in A\}\)。

关系(Relation)是更一般的概念:它不要求“每个输入对应唯一输出”。在集合论里,一个二元关系 \(R\) 可以看成笛卡尔积(Cartesian Product)上的子集:

\[R\subseteq A\times B,\quad (a,b)\in R\ \text{表示}\ a\ R\ b\]

典型例子:

  • 等价关系(Equivalence Relation):满足自反、对称、传递。例如定义 \(x\sim y\Leftrightarrow x-y\) 能被 \(m\) 整除(同余),它把整数划分为若干等价类(Equivalence Class)。
  • 偏序(Partial Order):满足自反、反对称、传递。例如 \(\le\) 是实数上的偏序;集合的包含关系 \(\subseteq\) 也是偏序。
  • 一般关系:例如“相似度大于阈值”定义了一个关系,但它通常不具备传递性,因此不是等价关系。

把关系写成矩阵/邻接矩阵(Adjacency Matrix)是常用表示:若 \(A=B=\{1,\ldots,n\}\),定义 \(M_{ij}=1\) 当且仅当 \((i,j)\in R\)。在图论(Graph Theory)与推荐/检索(Retrieval)里,这种表示会直接进入线性代数计算。

线性代数
向量
向量加减法(Vector Addition / Subtraction)

在 \(\mathbb{R}^n\) 中,向量加法与减法按分量(Component-wise)进行。对 \(\mathbf{a}=(a_1,\ldots,a_n)\)、\(\mathbf{b}=(b_1,\ldots,b_n)\):

\[\mathbf{a}+\mathbf{b}=(a_1+b_1,\ldots,a_n+b_n),\quad \mathbf{a}-\mathbf{b}=(a_1-b_1,\ldots,a_n-b_n)\]

几何上,加法对应向量合成;减法 \(\mathbf{a}-\mathbf{b}\) 是从 \(\mathbf{b}\) 指向 \(\mathbf{a}\) 的位移向量。

例:若 \(\mathbf{a}=(1,2)\)、\(\mathbf{b}=(3,-1)\),则 \(\mathbf{a}+\mathbf{b}=(4,1)\),\(\mathbf{a}-\mathbf{b}=(-2,3)\)。

在 AI 里,残差连接(Residual Connection)是 \(\mathbf{x}+f(\mathbf{x})\);梯度下降(Gradient Descent)的更新可写成 \(\theta\leftarrow\theta-\eta\nabla L(\theta)\)。它们都直接依赖向量加减法。

点积(Dot Product)

点积(Dot Product)把两个向量映射为标量(Scalar),常用于相似度、投影和方向一致性判断。对 \(\mathbf{a},\mathbf{b}\in\mathbb{R}^n\),定义为 \(\mathbf{a}\cdot\mathbf{b}=\sum_{i=1}^n a_i b_i\)。当 \(\mathbf{a},\mathbf{b}\ne\mathbf{0}\) 时,也可写为 \(\mathbf{a}\cdot\mathbf{b}=\|\mathbf{a}\|\|\mathbf{b}\|\cos\theta\)。

点积满足交换律(Commutativity):\(\mathbf{a}\cdot\mathbf{b}=\mathbf{b}\cdot\mathbf{a}\)。若 \(\mathbf{a}\cdot\mathbf{b}=0\),两向量正交(Orthogonal)。

向量 \(\mathbf{a}\) 在 \(\mathbf{b}\) 方向上的标量投影是 \(\frac{\mathbf{a}\cdot\mathbf{b}}{\|\mathbf{b}\|}\)。投影更常用的是向量形式(Vector Projection):

\[\mathrm{proj}_{\mathbf{b}}(\mathbf{a})=\frac{\mathbf{a}\cdot\mathbf{b}}{\|\mathbf{b}\|^2}\mathbf{b}\]

当把向量归一化到单位范数(Unit Norm)后,点积就等于余弦相似度(Cosine Similarity):\(\cos\theta=\mathbf{\hat a}\cdot\mathbf{\hat b}\),这也是检索与表示学习中常见的相似度度量。

单位向量(Unit Vector)是范数为 1 的向量,常用来“只表示方向”。对非零向量 \(\mathbf{a}\),其单位向量是 \(\mathbf{\hat a}=\frac{\mathbf{a}}{\|\mathbf{a}\|}\)。

方向角(Direction Angles)/方向余弦(Direction Cosines)描述单位向量与各坐标轴的夹角:在三维中,若单位向量 \(\mathbf{u}=(u_x,u_y,u_z)\),则 \(u_x=\cos\alpha\)、\(u_y=\cos\beta\)、\(u_z=\cos\gamma\),并满足 \(\cos^2\alpha+\cos^2\beta+\cos^2\gamma=1\)。

点积之所以会出现“乘积”,是因为它等于“被投影长度 × 参照向量长度”: \(\mathbf{a}\cdot\mathbf{b}=\|\mathbf{b}\|\cdot \mathrm{projLen}_{\mathbf{b}}(\mathbf{a})\)。当两向量同向时,投影长度就是 \(\|\mathbf{a}\|\),于是点积变为 \(\|\mathbf{a}\|\|\mathbf{b}\|\)。

二维向量的复数表示

在二维空间里,向量 \((a,b)\) 可以写成复数 \(z=a+bi\)。这不是把向量“变成另一种对象”,而是给同一个二维量换一种记法:实部对应 x 轴分量,虚部对应 y 轴分量。

若另一向量 \((c,d)\) 写成 \(w=c+di\),则复共轭乘积为

\[z\bar w=(a+bi)(c-di)=(ac+bd)+i(bc-ad)\]

其中实部 \(ac+bd\) 恰好就是二维向量的点积:

\[\mathbf{a}\cdot\mathbf{b}=ac+bd=\mathrm{Re}(z\bar w)\]

若再把它们写成极坐标形式 \(z=r_1e^{i\theta_1}\)、\(w=r_2e^{i\theta_2}\),则

\[\mathbf{a}\cdot\mathbf{b}=\mathrm{Re}(z\bar w)=r_1r_2\cos(\theta_1-\theta_2)\]

这里实部的来源可以直接从指数形式读出:因为 \(\bar w=r_2e^{-i\theta_2}\),所以 \(z\bar w=r_1r_2e^{i(\theta_1-\theta_2)}\)。再用欧拉公式 \(e^{i\phi}=\cos\phi+i\sin\phi\) 展开,就得到 \(z\bar w=r_1r_2\big(\cos(\theta_1-\theta_2)+i\sin(\theta_1-\theta_2)\big)\);其中实部正是 \(r_1r_2\cos(\theta_1-\theta_2)\)。

因此,点积既可以看成分量乘加,也可以看成“复数乘积取实部”。后一种写法把长度与相位差放进同一个式子里,在位置编码、旋转表示与频域分析中尤其方便。后文 RoPE 的复数视角正是沿用这层关系:二维块先写成复数,再让相位随位置旋转。

例:令 \(\mathbf{a}=(3,4)\)、\(\mathbf{b}=(4,0)\)。则 \(\mathbf{a}\cdot\mathbf{b}=12\)、\(\|\mathbf{a}\|=5\)、\(\|\mathbf{b}\|=4\),所以 \(\cos\theta=\frac{12}{20}=0.6\)。而 \(\mathbf{a}\) 在 \(\mathbf{b}\) 方向上的标量投影是 \(\frac{12}{4}=3\),恰好对应 \(\mathbf{a}\) 的 x 分量。

vector-ops

叉积(Cross Product)

叉积(Cross Product)定义在三维空间(3D Space)。结果是同时垂直于两个输入向量的向量,大小为 \(\|\mathbf{a}\times\mathbf{b}\|=\|\mathbf{a}\|\|\mathbf{b}\|\sin\theta\),等于两向量张成平行四边形的面积。

计算上,若 \(\mathbf{a}=(a_1,a_2,a_3)\)、\(\mathbf{b}=(b_1,b_2,b_3)\),则:

\[\mathbf{a}\times\mathbf{b}=(a_2b_3-a_3b_2,\ a_3b_1-a_1b_3,\ a_1b_2-a_2b_1)\]

例: \((1,0,0)\times(0,1,0)=(0,0,1)\)。这个例子在几何上对应两个单位正交基向量张成的“正方形面积为 1”,方向由右手定则给出。

叉积为零当且仅当两向量平行(Parallel/Colinear)或至少有一个为零向量:这是因为 \(\|\mathbf{a}\times\mathbf{b}\|=\|\mathbf{a}\|\|\mathbf{b}\|\sin\theta\),为 0 只能来自 \(\sin\theta=0\) 或 \(\|\mathbf{a}\|=0\) 或 \(\|\mathbf{b}\|=0\)。

方向由右手定则(Right-Hand Rule)确定:四指从 \(\mathbf{a}\) 旋向 \(\mathbf{b}\),拇指方向即 \(\mathbf{a}\times\mathbf{b}\) 方向。旋转“正负”不是绝对物理事实,而是由坐标系(Coordinate System)与观察方向(View Direction)约定决定。

力矩(Torque)可作为叉积方向的直观例子: \(\boldsymbol{\tau}=\mathbf{r}\times\mathbf{F}\)。这里保留物理解释的唯一目的,是帮助理解叉积的方向性。

基(Basis)

在 \(\mathbb{R}^n\) 中,一组向量 \(\{\mathbf{b}_1,\ldots,\mathbf{b}_n\}\) 若线性无关(Linearly Independent)且张成(Span)整个空间,则称为一组基(Basis)。任何向量 \(\mathbf{x}\) 都能唯一表示为 \(\mathbf{x}=\sum_{i=1}^{n} c_i\mathbf{b}_i\);系数向量 \(\mathbf{c}=(c_1,\ldots,c_n)^\top\) 就是 \(\mathbf{x}\) 在该基下的坐标(Coordinates)。

把基向量按列堆成矩阵 \(B=[\mathbf{b}_1\ \cdots\ \mathbf{b}_n]\in\mathbb{R}^{n\times n}\),则坐标与原向量满足 \(\mathbf{x}=B\mathbf{c}\)。换基(Change of Basis)在推导里本质就是在不同 \(B\) 之间切换坐标表示。

换基(Change of Basis):同一个向量,不同坐标

“换基”最容易被误解成“把向量变形”。它真正做的事情是:几何向量(Geometric Vector)不变,参考基(Basis)变了,因此坐标(Coordinates)变了。直观上,可把几何向量理解为平面/空间里的一支箭头。

为了不混淆“向量本身”和“向量的坐标表示”,可以用一个约定把它们分开:

  • \(\mathbf{x}\):把同一个几何向量用标准基(Standard Basis)写出来的分量列向量(数值计算里最常用的表示)。
  • \(\mathbf{c}\):把同一个几何向量用某组新基 \(\{\mathbf{b}_i\}\) 写出来的坐标向量(Coordinate Vector),也就是“在新基上要乘的系数”。

把新基向量在标准基下的分量按列组成 \(B=[\mathbf{b}_1\ \cdots\ \mathbf{b}_n]\)(可称为基矩阵(Basis Matrix)),则

\[\mathbf{x}=B\mathbf{c}\]

读法:右边 \(\mathbf{c}\) 是“在新基下的坐标”,左边 \(\mathbf{x}\) 是“在标准基下的分量”。乘上 \(B\) 就把“新基坐标”换算回“标准基分量”。

反过来,如果你已知标准基下的分量 \(\mathbf{x}\),想求新基坐标 \(\mathbf{c}\),就需要解线性方程组 \(B\mathbf{c}=\mathbf{x}\)。由于基向量线性无关,矩阵 \(B\) 必可逆(Invertible),因此可写成:

\[\mathbf{c}=B^{-1}\mathbf{x}\]

更一般地,若旧基矩阵为 \(B\)、新基矩阵为 \(C\),同一几何向量满足 \(\mathbf{x}=B\mathbf{c}_{B}=C\mathbf{c}_{C}\),于是坐标之间的换算是:

\[\mathbf{c}_{C}=C^{-1}B\,\mathbf{c}_{B}\]

矩阵 \(P=C^{-1}B\) 常被称为换基矩阵(Change-of-basis Matrix):它把“旧基坐标”直接映射为“新基坐标”。

例:在 \(\mathbb{R}^2\) 取 \(\mathbf{b}_1=(1,0)^\top,\ \mathbf{b}_2=(1,1)^\top\)。对 \(\mathbf{x}=(2,3)^\top\),解 \(\mathbf{x}=c_1\mathbf{b}_1+c_2\mathbf{b}_2\) 得 \(c_2=3,\ c_1=-1\),因此该基下坐标为 \(\mathbf{c}=(-1,3)^\top\)。同一个几何向量,在不同基下的坐标会不同。

把基矩阵写出来会更便于计算: \(B=[\mathbf{b}_1\ \mathbf{b}_2]=\begin{bmatrix}1 & 1\\ 0 & 1\end{bmatrix}\)。此时 \(B\mathbf{c}=\begin{bmatrix}1 & 1\\ 0 & 1\end{bmatrix}\begin{bmatrix}-1\\ 3\end{bmatrix}=\begin{bmatrix}2\\ 3\end{bmatrix}=\mathbf{x}\);反过来,解 \(B\mathbf{c}=\mathbf{x}\) 等价于 \(\mathbf{c}=B^{-1}\mathbf{x}\),因此“换基”在计算上就是解一个线性方程组。

标准基(Standard Basis)

标准基(Standard Basis)是最常用的一组基。第 \(i\) 个标准基向量 \(\mathbf{e}_i\) 只有第 \(i\) 个分量为 1,其余为 0:

\[\mathbf{e}_1=(1,0,\ldots,0)^\top,\ \mathbf{e}_2=(0,1,0,\ldots,0)^\top,\ \ldots,\ \mathbf{e}_n=(0,\ldots,0,1)^\top\]

例:在 \(\mathbb{R}^2\) 中,\((2,3)^\top=2\mathbf{e}_1+3\mathbf{e}_2\)。把 \(\{\mathbf{e}_i\}\) 作为列组成矩阵就是单位矩阵 \(I\),因此标准基下 \(\mathbf{x}=I\mathbf{x}\) 对应“坐标与分量一致”。

正交基(Orthogonal Basis)

正交基(Orthogonal Basis)是指基向量两两正交:对 \(i\ne j\) 有 \(\mathbf{b}_i^\top\mathbf{b}_j=0\)。它不要求单位长度。

正交基的一个关键性质是:坐标可以用投影直接算出。若 \(\mathbf{x}=\sum_i c_i\mathbf{b}_i\) 且 \(\{\mathbf{b}_i\}\) 正交,则

\[c_i=\frac{\mathbf{x}^\top\mathbf{b}_i}{\mathbf{b}_i^\top\mathbf{b}_i}\]

例:取 \(\mathbf{b}_1=(1,1)^\top,\ \mathbf{b}_2=(1,-1)^\top\),它们点积为 0。对 \(\mathbf{x}=(2,1)^\top\),有 \(c_1=\frac{3}{2},\ c_2=\frac{1}{2}\),因此 \(\mathbf{x}=\frac{3}{2}\mathbf{b}_1+\frac{1}{2}\mathbf{b}_2\)。

正交标准基(Orthonormal Basis)

正交标准基(Orthonormal Basis)要求两两正交且每个基向量单位长度: \(\|\mathbf{u}_i\|_2=1\),并满足 \(\mathbf{u}_i^\top\mathbf{u}_j=\delta_{ij}\)(克罗内克 delta(Kronecker Delta))。

此时坐标就是内积/投影:若 \(\mathbf{x}=\sum_i c_i\mathbf{u}_i\),则 \(c_i=\mathbf{x}^\top\mathbf{u}_i\)。计算上,这等价于把向量投影到各基方向。

例:令 \(\mathbf{u}_1=\frac{1}{\sqrt{2}}(1,1)^\top,\ \mathbf{u}_2=\frac{1}{\sqrt{2}}(1,-1)^\top\)。对 \(\mathbf{x}=(2,1)^\top\),有 \(c_1=\frac{3}{\sqrt{2}},\ c_2=\frac{1}{\sqrt{2}}\),于是 \(\mathbf{x}=c_1\mathbf{u}_1+c_2\mathbf{u}_2\)。

把 \(\{\mathbf{u}_i\}\) 按列组成矩阵 \(Q\),则 \(Q^\top Q=I\),并且坐标变换可写成 \(\mathbf{c}=Q^\top\mathbf{x}\)、重构为 \(\mathbf{x}=Q\mathbf{c}\)。在 PCA(Principal Component Analysis)与 SVD 中,主方向/奇异向量就是正交标准基;投影与重构只需要转置,不需要显式求逆。

矩阵运算

矩阵运算(Matrix Operations)是机器学习(Machine Learning)中最核心的计算骨架。前向传播、反向传播和参数更新都可以表示为矩阵与向量的组合。

加法与广播(Addition / Broadcasting)

矩阵加法按元素(Element-wise)进行:若 \(X,B\in\mathbb{R}^{m\times n}\),则 \((X+B)_{ij}=X_{ij}+B_{ij}\)。减法同理。

在深度学习框架里常见的是广播(Broadcasting):例如对 batch 特征 \(X\in\mathbb{R}^{B\times d}\) 与偏置 \(\mathbf{b}\in\mathbb{R}^{d}\),写作 \(Y=X+\mathbf{b}\) 意味着把 \(\mathbf{b}\) 复制到每一行后再相加。这是线性层 \(Y=XW+\mathbf{b}\) 的标准形式。

例:矩阵加法
\[X=\begin{bmatrix}1 & 2\\ 3 & 4\end{bmatrix},\ B=\begin{bmatrix}10 & 20\\ 30 & 40\end{bmatrix}\Rightarrow X+B=\begin{bmatrix}11 & 22\\ 33 & 44\end{bmatrix}\]
例:广播加偏置(Bias Broadcasting)

令 \(X\in\mathbb{R}^{2\times 3}\)、\(\mathbf{b}\in\mathbb{R}^{3}\):

\[X=\begin{bmatrix}1 & 2 & 3\\ 4 & 5 & 6\end{bmatrix},\ \mathbf{b}=\begin{bmatrix}10 & 20 & 30\end{bmatrix}\]

广播的语义是“把 \(\mathbf{b}\) 复制到每一行”,因此

\[Y=X+\mathbf{b}=\begin{bmatrix}11 & 22 & 33\\ 14 & 25 & 36\end{bmatrix}\]

从线性代数角度,把 \(\mathbf{b}\) 视作行向量,则广播等价于 \(Y=X+\mathbf{1}\mathbf{b}\),其中 \(\mathbf{1}\in\mathbb{R}^{B\times 1}\) 是全 1 列向量。

矩阵乘法(Matrix Multiplication)

矩阵乘法(Matrix Multiplication)在神经网络里通常对应线性层(Linear Layer):\(Y=XW\)。从“每个输出维度是一个点积”来看更容易记:

\[y_j=\sum_{i=1}^{d_{\text{in}}} x_i W_{ij}\]

在批处理(Batch)场景下,常用形状约定是 \(X\in\mathbb{R}^{B\times d_{\text{in}}}\)、\(W\in\mathbb{R}^{d_{\text{in}}\times d_{\text{out}}}\)、\(Y=XW\in\mathbb{R}^{B\times d_{\text{out}}}\)。矩阵乘法一般不满足交换律(Non-commutativity),形状不匹配时也无法相乘。

从几何(Geometry)角度看,矩阵定义了一个线性变换(Linear Transformation):它把空间中的点/向量整体“变形”(旋转、缩放、剪切、投影等)。一种实用记法是看基向量(Basis Vectors)如何被映射:如果用列向量约定,矩阵的每一列就是某个基向量变换后的像。

例(二维):标准基向量(Standard Basis Vectors)为 \(\mathbf{e}_1=(1,0)^\top\) 与 \(\mathbf{e}_2=(0,1)^\top\)。对

\[A=\begin{bmatrix}a & c\\ b & d\end{bmatrix}\]

有

\[A\mathbf{e}_1=\begin{bmatrix}a\\ b\end{bmatrix},\quad A\mathbf{e}_2=\begin{bmatrix}c\\ d\end{bmatrix}\]

因此 \(A\) 的第 1/2 列分别是 \(\mathbf{e}_1,\mathbf{e}_2\) 的像。对任意 \(\mathbf{x}=x_1\mathbf{e}_1+x_2\mathbf{e}_2\),根据线性变换的线性性(Linearity)\(A(\alpha\mathbf{u}+\beta\mathbf{v})=\alpha A\mathbf{u}+\beta A\mathbf{v}\),可得

\[A\mathbf{x}=x_1A\mathbf{e}_1+x_2A\mathbf{e}_2=x_1\begin{bmatrix}a\\ b\end{bmatrix}+x_2\begin{bmatrix}c\\ d\end{bmatrix}\]

数值例子:取

\[A=\begin{bmatrix}2 & 1\\ 0 & 1\end{bmatrix}\]

则 \(A\mathbf{e}_1=(2,0)^\top\)、\(A\mathbf{e}_2=(1,1)^\top\)。若 \(\mathbf{x}=(3,4)^\top=3\mathbf{e}_1+4\mathbf{e}_2\),则

\[A\mathbf{x}=3A\mathbf{e}_1+4A\mathbf{e}_2=3\begin{bmatrix}2\\ 0\end{bmatrix}+4\begin{bmatrix}1\\ 1\end{bmatrix}=\begin{bmatrix}10\\ 4\end{bmatrix}\]

这就是“看列向量理解变换”的核心:先画出两条基向量被送到哪里,整个网格会按相同线性组合随之平移/剪切/旋转/缩放。

matrix-trans

这对应两种等价视角:

  • 变换向量(Active View):固定坐标轴,让向量 \(\mathbf{x}\) 变成 \(A\mathbf{x}\)。
  • 变换坐标轴(Passive View):固定几何点,把坐标系按 \(A^{-1}\) 变换;同一个点在新坐标系下的坐标会变化。

两种视角描述的是同一个线性映射,只是“变的对象”不同。在做特征变换/白化(Whitening)/坐标变换推导时,这个区分能避免符号混乱。

矩阵乘法只有在内维度相等时才有定义:\((m\times n)(n\times p)=(m\times p)\)。把向量视为列向量(\(m\times 1\))或行向量(\(1\times m\))后,外积与点积也都可以统一为矩阵乘法的特例。

  1. 一般矩阵乘法:\((m\times n)(n\times p)=(m\times p)\)。

    \[A=\begin{bmatrix}1 & 2 & 3\\ 4 & 5 & 6\end{bmatrix}\in\mathbb{R}^{2\times 3},\quad B=\begin{bmatrix}7 & 8\\ 9 & 10\\ 11 & 12\end{bmatrix}\in\mathbb{R}^{3\times 2}\] \[AB=\begin{bmatrix}58 & 64\\ 139 & 154\end{bmatrix}\in\mathbb{R}^{2\times 2}\]
  2. 外积(Outer Product):\((m\times 1)(1\times n)=(m\times n)\)。

    \[\mathbf{u}=\begin{bmatrix}1\\ 2\\ 3\end{bmatrix}\in\mathbb{R}^{3\times 1},\quad \mathbf{v}=\begin{bmatrix}4 & 5\end{bmatrix}\in\mathbb{R}^{1\times 2}\] \[\mathbf{u}\mathbf{v}=\begin{bmatrix}4 & 5\\ 8 & 10\\ 12 & 15\end{bmatrix}\in\mathbb{R}^{3\times 2}\]

    这是一个秩一(Rank-1)矩阵:它把“列向量 × 行向量”变成矩阵;在低秩近似、注意力权重构造与二阶统计量里都很常见。

  3. 点积(Dot Product):\((1\times m)(m\times 1)=(1\times 1)\)。

    \[\mathbf{r}=\begin{bmatrix}1 & 2 & 3\end{bmatrix}\in\mathbb{R}^{1\times 3},\quad \mathbf{c}=\begin{bmatrix}4\\ 5\\ 6\end{bmatrix}\in\mathbb{R}^{3\times 1}\] \[\mathbf{r}\mathbf{c}=\begin{bmatrix}32\end{bmatrix}\in\mathbb{R}^{1\times 1}\equiv 32\]

    结果是标量 \(32\),等价于点积: \(\mathbf{r}\mathbf{c}=\sum_{i=1}^{m} r_i c_i\)。在实现里常写成 \(\mathbf{x}^\top\mathbf{y}\)。

仿射变换与仿射子空间

仿射(Affine)是线性(Linear)的一个自然扩展。线性变换要求 \(f(\mathbf{x})=A\mathbf{x}\),必须把原点 \(\mathbf{0}\) 映到原点;仿射变换则允许再加一个平移项:

\[f(\mathbf{x})=A\mathbf{x}+\mathbf{b}\]

这里 \(A\) 是线性部分,负责旋转、缩放、剪切、投影等形变; \(\mathbf{b}\) 是平移项(Translation / Bias),负责把整个空间整体推走一个位移。因此,仿射变换可以理解为“先做线性变换,再做平移”。

几何上,线性变换像在原点固定不动的前提下拉伸或扭转整张网格;仿射变换则像先把网格按 \(A\) 变形,再把整张网格连同原点一起平移到别的位置。两者最核心的区别是:线性变换保原点,仿射变换不一定保原点。

最简单的一维例子是 \(f(x)=2x\) 与 \(g(x)=2x+3\)。前者是线性的,因为 \(f(0)=0\);后者是仿射的,因为它先把数轴按 2 倍拉伸,再整体平移 3 个单位,所以 \(g(0)=3\),不再经过原点。二维里也是同样: \(f(\mathbf{x})=\mathbf{x}\) 是恒等线性变换,而 \(g(\mathbf{x})=\mathbf{x}+\begin{bmatrix}1\\2\end{bmatrix}\) 会把整张平面网格整体向右平移 1、向上平移 2。

仿射函数(Affine Function)在优化与机器学习里极其常见。一维情形的 \(f(x)=ax+b\) 就是最简单的仿射函数;高维里则写成 \(f(\mathbf{x})=\mathbf{w}^\top\mathbf{x}+b\)。因此,神经网络里通常口头说“线性层(Linear Layer)”,但如果带偏置 \(b\),更严格的数学名称其实是仿射层(Affine Layer):

\[Y=XW+\mathbf{1}b^\top\]

这里 \(X\) 是输入矩阵, \(W\) 是线性变换矩阵, \(b\) 是偏置向量, \(\mathbf{1}\) 是把偏置广播到每个样本上的全 1 列向量。若没有偏置,才是严格意义上的线性映射。

仿射还有一个重要性质:它保持仿射组合(Affine Combination)。若 \(\sum_i \alpha_i=1\),则

\[f\!\left(\sum_i \alpha_i \mathbf{x}_i\right)=\sum_i \alpha_i f(\mathbf{x}_i)\]

这意味着直线、平面、平行关系和凸组合结构在仿射变换下会被保留;因此很多几何对象在经过仿射变换后,仍然保持“像线还是线,像平面还是平面”的基本类型,但位置和方向可能改变。

仿射子空间(Affine Subspace)则是“线性子空间整体平移后得到的集合”。若 \(U\) 是一个线性子空间, \(\mathbf{x}_0\) 是空间中的某个固定点,则

\[\mathcal{A}=\mathbf{x}_0+U=\{\mathbf{x}_0+\mathbf{u}:\mathbf{u}\in U\}\]

就是一个仿射子空间。它和线性子空间的差别也在于是否经过原点:线性子空间必须包含原点,仿射子空间不必。例如二维中的直线 \(x+y=1\) 就是一个仿射子空间;它的方向部分与线性子空间 \(x+y=0\) 相同,但整条直线被平移开了,因此不经过原点。

这正是为什么超平面 \(\mathbf{w}^\top\mathbf{x}+b=0\) 被称为仿射子空间而不是线性子空间:当 \(b\ne 0\) 时,它通常不经过原点,只是由某个线性超平面整体平移而来。优化里的等式约束 \(h_j(x)=0\) 若要求 \(h_j\) 是仿射函数,含义也正是“约束边界仍然保持平直结构,但允许存在偏置和平移”。

更进一步,双仿射(Biaffine)也是同一族概念的延伸。它通常在两个向量之间做一个双线性项 \(h_i^\top U h_j\),再加上线性项和偏置项,因此既包含“两个变量之间的乘性交互”,也包含仿射偏置修正。理解了仿射,就能把“线性 / 仿射 / 双线性 / 双仿射”看成一条逐步加复杂度的函数族谱。

线性到双仿射的公式族谱

把输出视为一个标量时,这条族谱可以写成一组并列的标准形式:

\[f_{\mathrm{linear}}(\mathbf{x})=\mathbf{w}^\top \mathbf{x}\] \[f_{\mathrm{affine}}(\mathbf{x})=\mathbf{w}^\top \mathbf{x}+b\] \[s_{\mathrm{bilinear}}(\mathbf{x},\mathbf{z})=\mathbf{x}^\top U\mathbf{z}\] \[s_{\mathrm{biaffine}}(\mathbf{x},\mathbf{z})=\mathbf{x}^\top U\mathbf{z}+\mathbf{a}^\top\mathbf{x}+\mathbf{c}^\top\mathbf{z}+b\]

其中 \(\mathbf{x}\in\mathbb{R}^{m},\mathbf{z}\in\mathbb{R}^{n}\) 是两个输入向量, \(\mathbf{w},\mathbf{a}\in\mathbb{R}^{m}\), \(\mathbf{c}\in\mathbb{R}^{n}\), \(U\in\mathbb{R}^{m\times n}\), \(b\in\mathbb{R}\)。这里的 \(U\) 是双线性项的参数矩阵(Parameter Matrix):它不作用于单个向量本身,而是给“ \(x_p\) 与 \(z_q\) 同时出现”这类二元交互分配权重。把式子展开后可写成 \(\mathbf{x}^\top U\mathbf{z}=\sum_{p=1}^{m}\sum_{q=1}^{n}x_p\,U_{pq}\,z_q\),因此 \(U_{pq}\) 直接控制第 \(p\) 个 \(\mathbf{x}\) 特征与第 \(q\) 个 \(\mathbf{z}\) 特征之间的交互强度。 \(\mathbf{a}^\top\mathbf{x}\) 与 \(\mathbf{c}^\top\mathbf{z}\) 是单边线性项,分别描述各自独立的角色偏好; \(b\) 是全局基线偏置。

把这个定义写成一个最小的 2×3 例子,会更容易直接看出“连接强度”来自哪里。令

\[\mathbf{x}=\begin{bmatrix}x_1\\x_2\end{bmatrix},\quad \mathbf{z}=\begin{bmatrix}z_1\\z_2\\z_3\end{bmatrix},\quad U=\begin{bmatrix}u_{11} & u_{12} & u_{13}\\u_{21} & u_{22} & u_{23}\end{bmatrix}\]

则双线性项为

\[\mathbf{x}^\top U\mathbf{z}=\begin{bmatrix}x_1 & x_2\end{bmatrix}\begin{bmatrix}u_{11} & u_{12} & u_{13}\\u_{21} & u_{22} & u_{23}\end{bmatrix}\begin{bmatrix}z_1\\z_2\\z_3\end{bmatrix}\] \[=x_1u_{11}z_1+x_1u_{12}z_2+x_1u_{13}z_3+x_2u_{21}z_1+x_2u_{22}z_2+x_2u_{23}z_3\]

这一步把抽象的矩阵乘法拆成了六条显式连接: \(u_{11}\) 控制 \(x_1\) 与 \(z_1\) 的连接强度, \(u_{23}\) 控制 \(x_2\) 与 \(z_3\) 的连接强度。若某个 \(u_{pq}\) 很大且为正,只要对应的 \(x_p\) 与 \(z_q\) 同时取大值,这一对特征就会显著抬高总分;若某个 \(u_{pq}\) 为负,则说明这对特征的共同出现会压低分数。

在同一个例子里,双仿射只是在双线性项之外再加上单边项与偏置:

\[s_{\mathrm{biaffine}}(\mathbf{x},\mathbf{z})=\mathbf{x}^\top U\mathbf{z}+\mathbf{a}^\top\mathbf{x}+\mathbf{c}^\top\mathbf{z}+b\] \[=\mathbf{x}^\top U\mathbf{z}+(a_1x_1+a_2x_2)+(c_1z_1+c_2z_2+c_3z_3)+b\]

其中 \(a_1,a_2\) 描述 \(\mathbf{x}\) 一侧各特征自身的偏好, \(c_1,c_2,c_3\) 描述 \(\mathbf{z}\) 一侧各特征自身的偏好, \(b\) 给出无条件基线分数。于是,双线性回答的是“这两组特征配在一起有多合适”,双仿射回答的则是“它们配在一起有多合适,并且各自本身是否已经带有倾向”。

若输出不是一个标量分数,而是 \(K\) 个关系类别或标签分数,则通常不只使用一个 \(U\),而是为每个类别准备一张交互矩阵 \(U^{(k)}\),或等价地把它们堆成三阶张量 \(U\in\mathbb{R}^{K\times m\times n}\)。这时每个类别都拥有自己的一套“特征两两交互”权重。

从函数结构看,线性与仿射的区别在于是否含偏置;双线性与双仿射的区别同样在于是否在交互项之外再加入单边项与偏置。固定 \(\mathbf{z}\) 时, \(\mathbf{x}^\top U\mathbf{z}\) 对 \(\mathbf{x}\) 是线性的, \(s_{\text{biaffine}}(\mathbf{x},\mathbf{z})\) 对 \(\mathbf{x}\) 则是仿射的;固定 \(\mathbf{x}\) 时,对 \(\mathbf{z}\) 也是同样的性质。这正是 “biaffine” 这个名字的数学含义。

affine-biaffine-family

图中上排用一维切片显示“是否经过原点”这一关键差异: \(f(x)=ax\) 必然经过原点,而 \(f(x)=ax+b\) 由于加入偏置项,整条直线沿输出轴发生平移。下排保持与公式族谱一致,仍写成 \(\mathbf{x}^\top U\mathbf{z}\) 与 \(\mathbf{x}^\top U\mathbf{z}+\mathbf{a}^\top\mathbf{x}+\mathbf{c}^\top\mathbf{z}+b\);图像本身展示的是把高维向量关系压到二维后的一个切片。纯双线性项的零等值线体现为对称的交互边界;加入单边项与偏置后,零等值线整体偏移,分数面出现倾斜与平移,表示模型不仅关心“是否匹配”,还关心两个对象各自单独的倾向。

在依存句法(Dependency Parsing)、关系抽取(Relation Extraction)和成对匹配(Pairwise Matching)任务中,这个结构尤其有用。纯双线性项只能表达“组合后是否相容”,双仿射则进一步允许模型学习“某个对象本身就更像 head / dependent”或“某个实体本身就更像某类关系的一端”。因此,双仿射通常既比纯仿射更能表达交互,又比纯双线性更稳定。

转置(Transpose)

转置(Transpose)把行列互换:对 \(A\in\mathbb{R}^{m\times n}\),其转置 \(A^\top\in\mathbb{R}^{n\times m}\) 满足 \((A^\top)_{ij}=A_{ji}\)。

它常用于对齐乘法形状、把点积写成矩阵乘法,以及在推导中“移动”矩阵:例如 \((AB)^\top=B^\top A^\top\)。Transformer 注意力中的 \(QK^\top\) 就是典型的“先转置再相乘”。

例:行列互换与形状变化

令

\[A=\begin{bmatrix}1 & 2 & 3\\ 4 & 5 & 6\end{bmatrix}\in\mathbb{R}^{2\times 3}\]

则

\[A^\top=\begin{bmatrix}1 & 4\\ 2 & 5\\ 3 & 6\end{bmatrix}\in\mathbb{R}^{3\times 2}\]

可以直接看到:原矩阵的第 1 行变成转置后的第 1 列;因此 \((m\times n)^\top=(n\times m)\)。

Hadamard 乘积(Hadamard Product)

Hadamard 乘积(Hadamard Product)是逐元素(Element-wise)相乘:若 \(X,M\) 形状相同,则 \((X\odot M)_{ij}=X_{ij}M_{ij}\)。

典型用途是掩码(Masking)与门控(Gating)。例:令 \(M\in\{0,1\}^{B\times d}\),则 \(X\odot M\) 会把被屏蔽的特征位置直接置零;也可以用 \(M\in[0,1]^{B\times d}\) 做连续缩放。

矩阵分解(Factorization / Decomposition)

矩阵分解(Decomposition)把矩阵写成更“易处理”的结构乘积,用于求解、降维与稳定计算。常见形式包括:

  • SVD: \(A=U\Sigma V^\top\),用于 PCA(Principal Component Analysis)、低秩近似与数值稳健求解。
  • QR: \(A=QR\)(\(Q\) 正交、\(R\) 上三角),常用于最小二乘与正交化。
  • Cholesky:对对称正定(SPD)矩阵 \(A\),有 \(A=LL^\top\),常用于高斯模型与二次优化中的快速求解。
迹(Trace)

矩阵的迹(Trace)定义为对角线元素之和:对方阵 \(A\in\mathbb{R}^{n\times n}\),

\[\mathrm{tr}(A)=\sum_{i=1}^{n} A_{ii}\]

迹在推导里常用的性质是循环不变性(Cyclic Property):\(\mathrm{tr}(AB)=\mathrm{tr}(BA)\)(形状匹配时)。一个高频等式是 \(\mathrm{tr}(A^\top A)=\|A\|_F^2\),它把“平方和”写成迹,便于做矩阵微分与正则化推导。

范数(Matrix Norms)

范数(Norm)刻画矩阵的“大小”。最常用的是 Frobenius 范数:

\[\|A\|_F=\sqrt{\sum_{i,j}A_{ij}^2}\]

它等价于把矩阵按元素展平后的 \(\ell_2\) 范数,常用于权重衰减(Weight Decay)/L2 正则。另一个常见的是谱范数(Spectral Norm)\(\|A\|_2\)(最大奇异值),用于控制 Lipschitz 常数与训练稳定性(如 spectral normalization)。

外积与秩一更新(Outer Product / Rank-1 Update)

外积(Outer Product)把两个向量映射为矩阵:对 \(\mathbf{u}\in\mathbb{R}^{m}\) 与 \(\mathbf{v}\in\mathbb{R}^{n}\),

\[\mathbf{u}\mathbf{v}^\top\in\mathbb{R}^{m\times n}\]

它是一个秩一(Rank-1)矩阵。外积在统计与学习中常用于构造二阶量:例如样本协方差的无偏估计可写成中心化向量的外积平均 \(\Sigma\approx \frac{1}{N}\sum_{k=1}^{N}(\mathbf{x}_k-\bar{\mathbf{x}})(\mathbf{x}_k-\bar{\mathbf{x}})^\top\)。

例:令 \(\mathbf{u}=\begin{bmatrix}1\\ 2\\ 3\end{bmatrix}\)、\(\mathbf{v}=\begin{bmatrix}4\\ 5\end{bmatrix}\),则

\[\mathbf{u}\mathbf{v}^\top=\begin{bmatrix}4 & 5\\ 8 & 10\\ 12 & 15\end{bmatrix}\]

直观上,外积得到的矩阵每一列都是 \(\mathbf{u}\) 的缩放:第 \(j\) 列等于 \(v_j\mathbf{u}\)。因此所有列共线,矩阵的秩最多为 1(除非 \(\mathbf{u}\) 或 \(\mathbf{v}\) 为零向量)。

把外积视为线性算子更直接:对任意 \(\mathbf{x}\in\mathbb{R}^{n}\),有 \((\mathbf{u}\mathbf{v}^\top)\mathbf{x}=\mathbf{u}(\mathbf{v}^\top\mathbf{x})\)。这表示先沿 \(\mathbf{v}\) 做一次投影/打分得到标量 \(\mathbf{v}^\top\mathbf{x}\),再沿 \(\mathbf{u}\) 方向输出。例:取 \(\mathbf{x}=\begin{bmatrix}1\\ 1\end{bmatrix}\),则 \(\mathbf{v}^\top\mathbf{x}=9\),从而 \((\mathbf{u}\mathbf{v}^\top)\mathbf{x}=9\mathbf{u}=\begin{bmatrix}9\\ 18\\ 27\end{bmatrix}\)。

秩一更新(Rank-1 Update)则是把矩阵写成 \(A\leftarrow A+\mathbf{u}\mathbf{v}^\top\):只引入一个方向上的低秩结构,常用于用较低代价注入统计量/二阶近似,或在保持主结构的前提下做小幅调整。

行列式

行列式(Determinant)把一个方阵 \(A\in\mathbb{R}^{n\times n}\) 映射为标量 \(\det(A)\)。几何上,它是线性变换对体积的缩放因子(Volume Scaling Factor):绝对值表示缩放倍数,符号表示是否翻转取向(Orientation Flip)。

二维情形最直观:若

\[A=\begin{bmatrix}a & b\\ c & d\end{bmatrix}\]

则

\[\det(A)=ad-bc\]

例: \(A=\begin{bmatrix}2 & 1\\ 0 & 3\end{bmatrix}\),则 \(\det(A)=6\):面积被放大 6 倍。

关键结论:方阵可逆(Invertible)当且仅当行列式非零。当 \(\det(A)=0\) 时,变换会把体积压扁到低维(丢失信息),对应列向量线性相关(Linearly Dependent)。

常用性质:

  • \(\det(AB)=\det(A)\det(B)\)
  • \(\det(A^\top)=\det(A)\)
  • \(\det(I)=1\)

若把特征值(Eigenvalues)记作 \(\{\lambda_i\}_{i=1}^n\)(按代数重数计),则 \(\det(A)=\prod_i \lambda_i\)、\(\mathrm{tr}(A)=\sum_i \lambda_i\)。

矩阵的秩

矩阵的秩(Rank)刻画“列(或行)里最多有多少个线性无关(Linearly Independent)的方向”。对 \(A\in\mathbb{R}^{m\times n}\),秩定义为列空间(Column Space)的维数:

\[\mathrm{rank}(A)=\dim(\mathrm{col}(A))\]

它也等于行空间(Row Space)的维数(行秩=列秩)。把 \(A\) 看作线性映射 \(\mathbb{R}^n\to\mathbb{R}^m\),秩就是输出子空间的维度:最多能输出多少个自由方向。

满秩(Full Rank)通常指 \(\mathrm{rank}(A)=\min(m,n)\)。对方阵 \(n\times n\) 而言,满秩等价于可逆(也等价于 \(\det(A)\ne 0\))。

线性方程组(Linear System)\(A\mathbf{x}=\mathbf{b}\) 的解与秩直接相关:设增广矩阵为 \([A|\mathbf{b}]\),则

  • 若 \(\mathrm{rank}(A)\ne \mathrm{rank}([A|\mathbf{b}])\),无解。
  • 若 \(\mathrm{rank}(A)=\mathrm{rank}([A|\mathbf{b}])=n\)(未知数个数),唯一解。
  • 若 \(\mathrm{rank}(A)=\mathrm{rank}([A|\mathbf{b}])<n\),无穷多解(存在自由变量)。

与 SVD 的关系非常实用:秩等于非零奇异值(Singular Values)的个数,因此在数值计算里常用“奇异值是否接近 0”判断有效秩(Numerical Rank)。

二次型(Quadratic Form)

在高中里,一元二次函数常写成 \(ax^2+bx+c\)。把“二次”推广到多元,并且只保留二次项(没有一次项与常数项),就得到二次型(Quadratic Form)。二维里最常见的形式是:

\[q(x,y)=ax^2+bxy+cy^2\]

其中 \(bxy\) 是交叉项(Cross Term):它把不同变量“耦合在一起”。在解析几何(Analytic Geometry)里,交叉项常对应二次曲线(Conic Section)的主轴(Principal Axes)不与坐标轴对齐(图形呈旋转/倾斜)。

若再把一次项与常数项加回来,就得到更一般的二次多项式(Quadratic Polynomial)\(ax^2+bxy+cy^2+dx+ey+f\)。这时:交叉项 \(bxy\) 主要反映主轴旋转;一次项 \(dx+ey\) 往往表示图形的中心/顶点从原点平移出去;常数项 \(f\) 则改变整体基准值,进而影响图形的截距、大小以及是否与 \(q(x,y)=0\) 相交。只有把一次项和常数项都去掉时,我们讨论的才是纯粹的二次型。

下面两幅图都基于等值线(Level Set)生成:先固定常数 \(k\),在平面上求解 \(q(x,y)=k\) 得到等值线,再把不同 \(k\) 的结果叠加,并与 \(z=q(x,y)\) 的三维曲面对应显示。

quadratic-forms

第一幅展示无交叉项(\(b=0\))的典型形态:等值线与坐标轴对齐,曲面主轴方向也与坐标轴一致。

 

quadratic-forms-cross

第二幅展示含交叉项(\(b\ne 0\))的情形:等值线整体发生旋转/倾斜,三维曲面看起来更“不规则”。

在线性代数里,用矩阵(Matrix)把系数组织起来更方便。令 \(\mathbf{x}=(x_1,\ldots,x_n)^\top\)、\(A\in\mathbb{R}^{n\times n}\),则

\[q(\mathbf{x})=\mathbf{x}^\top A\mathbf{x}=\sum_{i=1}^{n}\sum_{j=1}^{n}A_{ij}x_i x_j\]

上面这条等式不是“记号游戏”,而是把矩阵乘法按分量(Component)展开后的结果。把它分两步看最清楚:

  1. 先做一次矩阵-向量乘法:令 \(\mathbf{y}=A\mathbf{x}\),则第 \(i\) 个分量是
\[y_i=(A\mathbf{x})_i=\sum_{j=1}^{n}A_{ij}x_j\]
  1. 再做一次点积: \(\mathbf{x}^\top\mathbf{y}=\sum_{i=1}^{n}x_i y_i\)。把第 1 步的 \(y_i\) 代入,就得到
\[\mathbf{x}^\top A\mathbf{x}=\mathbf{x}^\top(A\mathbf{x})=\sum_{i=1}^{n}x_i\left(\sum_{j=1}^{n}A_{ij}x_j\right)=\sum_{i=1}^{n}\sum_{j=1}^{n}A_{ij}x_i x_j\]

这就是“双重求和(Double Summation)”的含义:每一个矩阵元素 \(A_{ij}\) 都在给二次项 \(x_i x_j\) 分配一个权重;当 \(i=j\) 时就是平方项 \(x_i^2\),当 \(i\ne j\) 时就是交叉项 \(x_i x_j\)。

二维情形最直观:若希望展开后得到 \(ax^2+bxy+cy^2\),可以取

\[A=\begin{bmatrix}a & \frac{b}{2}\\ \frac{b}{2} & c\end{bmatrix}\]

这里把向量写成 \(\mathbf{x}=(x,y)^\top\),按矩阵乘法展开一遍:

\[A\mathbf{x}=\begin{bmatrix}a & \frac{b}{2}\\ \frac{b}{2} & c\end{bmatrix}\begin{bmatrix}x\\ y\end{bmatrix}=\begin{bmatrix}ax+\frac{b}{2}y\\ \frac{b}{2}x+cy\end{bmatrix}\] \[\mathbf{x}^\top(A\mathbf{x})=\begin{bmatrix}x & y\end{bmatrix}\begin{bmatrix}ax+\frac{b}{2}y\\ \frac{b}{2}x+cy\end{bmatrix}=ax^2+\frac{b}{2}xy+\frac{b}{2}yx+cy^2=ax^2+bxy+cy^2\]

可以看到:交叉项 \(xy\) 的系数 \(b\) 实际来自两处对称位置 \(A_{12}\) 与 \(A_{21}\) 的“合力”(各贡献一半)。这也会自然导向下一节的结论:二次型只依赖矩阵的对称部分。

例:取 \(q(x,y)=5x^2-4xy+5y^2\),对应 \(A=\begin{bmatrix}5 & -2\\ -2 & 5\end{bmatrix}\)。这一类表达式不仅在几何里出现(椭圆(Ellipse)/双曲线(Hyperbola)),在优化与统计里也高频出现(曲率(Curvature)、距离度量(Distance Metric))。

对称化(Symmetrization)

对任意方阵 \(A\),二次型只依赖其对称部分:

\[\mathbf{x}^\top A\mathbf{x}=\mathbf{x}^\top\left(\frac{A+A^\top}{2}\right)\mathbf{x}\]

这句话的意思是:无论 \(A\) 的非对称部分长什么样,只要 \(\frac{A+A^\top}{2}\) 不变,二次型 \(\mathbf{x}^\top A\mathbf{x}\) 对所有 \(\mathbf{x}\) 的取值就完全不变。

把 \(A\) 拆开看更直观。定义对称部分(Symmetric Part)与反对称部分(Skew-symmetric Part):

  • \(S=\frac{A+A^\top}{2}\),满足 \(S=S^\top\)。
  • \(K=\frac{A-A^\top}{2}\),满足 \(K^\top=-K\)。

这里“对称部分(Symmetric Part)”是一个定义:对任意方阵 \(A\),把 \(S=\frac{A+A^\top}{2}\) 定义为它的对称部分。它与 \(A\) 同型(同大小),并且一定是对称矩阵;它不是 \(A\) 的某个“子矩阵”。

按元素(Entry-wise)写得更直观:对任意 \(i,j\),

\[S_{ij}=\frac{A_{ij}+A_{ji}}{2},\quad K_{ij}=\frac{A_{ij}-A_{ji}}{2}\]

也就是说:对称部分就是把每一对对称位置 \((i,j)\) 与 \((j,i)\) 的元素取平均;反对称部分则记录它们的“差的一半”。因此 \(A=S+K\) 是把任意矩阵分解成“对称 + 反对称”的标准方式,并且这个分解是唯一的(Unique)。

为什么“取 \(A\) 与 \(A^\top\) 的平均值”就得到对称部分?因为转置(Transpose)会把非对角元素成对交换: \(A_{ij}\leftrightarrow A_{ji}\)。把它们相加后,非对称性(即 \(A_{ij}-A_{ji}\))会被抵消,只留下“对称的那一半”(即 \(A_{ij}+A_{ji}\))。再除以 2,是为了把“加了两份”的量恢复到原始尺度:如果 \(A\) 本来就对称(\(A=A^\top\)),那么 \(\frac{A+A^\top}{2}=A\),不会把矩阵放大一倍。

于是 \(A=S+K\),并且

\[\mathbf{x}^\top A\mathbf{x}=\mathbf{x}^\top S\mathbf{x}+\mathbf{x}^\top K\mathbf{x}\]

关键点在于:对任意 \(\mathbf{x}\),都有 \(\mathbf{x}^\top K\mathbf{x}=0\)。理由很短:它是一个标量,等于它自己的转置,而

\[(\mathbf{x}^\top K\mathbf{x})^\top=\mathbf{x}^\top K^\top \mathbf{x}=\mathbf{x}^\top(-K)\mathbf{x}=-(\mathbf{x}^\top K\mathbf{x})\]

一个数如果等于它的相反数,只能是 0。于是 \(\mathbf{x}^\top A\mathbf{x}=\mathbf{x}^\top S\mathbf{x}\),二次型确实只由对称部分决定。

二维展开能直接看到“只依赖对称部分”的具体含义。令 \(A=\begin{bmatrix}a & b\\ c & d\end{bmatrix}\)、\(\mathbf{x}=(x_1,x_2)^\top\),则

\[\mathbf{x}^\top A\mathbf{x}=ax_1^2+(b+c)x_1x_2+dx_2^2\]

交叉项系数只出现 \(b+c\)(也就是 \(A_{12}+A_{21}\)),而差值 \(b-c\)(反对称部分)完全不会出现。

例:两个不同矩阵,二次型完全一样

下面给一个“看得见”的数值例子。取

\[A=\begin{bmatrix}2 & 4\\ -2 & 4\end{bmatrix}\]

它显然不是对称矩阵(因为 \(A_{12}=4\ne -2=A_{21}\))。计算它的对称部分:

\[\frac{A+A^\top}{2}=\frac{1}{2}\left(\begin{bmatrix}2 & 4\\ -2 & 4\end{bmatrix}+\begin{bmatrix}2 & -2\\ 4 & 4\end{bmatrix}\right)=\begin{bmatrix}2 & 1\\ 1 & 4\end{bmatrix}=S\]

现在比较二次型。对任意 \(\mathbf{x}=(x,y)^\top\):

\[A\mathbf{x}=\begin{bmatrix}2x+4y\\ -2x+4y\end{bmatrix}\Rightarrow \mathbf{x}^\top A\mathbf{x}=x(2x+4y)+y(-2x+4y)=2x^2+2xy+4y^2\] \[S\mathbf{x}=\begin{bmatrix}2x+y\\ x+4y\end{bmatrix}\Rightarrow \mathbf{x}^\top S\mathbf{x}=x(2x+y)+y(x+4y)=2x^2+2xy+4y^2\]

两者对所有 \((x,y)\) 都完全相同;例如取 \(\mathbf{x}=(1,2)^\top\),都有 \(\mathbf{x}^\top A\mathbf{x}=\mathbf{x}^\top S\mathbf{x}=22\)。这就直观解释了“二次型只依赖对称部分”的含义:反对称的那一半怎么改,都不会改变 \(\mathbf{x}^\top A\mathbf{x}\) 的值。

因此讨论二次型时通常可假设 \(A=A^\top\)。这也解释了为什么二次型与对称矩阵/半正定性(Positive Semi-Definite, PSD)紧密绑定。

二次型的标准型(Standard Form)
标准型与对角标准型是什么

二次型 \(q(\mathbf{x})=\mathbf{x}^\top A\mathbf{x}\) 本身是一个几何对象;它在不同坐标系(Coordinate System)/基(Basis)下的矩阵表示会不同:同一个几何对象,用不同坐标轴/基表示时,系数矩阵 \(A\) 的元素会改变。

这里的标准型指的是:在一类允许的坐标变换(可逆线性变量替换(Invertible Linear Change of Variables))下,把同一个二次型写成某种约定的简化代表。不同教材的约定略有差异,但最常用的目标是:把交叉项(Cross Term)消掉,露出每个坐标轴方向上的“纯平方项”。

把 \(\mathbf{x}=T\mathbf{y}\) 理解成换基(Change of Basis)会更不容易出错: \(\mathbf{y}\) 是同一几何向量在新基下的坐标,矩阵 \(T\) 由新基向量在旧基下的坐标组成。因为 \(T\) 可逆,两套坐标是一一对应的,可以互相换回:

\[\mathbf{y}=T^{-1}\mathbf{x},\quad \mathbf{x}=T\mathbf{y}\]

把 \(\mathbf{x}=T\mathbf{y}\) 代入可得

\[q(\mathbf{x})=\mathbf{x}^\top A\mathbf{x}=\mathbf{y}^\top(T^\top A T)\mathbf{y}\]

这里要求 \(T\) 可逆(Invertible),意味着这个变量代换不会把空间压缩到低维(不会丢维度)。因此在新坐标 \(\mathbf{y}\) 下,二次型对应的系数矩阵变为 \(T^\top A T\)(这叫合同变换(Congruence Transformation))。可以把 \(T\) 理解为“旋转/缩放后的新坐标轴”在旧坐标里的表示:同一个二次型在新坐标系里的系数就由 \(T^\top A T\) 给出。标准型的目标就是选取合适的 \(T\),把 \(T^\top A T\) 化到更简单的结构。

对角标准型(Diagonal Form)指把二次型写成“只有平方项、没有交叉项”的形式(也常称对角规范形(Diagonal Canonical Form)):

\[q(\mathbf{x})=\sum_{i=1}^{n}\lambda_i y_i^2\]

其中 \(\lambda_i\) 是系数,\(\mathbf{y}\) 是新坐标。对角标准型等价于:在新坐标系下,二次型对应的矩阵是对角矩阵(Diagonal Matrix);“交叉项” \(y_i y_j\)(\(i\ne j\))消失。

结论需要明确:标准型与原来的二次型描述的是同一个二次型/同一组几何等值集合,只是坐标系不同。给定可逆变换 \(\mathbf{x}=T\mathbf{y}\),任何关于 \(\mathbf{x}\) 的几何描述都可以无损地翻译成关于 \(\mathbf{y}\) 的描述,并且可以随时“还原”回去。矩阵层面也一样:若 \(A' = T^\top A T\) 是标准型里的系数矩阵,则 \(A=(T^{-1})^\top A' T^{-1}\) 可把它变回原坐标下的表示。

接下来真正关心的是:如何选 \(T\) 才能把交叉项消掉。对二次型而言,一个关键简化是:二次型只依赖矩阵的对称部分,因此总可以先把 \(A\) 对称化为 \(\frac{A+A^\top}{2}\) 而不改变 \(\mathbf{x}^\top A\mathbf{x}\) 的值。于是“消交叉项”的核心问题就变成:对实对称矩阵,能否通过一次正交变基(Orthogonal Change of Basis)把它对角化(Diagonalize)。

怎么来的:换到特征向量基消掉交叉项

答案是肯定的;数学依据就是谱定理(Spectral Theorem,也常表述为“实对称矩阵可正交对角化(Orthogonal Diagonalization)”)。若 \(A\in\mathbb{R}^{n\times n}\) 是实对称矩阵(Real Symmetric Matrix, \(A=A^\top\)),则存在正交矩阵(Orthogonal Matrix)\(Q\) 与实对角矩阵(Real Diagonal Matrix)\(\Lambda\) 使得

\[A=Q\Lambda Q^\top,\quad \text{等价于}\quad Q^\top A Q=\Lambda\]

其中 \(Q=[\mathbf{v}_1,\ldots,\mathbf{v}_n]\) 的列向量是一组单位特征向量(Orthonormal Eigenvectors),\(\Lambda=\mathrm{diag}(\lambda_1,\ldots,\lambda_n)\) 的对角元素是对应特征值(Eigenvalues)。该定理同时包含两个常用事实:特征值都是实数;并且可以选出一组两两正交的特征向量作为基。

这就是你熟悉的特征值分解(Eigendecomposition / Eigenvalue Decomposition)的对称矩阵特例。

一般情况下,如果矩阵可对角化(Diagonalizable),可以写成 \(A=V\Lambda V^{-1}\)(或 \(V^{-1}AV=\Lambda\)),其中 \(V\) 的列是特征向量;但 \(V\) 不一定正交(Orthogonal),甚至矩阵可能不可对角化(Non-diagonalizable)。

对称矩阵的额外好处是:可以把 \(V\) 选成正交矩阵 \(Q\),因此 \(V^{-1}=Q^{-1}=Q^\top\),分解变成数值上更稳定、几何上更直观的 \(A=Q\Lambda Q^\top\)。

两个最小例子能把“\(V\) 不一定正交 / 甚至不可对角化”说得更具体:

  • 例 1:可对角化,但 \(V\) 不正交。取

    \[A_1=\begin{bmatrix}2 & 1\\ 0 & 1\end{bmatrix}\]

    它的特征值是 \(\lambda_1=2,\lambda_2=1\)(两个不同特征值意味着在二维里一定能找到两条线性无关的特征向量,因此可对角化)。对应一组特征向量可以取

    \[\mathbf{v}_1=\begin{bmatrix}1\\ 0\end{bmatrix},\quad \mathbf{v}_2=\begin{bmatrix}1\\ -1\end{bmatrix}\]

    它们并不正交,因为 \(\mathbf{v}_1^\top\mathbf{v}_2=1\ne 0\)。把它们按列组成矩阵 \(V=[\mathbf{v}_1\ \mathbf{v}_2]\),则

    \[V=\begin{bmatrix}1 & 1\\ 0 & -1\end{bmatrix},\quad \Lambda=\begin{bmatrix}2 & 0\\ 0 & 1\end{bmatrix},\quad V^{-1}=\begin{bmatrix}1 & 1\\ 0 & -1\end{bmatrix}\]

    注意:这个例子里 \(V^{-1}\) 恰好等于 \(V\)(只是代数上的巧合),但它仍然不是正交矩阵,因为正交要求 \(V^{-1}=V^\top\),而这里并不成立。

    并且确实有 \(A_1=V\Lambda V^{-1}\)。这个例子说明:一般矩阵即使可对角化,特征向量也未必能选成“互相垂直的方向”。

  • 例 2:不可对角化(特征值重复,但特征向量不够)。取

    \[A_2=\begin{bmatrix}1 & 1\\ 0 & 1\end{bmatrix}\]

    它的特征值只有 \(\lambda=1\)(在二维里重复出现)。求特征向量需要解 \((A_2-I)\mathbf{v}=\mathbf{0}\):

    \[A_2-I=\begin{bmatrix}0 & 1\\ 0 & 0\end{bmatrix}\Rightarrow (A_2-I)\begin{bmatrix}x\\ y\end{bmatrix}=\begin{bmatrix}y\\ 0\end{bmatrix}=\begin{bmatrix}0\\ 0\end{bmatrix}\Rightarrow y=0\]

    因此所有特征向量都形如 \((x,0)^\top\),只有 1 个线性无关方向。要写成 \(A_2=V\Lambda V^{-1}\),矩阵 \(V\) 必须可逆(Invertible),这要求有足够多(在二维里是 2 个)线性无关特征向量作为列;该矩阵做不到,所以它不可对角化。

把这个定理放回二次型就能立刻看出“交叉项为什么会消失”。令坐标变换 \(\mathbf{y}=Q^\top\mathbf{x}\)(把 \(\mathbf{x}\) 在特征向量基下的坐标记作 \(\mathbf{y}\)),则

\[\mathbf{x}^\top A\mathbf{x}=\mathbf{x}^\top(Q\Lambda Q^\top)\mathbf{x}=\mathbf{y}^\top\Lambda\mathbf{y}=\sum_{i=1}^{n}\lambda_i y_i^2\]

注意这里同时出现了两种“换坐标”的写法:线性变换里常写 \(Q^{-1}AQ\)(相似变换(Similarity Transformation)),二次型里写 \(Q^\top A Q\)(合同变换(Congruence Transformation))。对正交矩阵而言 \(Q^{-1}=Q^\top\),所以它们在这里完全一致:同一个正交变换既给出特征值分解,也把二次型化到没有交叉项的对角标准型。

因此:在对称矩阵的情形,“换到特征向量基”与“把二次型旋转到主轴”是同一件事,只是用不同语言描述。

直观上,特征向量(Eigenvector)给出“主轴方向”(把坐标轴转到这些方向后,交叉项会消失),特征值(Eigenvalue)则是标准型里各平方项前的系数。

详细例子:取

\[A=\begin{bmatrix}5 & -2\\ -2 & 5\end{bmatrix}\]

它是对称矩阵,因此可正交对角化。其特征值与一组单位特征向量可以取为:

\[\lambda_1=3,\ \mathbf{v}_1=\frac{1}{\sqrt{2}}\begin{bmatrix}1\\ 1\end{bmatrix};\quad \lambda_2=7,\ \mathbf{v}_2=\frac{1}{\sqrt{2}}\begin{bmatrix}1\\ -1\end{bmatrix}\]

把它们组成正交矩阵与对角矩阵:

\[Q=[\mathbf{v}_1\ \mathbf{v}_2]=\frac{1}{\sqrt{2}}\begin{bmatrix}1 & 1\\ 1 & -1\end{bmatrix},\quad \Lambda=\begin{bmatrix}3 & 0\\ 0 & 7\end{bmatrix}\]

则 \(A=Q\Lambda Q^\top\)。这里 \(\mathbf{y}\) 不是任意新变量,而是 \(\mathbf{x}\) 在特征向量基 \(\{\mathbf{v}_1,\mathbf{v}_2\}\) 下的坐标: \(\mathbf{x}=y_1\mathbf{v}_1+y_2\mathbf{v}_2=Q\mathbf{y}\)。

由于 \(Q\) 是正交矩阵(\(Q^\top Q=I\)),左乘 \(Q^\top\) 可得 \(\mathbf{y}=Q^\top\mathbf{x}\)。这一步就是换基(Change of Basis):把向量从标准坐标系表达改写为主轴坐标系表达。

因此可显式写出两组坐标关系:

\[y_1=\frac{x_1+x_2}{\sqrt{2}},\quad y_2=\frac{x_1-x_2}{\sqrt{2}}\] \[x_1=\frac{y_1+y_2}{\sqrt{2}},\quad x_2=\frac{y_1-y_2}{\sqrt{2}}\]

代入标准型:

\[\mathbf{x}^\top A\mathbf{x}=\mathbf{y}^\top\Lambda\mathbf{y}=3y_1^2+7y_2^2\]

把 \(\mathbf{y}\) 用 \(\mathbf{x}\) 展开,可直接验证“交叉项被旋转消掉”:

\[3y_1^2+7y_2^2=\frac{3}{2}(x_1+x_2)^2+\frac{7}{2}(x_1-x_2)^2=5x_1^2-4x_1x_2+5x_2^2\]

数值校验:取 \(\mathbf{x}=(1,2)^\top\),原式为 \(\mathbf{x}^\top A\mathbf{x}=17\);而 \(\mathbf{y}=Q^\top\mathbf{x}=\left(\frac{3}{\sqrt{2}},-\frac{1}{\sqrt{2}}\right)^\top\),代入 \(3y_1^2+7y_2^2\) 同样得到 17。

几何解释:正交矩阵 \(Q\) 表示旋转/换基,把坐标轴对齐到“主轴方向”(特征向量);对角矩阵 \(\Lambda\) 表示沿主轴的逐轴缩放(由特征值控制)。因此等值线在 \(\mathbf{y}\) 坐标系里与轴对齐,形状由 \(\lambda_i\) 决定。

若 \(\Lambda\) 中既有正特征值也有负特征值,则二次型是不定的(Indefinite):沿某些方向 \(q\) 增大,沿另一些方向 \(q\) 减小。二维里它的等值线(Level Set)典型呈双曲线(Hyperbola)形状,优化里对应鞍点(Saddle Point)结构。例:令 \(A=\begin{bmatrix}1 & 2\\ 2 & 1\end{bmatrix}\),其特征值为 3 与 -1,在某个正交坐标 \(\mathbf{y}\) 下有 \(\mathbf{x}^\top A\mathbf{x}=3y_1^2-y_2^2\),可取正也可取负。

进一步允许一般可逆线性变换(不要求是旋转)时,可把对角项缩放为 \(+1,-1,0\)(Sylvester 惯性定理(Law of Inertia)):二次型被分解为若干正平方项、负平方项与零方向,其中正/负/零项的个数在合同变换下保持不变(换言之,“正方向有几个、负方向有几个、平坦方向有几个”是坐标变换改不掉的性质);正/负项的个数也称为签名(Signature)。在优化里,它们分别对应局部最小、鞍点与平坦方向。

二次型与机器学习(Quadratic Form in Machine Learning)

下面这些场景看起来不同,但核心都在计算“某个方向上的能量/代价”:给一个向量 \(\mathbf{v}\),二次型 \(\mathbf{v}^\top A\mathbf{v}\) 会告诉你它在矩阵 \(A\) 定义的几何里有多大、代价有多高。

  • 平方范数(Squared \(L_2\) Norm):\(\|\mathbf{x}\|_2^2=\mathbf{x}^\top I\mathbf{x}\)。直白地说,它就是“向量长度的平方”,在训练里常作为最基础的“大小惩罚”。例如权重衰减(Weight Decay)把过大的参数拉回去,本质是在最小化 \(\|\theta\|_2^2\) 这种二次型。
  • 最小二乘与二次损失(Least Squares / MSE):线性回归目标 \(\|X\mathbf{w}-\mathbf{y}\|_2^2\) 展开后是关于 \(\mathbf{w}\) 的二次型。通俗理解:模型每偏一点,代价按“平方”增长,所以大误差会被更重惩罚。它的闭式解来自正规方程(Normal Equations)\(X^\top X\mathbf{w}=X^\top\mathbf{y}\)。
  • PCA(Principal Component Analysis):对中心化(Centering)数据,方向 \(\mathbf{u}\) 上的方差是 \(\mathbf{u}^\top\Sigma\mathbf{u}\)。这句话的直觉是:“把数据投影到某个方向后,能展开多宽”。PCA 就是在所有单位方向里找让这个二次型最大的方向(主成分),因此主成分就是“信息最密集”的方向。
  • 马氏距离(Mahalanobis Distance)与高斯负对数似然(Gaussian NLL):核心项是 \((\mathbf{x}-\boldsymbol{\mu})^\top\Sigma^{-1}(\mathbf{x}-\boldsymbol{\mu})\)。可以把它理解成“先按数据真实尺度做校正,再测距离”:方差大的方向偏离一点不算太异常,方差小的方向偏离同样大小则更异常。异常检测(Anomaly Detection)和高斯判别模型都依赖这个量。
  • 二阶近似与优化曲率(Second-order Approximation / Curvature):在参数点附近,损失变化可写成 \(\frac{1}{2}\Delta^\top H\Delta\)。它告诉你“往哪个方向走会涨得快/慢”:特征值大表示该方向很陡,特征值小表示平坦,正负混合则是鞍点(Saddle)。这也是为什么牛顿法、预条件(Preconditioning)和学习率调度都在关心 Hessian 的谱结构。

在机器学习的实现层面,二次型也常先通过可逆变量替换 \(\mathbf{x}=T\mathbf{y}\) 化到更易计算的表示: \(q(\mathbf{x})=\mathbf{x}^\top A\mathbf{x}=\mathbf{y}^\top(T^\top A T)\mathbf{y}\)。若 \(A=A^\top\),原坐标有 \(\nabla_{\mathbf{x}}q=2A\mathbf{x}\)、\(\nabla^2_{\mathbf{x}}q=2A\);在新坐标下 \(\nabla_{\mathbf{y}}q=2A'\mathbf{y}\)(\(A'=T^\top A T\))。若进一步化到对角标准型 \(A'=\Lambda\),则 \(\frac{\partial q}{\partial y_i}=2\lambda_i y_i\),逐坐标解耦,推导与实现都会更直接。

这里要区分“性质不变”和“数值不变”:在可逆变量替换下,正定/半正定/不定性质与正负零方向个数(惯性(Inertia))保持不变,因此局部最小/鞍点等优化结构不变;但一般合同变换 \(T^\top A T\) 不要求逐个保留特征值数值,只有正交相似变换 \(Q^\top A Q\) 才逐个保留特征值。

对角矩阵(Diagonal Matrix)

对角矩阵(Diagonal Matrix)是只有对角线元素可能非零的方阵。写作 \(D=\mathrm{diag}(d_1,\ldots,d_n)\),其非对角元素全为 0:

\[D=\begin{bmatrix}d_1 & 0 & \cdots & 0\\ 0 & d_2 & \cdots & 0\\ \vdots & \vdots & \ddots & \vdots\\ 0 & 0 & \cdots & d_n\end{bmatrix}\]

对角矩阵乘以向量等价于“逐维缩放”:若 \(\mathbf{x}=(x_1,\ldots,x_n)^\top\),则 \(D\mathbf{x}=(d_1x_1,\ldots,d_nx_n)^\top\)。例:令 \(D=\mathrm{diag}(2,0.5)\)、\(\mathbf{x}=(3,4)^\top\),则 \(D\mathbf{x}=(6,2)^\top\)。

在 AI 里,对角矩阵最常见的用途是把“逐元素缩放”写成线性算子:例如 \(\mathbf{x}\odot \mathbf{s}=\mathrm{diag}(\mathbf{s})\mathbf{x}\)。很多优化器的自适应学习率也可以视为对角预条件(Diagonal Preconditioner):例如 Adam/Adagrad 里的 \(1/\sqrt{v+\epsilon}\) 本质上是按参数维度缩放梯度。

单位矩阵(Identity Matrix)

单位矩阵(Identity Matrix)\(I_n\) 是对角线上全为 1、其他元素为 0 的方阵:

\[I_n=\begin{bmatrix}1 & 0 & \cdots & 0\\ 0 & 1 & \cdots & 0\\ \vdots & \vdots & \ddots & \vdots\\ 0 & 0 & \cdots & 1\end{bmatrix}\]

它是矩阵乘法的单位元:对任意形状匹配的矩阵 \(A\),有 \(AI=IA=A\);对任意向量 \(\mathbf{x}\),有 \(I\mathbf{x}=\mathbf{x}\)。例:若 \(I_2=\begin{bmatrix}1 & 0\\ 0 & 1\end{bmatrix}\),则 \(I_2(3,4)^\top=(3,4)^\top\)。

在 AI/数值计算里,\(A+\lambda I\)(\(\lambda>0\))用于改善条件数、提高可逆性与数值稳定性:例如岭回归(Ridge Regression)把 \(X^\top X\) 替换为 \(X^\top X+\lambda I\);在高斯模型与协方差估计里常见 \(\Sigma+\epsilon I\) 来保证 Cholesky 分解可用。

对称矩阵(Symmetric Matrix)

对称矩阵(Symmetric Matrix)是满足 \(A=A^\top\) 的实方阵,即 \(A_{ij}=A_{ji}\)。直观上,它的上三角与下三角互为镜像。

例: \(\begin{bmatrix}2 & 1\\ 1 & 3\end{bmatrix}\) 是对称矩阵;而 \(\begin{bmatrix}2 & 1\\ 0 & 3\end{bmatrix}\) 不是,因为非对角元素不成对相等。

对称矩阵拥有更“干净”的谱结构:所有特征值都是实数,并且可正交对角化(Spectral Theorem):\(A=Q\Lambda Q^\top\)(\(Q^\top Q=I\))。这使得很多推导都可以在旋转后的坐标系里逐维分析二次型、曲率与能量。

在 AI 里,对称矩阵高频出现于:

  • 协方差矩阵(Covariance Matrix)\(\Sigma\):例如高斯模型与特征白化(Whitening)里,要求 \(\Sigma\succeq 0\),并常用 \(\Sigma+\epsilon I\) 保证数值稳定。
  • Gram 矩阵(Gram Matrix)\(X^\top X\) 与核矩阵(Kernel Matrix)\(K\):它们天然对称/半正定,是最小二乘、岭回归与核方法的核心对象。
  • 海森矩阵(Hessian):当目标函数二阶连续可导时,Hessian 对称;其特征值决定局部曲率,从而决定“极小/极大/鞍点”的类型与优化难度。
可逆矩阵与奇异矩阵(Invertible vs Singular)

可逆矩阵(Invertible Matrix)是存在逆矩阵的方阵:对 \(A\in\mathbb{R}^{n\times n}\),若存在 \(A^{-1}\) 使得 \(AA^{-1}=A^{-1}A=I\),则 \(A\) 可逆;否则称 \(A\) 为奇异矩阵(Singular Matrix)。

等价判据(常用):\(A\) 可逆 \(\Leftrightarrow \det(A)\ne 0 \Leftrightarrow \mathrm{rank}(A)=n\)(列向量线性无关)。

例(可逆):令 \(A=\begin{bmatrix}2 & 1\\ 1 & 1\end{bmatrix}\),则 \(\det(A)=1\),并且 \(A^{-1}=\begin{bmatrix}1 & -1\\ -1 & 2\end{bmatrix}\)。

例(奇异):令 \(B=\begin{bmatrix}1 & 2\\ 2 & 4\end{bmatrix}\),第二行是第一行的 2 倍,因此秩为 1、行列式为 0,无法求逆。对应线性方程组 \(B\mathbf{x}=\mathbf{b}\) 可能无解(例如 \(\mathbf{b}=(3,5)^\top\)),也可能有无穷多解(例如 \(\mathbf{b}=(3,6)^\top\))。

在 AI 里,奇异性最常出现在最小二乘与协方差:当特征共线、维度远大于样本数(\(d\gg N\))时,\(X^\top X\) 往往奇异或病态(Ill-conditioned)。常见处理是正则化(\(X^\top X+\lambda I\))或用 SVD/QR 求解并使用伪逆(Pseudoinverse)\(A^+\)。

实现上通常避免显式求 \(A^{-1}\):更稳定的做法是直接求解 \(A\mathbf{x}=\mathbf{b}\)(Solve),或用分解(Cholesky / QR / SVD)替代。

正交矩阵(Orthogonal Matrix)

正交矩阵(Orthogonal Matrix)是满足 \(Q^\top Q=QQ^\top=I\) 的实方阵。它的列向量(或行向量)构成一组正交标准基(Orthonormal Basis),因此保持长度与点积:对任意向量 \(\mathbf{x}\) 有 \(\|Q\mathbf{x}\|_2=\|\mathbf{x}\|_2\),对任意向量 \(\mathbf{a},\mathbf{b}\) 有 \((Q\mathbf{a})^\top(Q\mathbf{b})=\mathbf{a}^\top\mathbf{b}\)。

正交矩阵的列向量不需要“沿着坐标轴方向”。要求只有一个:列向量两两正交且都是单位向量,也就是构成一组正交标准基。标准基(\(\mathbf{e}_1,\mathbf{e}_2,\ldots\))只是其中最常用的一组。

例(旋转 45°):令

\[Q=\frac{1}{\sqrt{2}}\begin{bmatrix}1 & -1\\ 1 & 1\end{bmatrix}\]

它的两列分别是 \(\frac{1}{\sqrt{2}}(1,1)^\top\) 与 \(\frac{1}{\sqrt{2}}(-1,1)^\top\),都不与坐标轴对齐,但它们正交且单位长度,因此

\[Q^\top Q=\frac{1}{2}\begin{bmatrix}1 & 1\\ -1 & 1\end{bmatrix}\begin{bmatrix}1 & -1\\ 1 & 1\end{bmatrix}=\begin{bmatrix}1 & 0\\ 0 & 1\end{bmatrix}=I\]

例(二维旋转 90°):令

\[R=\begin{bmatrix}0 & -1\\ 1 & 0\end{bmatrix},\quad R^\top=\begin{bmatrix}0 & 1\\ -1 & 0\end{bmatrix}\]

则

\[R^\top R=RR^\top=\begin{bmatrix}1 & 0\\ 0 & 1\end{bmatrix}=I\]

在 AI 里,正交矩阵常用于正交初始化(Orthogonal Initialization)、QR 分解与正交约束参数化;核心目的是把谱范数控制在 1 附近,改善深层网络与 RNN 的数值稳定性。

酉矩阵(Unitary Matrix)

酉矩阵(Unitary Matrix)是复数域上的“长度保持”线性变换。对复矩阵 \(U\in\mathbb{C}^{n\times n}\),若满足

\[U^\ast U=UU^\ast=I\]

则称 \(U\) 为酉矩阵,其中 \(U^\ast\) 是共轭转置(Conjugate Transpose)。酉矩阵的列向量构成一组正交归一基(Orthonormal Basis),因此对任意向量 \(\mathbf{x}\) 都有 \(\|U\mathbf{x}\|_2=\|\mathbf{x}\|_2\)。

实数域特例:当矩阵元素为实数时,酉矩阵退化为正交矩阵(Orthogonal Matrix),即满足 \(Q^\top Q=QQ^\top=I\)。

例(复数域):令

\[U=\begin{bmatrix}1 & 0\\ 0 & i\end{bmatrix},\quad U^\ast=\begin{bmatrix}1 & 0\\ 0 & -i\end{bmatrix}\]

则可直接计算:

\[U^\ast U=\begin{bmatrix}1 & 0\\ 0 & -i\end{bmatrix}\begin{bmatrix}1 & 0\\ 0 & i\end{bmatrix}=\begin{bmatrix}1 & 0\\ 0 & 1\end{bmatrix}=I,\quad UU^\ast=\begin{bmatrix}1 & 0\\ 0 & i\end{bmatrix}\begin{bmatrix}1 & 0\\ 0 & -i\end{bmatrix}=I\]

在 AI 里,正交/酉矩阵常用于控制数值稳定性:例如正交初始化(Orthogonal Initialization)与正交/酉参数化可把谱范数压在 1 附近,缓解深层网络与 RNN 中的梯度爆炸/消失;一些长序列建模会使用 unitary/orthogonal RNN 来更好地传播长程信息。

正定矩阵

正定矩阵(Positive Definite Matrix)把“二次型总是正”形式化。对对称矩阵(Symmetric Matrix)\(A=A^\top\),若对任意非零向量 \(\mathbf{x}\ne\mathbf{0}\) 都有

\[\mathbf{x}^\top A\mathbf{x} > 0\]

则称 \(A\) 正定,记作 \(A\succ 0\)。若是 \(\ge 0\) 则为半正定(Positive Semi-Definite, PSD),记作 \(A\succeq 0\)。

几何上,把 \(q(x,y)=\mathbf{x}^\top A\mathbf{x}\) 画成 \(z=q(x,y)\) 的三维曲面时,正定对应“向上开口的碗”(椭圆抛物面(Elliptic Paraboloid)):原点是唯一最低点,任意非零方向都往上抬升。若没有交叉项(\(bxy\) 项为 0),等值线与坐标轴对齐;若有交叉项(\(b\ne 0\)),碗的主轴会旋转,但“向上碗”的本质不变。半正定则可能出现平坦方向(Flat Direction),典型形状是槽(Trough)而非严格碗底。

matrix-pd-psd

从特征值(Eigenvalues)角度看,对称矩阵 \(A\) 的二次型类型可直接由特征值符号判别(下述以二维 \(\lambda_1,\lambda_2\) 为例):

  • \(\lambda_1>0,\lambda_2>0\):正定(Positive Definite, PD),向上开口碗。
  • \(\lambda_1<0,\lambda_2<0\):负定(Negative Definite, ND),向下开口碗。
  • 一个为 0、另一个大于 0:半正定(Positive Semi-Definite, PSD),出现平坦方向,形状更像槽。
  • 一个为 0、另一个小于 0:半负定(Negative Semi-Definite, NSD),对应“倒槽”。
  • 一正一负:不定(Indefinite),对应鞍面(Saddle Surface)。

因此图里“有交叉项”并不改变正负定类型;它主要改变主轴方向(旋转等值线),而“是不是碗/槽/鞍”由特征值符号决定。

matrix-nd-nsd

例:令

\[A=\begin{bmatrix}2 & 1\\ 1 & 2\end{bmatrix}\]

对任意 \(\mathbf{x}=(x_1,x_2)^\top\),有

\[\mathbf{x}^\top A\mathbf{x}=2x_1^2+2x_1x_2+2x_2^2=(x_1+x_2)^2+x_1^2+x_2^2>0\quad (\mathbf{x}\ne\mathbf{0})\]

因此 \(A\succ 0\)。同时它的特征值为 3 与 1(均为正),并且存在 Cholesky 分解:

\[A=LL^\top,\quad L=\begin{bmatrix}\sqrt{2} & 0\\ \frac{1}{\sqrt{2}} & \sqrt{\frac{3}{2}}\end{bmatrix}\]

等价刻画(常用):

  • \(A\succ 0\) 当且仅当所有特征值 \(\lambda_i>0\)。
  • \(A\succ 0\) 当且仅当存在 Cholesky 分解 \(A=LL^\top\)(\(L\) 下三角且对角为正)。

它在优化里非常关键:若函数的海森矩阵(Hessian)在某点正定,则该点是严格局部极小;若 Hessian 半正定,则函数局部凸(Locally Convex)。

特征值与特征向量

特征值(Eigenvalue)与特征向量(Eigenvector)描述线性变换的“固有方向”:若存在非零向量 \(\mathbf{v}\ne\mathbf{0}\) 与标量 \(\lambda\) 使得

\[A\mathbf{v}=\lambda \mathbf{v}\]

则 \(\mathbf{v}\) 是特征向量,\(\lambda\) 是对应特征值。几何上,沿特征向量方向的向量经过变换后方向不变,只被缩放(若 \(\lambda<0\) 还会翻转)。

当矩阵可对角化(Diagonalizable)时,可写为 \(A=V\Lambda V^{-1}\),其中 \(\Lambda\) 是特征值对角矩阵,列向量 \(V=[\mathbf{v}_1,\dots,\mathbf{v}_n]\) 是特征向量。

对称矩阵(Symmetric Matrix)是最重要的特例:它的特征向量可取为一组正交归一基(Orthonormal Basis),因此

\[A=Q\Lambda Q^\top,\quad Q^\top Q=I\]

这正是 PCA(Principal Component Analysis)等方法背后的谱分解(Spectral Decomposition)基础。

奇异值分解(SVD)

奇异值分解(SVD, Singular Value Decomposition)对任意矩阵 \(A\in\mathbb{R}^{m\times n}\) 都成立:

\[A=U\Sigma V^\top\]

其中 \(U\in\mathbb{R}^{m\times m}\)、\(V\in\mathbb{R}^{n\times n}\) 是正交矩阵(Orthogonal Matrix),\(\Sigma\in\mathbb{R}^{m\times n}\) 是对角(更准确说是“对角形”)矩阵,其对角线元素 \(\sigma_1\ge\sigma_2\ge\cdots\ge 0\) 为奇异值(Singular Values)。

几何解释非常直接:先用 \(V^\top\) 旋转/换基,再用 \(\Sigma\) 沿坐标轴缩放,最后用 \(U\) 再旋转。因此 SVD 是“旋转-缩放-旋转”的标准分解。

SVD 与特征值的关系要分左右两侧一起看:

  • 右奇异向量(Right Singular Vectors)是 \(A^\top A\) 的特征向量,即 \(A^\top A\mathbf{v}_i=\sigma_i^2\mathbf{v}_i\)。
  • 左奇异向量(Left Singular Vectors)是 \(AA^\top\) 的特征向量,即 \(AA^\top\mathbf{u}_i=\sigma_i^2\mathbf{u}_i\)。

其中\(\sigma_i^2\) 是 \(A^\top A\) 与 \(AA^\top\) 的特征值;\(\sigma_i\) 为奇异值(即这些非零特征值的平方根)。

矩阵形式分别是 \(A^\top A=V\Sigma^\top\Sigma V^\top\) 与 \(AA^\top=U\Sigma\Sigma^\top U^\top\),因此非零奇异值满足 \(\sigma_i=\sqrt{\lambda_i(A^\top A)}=\sqrt{\lambda_i(AA^\top)}\)。这也解释了为什么奇异值总是非负,而一般矩阵的特征值可以为负甚至为复数。

若 \(\sigma_i>0\),左右奇异向量还可互相对应: \(\mathbf{u}_i=\frac{A\mathbf{v}_i}{\sigma_i}\)、\(\mathbf{v}_i=\frac{A^\top\mathbf{u}_i}{\sigma_i}\)。

特殊地,若 \(A\) 是对称矩阵,则它可正交对角化,此时奇异值等于特征值的绝对值:\(\sigma_i=|\lambda_i(A)|\);若 \(A\succeq 0\)(半正定),则 \(\sigma_i=\lambda_i(A)\)。

为什么 SVD 可用于压缩与降维(Compression & Dimensionality Reduction)?因为很多数据/权重矩阵在有效意义下是低秩(Low-rank)的:只有前几个 \(\sigma_i\) 很大,后面的奇异值接近 0。保留前 \(k\) 项得到秩 \(k\) 近似:

\[A_k=U_{(:,1:k)}\Sigma_{(1:k,1:k)}V_{(:,1:k)}^\top\]

它在 Frobenius 范数(Frobenius Norm)与谱范数(Spectral Norm)意义下都是最优的秩 \(k\) 近似(Eckart–Young 定理):用最少的信息保留最大的能量(由奇异值平方决定)。

在 PCA 中,对中心化数据矩阵 \(X\) 做 SVD: \(X=U\Sigma V^\top\),右奇异向量 \(V\) 给出主方向(Principal Directions),奇异值刻画各方向的方差贡献(Variance Explained)。

范数(L0 / L1 / L2 / L∞)

范数(Norm)刻画“向量大小”。在 AI 中,它最常出现在三类地方:距离度量(Distance Metric)、正则化(Regularization)与鲁棒性约束(Robustness Constraint)。对 \(\mathbf{x}\in\mathbb{R}^d\),当 \(p\ge 1\) 时 \(L_p\) 范数定义为

\[\|\mathbf{x}\|_p=\left(\sum_{i=1}^{d}|x_i|^p\right)^{1/p},\quad p\ge 1\]

并且 \(\|\mathbf{x}\|_\infty=\max_i |x_i|=\lim_{p\to\infty}\|\mathbf{x}\|_p\)。

L0 “范数”(L0 “norm”)

\(\|\mathbf{x}\|_0\) 定义为非零分量的个数:

\[\|\mathbf{x}\|_0=\#\{i\mid x_i\ne 0\}\]

严格来说它不是范数:例如对任意非零标量 \(\alpha\ne 0\),有 \(\|\alpha\mathbf{x}\|_0=\|\mathbf{x}\|_0\),不满足齐次性(Homogeneity)\(\|\alpha\mathbf{x}\|=|\alpha|\|\mathbf{x}\|\)。

例:若 \(\mathbf{x}=(3,0,-1,0)\),则 \(\|\mathbf{x}\|_0=2\)。

在 AI 里,\(\|\cdot\|_0\) 用来表达稀疏性(Sparsity):特征选择(Feature Selection)、压缩感知(Compressed Sensing)与网络剪枝(Pruning)常以“非零个数最少”为目标。但直接优化 \(\|\cdot\|_0\) 一般是组合优化,常用 \(\|\cdot\|_1\) 或其他可优化的替代目标近似。

L1 范数(L1 Norm)
\[\|\mathbf{x}\|_1=\sum_{i=1}^{d}|x_i|\]

例:若 \(\mathbf{x}=(3,4)\),则 \(\|\mathbf{x}\|_1=7\)。几何上,二维 \(L_1\) 等值线是菱形;与 \(L_2\) 的圆相比,它更容易在坐标轴上产生“尖角”,对应优化时更容易把部分坐标推到 0。

在 AI 里,\(L_1\) 正则化是稀疏学习(Sparse Learning)的标准工具:在凸模型中会得到稀疏解(例如 Lasso);在深度模型中也常用于诱导稀疏权重/稀疏特征、做轻量化。

L2 范数(L2 Norm)
\[\|\mathbf{x}\|_2=\sqrt{\sum_{i=1}^{d}x_i^2}\]

例:若 \(\mathbf{x}=(3,4)\),则 \(\|\mathbf{x}\|_2=5\),对应欧氏距离(Euclidean Distance)。在连续优化中,\(\|\theta\|_2^2\) 具有良好的光滑性(Smoothness),使得许多推导与数值计算更稳定。

在 AI 里,\(L_2\) 正则化(权重衰减(Weight Decay))会惩罚大权重、改善泛化并缓解病态问题;在二次目标里它也对应“加 \(\lambda I\)”的稳定化(例如岭回归)。

L∞ 范数(L-infinity Norm)
\[\|\mathbf{x}\|_\infty=\max_{i}|x_i|\]

例:若 \(\mathbf{x}=(3,0,-1,0)\),则 \(\|\mathbf{x}\|_\infty=3\)。它度量的是“最大坐标幅度”。

在 AI 里,\(L_\infty\) 最常与鲁棒性相关:对抗样本(Adversarial Examples)中的 \(L_\infty\) 约束表示“每个像素的改动幅度不超过 \(\epsilon\)”;一些鲁棒优化与最坏情况界也会用 \(\|\cdot\|_\infty\) 表达最大误差。

距离与正则化

由范数诱导的距离(Norm-induced Distance)写作 \(d(\mathbf{x},\mathbf{y})=\|\mathbf{x}-\mathbf{y}\|\)。常见对应关系:

  • \(L_2\):欧氏距离(Euclidean Distance),\(d_2(\mathbf{x},\mathbf{y})=\|\mathbf{x}-\mathbf{y}\|_2=\sqrt{\sum_{i=1}^{d}(x_i-y_i)^2}\)。
  • \(L_1\):曼哈顿距离(Manhattan Distance),\(d_1(\mathbf{x},\mathbf{y})=\|\mathbf{x}-\mathbf{y}\|_1=\sum_{i=1}^{d}|x_i-y_i|\)。
  • \(L_\infty\):切比雪夫距离(Chebyshev Distance),\(d_\infty(\mathbf{x},\mathbf{y})=\|\mathbf{x}-\mathbf{y}\|_\infty=\max_{i}|x_i-y_i|\)。它度量的是“最坏维度”的偏差:例如 \(d_\infty(\mathbf{x},\mathbf{y})\le \epsilon \Leftrightarrow \forall i,\ |x_i-y_i|\le \epsilon\),即每一维的误差都被同一个上界约束。直觉上,如果一次操作允许同时修改所有坐标、且每步每个坐标最多改 1,那么从 \(\mathbf{x}\) 变到 \(\mathbf{y}\) 的最少步数就是 \(\max_i|x_i-y_i|\)(更一般地,每步上限为 \(\epsilon\) 时步数为 \(d_\infty(\mathbf{x},\mathbf{y})/\epsilon\) 的向上取整)。

关于 \(L_0\):常见写法是 \(d_0(\mathbf{x},\mathbf{y})=\|\mathbf{x}-\mathbf{y}\|_0=\#\{i\mid x_i\ne y_i\}\),它统计两向量在多少个坐标上不相等。本质上这是逐坐标“相等/不相等”的计数度量;当取值来自离散集合时,它对应哈明距离(Hamming Distance)。但 \(\|\cdot\|_0\) 严格来说不是范数,因此 \(d_0\) 不属于“由范数诱导”的距离家族。

在学习目标中,正则化通常写成:

\[\min_{\theta}\ \frac{1}{m}\sum_{i=1}^{m}\ell\!\left(f_{\theta}(x^{(i)}),y^{(i)}\right)+\lambda\Omega(\theta)\]

式中各成分含义如下:

  • \(\theta\):模型参数(Parameters),优化的对象。
  • \(m\):训练样本数(Number of Samples)。
  • \((x^{(i)},y^{(i)})\):第 \(i\) 个样本与标签。
  • \(f_{\theta}(x^{(i)})\):模型对第 \(i\) 个样本的预测。
  • \(\ell(\cdot,\cdot)\):单样本损失函数(Per-sample Loss),衡量预测与标签偏差。
  • \(\frac{1}{m}\sum_{i=1}^{m}\ell(\cdot)\):经验风险(Empirical Risk),即平均训练误差。
  • \(\Omega(\theta)\):正则项(Regularizer),约束参数复杂度。
  • \(\lambda\):正则化系数(Regularization Strength),平衡“拟合训练数据”与“控制模型复杂度”。

常见的 \(\Omega(\theta)\) 包括 \(\|\theta\|_1\)、\(\|\theta\|_2^2\)、\(\|\theta\|_0\)(稀疏性目标)与 \(\|\theta\|_\infty\)(最大幅度约束)。同一个思想也可写成“约束形式”(Constraint Form):\(\min_\theta \frac{1}{m}\sum_i \ell(\cdot)\ \text{s.t.}\ \Omega(\theta)\le c\)。惩罚系数 \(\lambda\) 与约束半径 \(c\) 在凸优化(Convex Optimization)里可通过对偶(Duality)联系起来。

微积分
极限与连续
极限的定义

极限(Limit)回答的问题是:当输入“逼近”某个值时,函数输出“逼近”什么值。它关心的是趋势而不是是否刚好取到该点。

\[\lim_{x\to a}f(x)=L\]

严格定义(\(\varepsilon-\delta\) 定义)可写为:

\[\forall \varepsilon \gt 0,\ \exists \delta \gt 0,\ \text{s.t.}\ 0 \lt |x-a| \lt \delta \Rightarrow |f(x)-L| \lt \varepsilon\]

工程上可把它理解为:把输入控制得足够近,输出误差就能被压到任意小。

在 AI 里,极限直觉用于理解“收敛(Convergence)”:例如训练步长变小后,参数更新是否趋于稳定;以及损失函数在某点附近是否可被低阶展开近似。

连续性

连续(Continuity)可理解为“函数图像没有跳断”。在点 \(a\) 处连续的三个条件是:

  1. \(f(a)\) 有定义;
  2. \(\lim_{x\to a}f(x)\) 存在;
  3. \(\lim_{x\to a}f(x)=f(a)\)。

连续是可导(Differentiable)的前提之一(但连续不必然可导)。例如 \(|x|\) 在 \(x=0\) 连续但不可导。

在优化里,连续性保证“小步更新不会导致目标突变”,这也是学习率(Learning Rate)可调与训练可控的基础假设之一。

无穷小与无穷大

无穷小(Infinitesimal)描述“趋近于 0 的量”,无穷大(Infinity)描述“无界增长”。在推导里常通过渐近记号(Asymptotic Notation)表达量级关系:

这里的 \(o\) 与 \(O\) 不是变量,而是两种记号:小 \(o\)(little-o)表示“严格更小一个量级”,大 \(O\)(big-O)表示“至多同量级的上界”。

  • \(f(x)=o(g(x))\):当 \(x\to a\) 时 \(f/g\to 0\)(高阶小量,增长/衰减速度严格慢于 \(g\))。
  • \(f(x)=O(g(x))\):存在常数 \(C\) 使 \(|f(x)|\le C|g(x)|\)(同阶或更小的上界)。

例如一阶 Taylor 展开里的 \(o(\Delta x)\) 表示“比 \(\Delta x\) 更小得多”的误差项。算法分析中的时间复杂度 \(O(Nd)\)、\(O(N^2)\) 也属于同一套量级语言。

常见求导法则与公式
法则 公式 条件
常数倍法则 \((Cu)' = C u'\) \(C\) 为常数
和差法则 \((u \pm v)' = u' \pm v'\) \(u,v\) 可导
乘法法则 \((uv)' = u'v + uv'\) \(u,v\) 可导
除法法则 \(\left(\frac{u}{v}\right)'=\frac{u'v-uv'}{v^2}\) \(u,v\) 可导,且 \(v \ne 0\)
链式法则 \(\frac{d}{dx}f(g(x)) = f'(g(x))g'(x)\) \(f,g\) 可导
常见函数导数
函数 \(f(x)\) 导数 \(f'(x)\) 备注/条件
\(c\) \(0\) \(c\) 为常数
\(x^n\) \(n x^{n-1}\) \(n\) 为常数;非整数 \(n\) 时需注意实数域定义域
\(\sqrt{x}\) \(\frac{1}{2\sqrt{x}}\) \(x>0\)
\(e^x\) \(e^x\) 自然指数(Natural Exponential)
\(a^x\) \(a^x\ln a\) \(a>0,a\ne 1\)
\(\ln x\) \(\frac{1}{x}\) \(x>0\)
\(\log_a x\) \(\frac{1}{x\ln a}\) \(x>0,\ a>0,\ a\ne 1\)
\(\sin x\) \(\cos x\)  
\(\cos x\) \(-\sin x\)  
\(\tan x\) \(\sec^2 x\) \(\cos x\ne 0\)
\(|x|\) \(\mathrm{sign}(x)\) \(x>0\) 时导数为 \(1\)

\(x<0\) 时导数为 \(-1\)

在 \(x=0\) 不可导(优化中常用次梯度 \(g\in[-1,1]\))

导数(Derivative)

导数是点 \(x_0\) 处的瞬时变化率(Instantaneous Rate of Change):

\[f'(x_0)=\lim_{\Delta x\to 0}\frac{f(x_0+\Delta x)-f(x_0)}{\Delta x}\]

\(x_0\) 不是“很小的数”,而是定义域中的固定位置;趋近于 0 的小量是 \(\Delta x\)(或记作 \(dx\))。

一阶展开把导数解释为“线性项的系数”:当 \(\Delta x\to 0\) 时,

\[f(x_0+\Delta x)=f(x_0)+f'(x_0)\Delta x+o(\Delta x)\]

可按“等于三项相加”理解:左边 \(f(x_0+\Delta x)\) 是扰动后的真实函数值;右边第一项 \(f(x_0)\) 是基点函数值,第二项 \(f'(x_0)\Delta x\) 是一阶线性近似,第三项 \(o(\Delta x)\) 是比 \(\Delta x\) 更小的高阶余项(High-order Remainder)。

中值定理(Mean Value Theorems)

中值定理(Mean Value Theorems)是一组把“区间上的平均变化”与“某一点的瞬时变化率”连接起来的核心定理。它们在形式上不同,但共同结构是:在闭区间连续、在开区间可导,进而保证存在某个中间点 \(c\in(a,b)\) 使得斜率关系成立。

罗尔中值定理

设 \(f\) 在 \([a,b]\) 上连续、在 \((a,b)\) 上可导,且 \(f(a)=f(b)\)。则存在 \(c\in(a,b)\) 使

\[f'(c)=0\]

几何直觉:若曲线两端高度相同,那么中间至少有一点的切线是水平的。

拉格朗日中值定理

设 \(f\) 在 \([a,b]\) 上连续、在 \((a,b)\) 上可导。则存在 \(c\in(a,b)\) 使

\[f'(c)=\frac{f(b)-f(a)}{b-a}\]

几何直觉:区间割线斜率(平均变化率)等于某个点的切线斜率(瞬时变化率)。

柯西中值定理

设 \(f,g\) 在 \([a,b]\) 上连续、在 \((a,b)\) 上可导。则存在 \(c\in(a,b)\) 使

\[(f(b)-f(a))g'(c)=(g(b)-g(a))f'(c)\]

当分母不为 0 时,可写成比值形式:

\[\frac{f'(c)}{g'(c)}=\frac{f(b)-f(a)}{g(b)-g(a)}\]

它把“单函数斜率比较”推广为“两个函数变化率的比较”,是洛必达法则(L'Hospital's Rule)证明链中的关键步骤。

三类中值定理的区别
定理 涉及函数 额外条件 结论形式 关系
罗尔中值定理 1 个函数 \(f\) \(f(a)=f(b)\) \(f'(c)=0\) 拉格朗日定理的特殊情形
拉格朗日中值定理 1 个函数 \(f\) 无额外端点相等条件 \(f'(c)=\frac{f(b)-f(a)}{b-a}\) 柯西定理取 \(g(x)=x\) 的特例
柯西中值定理 2 个函数 \(f,g\) 两个函数都满足连续+可导 \((f(b)-f(a))g'(c)=(g(b)-g(a))f'(c)\) 三者中最一般形式

mean-value-theorems

中值定理和AI

在 AI 系统中,中值定理主要作为理论工具出现:工程代码很少直接“调用定理”,但大量优化、稳定性与误差分析都在使用它的核心变形,即把“两个点的函数值差”转写为“某个中间点的导数(梯度)信息”。

  • 优化收敛分析(Optimization Convergence):训练中常关心一步更新后损失变化 \(L(\theta+\Delta)-L(\theta)\)。中值定理把它连接到中间点的梯度,进而用于学习率条件与下降性证明。
  • Lipschitz 界与鲁棒性(Lipschitz Bound & Robustness):中值定理给出“输入小扰动导致输出变化”的上界形式。若梯度有界,则输出变化可控;这正是对抗鲁棒性分析和梯度惩罚(Gradient Penalty)类方法的数学基础之一。
  • 有限差分与梯度估计(Finite Difference / Gradient Estimation):割线斜率与切线斜率之间的关系来自拉格朗日中值定理,是数值优化里差分近似、线搜索(Line Search)和误差估计的核心依据。

从“纯数学”到“AI 实践”的桥梁可以一句话概括:中值定理把宏观变化量(函数值差)变成可优化的微观信息(导数/梯度)。

偏导数(Partial Derivative)

对多元函数 \(f:\mathbb{R}^n\to\mathbb{R}\),偏导数把“只沿某一坐标轴方向的导数”形式化:固定其余变量,只让第 \(i\) 个变量变化。先写成最直接的极限定义:

\[\frac{\partial f}{\partial x_i}(x_0)=\lim_{h\to 0}\frac{f(x_{0,1},\dots,x_{0,i-1},x_{0,i}+h,x_{0,i+1},\dots,x_{0,n})-f(x_0)}{h}\]

这里的 \(h\) 是“第 \(i\) 个变量的微小增量”(Increment):只加在第 \(i\) 个坐标上,其他坐标保持不变。

在线性代数记号下,上式等价写成(更紧凑):令 \(e_i\) 为第 \(i\) 个标准基向量(Standard Basis Vector),则

\[\frac{\partial f}{\partial x_i}(x_0)=\lim_{h\to 0}\frac{f(x_0+h e_i)-f(x_0)}{h}\]

更常用的导数视角(计算视角)是:把其余变量暂时当常数,把目标变量当自变量,直接套一元求导法则。也就是说,极限定义负责“定义正确性”,日常计算通常用求导规则完成。

例如 \(f(x,y)=x^2y\):对 \(x\) 求偏导时把 \(y\) 视作常数,得 \(\frac{\partial f}{\partial x}=2xy\);对 \(y\) 求偏导时把 \(x\) 视作常数,得 \(\frac{\partial f}{\partial y}=x^2\)。

切换为极限视角,令 \(f(x,y)=x^2y\),在点 \((1,2)\)。

\[\frac{\partial f}{\partial x}(1,2)=\lim_{h\to 0}\frac{f(1+h,2)-f(1,2)}{h}\] \[=\lim_{h\to 0}\frac{2(1+h)^2-2}{h}\] \[=\lim_{h\to 0}(4+2h)=4\] \[\frac{\partial f}{\partial y}(1,2)=\lim_{h\to 0}\frac{f(1,2+h)-f(1,2)}{h}\] \[=\lim_{h\to 0}\frac{(2+h)-2}{h}=1\]

可以看到:求 \(\partial f/\partial x\) 时把 \(y\) 当常数;求 \(\partial f/\partial y\) 时把 \(x\) 当常数。这正是“其余变量固定”的具体计算含义。

梯度(Gradient)就是把所有偏导数按坐标收集成向量: \(\nabla f(x)=(\partial f/\partial x_1,\dots,\partial f/\partial x_n)^\top\)。

微分(Differential)

在一元情形中,微分是“把函数增量线性化”的记号:给定一个小增量 \(dx\),定义

\[df\big|_{x_0}=f'(x_0)\,dx\]

此时真实增量满足 \(\Delta f = df + o(dx)\)。给定 \(dx\) 后, \(df\) 才对应一个确定数值。

例:若 \(f(x)=x^2\),在 \(x_0=3\) 且 \(dx=0.1\) 时, \(df=2x_0dx=0.6\),而 \(\Delta f=f(3.1)-f(3)=0.61\)。微分给出一阶近似,误差来自高阶项。

全微分(Total Differential)

对多元函数 \(f(x_1,\dots,x_n)\),全微分把“多方向小扰动下的一阶线性响应”写成:

\[df=\sum_{i=1}^n \frac{\partial f}{\partial x_i}dx_i\]

令 \(d\mathbf{x}=(dx_1,\dots,dx_n)^\top\),则向量形式是:

\[df=(\nabla f(x))^\top d\mathbf{x}\]

若进一步把扰动分解为“方向 + 步长”: \(d\mathbf{x}=\mathbf{u}\,ds\)(\(\|\mathbf{u}\|_2=1\)),则

\[\frac{df}{ds}=\nabla f(x)\cdot \mathbf{u}\]

右侧就是方向导数(Directional Derivative):全微分给出任意小位移的一阶近似,方向导数则把位移约束在单位方向并除去步长。

例:令 \(f(x,y)=x^2y\),则 \(\frac{\partial f}{\partial x}=2xy\)、\(\frac{\partial f}{\partial y}=x^2\)。在点 \((x_0,y_0)=(1,2)\),若 \(dx=0.1\)、\(dy=-0.05\),则 \(df=2xy\,dx+x^2dy=2\cdot1\cdot2\cdot0.1+1\cdot(-0.05)=0.35\),给出 \(\Delta f\) 的一阶近似。

向量微积分

Nabla 算子(Nabla Operator)记作 \(\nabla\),本质上是把偏导算子按坐标排列成的“向量形式”:

\[\nabla=\left(\frac{\partial}{\partial x_1},\dots,\frac{\partial}{\partial x_n}\right)^\top\]

它本身不是一个数,而是一个算子(Operator)。作用在标量场上得到梯度(Gradient);与向量场点乘得到散度(Divergence);与向量场叉乘得到旋度(Curl);对标量场再取散度得到拉普拉斯(Laplacian)。

符号 \(\|\cdot\|\)(双竖线)表示范数(Norm)。因此 \(\|\nabla f(x)\|\) 是梯度向量的长度;而 \(\|\nabla\|\) 作为“算子范数”在工程推导中很少直接使用,通常需要明确它作用的函数空间与范数定义。

nabla

梯度

梯度(Gradient)把标量函数 \(f:\mathbb{R}^n\to\mathbb{R}\) 的局部变化率组织成向量:

\[\nabla f(x)=\left(\frac{\partial f}{\partial x_1},\dots,\frac{\partial f}{\partial x_n}\right)^\top\]

它指向函数增长最快的方向(Steepest Ascent Direction),模长刻画该方向上的最大斜率。在优化里,梯度下降(Gradient Descent)沿 \(-\nabla f\) 走,是因为这是一阶近似下最快下降方向。

例: \(f(x,y)=x^2+2y^2\),则 \(\nabla f=(2x,4y)\),在点 \((1,1)\) 处梯度为 \((2,4)\),表示沿 y 方向的增长更陡。

方向导数(Directional Derivative)把“沿某个方向的变化率”写成点积:若 \(\mathbf{u}\) 是单位方向向量,则

\[D_{\mathbf{u}}f(x)=\nabla f(x)\cdot \mathbf{u}\]

符号先约定: \(x\) 是当前点, \(\mathbf{u}\) 是单位方向(\(\|\mathbf{u}\|_2=1\)), \(\varepsilon\) 是沿该方向的步长(可正可负的小实数)。方向导数定义为

\[D_{\mathbf{u}}f(x)=\lim_{\varepsilon\to 0}\frac{f(x+\varepsilon\mathbf{u})-f(x)}{\varepsilon}\]

对 \(f(x+\varepsilon\mathbf{u})\) 做一阶 Taylor 展开:

\[f(x+\varepsilon\mathbf{u})=f(x)+\varepsilon\,\nabla f(x)\cdot\mathbf{u}+o(\varepsilon)\]

代回定义式:

\[\frac{f(x+\varepsilon\mathbf{u})-f(x)}{\varepsilon}\] \[=\nabla f(x)\cdot\mathbf{u}+\frac{o(\varepsilon)}{\varepsilon}\]

令 \(\varepsilon\to 0\),由于 \(o(\varepsilon)/\varepsilon\to 0\),得到 \(D_{\mathbf{u}}f(x)=\nabla f(x)\cdot\mathbf{u}\)。

散度

场(Field)是“把空间中每个点映射到一个量”的函数。标量场(Scalar Field)\(f(x)\) 在每个点输出一个标量;向量场(Vector Field)\(\mathbf{F}(x)\) 在每个点输出一个向量。梯度作用在标量场上,散度/旋度作用在向量场上。

散度(Divergence)作用在向量场 \(\mathbf{F}=(F_1,\dots,F_n)^\top:\mathbb{R}^n\to\mathbb{R}^n\) 上。这里先把两个术语说清楚:

\[J_{\mathbf{F}}(x)=\left[\frac{\partial F_i}{\partial x_j}\right]_{i,j=1}^n\]

上式是雅可比矩阵(Jacobian):第 \(i\) 行第 \(j\) 列表示 \(F_i\) 对 \(x_j\) 的偏导。迹(Trace)是矩阵对角线元素之和,因此

\[\mathrm{tr}(J_{\mathbf{F}})=\sum_{i=1}^n \frac{\partial F_i}{\partial x_i}\]

而散度按定义正是这条和式,所以“散度 = Jacobian 的迹”:

\[\nabla\cdot \mathbf{F}(x)=\mathrm{tr}(J_{\mathbf{F}}(x))=\sum_{i=1}^n \frac{\partial F_i}{\partial x_i}\]

几何/物理直觉:把 \(\mathbf{F}\) 想成“流体速度场(Velocity Field)”,散度衡量一个点附近是否像“源(Source)/汇(Sink)”——单位体积的净流出率。散度为正表示净流出,为负表示净流入。

例:二维场 \(\mathbf{F}(x,y)=(x,y)\) 的 Jacobian 是 \(\begin{bmatrix}1&0\\0&1\end{bmatrix}\),其迹为 \(1+1=2\),所以散度也等于 2,在任意点都表现为均匀“发散”。

旋度

旋度(Curl)衡量向量场的局部旋转(Local Rotation)。在三维中:

\[\nabla\times \mathbf{F}=\left(\frac{\partial F_3}{\partial y}-\frac{\partial F_2}{\partial z},\ \frac{\partial F_1}{\partial z}-\frac{\partial F_3}{\partial x},\ \frac{\partial F_2}{\partial x}-\frac{\partial F_1}{\partial y}\right)\]

直觉上,可把它理解为“放一个很小的桨轮(Paddle Wheel)在该点附近,桨轮是否会被带着转”。保守场(Conservative Field)满足 \(\nabla\times\mathbf{F}=\mathbf{0}\),这与“路径无关”/“存在势函数”是等价刻画。

例:二维旋转场 \(\mathbf{F}(x,y)=(-y,x,0)\) 的旋度为 \((0,0,2)\),表示绕 z 轴的均匀旋转趋势。

拉普拉斯算子(Laplacian)作用在标量场上,定义为梯度的散度:

\[\nabla^2 f=\nabla\cdot(\nabla f)=\sum_{i=1}^n \frac{\partial^2 f}{\partial x_i^2}\]

它常出现在扩散(Diffusion)与平滑(Smoothing)问题中,也常被用作“曲率/粗糙度”的度量。例: \(f(x,y)=x^2+y^2\) 则 \(\nabla^2 f=2+2=4\)。

Jacobian 矩阵

当函数的输出不再是一个标量,而是一个向量时,梯度这个概念就不够用了。此时需要把“每个输出分量对每个输入变量的一阶变化率”统一收集起来,这个对象就是 Jacobian 矩阵(Jacobian Matrix)。它是一阶导数在向量值函数上的自然推广,也是 Hessian 的直接前置概念。

设向量值函数

\[\mathbf{F}:\mathbb{R}^n\to\mathbb{R}^m,\qquad \mathbf{F}(\mathbf{x})=\begin{bmatrix}F_1(\mathbf{x})\\ \vdots\\ F_m(\mathbf{x})\end{bmatrix}\]

其中输入 \(\mathbf{x}=(x_1,\dots,x_n)^\top\),输出 \(\mathbf{F}(\mathbf{x})\) 有 \(m\) 个分量。Jacobian 矩阵定义为:

\[J_{\mathbf{F}}(\mathbf{x})=\left[\frac{\partial F_i}{\partial x_j}(\mathbf{x})\right]_{i=1,\dots,m;\,j=1,\dots,n}\]

按矩阵展开,就是一个 \(m\times n\) 矩阵:

\[J_{\mathbf{F}}(\mathbf{x})=
\begin{bmatrix}
\frac{\partial F_1}{\partial x_1} & \frac{\partial F_1}{\partial x_2} & \cdots & \frac{\partial F_1}{\partial x_n}\\
\frac{\partial F_2}{\partial x_1} & \frac{\partial F_2}{\partial x_2} & \cdots & \frac{\partial F_2}{\partial x_n}\\
\vdots & \vdots & \ddots & \vdots\\
\frac{\partial F_m}{\partial x_1} & \frac{\partial F_m}{\partial x_2} & \cdots & \frac{\partial F_m}{\partial x_n}
\end{bmatrix}\]

这里第 \(i\) 行第 \(j\) 列的元素 \(\frac{\partial F_i}{\partial x_j}\) 表示:第 \(j\) 个输入变量发生微小变化时,第 \(i\) 个输出分量会怎样一阶变化。按矩阵读法,行对应输出分量,列对应输入变量,因此 Jacobian 本质上是一张局部灵敏度表(Local Sensitivity Table)。

它描述的不是全局非线性结构,而是函数在某个点附近的局部线性映射:输入空间里的一个小扰动向量 \(d\mathbf{x}\) 经过 Jacobian 作用后,变成输出空间中的一阶近似扰动 \(d\mathbf{F}\)。因此,Jacobian 可以理解为“该点附近最能代表原函数的一阶线性算子”。

它与全微分的关系最直接。若在点 \(\mathbf{x}\) 附近加入一个小扰动 \(d\mathbf{x}\),则输出的一阶变化满足:

\[d\mathbf{F}\approx J_{\mathbf{F}}(\mathbf{x})\,d\mathbf{x}\]

这条式子就是向量值函数的一阶线性化。也就是说,Jacobian 在局部扮演的角色,类似于一元函数里的导数:它给出“最好的线性近似”。若输出是一维,即 \(m=1\),Jacobian 就退化成一个 \(1\times n\) 的行向量;它与梯度本质上包含同一组偏导数,只是排布约定可能不同。

一个二维到二维的例子最容易看清。设

\[\mathbf{F}(x,y)=\begin{bmatrix}x^2y\\ x+y^2\end{bmatrix}\]

则第一行来自分量函数 \(F_1(x,y)=x^2y\),第二行来自 \(F_2(x,y)=x+y^2\)。逐项求偏导可得:

\[J_{\mathbf{F}}(x,y)=
\begin{bmatrix}
2xy & x^2\\
1 & 2y
\end{bmatrix}\]

例如在点 \((1,2)\),Jacobian 为

\[J_{\mathbf{F}}(1,2)=
\begin{bmatrix}
4 & 1\\
1 & 4
\end{bmatrix}\]

这表示:在该点附近,若输入发生微小变化 \((dx,dy)^\top\),则输出变化近似为

\[d\mathbf{F}\approx
\begin{bmatrix}
4 & 1\\
1 & 4
\end{bmatrix}
\begin{bmatrix}
dx\\
dy
\end{bmatrix}\]

第一行说明输出第一分量大致按 \(4dx+dy\) 变化,第二行说明输出第二分量大致按 \(dx+4dy\) 变化。Jacobian 因而可以被理解为局部灵敏度矩阵(Sensitivity Matrix)。

对标量函数 \(f:\mathbb{R}^n\to\mathbb{R}\),梯度 \(\nabla f:\mathbb{R}^n\to\mathbb{R}^n\) 本身就是一个向量值函数,因此 Hessian 可以直接看成梯度映射的 Jacobian:

\[\nabla^2 f(\mathbf{x})=J_{\nabla f}(\mathbf{x})\]

这就是把 Jacobian 放在 Hessian 前面的原因:先理解“向量值函数的一阶导数如何组织成矩阵”,再看“标量函数的梯度再求一次导”,Hessian 的结构就不会显得突兀。

在机器学习中,Jacobian 最常出现在三类地方。第一,反向传播(Backpropagation)本质上是在链式法则(Chain Rule)下逐层组合这些局部 Jacobian:前一层输出的微小变化如何传到后一层,正是由对应层的 Jacobian 决定。第二,向量场分析中的散度(Divergence)等于 Jacobian 的迹(Trace)。第三,生成模型、正则化和鲁棒性分析常关心 Jacobian 的谱范数(Spectral Norm)或 Frobenius 范数,以度量局部放大效应。若输出维度和输入维度都很大,显式构造完整 Jacobian 也会很贵,因此工程上常直接计算 Jacobian-Vector Product 或 Vector-Jacobian Product,而不是把整块矩阵完全展开。

在神经网络语境里,Jacobian 到底“针对激活值还是针对权重”,取决于谁被当作自变量。若研究层与层之间的信号传播,常写成 \(\frac{\partial h^{(l+1)}}{\partial h^{(l)}}\),这时它针对的是激活值(Activation)或层表示;若研究模型输出对输入的敏感度,可写成 \(\frac{\partial y}{\partial x}\);若研究输出对参数的敏感度,也可以写成 \(\frac{\partial y}{\partial \theta}\)。因此,Jacobian 的本质是“一个向量怎样对另一个向量发生一阶变化”,并不预先限定变量一定是激活值还是权重。

Hessian 矩阵

梯度(Gradient)回答的是“函数沿各坐标方向的一阶变化率”;Hessian 矩阵(Hessian Matrix)进一步回答的是“这些一阶变化率本身又在怎样变化”。若把梯度 \(\nabla f\) 看成向量值函数,那么 Hessian 正是这个梯度映射的 Jacobian。因此,Hessian 是多元函数的二阶导数对象,用来描述局部曲率(Curvature)、凹凸性以及临界点附近的二阶形状。

设标量函数 \(f:\mathbb{R}^n\to\mathbb{R}\),输入向量为 \(\mathbf{x}=(x_1,\dots,x_n)^\top\)。Hessian 矩阵记作 \(\nabla^2 f(\mathbf{x})\) 或 \(H_f(\mathbf{x})\),定义为:

\[\nabla^2 f(\mathbf{x})=\left[\frac{\partial^2 f}{\partial x_i\partial x_j}(\mathbf{x})\right]_{i,j=1}^{n}\]

把它按矩阵完全展开,就是:

\[\nabla^2 f(\mathbf{x})=\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_1\partial x_n}\\
\frac{\partial^2 f}{\partial x_2\partial x_1} & \frac{\partial^2 f}{\partial x_2^2} & \cdots & \frac{\partial^2 f}{\partial x_2\partial x_n}\\
\vdots & \vdots & \ddots & \vdots\\
\frac{\partial^2 f}{\partial x_n\partial x_1} & \frac{\partial^2 f}{\partial x_n\partial x_2} & \cdots & \frac{\partial^2 f}{\partial x_n^2}
\end{bmatrix}\]

把梯度记为 \(\nabla f(\mathbf{x})=(g_1,\dots,g_n)^\top\),其中 \(g_i=\frac{\partial f}{\partial x_i}\),则 Hessian 的第 \((i,j)\) 个元素可以直接写成 \(H_{ij}=\frac{\partial g_i}{\partial x_j}\)。这个记号把它的意义说得很清楚:它衡量“第 \(i\) 个方向上的斜率”会不会随着第 \(j\) 个变量的变化而改变。

对角线元素 \(\frac{\partial^2 f}{\partial x_i^2}\) 描述沿单一坐标方向的纯二阶曲率,也就是该方向本身的弯曲强弱;非对角元素 \(\frac{\partial^2 f}{\partial x_i\partial x_j}\) 描述不同方向之间的局部耦合(Local Coupling)。当 \(H_{ij}=0\) 时,意味着在当前点附近,变量 \(x_j\) 的微小变化不会改变第 \(i\) 个方向上的一阶斜率;当 \(H_{ij}\neq 0\) 时,两个方向在局部二阶结构上发生耦合。

这种耦合会直接反映在等高线(Contour)形状上:若非对角项接近零,局部二次近似更接近与坐标轴对齐的“正椭圆碗”;若非对角项明显非零,等高线会发生倾斜,说明改变一个变量会连带改变另一个方向上的坡度。

若 \(f\) 足够光滑,满足二阶混合偏导连续,则由 Clairaut / Schwarz 定理可得

\[\frac{\partial^2 f}{\partial x_i\partial x_j}=\frac{\partial^2 f}{\partial x_j\partial x_i}\]

因此 Hessian 矩阵是对称矩阵(Symmetric Matrix)。这点非常重要,因为一旦 Hessian 对称,就可以用特征值(Eigenvalue)来判断局部曲率:正特征值对应向上弯,负特征值对应向下弯,正负并存则意味着不同方向上的弯曲趋势相反。

Hessian 的几何意义可以通过二阶 Taylor 展开看得最清楚。对点 \(\mathbf{x}\) 附近的微小扰动 \(\Delta \mathbf{x}\),有:

\[f(\mathbf{x}+\Delta\mathbf{x})\approx f(\mathbf{x})+\nabla f(\mathbf{x})^\top \Delta\mathbf{x}+\frac{1}{2}\Delta\mathbf{x}^\top \nabla^2 f(\mathbf{x})\Delta\mathbf{x}\]

这里第一项 \(f(\mathbf{x})\) 是当前函数值,第二项 \(\nabla f(\mathbf{x})^\top \Delta\mathbf{x}\) 是一阶线性变化,第三项 \(\frac{1}{2}\Delta\mathbf{x}^\top \nabla^2 f(\mathbf{x})\Delta\mathbf{x}\) 就是二阶曲率修正项。也就是说,梯度告诉你“朝哪边走函数会立刻增减”,Hessian 则告诉你“地形本身是碗状、山丘状,还是马鞍状”。

hessian-locality

二维情形最直观。设

\[f(x_1,x_2)=x_1^2+3x_1x_2+2x_2^2\]

先求梯度:

\[\nabla f(x_1,x_2)=\begin{bmatrix}2x_1+3x_2\\3x_1+4x_2\end{bmatrix}\]

再求二阶偏导,可得:

\[\frac{\partial^2 f}{\partial x_1^2}=2,\qquad \frac{\partial^2 f}{\partial x_1\partial x_2}=3,\qquad \frac{\partial^2 f}{\partial x_2^2}=4\]

因此 Hessian 为:

\[\nabla^2 f(x_1,x_2)=\begin{bmatrix}2 & 3\\3 & 4\end{bmatrix}\]

这个例子还有一个关键特征:Hessian 与 \((x_1,x_2)\) 无关,因此它说明该函数在整个空间里都是同一种二次曲面(Quadratic Surface)。对二次函数而言,Hessian 足以完整决定其曲率结构。

在极值判别里,Hessian 主要出现在临界点(Critical Point)附近。若某点 \(\mathbf{x}^*\) 满足 \(\nabla f(\mathbf{x}^*)=\mathbf{0}\),则:

  • 若 \(\nabla^2 f(\mathbf{x}^*)\) 正定(Positive Definite),即对任意非零向量 \(\mathbf{v}\) 都有 \(\mathbf{v}^\top \nabla^2 f(\mathbf{x}^*)\mathbf{v}>0\),则该点是局部极小值(Local Minimum)。
  • 若 \(\nabla^2 f(\mathbf{x}^*)\) 负定(Negative Definite),即对任意非零向量 \(\mathbf{v}\) 都有 \(\mathbf{v}^\top \nabla^2 f(\mathbf{x}^*)\mathbf{v}<0\),则该点是局部极大值(Local Maximum)。
  • 若 Hessian 不定(Indefinite),即存在方向使二次型为正,也存在方向使其为负,则该点是鞍点(Saddle Point)。
  • 若 Hessian 只有半正定、半负定,或出现零特征值,则二阶信息不足以单独判定,还需要更高阶分析或结合函数结构进一步判断。

这套判据和一维情形完全一致:一维里 \(f''(x^*)>0\) 表示“碗底”, \(f''(x^*)<0\) 表示“山顶”;Hessian 只是把这个二阶导概念推广到了多维空间。

在优化中,Hessian 的意义更直接。牛顿法(Newton's Method)用它近似局部曲面,并据此选择更合理的更新方向:

\[\mathbf{x}_{t+1}=\mathbf{x}_t-\big(\nabla^2 f(\mathbf{x}_t)\big)^{-1}\nabla f(\mathbf{x}_t)\]

与只看一阶斜率的梯度下降不同,牛顿法还利用了局部曲率信息:若某个方向很陡但也弯得很厉害,步长就应更谨慎;若某个方向很平缓,更新可以相对更大。这也是为什么 Hessian 会出现在牛顿法、拟牛顿法(BFGS / L-BFGS)以及很多二阶优化分析中。

在机器学习里,Hessian 还常用来讨论损失面的尖锐度(Sharpness)、参数可辨识性以及训练稳定性。但深度学习模型维度极高,完整 Hessian 的存储与求逆代价非常大:若参数维度为 \(d\),Hessian 大小就是 \(d\times d\)。因此工程上更常用 Hessian 向量积(Hessian-Vector Product)、对角近似、低秩近似,或拟牛顿方法来间接利用二阶信息,而不是显式构造整块矩阵。

在神经网络里,单独说 Hessian 时,默认通常指损失函数对参数向量 \(\theta\) 的 Hessian,即 \(\nabla_\theta^2 L(\theta)\)。原因很直接:优化真正要更新的是权重,因此人们最关心的是“损失面对参数空间的局部曲率”。当然,Hessian 也可以对输入或中间激活值来求,例如 \(\nabla_x^2 f(x)\) 或 \(\nabla_h^2 f(h)\),它们分别描述输入空间或表示空间中的局部弯曲;只是从工程语境看,这类用法通常不是默认含义。

积分
不定积分

不定积分(Indefinite Integral)也叫反导数、原函数。是“由变化率反推原函数(Antiderivative)”:已知 \(f\),寻找所有满足 \(F'(x)=f(x)\) 的函数 \(F\)。

一句话强调:不定积分就是“已知导函数(导数),求原函数”的过程。

\[\int f(x)\,dx=F(x)+C\]
从变化率反推状态

把导数看作“瞬时变化率”最容易理解积分的方向。若 \(s(t)\) 是位置、\(v(t)\) 是速度,则 \(s'(t)=v(t)\)。当只知道 \(v(t)\) 时,要恢复 \(s(t)\) 就是在做积分。

\[s'(t)=v(t)\ \Longrightarrow\ s(t)=\int v(t)\,dt\]
为什么必须有 +C

因为微分会“抹掉常数项”。不同函数只要相差一个常数,导数就完全一样:

\[\frac{d}{dx}(x^2)=\frac{d}{dx}(x^2+5)=\frac{d}{dx}(x^2-100)=2x\]

所以当你从 \(f(x)=2x\) 反推原函数时,只能确定主体是 \(x^2\),无法确定常数偏移。这就是积分常数(Constant of Integration)\(C\) 的来源。若再给一个初值条件(Initial Condition),例如 \(F(x_0)=y_0\),\(C\) 才会被唯一确定。

几何图像:不是一条曲线,而是一族

\(\int f(x)\,dx\) 的结果对应一族函数 \(\{F(x)+C\mid C\in\mathbb{R}\}\)。它们形状完全相同,只是沿 \(y\) 轴上下平移;在同一个 \(x\) 处,这族曲线的切线斜率都等于 \(f(x)\)。

一个最小可算例
\[\int 2x\,dx=x^2+C\]

验算: \(\frac{d}{dx}(x^2+C)=2x\)。这一步强调的是“求导与积分互为逆过程”,但逆过程会保留一个常数不确定性。

indefinite-integral

微积分基本定理(Fundamental Theorem of Calculus)

不定积分与定积分的连接点是微积分基本定理(Fundamental Theorem of Calculus)。它包含两条互补结论:

  1. 若 \(F'(x)=f(x)\),则 \(\int_a^b f(x)\,dx=F(b)-F(a)\)。这告诉我们:定积分可以通过任意一个原函数在端点处相减来计算。
  2. 定义 \(G(x)=\int_a^x f(t)\,dt\),则 \(G'(x)=f(x)\)。这告诉我们:把函数从 \(a\) 到 \(x\) 累积起来,得到的累积函数本身就是一个原函数。

一句话强调:定积分就是原函数(不定积分)在区间两端的函数值“收尾相减”,即 \(\int_a^b f(x)\,dx=F(b)-F(a)\)。

例: \(f(x)=2x\),取原函数 \(F(x)=x^2\),则

\[\int_1^3 2x\,dx=F(3)-F(1)=9-1=8\]
定积分

定积分(Definite Integral)可看成“带符号面积(Signed Area)”或“连续求和”。Riemann 和定义为:

\[\int_a^b f(x)\,dx=\lim_{n\to\infty}\sum_{k=1}^{n}f(\xi_k)\Delta x_k\]

若上下界中出现 \(\infty\) 或 \(-\infty\),它仍然属于定积分范畴,只是更准确地叫广义积分(Improper Integral)或广义定积分:本质上仍是在一个区间上求累积量,只是需要先把无穷区间截断,再用极限恢复。例如

\[\int_a^{\infty} f(x)\,dx:=\lim_{R\to\infty}\int_a^R f(x)\,dx\]

因此“上下界无穷”不是不定积分,而是定积分的特殊形式。

在 AI 里,连续概率密度函数(Probability Density Function, PDF)的概率计算 \(P(a\le X\le b)=\int_a^b p(x)\,dx\) 本质上就是定积分。

常用积分公式
被积函数 积分结果 备注
\(x^n\) \(\frac{x^{n+1}}{n+1}+C\) \(n\ne -1\)
\(\frac{1}{x}\) \(\ln|x|+C\) \(x\ne 0\)
\(e^x\) \(e^x+C\) 指数函数
\(\sin x\) \(-\cos x+C\) 三角函数
\(\cos x\) \(\sin x+C\) 三角函数
\(\frac{1}{1+x^2}\) \(\arctan x+C\) 反三角函数
多重积分

多重积分(Multiple Integrals)最容易卡住人的地方,不是计算,而是符号一上来就把几何直觉遮住了。理解它的关键是把“积分”继续看成连续求和,只不过求和对象不再只是线段上的小长度,而是区域上的小面积、空间中的小体积,或者曲面上的小面片。

multiple-integral

从一维面积到三维体积

一重积分 \(\int f(x)\,dx\) 常被理解为曲线下的面积:在 \(x\) 轴上切出很多极窄的小条,每条小条的面积近似是“高度 \(\times\) 宽度”,也就是 \(f(x)\,dx\),再把它们全部加起来。

双重积分把这个想法从“一条线”推广到“一块区域”。设 \(D\) 是平面上的一块区域,曲面高度由 \(z=f(x,y)\) 给出,那么

\[\iint_D f(x,y)\,dx\,dy\]

就可以理解为:在区域 \(D\) 的每个小块 \(dx\,dy\) 上立起一根很细的小柱子,柱高是 \(f(x,y)\)。这些小柱子拼起来,形成曲面下方的一整块立体体积。于是双重积分最直观的几何意义就是:把区域上方由高度函数堆出来的整块三维体积连续累加起来。

再往上推广,三重积分

\[\iiint_\Omega f(x,y,z)\,dV\]

表示在空间区域 \(\Omega\) 内,对每个微小体积元 \(dV\) 的函数值做累加。此时它不一定是在“求一个更高维体积”,更准确地说,是在整个空间体内部对某个量做总汇总,例如总质量、总能量、总代价或总概率权重。可以把它和一重积分放在同一条理解链上来看:速度函数在时间上的累积给出位移,密度函数在空间上的累积给出质量,能量密度(Energy Density)在区域或体积上的累积给出总能量。若 \(\rho(x,y)\) 是面密度,则 \(\iint_D \rho(x,y)\,dA\) 表示区域 \(D\) 上的总质量;若 \(\rho(x,y,z)\) 是体密度,则 \(\iiint_\Omega \rho(x,y,z)\,dV\) 表示空间区域 \(\Omega\) 内的总质量。积分符号的重数,本质上对应的是累积区域的维度。

高度函数到底表示什么

双重积分里最需要读懂的是 \(f(x,y)\)。它并不总是“真实高度”,而是一个随位置变化的量。你可以把它看成“每个点上放了多少东西”。积分的过程,就是把整块区域上的这些局部贡献全部收集起来。

  • 当 \(f(x,y)=1\) 时,每个位置的高度都恒为 1,所以积分值在数值上就等于区域 \(D\) 的面积。此时双重积分退化为“面积公式”。
  • 当 \(f(x,y)\) 是密度函数(Density Function)时,积分得到的是总质量、总电荷或总概率。也就是说,函数值越大,说明该位置“堆得越多”,对总量贡献越大。
  • 当 \(f(x,y)\) 表示代价、风险、热量、响应强度等场量时,积分得到的是这类量在整个区域上的累积结果。

因此,多重积分不是在机械地操纵符号,而是在做一件很具体的事:把无穷多个微小局部量累加成一个整体量。

带圈的积分号是什么意思

有时会看到带圈的双积分号 ∯。这个圈表示积分域是闭合的(Closed):不是一块敞开的平面区域,而是一个完整包起来的曲面,例如球壳表面、气泡表面或任意封闭外壳。为了把这个“带圈”符号直接看出来,下面就直接写成在闭合曲面 \(S\) 上的积分。

∯S \(\mathbf{F}\cdot d\mathbf{S}\)

这里的含义通常不是“求面积”,而是计算向量场(Vector Field)穿过闭合曲面的总通量(Flux)。直观地说,就是看有多少“流”从这个封闭外壳内部穿出,或者从外部流入。它和高斯散度定理(Gauss's Divergence Theorem)直接相关,因此在偏微分方程(PDE)、连续介质建模、计算流体以及物理信息神经网络(Physics-Informed Neural Networks, PINNs)中十分重要。

多重积分和AI

在 AI 中,多重积分最常见的身份是概率分布上的总量计算器。如果 \(p(x,y)\) 是二维随机变量的概率密度,那么

\[\iint p(x,y)\,dx\,dy=1\]

表示整张概率曲面下方的总体积必须等于 1。这句话的本质是:所有可能情况加起来,概率总和必须是 100%。

进一步,期望(Expectation)就是在这个概率地形上做加权平均。以一维为例,

\[\mathbb{E}[X]=\int x\,p(x)\,dx\]

表示每个位置 \(x\) 都按其概率权重 \(p(x)\) 参与平均;多维情形下则自然推广为多重积分。用几何语言说,期望就是这堆“概率质量”在各坐标方向上的重心位置。

这也是为什么高斯分布归一化、边缘分布(Marginal Distribution)、条件分布、变分推断(Variational Inference)、连续潜变量模型以及能量模型(Energy-Based Models)都离不开多重积分。很多时候模型真正要做的事,并不是求一个公式值,而是在高维概率空间里累计、归一化、消去变量或计算期望。

卷积(Convolution)

卷积(Convolution)把两个函数/序列组合成第三个函数/序列,最常见的语义是:“一个信号在另一个信号的权重/响应下做累积叠加”。它同时是信号处理(Signal Processing)、系统理论(Systems Theory)与 CNN 的基础运算。

连续卷积(Continuous Convolution)

对连续函数 \(f(t)\) 与 \(g(t)\),卷积定义为:

\[(f*g)(t)=\int_{-\infty}^{+\infty} f(\tau)\,g(t-\tau)\,d\tau\]

经典记忆法:翻转(Flip)→ 平移(Shift)→ 相乘(Multiply)→ 积分(Integrate)。其中 \(g(t-\tau)\) 这一项等价于把 \(g\) 先时间反转再按 \(t\) 平移。

离散卷积(Discrete Convolution)

对离散序列 \(x[n]\) 与 \(h[n]\),卷积定义为:

\[(x*h)[n]=\sum_{k=-\infty}^{+\infty} x[k]\,h[n-k]\]

当序列有限长度时,上式求和区间会自然收缩为有限项。二维卷积(2D Convolution)/图像滤波可以视为把求和从一维扩展到二维索引。

因果性与单侧卷积(Causality)

工程系统常满足因果性(Causality):系统在时刻 \(t\) 的输出只依赖过去与当前输入,不依赖未来输入。若输入 \(f(t)\) 与系统的冲激响应(Impulse Response)\(g(t)\) 都是因果的(\(t<0\) 时为 0),则卷积积分可写成单侧形式:

\[(f*g)(t)=\int_{0}^{t} f(\tau)\,g(t-\tau)\,d\tau\]

这个形式更符合直觉:时刻 \(t\) 的结果由 \([0,t]\) 区间内“所有过去输入”的贡献叠加而来。

直觉例子:打点滴的累积药效

把卷积理解成“累积药效”通常更直观。设 \(r(t)\) 是单位时间的滴注速率(Infusion Rate),\(h(t)\) 是“单位剂量在体内的药效/浓度随时间衰减曲线”(可以把它理解为冲激响应)。在时刻 \(t\) 的总药效/浓度 \(c(t)\) 可以写成:

\[c(t)=(r*h)(t)=\int_{0}^{t} r(\tau)\,h(t-\tau)\,d\tau\]

解释:在过去每个时刻 \(\tau\) 滴入的一小部分药量 \(r(\tau)\,d\tau\),到现在时刻 \(t\) 已经“经过了” \(t-\tau\) 的代谢时间,因此它的残留贡献按 \(h(t-\tau)\) 衰减;把所有过去贡献叠加,就得到当前总效果。这正是卷积“用一个响应核去累积历史”的核心语义。

convolution

卷积与互相关(Cross-Correlation)

互相关(Cross-Correlation)与卷积的形式非常接近,但没有“核翻转”(Kernel Flip):一维离散互相关常写成 \(\sum_k x[k]\,w[n+k]\)(不同资料索引略有差异)。深度学习框架里多数“卷积层”实现的是互相关,而不是严格数学卷积;由于卷积核参数是可学习的,翻不翻转并不会改变可表达的函数族,但在信号处理里二者语义不同,需注意约定。

链式法则

链式法则(Chain Rule)是反向传播(Backpropagation)的核心:当计算图(Computation Graph)由一系列函数复合组成时,总导数等于沿路径的局部导数相乘。

在微分语言下更紧凑:若 \(y=g(x)\)、\(z=f(y)\),则 \(dz=f'(y)\,dy\) 且 \(dy=g'(x)\,dx\),合并得 \(dz=f'(g(x))g'(x)\,dx\)。反向传播做的就是把这些局部“系数”从输出一路乘回输入。

rule-of-chains

最小二乘法

最小二乘法(Least Squares)解决“拟合误差最小”的问题。给定样本矩阵 \(X\) 与目标 \(\mathbf{y}\),线性模型 \(\hat{\mathbf{y}}=X\mathbf{w}\) 的目标是:

\[\min_{\mathbf{w}}\ \|X\mathbf{w}-\mathbf{y}\|_2^2\]

当 \(X^\top X\) 可逆时,闭式解满足正规方程(Normal Equations):

\[X^\top X\mathbf{w}=X^\top\mathbf{y},\quad \mathbf{w}^*=(X^\top X)^{-1}X^\top\mathbf{y}\]

几何直觉: \(X\mathbf{w}\) 只能落在 \(X\) 的列空间(Column Space)中,最小二乘解就是把 \(\mathbf{y}\) 正交投影(Orthogonal Projection)到这个空间上,剩余误差向量与列空间正交。

在 AI/统计实践中,若 \(X^\top X\) 病态或奇异,常用岭回归(Ridge Regression):

\[\min_{\mathbf{w}}\ \|X\mathbf{w}-\mathbf{y}\|_2^2+\lambda\|\mathbf{w}\|_2^2,\quad (X^\top X+\lambda I)\mathbf{w}=X^\top\mathbf{y}\]

它本质上是把二次目标做稳定化,降低方差并提升泛化。

凸函数与凸优化

凸函数(Convex Function)是“碗状”的函数:任意两点连线上的函数值不超过端点函数值的线性插值。形式化定义:

\[f(\lambda x_1+(1-\lambda)x_2)\le \lambda f(x_1)+(1-\lambda)f(x_2),\quad \lambda\in[0,1]\]

凸优化(Convex Optimization)之所以重要,是因为凸目标在凸可行域上没有“坏局部最小值”:任一局部最小值都是全局最小值。

若 \(f\) 二阶可导,则 Hessian 提供了最直接的局部判据:在一维中 \(f''(x)\ge 0\) 对应凸;在多维中,若对所有 \(x\) 都有 \(\nabla^2 f(x)\succeq 0\)(半正定,Positive Semidefinite),则 \(f\) 是凸函数。若处处 \(\nabla^2 f(x)\succ 0\)(正定,Positive Definite),则函数通常具有更强的严格凸性(Strict Convexity)。

损失函数的形状可以非常多样。需要区分两层含义:

  • 损失形式本身:例如 BCE/CE(对概率或对线性模型的 logits)是凸的,MSE 也是凸的。
  • 对参数的整体目标:当把损失与深度网络的非线性参数化组合后,目标函数通常变成非凸(Non-convex),这不是“交叉熵不凸”,而是“网络映射让问题不凸”。

loss-fn-convex

拉格朗日乘数法

拉格朗日乘数法(Lagrange Multiplier Method)处理约束优化(Constrained Optimization):在满足约束的前提下最小化/最大化目标函数。常用写法是把约束写成函数形式:等式约束(Equality Constraints)\(g_i(x)=0\),不等式约束(Inequality Constraints)\(g_i(x)\le 0\)。

对等式约束,构造拉格朗日函数(Lagrangian):

\[\mathcal{L}(x,\lambda)=f(x)+\sum_{i=1}^{m}\lambda_i g_i(x)\]

其中 \(f(x)\) 是目标函数(Objective),\(g_i(x)\) 是约束函数(Constraint Function),\(\lambda_i\) 是拉格朗日乘子(Lagrange Multiplier)。新增部分 \(\sum_i \lambda_i g_i(x)\) 称为拉格朗日项(Lagrange Term),单个约束对应的项是 \(\lambda_i g_i(x)\)。

在不同应用里乘子的记号可能不同:在优化理论里常写 \(\lambda_i\),在支持向量机(SVM)里常写 \(\alpha_i\)(每个样本约束对应一个乘子)。

把 \(\mathcal{L}(x,\lambda)\) 看作关于原变量 \(x\) 与乘子 \(\lambda\) 的二元函数后,鞍点(Saddle Point)结构是约束被编码进目标函数后的直接结果。 \(x\) 的角色是压低总代价, \(\lambda\) 的角色是放大任何尚未满足的约束,因此两者天然形成极小极大(Min-Max)结构。

先看等式约束 \(g(x)=0\)。这里必须先把“为什么内层是最大化”说清楚:这不是记号习惯,而是为了把约束编码成一个可行点保留原目标、不可行点直接罚到 \(+\infty\) 的机制。因此,固定某个 \(x\) 后,内层写成 \(\max_\lambda \, (f(x)+\lambda g(x))\)。如果 \(g(x)\neq 0\),由于 \(\lambda\) 不受符号限制,最大化者总能把 \(\lambda\) 取到与 \(g(x)\) 同号且绝对值任意大,使 \(\mathcal{L}(x,\lambda)\to\infty\);只有当 \(g(x)=0\) 时,拉格朗日项才消失,内层最大值才退化为 \(f(x)\)。因此 \(\max_\lambda \mathcal{L}(x,\lambda)\) 的作用,是把所有不满足等式约束的点直接排除掉。

不等式约束更容易看出这种“过滤”机制。若约束是 \(g(x)\le 0\) 且乘子满足 \(\lambda\ge 0\),那么当 \(g(x)>0\) 时,最大化者会把 \(\lambda\) 推大,使 \(\lambda g(x)\to\infty\);当 \(g(x)\le 0\) 时,继续增大 \(\lambda\) 只会让值变小,因此最优选择是 \(\lambda=0\)。于是 \(\max_{\lambda\ge 0}\mathcal{L}(x,\lambda)\) 对可行点返回原始代价 \(f(x)\),对不可行点返回“无限罚款”。外层再对 \(x\) 做最小化,就等价于只在可行域内最小化 \(f(x)\)。

\[\min_x\ \max_\lambda\ \mathcal{L}(x,\lambda)\]

几何上,这正对应马鞍形曲面:沿 \(x\) 方向切开, \(\mathcal{L}\) 像一个向上开的“碗”,因为这里在做最小化;沿 \(\lambda\) 方向切开, \(\mathcal{L}\) 像一个向下开的“拱”,因为这里在做最大化。鞍点 \((x^*,\lambda^*)\) 的含义是:固定 \(\lambda=\lambda^*\) 时, \(x^*\) 已经不能再把值压低;固定 \(x=x^*\) 时, \(\lambda^*\) 也已经不能再把值抬高。原问题的最优解与约束的恰当作用强度,就在这个交点同时确定。

记号约定:上标星号(Asterisk)\(^*\) 通常表示“最优/最优点处的取值”,例如 \(x^*\) 是最优解, \(\lambda^*\) 是与之对应的最优乘子。

在鞍点 \((x^*,\lambda^*)\),固定 \(\lambda=\lambda^*\) 时 \(x^*\) 使 \(\mathcal{L}\) 最小;固定 \(x=x^*\) 时 \(\lambda^*\) 使 \(\mathcal{L}\) 最大,可用不等式写成:

\[\mathcal{L}(x^*,\lambda)\le \mathcal{L}(x^*,\lambda^*)\le \mathcal{L}(x,\lambda^*)\]

上面的鞍点不等式给出的是几何刻画;真正求解时,还需要把“这个点已经不能再降、也不能再升”的直观条件改写成可计算的方程。做法是检查拉格朗日函数(Lagrangian)\(\mathcal{L}\) 对各个变量的一阶变化:若在候选点附近,沿某个允许方向还能继续把值压低(对 \(x\))或继续把值抬高(对 \(\lambda\)),那么该点就不可能是鞍点。

这就是一阶必要条件(First-Order Necessary Condition)的来源:若 \(x^*\) 是最优解,则一阶(线性)变化项必须已经消失,否则还存在继续改进的方向。这里“必要”不等于“充分”:满足一阶条件只说明它有可能是最优点,不说明它一定最优;要得到充分结论,还需要二阶条件、凸性(Convexity)或其他结构。

无约束情形最直接。在一维中,若 \(x^*\) 是可微且不在边界上的局部最小点,则向左或向右移动都不能让函数更小,因此斜率必须满足 \(f'(x^*)=0\);多维里把“斜率”推广为梯度(Gradient),于是条件变为 \(\nabla f(x^*)=0\)。

把同样的思路移到等式约束上,求解目标就从“找原函数 \(f\) 的极小点”变成“找拉格朗日函数 \(\mathcal{L}(x,\lambda)\) 的鞍点”。对可导问题,一阶条件写成:

\[\nabla_x \mathcal{L}(x^*,\lambda^*)=0,\quad g_i(x^*)=0\]

第一式表示:固定 \(\lambda=\lambda^*\) 后,已经找不到能继续降低 \(\mathcal{L}\) 的 \(x\) 方向;第二式就是可行性(Feasibility)本身。又因为 \(\frac{\partial \mathcal{L}}{\partial \lambda_i}=g_i(x)\),所以“对乘子求偏导为 0”本质上只是把约束 \(g_i(x)=0\) 原样写回。

不等式约束时,乘子必须满足 \(\lambda_i\ge 0\),因此鞍点结构相应写成:

\[\min_x\ \max_{\lambda\ge 0}\ \mathcal{L}(x,\lambda)\]

此时除了驻点条件,还必须同时满足 KKT 条件(Karush–Kuhn–Tucker Conditions)。其中最关键的是互补松弛(Complementary Slackness)\(\lambda_i g_i(x^*)=0\):每个约束在最优点只有两种状态——要么它是紧的(Active),即 \(g_i(x^*)=0\);要么它不紧,此时对应乘子必须为 0,表示该约束在最优点处没有实际作用。

例(等式约束):最小化 \(f(x,y)=x^2+y^2\),约束 \(x+y=1\)。拉格朗日函数:

\[\mathcal{L}(x,y,\lambda)=x^2+y^2+\lambda(x+y-1)\]

plot-lagrange

其中 \(\lambda(x+y-1)\) 是拉格朗日项(Lagrange Term):它把等式约束 \(x+y-1=0\) 以乘子加权的形式并入目标函数。

令偏导为零: \(\frac{\partial \mathcal{L}}{\partial x}=2x+\lambda=0\)、\(\frac{\partial \mathcal{L}}{\partial y}=2y+\lambda=0\)、\(\frac{\partial \mathcal{L}}{\partial \lambda}=x+y-1=0\)。注意 \(\frac{\partial \mathcal{L}}{\partial \lambda}=0\) 就是把约束 \(x+y=1\) 写回来;联立可得 \(x=y=\frac{1}{2}\)。几何上,这意味着最优点处目标函数等高线与约束曲线相切。

例(不等式约束):最小化 \(f(x)=x^2\),约束 \(x\ge 1\)。直觉上,无约束最小值在 \(x=0\),但它不满足约束,所以最优点只能落在边界 \(x=1\)。

  1. 把约束改写成标准形式:令 \(g(x)=1-x\),则 \(x\ge 1\Leftrightarrow g(x)\le 0\)。
  2. 构造拉格朗日函数: \(\mathcal{L}(x,\lambda)=f(x)+\lambda g(x)=x^2+\lambda(1-x)\)。其中 \(\lambda(1-x)\) 是拉格朗日项(Lagrange Term),不等式情形要求 \(\lambda\ge 0\)。
  3. 写出 KKT 的核心条件:可行性(Feasibility)\(1-x\le 0\);乘子非负 \(\lambda\ge 0\);驻点(Stationarity)\(\frac{d\mathcal{L}}{dx}=2x-\lambda=0\);互补松弛(Complementary Slackness)\(\lambda(1-x)=0\)。
  4. 解:由 \(2x-\lambda=0\) 得 \(\lambda=2x\)。互补松弛要求 \(\lambda=0\) 或 \(x=1\)。若 \(\lambda=0\) 则 \(x=0\),但违反 \(x\ge 1\);因此 \(x^*=1\),进而 \(\lambda^*=2\)。
  5. 解释:在最优点处 \(1-x^*=0\),该约束是“紧的”(Active),互补松弛允许乘子 \(\lambda^*>0\),它刻画了该约束在最优点处对解的影响强度。如果最优点落在可行域(Feasible Set)内部(约束不紧, \(1-x^*<0\)),互补松弛会强制 \(\lambda^*=0\)。

plot-lagrange-2

对偶问题

对偶问题(Dual Problem)从原始问题(Primal Problem)导出下界函数,用于分析可行性、间隙与最优性。标准形式:

\[\min_x\ f(x)\ \text{s.t.}\ g_i(x)\le 0,\ h_j(x)=0\] \[g(\lambda,\nu)=\inf_x\Big(f(x)+\sum_i \lambda_i g_i(x)+\sum_j \nu_j h_j(x)\Big),\ \lambda_i\ge 0\] \[\max_{\lambda,\nu}\ g(\lambda,\nu)\ \text{s.t.}\ \lambda\ge 0\]

把括号中的表达式记为拉格朗日函数(Lagrangian)\(\mathcal{L}(x,\lambda,\nu)=f(x)+\sum_i \lambda_i g_i(x)+\sum_j \nu_j h_j(x)\),则对偶函数(Dual Function)就是 \(g(\lambda,\nu)=\inf_x \mathcal{L}(x,\lambda,\nu)\):固定乘子后先对原变量求下确界,把它“消去”,再对乘子最大化这个下界。

例:SVM 对偶函数是怎么把变量“消掉”的

“对偶(Dual)”不是凭空再造一个新问题,而是从同一个原始问题(Primal Problem)的拉格朗日函数(Lagrangian)出发,先对原变量取下确界(Infimum),再只对乘子变量做优化后得到的伴随问题。在线性支持向量机(Support Vector Machine, SVM)里,这个过程最清楚,因为 \(\boldsymbol{\alpha}\) 的出现既解释了“为什么叫对偶”,也把“把原变量消掉”变成了可逐步计算的代换。

考虑硬间隔(Hard-margin)线性 SVM。原始问题是:

\[\min_{\mathbf{w},b}\ \frac{1}{2}\|\mathbf{w}\|_2^2\quad \text{s.t.}\quad y_i(\mathbf{w}^\top \mathbf{x}_i+b)-1\ge 0,\ i=1,\dots,n\]

把约束改写成标准不等式形式:

\[g_i(\mathbf{w},b)=1-y_i(\mathbf{w}^\top \mathbf{x}_i+b)\le 0\]

于是拉格朗日函数为:

\[\mathcal{L}(\mathbf{w},b,\boldsymbol{\alpha})=\frac{1}{2}\|\mathbf{w}\|_2^2+\sum_{i=1}^{n}\alpha_i\big(1-y_i(\mathbf{w}^\top \mathbf{x}_i+b)\big),\quad \alpha_i\ge 0\]

对偶函数(Dual Function)的定义是:固定乘子 \(\boldsymbol{\alpha}\),对原变量 \(\mathbf{w},b\) 取下确界:

\[g(\boldsymbol{\alpha})=\inf_{\mathbf{w},b}\mathcal{L}(\mathbf{w},b,\boldsymbol{\alpha})\]

这里的关键结构已经出现了:原始问题直接优化 \(\mathbf{w},b\),而对偶函数先把 \(\boldsymbol{\alpha}\) 固定住,把 \(\mathbf{w},b\) 当成待消去变量。随后得到的最大化问题,只剩乘子变量 \(\boldsymbol{\alpha}\)。这就是“对偶”的来源:同一个最优化问题,被改写成了另一组变量上的伴随优化问题。

现在把 \(\mathbf{w},b\) 完整消掉。先求驻点条件(Stationarity Conditions)。对 \(\mathbf{w}\) 求偏导:

\[\frac{\partial \mathcal{L}}{\partial \mathbf{w}}=\mathbf{w}-\sum_{i=1}^{n}\alpha_i y_i \mathbf{x}_i=\mathbf{0}\]

因此

\[\mathbf{w}=\sum_{i=1}^{n}\alpha_i y_i \mathbf{x}_i\]

对 \(b\) 求偏导:

\[\frac{\partial \mathcal{L}}{\partial b}=-\sum_{i=1}^{n}\alpha_i y_i=0\]

因此

\[\sum_{i=1}^{n}\alpha_i y_i=0\]

把这些结果代回拉格朗日函数之前,先把它展开成便于逐项代换的形式:

\[\mathcal{L}(\mathbf{w},b,\boldsymbol{\alpha})=\frac{1}{2}\mathbf{w}^\top\mathbf{w}+\sum_{i=1}^{n}\alpha_i-\sum_{i=1}^{n}\alpha_i y_i\,\mathbf{w}^\top\mathbf{x}_i-b\sum_{i=1}^{n}\alpha_i y_i\]

第一项代入 \(\mathbf{w}=\sum_{i=1}^{n}\alpha_i y_i \mathbf{x}_i\):

\[\frac{1}{2}\mathbf{w}^\top\mathbf{w}=\frac{1}{2}\Big(\sum_{i=1}^{n}\alpha_i y_i \mathbf{x}_i\Big)^\top\Big(\sum_{j=1}^{n}\alpha_j y_j \mathbf{x}_j\Big)\] \[=\frac{1}{2}\sum_{i=1}^{n}\sum_{j=1}^{n}\alpha_i\alpha_j y_i y_j\,\mathbf{x}_i^\top\mathbf{x}_j\]

第二项保持不变:

\[\sum_{i=1}^{n}\alpha_i\]

第三项代入同一个 \(\mathbf{w}\) 表达式:

\[-\sum_{i=1}^{n}\alpha_i y_i\,\mathbf{w}^\top\mathbf{x}_i=-\sum_{i=1}^{n}\alpha_i y_i\Big(\sum_{j=1}^{n}\alpha_j y_j \mathbf{x}_j\Big)^\top\mathbf{x}_i\] \[=-\sum_{i=1}^{n}\sum_{j=1}^{n}\alpha_i\alpha_j y_i y_j\,\mathbf{x}_j^\top\mathbf{x}_i\] \[=-\sum_{i=1}^{n}\sum_{j=1}^{n}\alpha_i\alpha_j y_i y_j\,\mathbf{x}_i^\top\mathbf{x}_j\]

最后一项利用 \(\sum_{i=1}^{n}\alpha_i y_i=0\) 直接消失:

\[-b\sum_{i=1}^{n}\alpha_i y_i=0\]

因此

\[g(\boldsymbol{\alpha})=\frac{1}{2}\sum_{i=1}^{n}\sum_{j=1}^{n}\alpha_i\alpha_j y_i y_j\,\mathbf{x}_i^\top\mathbf{x}_j+\sum_{i=1}^{n}\alpha_i-\sum_{i=1}^{n}\sum_{j=1}^{n}\alpha_i\alpha_j y_i y_j\,\mathbf{x}_i^\top\mathbf{x}_j\] \[=\sum_{i=1}^{n}\alpha_i-\frac{1}{2}\sum_{i=1}^{n}\sum_{j=1}^{n}\alpha_i\alpha_j y_i y_j\,\mathbf{x}_i^\top\mathbf{x}_j\]

于是对偶问题(Dual Problem)就是:

\[\max_{\boldsymbol{\alpha}}\ g(\boldsymbol{\alpha})\quad \text{s.t.}\quad \alpha_i\ge 0,\ \sum_{i=1}^{n}\alpha_i y_i=0\]

此时“对偶”二字的含义就精确了:原始问题在参数空间里直接求 \(\mathbf{w},b\),对偶问题则在乘子空间里求 \(\boldsymbol{\alpha}\);两者来自同一个拉格朗日结构,描述的是同一个最优解的两种表示。对 SVM 而言,更重要的结构变化是:数据 \(\mathbf{x}_i\) 不再单独出现,而只通过内积(Inner Product)\(\mathbf{x}_i^\top\mathbf{x}_j\) 进入目标函数,这正是核技巧(Kernel Trick)的入口。

若问题是凸的且满足 Slater 条件,则强对偶(Strong Duality)成立,可以用鞍点形式表达“先最小化再最大化”与“先最大化再最小化”等价:

\[\min_x\max_{\lambda\ge 0,\nu}\mathcal{L}(x,\lambda,\nu)=\max_{\lambda\ge 0,\nu}\min_x\mathcal{L}(x,\lambda,\nu)\]

对偶函数之所以是“下界”,来自一个简单但关键的不等式:对任意可行解 \(x\)(满足所有约束)与任意 \(\lambda\ge 0\),都有

\[f(x)\ge f(x)+\sum_i \lambda_i g_i(x)+\sum_j \nu_j h_j(x)\ge \inf_{x'}\Big(f(x')+\sum_i \lambda_i g_i(x')+\sum_j \nu_j h_j(x')\Big)=g(\lambda,\nu)\]

因此对任何 \((\lambda,\nu)\),都有 \(g(\lambda,\nu)\le p^*\)(原始最优值),这就是弱对偶(Weak Duality)。

弱对偶(Weak Duality)总成立;也就是说,对偶问题给出的值永远不会高于原始问题的最优值。但弱对偶只保证“对偶值是下界”,并不保证这个下界恰好贴住原始最优值。若两者之间还差一截,这个差距就叫对偶间隙(Duality Gap)。

强对偶(Strong Duality)则更进一步:它要求原始最优值与对偶最优值完全相等,也就是对偶问题不只是给出一个保守下界,而是精确刻画了原问题的最优值。对很多凸优化问题而言,Slater 条件正是让这种“下界刚好贴住最优值”的关键保证。

从直观上看,Slater 条件要求可行域内部真的存在一个严格可行点。这意味着约束系统不是被边界死死卡住的退化结构,而是有真实的内部空间。可行域一旦有内部,拉格朗日乘子就更容易稳定地描述“目标函数下降趋势”和“约束反作用力”之间的平衡,因此原始问题与对偶问题之间更不容易出现缝隙。在凸优化里,这就是为什么 Slater 条件常被看作强对偶成立的重要通行证。

直观上,对偶变量(Dual Variables)可以看作约束的“影子价格(Shadow Price)”:如果把约束放宽一点点,最优目标值会如何变化。在很多问题中(例如支持向量机(SVM)),对偶化会把优化变量从“模型参数”转成“约束乘子”,并把数据依赖压缩为内积,从而自然导出核技巧(Kernel Trick)。

影子价格(Shadow Price)

对偶变量(Dual Variable)常被称为影子价格(Shadow Price),因为它衡量的是:如果把某条约束稍微放宽一点,最优目标值会改善多少。这里的“价格”不是市场价格,而是“约束资源有多值钱”的边际刻度。

可以把约束想成一种稀缺资源。例如训练时有显存限制、预算限制、风险限制或几何边界限制;如果某条约束非常紧,那么它就像一个卡脖子的瓶颈。此时只要把这条约束稍微放宽一点,最优目标值就可能明显改善,于是它对应的对偶变量就会比较大。反过来,如果某条约束本来就很松,放宽它也几乎没有收益,那么它对应的对偶变量通常就是 0 或接近 0。

在数学上,这个直觉可以写成一种局部敏感度关系。若把约束写成

\[g_i(x)\le b_i\]

其中 \(b_i\) 表示第 \(i\) 条约束允许的“资源上限”或“边界位置”,那么对应的最优值函数可以记为 \(p^*(b)\)。在适当条件下,对偶变量 \(\lambda_i^*\) 可以理解为最优值对 \(b_i\) 的边际变化率,也就是“把第 \(i\) 条约束放宽一点,最优值会朝什么方向变化、变化多快”。

在最小化问题中,若某条约束对应的 \(\lambda_i^*\) 很大,通常表示这条约束非常关键:它一旦被放宽,最优目标值会明显下降;若 \(\lambda_i^*=0\),则说明该约束在当前最优点并没有真正起作用,放宽它也不会立刻带来收益。这与前面的互补松弛完全一致:只有真正卡住最优解的约束,才会拥有非零影子价格。

因此,影子价格提供了一个非常有用的解释视角:原始变量告诉我们“最优解长什么样”,而对偶变量告诉我们“哪些约束最贵、最紧、最值得被放宽”。这也是为什么在优化理论、经济学和机器学习里,对偶变量不仅是求解工具,也是理解模型结构的重要语言。

Slater 条件

Slater 条件(Slater's Condition)是凸优化(Convex Optimization)里最常见的正则性条件(Regularity Condition)之一。它的作用不是改变优化问题本身,而是保证对偶理论能够“工作得很干净”:在满足它时,很多凸问题会满足强对偶(Strong Duality),也就是原始问题最优值与对偶问题最优值相等;同时,KKT 条件也更容易从“必要条件”提升为判定最优性的核心条件。

对标准凸优化问题

\[
\min_x f(x)\quad \text{s.t.}\quad g_i(x)\le 0,\ h_j(x)=0
\]

如果 \(f(x)\) 和每个 \(g_i(x)\) 都是凸函数(Convex Function),每个 \(h_j(x)\) 都是仿射函数(Affine Function),那么 Slater 条件要求:至少存在一个严格可行点(Strictly Feasible Point) \(\tilde{x}\),使得所有不等式约束都被“严格满足”,也就是

\[
g_i(\tilde{x})<0,\ \forall i,\qquad h_j(\tilde{x})=0,\ \forall j
\]

这里“严格满足”四个字最关键。普通可行点只要求 \(g_i(x)\le 0\),也就是允许刚好压在边界上;而 Slater 条件要求存在某个点,能让所有不等式约束都留出一点余量,也就是完全处在可行域内部,而不是贴着边界。

这个条件可以用一个非常直观的图像来理解。把不等式约束围成的可行域想成一个房间:

  • 如果房间内部真的有空间,存在一个点站在房间里,不碰任何墙,这就是满足 Slater 条件。
  • 如果所谓“可行域”其实只是几面墙交出来的一条线、一个角、甚至一个点,根本没有真正的内部空间,那么 Slater 条件通常就不满足。

因此,Slater 条件本质上是在说:这个凸约束系统不能只是勉强拼出一个边界碎片,而要有真正的内部。一旦内部存在,原始问题和对偶问题之间的间隙通常就会消失,拉格朗日乘子和 KKT 条件也会变得更稳定、更有解释力。

一个简单例子可以把它说清楚。考虑约束

\[x\ge 0\]

写成标准形式是 \(g(x)=-x\le 0\)。这个约束满足 Slater 条件,因为取 \(\tilde{x}=1\) 时,有 \(g(1)=-1<0\)。这说明可行域 \([0,+\infty)\) 不只是边界点 \(x=0\),而是真正包含内部区域。

再看一个不满足 Slater 条件的例子:

\[x^2\le 0\]

由于 \(x^2\) 永远不小于 0,这个约束唯一允许的点只有 \(x=0\)。可行域虽然非空,但没有任何点能让 \(x^2<0\) 成立,所以不存在严格可行点,Slater 条件不成立。这样的约束系统只有边界、没有内部。

在机器学习常见的凸问题里,Slater 条件之所以频繁出现,是因为它几乎就是“强对偶成立的通行证”。例如在线性规划、逻辑回归的某些约束变体、支持向量机(SVM)的凸二次规划中,只要能找到一个严格可行点,就通常可以放心地从原始问题走到对偶问题,再用 KKT 条件解释最优解结构。反过来,如果没有 Slater 条件,就可能出现对偶间隙(Duality Gap),也就是对偶最优值严格小于原始最优值,此时只看对偶或只看 KKT 就不一定足够。

概念速查
概念 它回答的问题 最核心的一句话 在这一章里的作用
弱对偶(Weak Duality) 对偶问题和原始问题之间至少有什么关系 对偶最优值永远不会高于原始最优值;它天然是一个下界 先建立“对偶为什么有意义”的最低保证
对偶间隙(Duality Gap) 为什么有时对偶值还不等于原始最优值 如果对偶下界还没贴住原始最优值,两者之间的差就是对偶间隙 解释为什么“有对偶”不等于“对偶已经足够”
强对偶(Strong Duality) 什么时候对偶问题就足以精确刻画原问题 原始最优值与对偶最优值完全相等,对偶不再只是保守下界 为从原始问题转到对偶问题提供理论正当性
Slater 条件(Slater's Condition) 凸优化里什么条件有助于强对偶成立 只要可行域内部存在严格可行点,很多凸问题就能消除对偶间隙 说明为什么强对偶和 KKT 在凸问题里经常可用
影子价格(Shadow Price) 对偶变量到底在解释什么 它衡量“把某条约束放宽一点,最优值会改善多少” 赋予拉格朗日乘子清晰的经济 / 几何解释
KKT 条件 最优解在约束下必须满足哪些平衡关系 目标函数的下降趋势与约束施加的反作用力在最优点平衡 把可行性、乘子、驻点与互补松弛统一成最优性条件
KKT 条件
背景和定义

KKT 条件(Karush–Kuhn–Tucker Conditions)讨论的是带约束优化问题在最优点必须满足什么条件。无约束优化里,常见做法是令梯度(Gradient)为 0;但一旦问题带有不等式约束或等式约束,只看 \(\nabla f(x)=0\) 就不够了,因为最优点很可能被约束“顶”在边界上,而不是落在自由空间里的普通驻点。

标准形式写作:

\[\min_x f(x)\quad \text{s.t.}\quad g_i(x)\le 0,\ h_j(x)=0\]

这里 \(f(x)\) 是目标函数(Objective Function),表示希望最小化的量;\(x\) 是优化变量(Optimization Variable);\(g_i(x)\le 0\) 是第 \(i\) 个不等式约束(Inequality Constraint);\(h_j(x)=0\) 是第 \(j\) 个等式约束(Equality Constraint)。KKT 条件给出的就是:当 \(x^*\) 真的是一个最优解时,它与对应的拉格朗日乘子(Lagrange Multipliers)之间必须满足一组相互配合的条件。

在凸优化(Convex Optimization)里,如果问题满足适当的正则性条件,例如 Slater 条件(Slater's Condition),KKT 条件往往不只是必要条件,还可以成为判定最优性的核心工具。在线性规划、二次规划、支持向量机(Support Vector Machine, SVM)和许多机器学习训练问题中,KKT 条件都直接参与求解过程。

kkt-paraboloid-plane

图解:四组条件如何逐条理解

上图使用的是活跃边界 \(g(x)=1-x_1-x_2=0\)。边界 \(x_1+x_2=1\) 的切向方向可取 \((1,-1)\);与它垂直的向量都是法向量(Normal Vector),例如 \((1,1)\) 或 \((-1,-1)\)。如果把约束写成函数 \(g(x)=1-x_1-x_2\),那么梯度 \(\nabla g(x)=(-1,-1)\) 就是一条法向量;它指向 \(g(x)\) 增大的方向,也就是不可行侧。

图中的橙色箭头对应驻点条件(Stationarity)里真正参与平衡的两个向量:目标梯度 \(\nabla f(x^*)\) 与乘子加权后的约束法向量 \(\lambda^*\nabla g(x^*)\)。它们在最优点首尾相接后得到 0,于是 \(\nabla f(x^*)+\lambda^*\nabla g(x^*)=0\) 不是抽象记号,而是边界最优点上的几何平衡。

  • 原始可行性(Primal Feasibility):解必须落在可行域内。对这张图而言,可行域是半空间 \(x_1+x_2\ge 1\),最优点 \(x^*\) 落在它的活跃边界 \(x_1+x_2=1\) 上。
  • 对偶可行性(Dual Feasibility):不等式约束的乘子必须非负,即 \(\lambda^*\ge 0\)。图中的计算给出 \(\lambda^*=0.65\),表示这条边界在最优点处确实对目标下降施加了正的“反作用”。
  • 驻点条件(Stationarity):沿边界的切向方向已经不能继续下降,因此目标梯度不再含有切向分量,只能落在法向空间里。单个活跃约束时,这就变成 \(\nabla f(x^*)=-\lambda^*\nabla g(x^*)\)。图中的两根橙色箭头正是这两个大小相等、方向相反的向量。
  • 互补松弛(Complementary Slackness):约束若不接触最优点,就不会产生乘子;约束一旦卡在最优点上,对应乘子才会变成正值。当前图像展示的是活跃边界情形,所以 \(g(x^*)=0\) 且 \(\lambda^*>0\) 同时成立。

法向量之所以关键,是因为它刻画了“离开边界最快”的方向;切向方向则刻画了“沿边界滑动”的方向。边界最优点的本质结论是:目标函数想继续下降的那一部分趋势,已经完全被约束边界的法向作用抵消;沿边界本身则不存在进一步下降方向。

具像化描述

可以把 KKT 条件想成一个“受围栏限制的小球找最低点”的问题。目标函数 \(f(x)\) 决定地形:哪里高、哪里低;约束 \(g_i(x)\le 0\) 和 \(h_j(x)=0\) 决定活动范围:哪些区域允许进入,哪些区域不允许进入。

如果没有围栏,小球会沿着坡度一路滚到某个最低点,此时常见条件是梯度为 0,也就是周围已经没有继续下降的方向。但有了围栏以后,最低点可能不在地形内部,而在边界上。此时小球还想往更低的地方滚,却被围栏挡住了。KKT 条件刻画的正是这种“地形的下降趋势与边界施加的反作用力在最优点达到平衡”的状态。

其中最形象的一条是互补松弛(Complementary Slackness)。它表达的是:每一个不等式约束在最优点都只有两种状态。

  • 如果某个约束正好卡在边界上,即 \(g_i(x^*)=0\),说明这道围栏真的“顶住了”最优解,这时它对应的乘子 \(\lambda_i^*\) 可以大于 0。
  • 如果某个约束离边界还有余量,即 \(g_i(x^*)<0\),说明这道围栏根本没有碰到最优解,那么它对应的乘子必须是 0,也就是 \(\lambda_i^*=0\)。

因此,乘子 \(\lambda_i^*\) 可以直观理解为“约束对最优解施加的压力”。压力不为 0,说明这条约束正在真正影响解;压力为 0,说明这条约束虽然存在,但在最优点处并没有发挥作用。

公式逐元素解释

把原问题写成统一形式后,先定义拉格朗日函数(Lagrangian):

\[\mathcal{L}(x,\lambda,\nu)=f(x)+\sum_i \lambda_i g_i(x)+\sum_j \nu_j h_j(x)\]

这个式子里的每个元素都有明确含义:

  • \(\mathcal{L}\):拉格朗日函数,把目标函数和约束统一写进一个式子里。
  • \(x\):原始变量(Primal Variable),也就是模型真正要优化的参数。
  • \(f(x)\):目标函数,表示希望最小化的代价、损失或能量。
  • \(g_i(x)\):第 \(i\) 个不等式约束函数;要求它满足 \(g_i(x)\le 0\)。
  • \(h_j(x)\):第 \(j\) 个等式约束函数;要求它满足 \(h_j(x)=0\)。
  • \(\lambda_i\):第 \(i\) 个不等式约束对应的拉格朗日乘子;它衡量该约束的“压力”大小。
  • \(\nu_j\):第 \(j\) 个等式约束对应的拉格朗日乘子。
  • \(\sum_i\) 和 \(\sum_j\):分别表示把所有不等式约束和所有等式约束的影响累加起来。

在此基础上,KKT 条件通常写成四组:

\[\text{Primal feasibility: } g_i(x^*)\le 0,\ h_j(x^*)=0\] \[\text{Dual feasibility: } \lambda_i^*\ge 0\] \[\text{Stationarity: } \nabla f(x^*)+\sum_i \lambda_i^*\nabla g_i(x^*)+\sum_j \nu_j^*\nabla h_j(x^*)=0\] \[\text{Complementary slackness: } \lambda_i^* g_i(x^*)=0\]

这四组条件可以逐条理解:

  • 原始可行性(Primal Feasibility):最优解 \(x^*\) 首先必须是合法的,不能跑到可行域之外。也就是说,所有不等式约束都要满足 \(g_i(x^*)\le 0\),所有等式约束都要精确满足 \(h_j(x^*)=0\)。
  • 对偶可行性(Dual Feasibility):不等式约束的乘子必须非负,即 \(\lambda_i^*\ge 0\)。这保证了它们表达的是“阻止变量越界的压力”,而不是把解往不可行方向拉过去的反向力量。
  • 驻点条件(Stationarity):在最优点处,目标函数的梯度 \(\nabla f(x^*)\) 与所有约束梯度加权后的合力必须平衡为 0。这里 \(\nabla f(x^*)\) 表示目标函数在 \(x^*\) 处最陡上升方向;\(\nabla g_i(x^*)\) 和 \(\nabla h_j(x^*)\) 分别表示约束边界的法向方向;乘子 \(\lambda_i^*\)、\(\nu_j^*\) 则控制这些方向各自施加多少“反作用力”。这条式子本质上是在说:最优点处已经不存在任何仍然可行且还能继续下降的方向。
  • 互补松弛(Complementary Slackness):每个不等式约束都满足 \(\lambda_i^* g_i(x^*)=0\)。因为这是两个量的乘积等于 0,所以只能出现两种情况:要么 \(g_i(x^*)=0\),说明约束正好顶在边界上;要么 \(\lambda_i^*=0\),说明这条约束在最优点没有施加压力。它精确区分了“活跃约束(Active Constraint)”和“不活跃约束(Inactive Constraint)”。

一个一维例子可以把这些符号落到实处。考虑:

\[\min_x\ (x+1)^2\quad \text{s.t.}\quad x\ge 0\]

把约束写成标准形式 \(g(x)=-x\le 0\),于是拉格朗日函数是:

\[\mathcal{L}(x,\lambda)=(x+1)^2+\lambda(-x)\]

这里 \((x+1)^2\) 是目标函数;\(-x\le 0\) 是不等式约束;\(\lambda\) 是这条约束对应的乘子。KKT 条件变成:

\[x\ge 0,\quad \lambda\ge 0,\quad 2(x+1)-\lambda=0,\quad \lambda x=0\]

这四项分别表示:解必须在 \(x\ge 0\) 的合法区域内;乘子必须非负;目标函数与约束施加的作用力在最优点平衡;约束要么卡住解、要么不施加压力。无约束时, \((x+1)^2\) 的最低点在 \(x=-1\),但这不满足 \(x\ge 0\),所以真正最优点被“推”到边界 \(x^*=0\);再代入驻点条件 \(2(x+1)-\lambda=0\),得到 \(\lambda^*=2\)。这正对应“边界在最优点处确实对解施加了压力”。

如果把目标函数换成 \(\min_x (x-2)^2\ \text{s.t.}\ x\ge 0\),无约束最优点就是 \(x=2\),它本来就在可行域内部,因此约束没有真正碰到最优点。此时 KKT 会给出 \(x^*=2\)、\(\lambda^*=0\)。这就是互补松弛最直观的含义:边界没有碰到解,压力就自动消失;边界一旦碰到解,乘子就会变成非零。

概率论与统计

概率论与统计处理两类问题:第一类是在不确定性下如何描述事件、变量与数据生成过程;第二类是在只观察到有限样本时,如何反推总体规律与模型参数。在 AI 中,分类概率、回归噪声、采样、似然训练、置信评估与后验推断都建立在这套语言之上。

基础概念

在进入公式前,先区分几个最常混淆的基础对象。概率论不是一开始就讨论“均值”和“方差”,而是先规定随机试验的结果空间、结果上的事件,以及把结果映射成数的随机变量,之后才谈分布、期望和统计推断。

  • 样本空间(Sample Space)\(\Omega\):一次随机试验所有可能结果的集合,其中希腊字母 \(\Omega\) 只是“全部可能结果”的记号。掷骰子时 \(\Omega=\{1,2,3,4,5,6\}\),表示所有可能点数组成的集合。
  • 事件(Event):样本空间的子集,表示“哪些结果算作某件事发生”。例如“点数为偶数”对应集合 \(\{2,4,6\}\);这句话的意思是,只要试验结果落在这个集合里,就说该事件发生。
  • 随机变量(Random Variable)\(X\):把随机结果映射为数的函数,可写作 \(X:\Omega\to\mathbb{R}\)。这里 \(X\) 是这个函数的名字, \(\Omega\) 是输入端的样本空间,箭头 \(\to\) 表示“映射到”, \(\mathbb{R}\) 表示实数集合。也就是说,每个随机结果都会被 \(X\) 变成一个实数。掷骰子时最自然的随机变量就是“点数本身”;在机器学习里,输入 \(X\)、标签 \(Y\)、噪声 \(\epsilon\) 都是随机变量。
  • 概率分布(Probability Distribution):描述随机变量取不同值的概率规律。离散情形常写作 \(P(X=x)\),意思是“随机变量 \(X\) 恰好取值 \(x\) 的概率”;连续情形常写作密度 \(p(x)\),它不是某一点的概率本身,而是概率密度函数(Probability Density Function, PDF),需要在区间上积分才得到概率。
  • 期望(Expectation)\(\mathbb{E}[X]\):按概率加权的平均,回答“长期来看这个随机变量的典型水平在哪里”。这里 \(\mathbb{E}\) 是 expectation 的标准记号,方括号中的 \(X\) 表示“对哪个随机变量取期望”。
  • 方差(Variance)\(\mathrm{Var}(X)\):围绕期望的波动强度,回答“它通常偏离平均水平多大”。其中 \(\mathrm{Var}\) 是 variance 的记号,括号里的 \(X\) 表示“考察哪个随机变量的波动”。
  • 参数(Parameter)与统计量(Statistic):参数描述总体,例如高斯分布中的 \(\mu\) 表示均值(Mean), \(\sigma^2\) 表示方差(Variance);统计量则由样本计算出来,例如 \(\bar{x}\) 表示样本均值(Sample Mean),上面的横线读作“x bar”,意思是“样本中所有 \(x\) 的平均值”。统计学习的核心任务之一,就是用统计量去估计未知参数。

probability

似然和概率

似然(Likelihood)和概率(Probability)最容易混淆的原因,在于公式相同却回答的是相反方向的问题。 条件分布 \(p(x|\theta)\) 在统计里经常同时出现在两种语境中:当参数 \(\theta\) 固定、数据 \(x\) 变化时,它表示“在这个模型下观察到不同数据的概率有多大”;当数据 \(x\) 固定、参数 \(\theta\) 变化时,它表示“哪些参数更能解释这份已经观察到的数据”。

因此,概率的读法是参数已知,看数据。例如抛硬币模型里,若已知正面概率 \(\theta=0.7\),那么 10 次里出现 8 次正面的概率是

\[P(X=8|\theta=0.7)={10 \choose 8}0.7^8 0.3^2\]

其中 \({10 \choose 8}\) 表示组合数(Binomial Coefficient):从 10 次试验里选出 8 次作为正面的不同选法一共有多少种。它负责计数“8 次正面可以出现在哪 8 个位置上”,不是额外的概率项。

而 \(0.7^8 0.3^2\) 来自独立重复试验的乘法法则:如果每次抛掷相互独立,且正面概率是 \(0.7\)、反面概率是 \(0.3\),那么任意一个“8 次正面、2 次反面”的具体序列,其概率都是 8 个 \(0.7\) 与 2 个 \(0.3\) 的乘积,也就是 \(0.7^8 0.3^2\)。

这里被当作变量的是结果 \(X\);问题是“给定参数,这样的数据是否常见”。这就是通常意义上的概率或概率密度。

似然的读法正好反过来:数据已知,看参数。假设现在已经观察到 10 次抛硬币里有 8 次正面,这组数据不再变化;真正变化的是候选参数 \(\theta\)。于是同一个模型被改写为似然函数(Likelihood Function):

\[L(\theta|X=8)=P(X=8|\theta)={10 \choose 8}\theta^8(1-\theta)^2\]

此时 \(L(\theta|x)\) 不是“参数取某个值的概率”,而是一个关于 \(\theta\) 的评分函数:哪个 \(\theta\) 让已观察到的数据 \(x\) 更容易出现,哪个 \(\theta\) 的似然就更大。最大似然估计(Maximum Likelihood Estimation, MLE)做的正是这件事:寻找使 \(L(\theta|x)\) 最大的参数。

likelihood

这里有一个必须严格区分的点:似然不是参数的概率分布。对固定数据来说, \(L(\theta|x)\) 不要求对 \(\theta\) 积分为 1,也不能直接解释为 \(P(\theta|x)\)。只有在贝叶斯框架里,把似然与先验(Prior) \(p(\theta)\) 相乘并做归一化之后,才得到参数的后验概率(Posterior):

\[p(\theta|x)=\frac{p(x|\theta)p(\theta)}{p(x)}\]

所以可以把三者关系记成一条清晰的链: \(p(x|\theta)\) 作为“关于 \(x\) 的函数”时是概率模型;作为“关于 \(\theta\) 的函数”时是似然函数;再结合先验并归一化后,才变成参数的后验概率。很多机器学习教材里说“最小化交叉熵等价于最大化对数似然”,本质上就是固定数据后,在参数空间里寻找最能解释样本的模型。

机器学习视角:概率、似然与损失

在机器学习模型里,这种“同一个式子,换个视角名字就变”的现象非常常见。设模型写成 \(p_\theta(y|x)\),其中 \(x\) 是输入或上下文, \(y\) 是真实标签或真实 token, \(\theta\) 是模型参数。

当参数 \(\theta\) 固定、把输出 \(y\) 当作随机变量时, \(p_\theta(y|x)\) 是概率模型:它回答“在这个模型已经定好的前提下,不同输出有多可能”。例如语言模型会对整个词表输出一个条件概率分布,其中 \(c_t\) 表示第 \(t\) 个位置之前的上下文(context), \(y_t\) 表示该位置真实出现的 token,因此 \(p_\theta(y_t|c_t)\) 就是“在上下文 \(c_t\) 下,模型给真实 token \(y_t\) 分配的概率”。

当观测到的 \((x,y)\) 固定、把参数 \(\theta\) 当作变量时,同一个式子 \(p_\theta(y|x)\) 就变成似然:它回答“哪些参数更能让这条已经看到的数据显得合理”。于是训练时最大化似然,就等价于最小化负对数似然:

\[-\log p_\theta(y|x)\]

因此可以把这个困惑直接拆开:固定参数看输出,它是概率;固定输出看参数,它是似然;对它取负对数后,它就是训练里使用的损失项。在语言建模里,对一个具体 token 而言,给定当前模型参数后, \(-\log p_\theta(y_t|c_t)\) 既可以看成该 token 的负对数概率,也可以在训练语境下看成该 token 对参数的负对数似然;两者是同一个数值对象,只是观察角度不同。

基本概率

概率(Probability)描述不确定事件发生的可能性。设样本空间(Sample Space)为 \(\Omega\),事件(Event)为 \(A\subseteq\Omega\),则概率公理要求 \(P(A)\in[0,1]\)、\(P(\Omega)=1\),以及互斥事件可加。这里“互斥事件可加”的意思是:如果两个事件不能同时发生,即 \(A\cap B=\{\}\),那么“\(A\) 或 \(B\) 发生”的概率就是两者概率直接相加:

\[P(A\cup B)=P(A)+P(B),\quad A\cap B=\{\}\]

之所以能直接相加,是因为两者没有重叠部分,不会重复计数。若有重叠,则不能直接相加,而要减去交集 \(P(A\cap B)\)。

最小例子:掷一枚公平六面骰。样本空间是 \(\Omega=\{1,2,3,4,5,6\}\)。若事件 \(A\) 表示“点数为 1”,事件 \(B\) 表示“点数为 2”,则它们互斥,因此 \(P(A\cup B)=1/6+1/6=1/3\)。再看一个非互斥例子:若事件 \(C\) 表示“点数为偶数”,则 \(C=\{2,4,6\}\),因此 \(P(C)=3/6=1/2\)。

联合概率

联合概率(Joint Probability)表示多个事件同时发生的概率,即 \(P(A,B)=P(A\cap B)\)。它回答的是“这些条件一起成立的可能性有多大”。

\[P(A,B)=P(A\cap B)\]

仍用骰子例子:令 \(A\) 表示“点数为偶数”,\(B\) 表示“点数至少为 4”,则 \(A\cap B=\{4,6\}\),所以 \(P(A,B)=2/6=1/3\)。在机器学习里,联合分布 \(p(x,y)\) 表示“输入 \(x\) 与标签 \(y\) 一起出现”的总体规律。

独立性与乘法法则

独立(Independence)表示一个事件是否发生,不会改变另一个事件发生的概率。若事件 \(A,B\) 相互独立,则它们同时发生的概率可直接写成概率乘积:

\[P(A\cap B)=P(A)P(B)\]

更一般地,若 \(A_1,\dots,A_n\) 相互独立,则

\[P\!\left(\bigcap_{i=1}^{n}A_i\right)=\prod_{i=1}^{n}P(A_i)\]

例:掷一枚公平硬币并同时掷一枚公平骰子。令 \(A\) 表示“硬币为正面”,\(B\) 表示“骰子为偶数”,则 \(P(A)=1/2\)、\(P(B)=1/2\),且二者独立,因此 \(P(A\cap B)=1/2\times 1/2=1/4\)。

独立时还可等价写成 \(P(A|B)=P(A)\):知道 \(B\) 发生,并不会改变对 \(A\) 的判断。

要注意:互斥(Mutually Exclusive)和独立(Independent)不是一回事。互斥表示不能同时发生;独立表示是否发生彼此无关。对非零概率事件而言,互斥通常意味着不独立,因为一旦知道 \(A\) 发生,就立刻知道 \(B\) 不可能发生。

条件概率

条件概率(Conditional Probability)表示“已知 \(B\) 发生时,\(A\) 发生的概率”:

\[P(A|B)=\frac{P(A,B)}{P(B)},\quad P(B)>0\]

关键点不是“再算一次概率”,而是样本空间被缩小了。在上面的骰子例子中,已知 \(B\)(点数至少为 4)后,只剩 \(\{4,5,6\}\) 三种可能,其中偶数是 \(\{4,6\}\),所以 \(P(A|B)=2/3\),明显不同于原来的 \(P(A)=1/2\)。

在建模中,几乎所有监督学习目标都可写成条件概率最大化,例如分类模型学习的是 \(P(y|x)\):给定特征 \(x\),标签 \(y\) 的概率有多大。

边缘概率

边缘概率(Marginal Probability)是把不关心的变量“求和/积分掉”后得到的概率:

\[P(A)=\sum_b P(A,b),\quad p(x)=\int p(x,z)\,dz\]

这两个公式的意思完全一致,只是分别对应离散情形与连续情形。 \(P(A,b)\) 表示“\(A\) 与 \(b\) 同时发生”的联合概率;若现在只关心 \(A\),就必须把所有可能的 \(b\) 都加起来。连续情形下同理: \(p(x,z)\) 是关于 \((x,z)\) 的联合密度,若只关心 \(x\),就把所有 \(z\) 的可能性沿该维度积分掉,得到 \(p(x)\)。

几何上,可以把边缘化(Marginalization)理解为把高维分布沿某个方向压扁后得到的投影。设二维联合分布的两个维度分别是身高与体重,平面上的每个位置都对应一个联合概率密度 \(p(\text{height},\text{weight})\)。如果现在根本不关心体重,只想知道身高的总体分布,那么就把每个固定身高处、沿着体重方向的所有概率质量全部累加起来;累加后的结果就是该身高对应的边缘密度 \(p(\text{height})\)。

因此,求和符号 \(\sum_b P(A,b)\) 或积分符号 \(\int p(x,z)\,dz\) 的几何含义,不是“神秘地消掉一个变量”,而是把那个维度上的所有可能性叠加到剩余维度上。它像从侧面看一个三维物体的投影:原来的结构仍然在,但你只保留了当前关心的坐标轴信息。

在 AI 中,边缘概率几乎总伴随着隐藏变量(Latent Variable)。例如主题模型里 \(z\) 可以表示隐藏主题(Hidden Topic),\(x\) 表示某个词;若只关心词出现的总体概率,就要把主题变量消去,得到 \(p(x)=\sum_z p(x,z)\)。很多推断算法的难点,本质上就是这个“沿隐藏维度求和/积分”的步骤代价很高。

marginzation

补事件

补事件(Complementary Event)满足

\[P(A^c)=1-P(A)\]

它表示“\(A\) 不发生”的概率等于总概率 1 减去 \(A\) 发生的概率。

全概率公式

第二,若 \(A_1,\dots,A_n\) 把样本空间划分为互斥且完备的几部分(即两两互斥,且并集为 \(\Omega\)),则全概率公式(Law of Total Probability)为

\[P(B)=\sum_{i=1}^{n}P(B|A_i)P(A_i)\]

它的含义是:事件 \(B\) 的总概率,可以拆成“先落入哪一种原因 \(A_i\),再在该原因下发生 \(B\)”的加权和。贝叶斯公式中的分母 \(P(B)\),很多时候就是用全概率公式展开出来的。

贝叶斯定理

贝叶斯定理(Bayes' Theorem)把“从原因到结果”的概率反转为“从结果反推原因”:

\[P(A|B)=\frac{P(B|A)\,P(A)}{P(B)}\]

把式子写出来并不难,真正容易混淆的是每一项到底在说什么。下面直接用一个具体场景来解释:设 \(A\) 表示“患者真的患病”,\(B\) 表示“检测结果为阳性”。已知患病率为 1%,检测的灵敏度(Sensitivity)为 99%,假阳性率(False Positive Rate)为 5%。则:

  • 先验(Prior) \(P(A)\):在还没看到这次检测结果前,对“此人患病”的原始判断。在这个例子里,先验就是总体患病率 \(P(A)=0.01\)。
  • 似然(Likelihood) \(P(B|A)\):如果一个人确实患病,那么检测为阳性的概率有多大。在这个例子里,检测灵敏度是 99%,因此 \(P(B|A)=0.99\)。
  • 证据(Evidence) \(P(B)\):不管一个人是否患病,检测结果为阳性在总体上出现的概率。它等于“真阳性 + 假阳性”的总和: \(P(B)=0.99\times 0.01 + 0.05\times 0.99 = 0.0594\)。
  • 后验(Posterior) \(P(A|B)\):在已经看到“检测阳性”这个证据之后,此人真正患病的更新后概率。代入上面的数值,有
\[P(\text{disease}|+) = \frac{0.99\times 0.01}{0.99\times 0.01 + 0.05\times 0.99} = \frac{1}{6} \approx 16.7\%\]

因此,贝叶斯定理说的不是“把公式套进去算一下”,而是一个非常具体的更新过程:先从原始信念出发,用证据对它重新加权,再归一化,得到更新后的信念。这也是为什么常把它概括成:后验 = 似然 × 先验 ÷ 证据。

这个例子最重要的结论是:检测阳性后,真实患病概率并不是 99%,而只有约 16.7%。原因不是检测太差,而是先验患病率本来就很低;假阳性虽然比例不高,但基数更大。换言之,证据不会凭空决定结论,证据必须结合基线发生率一起解释。在 AI 里,这就是“看到证据后更新信念”的统一公式:朴素贝叶斯分类、贝叶斯滤波、概率图模型都在做这件事。

概率分布

这里的“分布(Distribution)”指随机变量取值的不确定性如何在取值空间上分配。严格地说,概率分布(Probability Distribution)是一种概率测度(Probability Measure),它为每个事件 \(A\) 赋予概率 \(P(A)\)。

对一维实值随机变量 \(X\),分布最常用的统一表述是累积分布函数(Cumulative Distribution Function, CDF)\(F(x)=P(X\le x)\)。离散与连续的差别,主要体现在如何从 \(F\) 得到“点上/区间上”的概率。

不同任务对应不同的数据分布假设(Distribution Assumption)。分布选得对,建模与推断会更稳定;分布假设错得太远,参数估计、置信区间乃至损失函数解释都会失真。

plot_six_basic_dist

概率密度/概率质量函数

若 \(X\) 是离散型随机变量,其概率质量函数(Probability Mass Function, PMF)为 \(p(x)=P(X=x)\),并满足 \(\sum_x p(x)=1\)。

若 \(X\) 是连续型随机变量,其概率密度函数(Probability Density Function, PDF)为 \(p(x)\),满足 \(p(x)\ge 0\) 与 \(\int_{-\infty}^{+\infty} p(x)\,dx=1\);区间概率由积分给出:\(P(a\le X\le b)=\int_a^b p(x)\,dx\)。因此 \(p(x)\) 本身不是“点上概率”。

两者都可写成同一 CDF 关系:连续情形 \(F(x)=\int_{-\infty}^{x} p(t)\,dt\),离散情形 \(F(x)=\sum_{t\le x} p(t)\)。

高斯分布(正态分布)

高斯分布(Gaussian / Normal Distribution)由均值 \(\mu\) 与方差 \(\sigma^2\) 决定:

\[p(x)=\frac{1}{\sqrt{2\pi}\sigma}\exp\!\left(-\frac{(x-\mu)^2}{2\sigma^2}\right)\]

它的图像是熟悉的“钟形曲线(Bell Curve)”:离 \(\mu\) 越近,概率密度越高;离得越远,概率密度衰减越快。大量独立小扰动叠加后常近似高斯(中心极限定理的结果),所以测量误差、回归残差、传感器噪声、嵌入向量某些方向上的统计近似都常采用高斯模型。

例:若成年男性身高近似服从 \(\mathcal{N}(170,6^2)\),则 170 cm 附近最常见,而 190 cm 属于离均值超过 3 个标准差的少见样本。回归里假设残差服从高斯,本质上是在说“误差多数小、极大误差少”。

拉普拉斯分布

拉普拉斯分布(Laplace Distribution)也是定义在实数轴上的连续分布,常用位置参数(Location) \(\mu\) 与尺度参数(Scale) \(b>0\) 描述:

\[p(x)=\frac{1}{2b}\exp\left(-\frac{|x-\mu|}{b}\right)\]

它的图像在中心点 \(\mu\) 处更尖、尾部比高斯分布更厚(Heavier Tails)。这表示模型更偏好“大多数误差很小,但偶尔出现相对较大偏差”这一类数据形状,因此它对离群点(Outliers)的容忍度通常高于高斯模型。

拉普拉斯分布和绝对误差(Absolute Error)关系非常紧密:若回归残差假设服从拉普拉斯分布,那么最大似然估计会导向 \(L_1\) 损失;若把参数先验设为拉普拉斯分布,最大后验估计则会导向 \(L_1\) 正则。这也是它在稀疏建模(Sparse Modeling)和鲁棒回归(Robust Regression)里很常见的原因。

例:若某传感器大多数时刻误差接近 0,但偶尔会因为抖动或遮挡产生较大的偏差,那么用拉普拉斯分布描述误差,往往比高斯分布更贴近这种“中心尖、尾部较厚”的统计形状。

伯努利分布

伯努利分布(Bernoulli Distribution)描述一次二元结果试验(0/1):

\[P(X=1)=p,\quad P(X=0)=1-p\]

它是二分类标签建模的最小单元,也是逻辑回归与二分类交叉熵的概率基础。若 \(X\) 表示“用户是否点击广告”,则 \(X=1\) 代表点击、\(X=0\) 代表未点击,模型输出的 \(p\) 就是点击概率。

伯努利变量的期望是 \(\mathbb{E}[X]=p\),方差是 \(p(1-p)\)。因此当 \(p\) 接近 0 或 1 时,不确定性反而更小;当 \(p=0.5\) 时,不确定性最大。

如果把同一个伯努利试验独立重复 \(n\) 次,并把成功次数加总,那么得到的就不是伯努利分布,而是二项分布(Binomial Distribution)。换句话说,伯努利分布描述“单次是否成功”,二项分布描述“总共成功了多少次”。

二项分布

二项分布(Binomial Distribution)描述 \(n\) 次独立伯努利试验中的成功次数。若每次成功概率都是 \(p\),随机变量 \(X\) 表示总成功次数,则

\[P(X=k)={n \choose k}p^k(1-p)^{n-k},\quad k=0,1,\dots,n\]

这里 \({n \choose k}\) 表示“从 \(n\) 次试验里选出 \(k\) 次成功”的组合数;后面的 \(p^k(1-p)^{n-k}\) 表示某一种具体排列出现的概率。两者相乘,就得到“恰好成功 \(k\) 次”的总概率。

如果 \(X_1,\dots,X_n\) 独立同分布且 \(X_i\sim\mathrm{Bernoulli}(p)\),那么它们的和

\[S_n=\sum_{i=1}^{n}X_i\sim\mathrm{Binomial}(n,p)\]

因此,二项分布本质上就是“多个伯努利随机变量求和后的分布”。它的期望是 \(\mathbb{E}[X]=np\),方差是 \(np(1-p)\)。

例:若一枚硬币正面概率为 \(p=0.7\),连续抛 10 次,则“正面出现几次”服从二项分布。此时恰好出现 7 次正面的概率是

\[P(X=7)={10 \choose 7}0.7^7 0.3^3\]
多项式分布

多项式分布(Multinomial Distribution)是“多类别计数版”的伯努利:进行 \(n\) 次独立试验,类别概率为 \(\mathbf{p}\),计数向量 \(\mathbf{k}\) 的概率为

\[P(\mathbf{k})=\frac{n!}{\prod_i k_i!}\prod_i p_i^{k_i},\quad \sum_i k_i=n\]

若只有一次抽样,通常写作分类分布(Categorical Distribution):

distribution-categorical

若把一次抽样重复 \(n\) 次并统计每类出现次数,就得到多项式分布,语言模型里的词频计数、主题模型中的词袋(Bag of Words)都与这种计数视角一致。概率分布一节的第三个图就是多项式分布:总计抽样6次,横轴表示分类1的次数,纵轴表示分类2的次数(因为只有3分类,因此不需要绘制三维),颜色表示抽取到不同分类的次数组合的概率。

泊松分布

泊松分布(Poisson Distribution)描述单位时间或单位空间内稀有事件的发生次数:

\[P(X=k)=e^{-\lambda}\frac{\lambda^k}{k!},\quad k=0,1,2,\ldots\]

其中 \(\lambda\) 既是平均发生次数,也是方差。它适用于“事件相互独立、平均速率稳定、短时间内多次同时发生概率很小”的场景,例如单位分钟请求数、单位小时故障数、单位页面点击数。

例:若一个接口平均每分钟收到 3 次请求,则 \(\lambda=3\)。此时一分钟内 0 次请求的概率是 \(e^{-3}\approx 0.05\);5 次请求的概率是 \(e^{-3}3^5/5!\approx 0.10\)。泊松分布常被用来做“到达数 / 故障数 / 事件数”建模。

期望

期望(Expectation)是随机变量的“按概率加权的平均”,回答“长期来看这个量的典型水平在哪里”。离散情形下,它把每个可能取值按对应概率加权;连续情形下,则对概率密度做积分:

\[\mathbb{E}[X]=\sum_x x\,p(x)\ \ (\text{或 } \int x\,p(x)\,dx)\]

期望和均值很像,但不是同一个概念。 期望(Expectation)是总体分布层面的量,由概率模型 \(p(x)\) 决定,描述“如果无限次重复抽样,平均会稳定到哪里”;均值(Mean)通常有两种语境:一是把总体的中心位置也叫“总体均值”,这时它与期望是同一个量;二是指有限样本算出来的样本均值(Sample Mean) \(\bar{x}=\frac{1}{n}\sum_{i=1}^{n}x_i\),这是用样本近似期望的统计量。

因此可以把三者关系记成:总体均值 = 期望;样本均值 = 对期望的估计。例如公平骰子点数的期望是 \(\mathbb{E}[X]=3.5\);如果你真的掷 6 次,样本均值可能是 3、4 或 4.5,不必恰好等于 3.5,但随着试验次数增多,它会越来越接近期望。

期望最重要的性质之一是线性性(Linearity):\(\mathbb{E}[aX+b]=a\mathbb{E}[X]+b\),不要求独立。例:公平骰子点数 \(X\) 的期望是 \((1+2+3+4+5+6)/6=3.5\);若收入模型写成 \(Y=2X+1\),则 \(\mathbb{E}[Y]=2\times 3.5+1=8\)。

矩(Moments)

矩(Moment)是概率统计里用来概括分布形状的一组数。理论上,“第 \(k\) 阶”指对 \(k\) 次幂取期望:矩天然与期望/均值绑定。

常用两类定义是:

  • 原点矩(Raw Moment / Non-central Moment):\(m_k=\mathbb{E}[X^k]\)(以 0 为参照)。
  • 中心矩(Central Moment):\(\mu_k=\mathbb{E}\big[(X-\mathbb{E}[X])^k\big]\)(以均值为参照)。

直觉上可以用“跷跷板”来理解:把概率质量看作分布在数轴上的“重量”,期望/均值决定“支点放哪里”才平衡;更高阶矩描述“重量围绕支点如何分布”。

一阶矩(First Moment)回答“中心在哪里”:均值/期望 \(\mathbb{E}[X]\) 给出平衡点。但一阶矩无法刻画离散程度:例如 \(X\in\{-1,+1\}\) 与 \(X\in\{-10,+10\}\) 都满足 \(\mathbb{E}[X]=0\),但后者离中心更远。

二阶量用平方偏差的期望刻画离散程度:平方保证非负、避免正负偏差相互抵消,并对远离均值的样本赋予更大权重。在统计里,这对应二阶中心矩——方差 \(\mathrm{Var}(X)=\mathbb{E}[(X-\mathbb{E}[X])^2]\);在力学类比里,这与转动惯量(Moment of Inertia)中按 \(r^2\) 加权的直觉一致:远处的“重量”对系统的“难摆动/难转动”贡献更大。

二阶原点矩与方差之间满足恒等式:

\[\mathrm{Var}(X)=\mathbb{E}\big[(X-\mathbb{E}[X])^2\big]=\mathbb{E}[X^2]-\mathbb{E}[X]^2\] \[\mathbb{E}[X^2]=\mathrm{Var}(X)+\mathbb{E}[X]^2\]

它说明二阶原点矩 \(\mathbb{E}[X^2]\) 以 0 为参照,会把两类效应叠加在一起:一是分布整体离 0 的偏移(由均值项 \(\mathbb{E}[X]^2\) 表示),二是围绕自身均值的离散/抖动(由方差项 \(\mathrm{Var}(X)\) 表示)。因此 \(\mathbb{E}[X^2]\) 变大并不等价于“波动更大”;把所有取值整体平移一个常数,方差不变,但二阶原点矩会随偏移显著改变。

一个最小例子可以把差异看得非常清楚。令 \(X\) 等概率取值 \(\{99,100,101\}\),则

\[\mathbb{E}[X]=\frac{99+100+101}{3}=100,\quad \mathbb{E}[X]^2=100^2=10000\] \[\mathbb{E}[X^2]=\frac{99^2+100^2+101^2}{3}=\frac{30002}{3}\approx 10000.67\] \[\mathrm{Var}(X)=\mathbb{E}[X^2]-\mathbb{E}[X]^2=\frac{30002}{3}-10000=\frac{2}{3}\]

可以直接读成一句话:这组数“离 0 很远”(所以 \(\mathbb{E}[X^2]\) 很大),但“围绕自身均值很稳定”(所以方差很小)。

这也解释了 Adam 里的常见误解。Adam 说的“一阶矩/二阶矩”是把 mini-batch 梯度 \(g\) 当作随机变量,分别估计 \(\mathbb{E}[g]\) 与 \(\mathbb{E}[g^2]\)(逐参数维度)。它用的是二阶原点矩 \(\mathbb{E}[g^2]\),不是方差 \(\mathrm{Var}(g)\)。原因很直接:如果梯度在一段时间内几乎恒定(例如每步都是 \(g=10\)),那么方差为 0,拿它做除法会造成数值灾难;但 \(\mathbb{E}[g^2]=100\) 给出了稳定的“绝对尺度”,使更新项 \(\frac{\mathbb{E}[g]}{\sqrt{\mathbb{E}[g^2]}}\) 仍然是有界的(再加上 \(\epsilon\) 做数值稳定)。

方差

方差(Variance)衡量随机变量围绕均值的波动大小。它不是“偏离均值后再平均”,而是“偏离均值的平方再平均”;平方的作用是避免正负抵消,并放大大偏差:

\[\mathrm{Var}(X)=\mathbb{E}[(X-\mu)^2]\]

因此,方差小表示样本更集中在均值附近;方差大表示波动更强。它刻画的是“不确定性的尺度”,而不是取值本身的大小。例如两个模型的平均误差相同,方差更大的那个模型,输出往往更不稳定。

协方差

协方差(Covariance)描述两个变量是否倾向同向变化:

\[\mathrm{Cov}(X,Y)=\mathbb{E}[(X-\mu_X)(Y-\mu_Y)]\]

若 \(\mathrm{Cov}(X,Y)>0\),说明 \(X\) 大时 \(Y\) 也倾向变大;若 \(\mathrm{Cov}(X,Y)<0\),说明一个变大时另一个倾向变小。直觉例子是:身高与体重常为正协方差,室外温度与暖气功率常为负协方差。

还要区分一点:协方差为 0 不必然意味着独立。例如令 \(X\) 在 \(\{-1,1\}\) 上等概率取值,定义 \(Y=X^2\),则 \(Y\) 被 \(X\) 完全决定,但 \(\mathrm{Cov}(X,Y)=0\)。因此“零相关”比“独立”弱得多。

协方差矩阵(Covariance Matrix)\(\Sigma\) 在 AI 中极其关键:PCA、马氏距离(Mahalanobis Distance)、卡尔曼滤波与高斯模型都直接依赖它。它编码的是“各方向上的尺度”与“不同维度之间的耦合”。

标准差(Standard Deviation)

标准差(Standard Deviation)衡量数据相对均值(Mean)的离散程度(Dispersion)。总体标准差(Population Standard Deviation)定义为:

\[\sigma=\sqrt{\frac{1}{n}\sum_{i=1}^{n}(x_i-\mu)^2}\]

样本标准差(Sample Standard Deviation)使用贝塞尔校正(Bessel's Correction):

\[s=\sqrt{\frac{1}{n-1}\sum_{i=1}^{n}(x_i-\bar{x})^2}\]

先平方再平均是为了避免正负抵消并加重大偏差;最后开平方是为了把单位恢复到原始尺度。若直接用方差,单位会变成“平方单位”,解释往往不直观;标准差则可以直接说成“典型偏离均值大约多少个原始单位”。

例:数据 \(\{2,4,4,4,5,5,7,9\}\) 的均值是 \(5\),总体方差是 \(4\),标准差是 \(2\)。这意味着一个典型样本与均值的偏离量级大约是 2,而不是每个点都恰好偏 2。

标准差还常被用来做标准化(Standardization)。例如某考试分数 80 分,班级均值 70、标准差 5,则它的 z-score 是 \((80-70)/5=2\),表示它比均值高 2 个标准差。近似正态分布下,经验上约有 68% 样本落在 \(\mu\pm\sigma\),95% 落在 \(\mu\pm2\sigma\),99.7% 落在 \(\mu\pm3\sigma\);这就是常见的 68-95-99.7 规则。

最大似然估计(MLE)

最大似然估计(Maximum Likelihood Estimation, MLE)先把已经观察到的数据(例如上面抛硬币10次有8次正面)固定住,再在参数空间里寻找“最能生成这批数据”的参数。设数据集为 \(D=\{x_1,\dots,x_n\}\),参数为 \(\theta\),则定义是:

\[\hat{\theta}_{\mathrm{MLE}}=\arg\max_{\theta}p(D|\theta)\]

其中\(p(D|\theta)\) 是“参数取 \(\theta\) 时看到整批数据 \(D\) 的概率/密度”; \(\arg\max\) 表示“找出让这个值最大的那个参数”。

若样本独立同分布(不相关且在同一个分布,例如抛硬币中10个独立事件。Independent and Identically Distributed, i.i.d.),联合似然可以拆成单个样本似然的乘积:

\[p(D|\theta)=\prod_{i=1}^{n}p(x_i|\theta)\]

于是 MLE 常写成

\[\hat{\theta}_{\mathrm{MLE}}=\arg\max_{\theta}\prod_{i=1}^{n}p(x_i|\theta)\]

实际训练几乎总是改为最大化对数似然(Log-Likelihood):

\[\ell(\theta)=\log p(D|\theta)=\sum_{i=1}^{n}\log p(x_i|\theta)\]

取对数不会改变最优解,因为 \(\log\) 是单调递增函数;它只是把难处理的连乘变成易处理的求和。因此,最大化似然与最小化负对数似然(Negative Log-Likelihood, NLL)完全等价。

继续看抛硬币的例子。设单次结果 \(x_i\in\{0,1\}\),其中 1 表示正面,0 表示反面。设正面概率为 \(\theta\),那么单个样本就服从伯努利分布(Bernoulli Distribution)。它的概率质量函数(Probability Mass Function, PMF,用于描述离散随机变量,直接给出概率。对应概率密度函数PDF,给出给定连续随机变量对应位置的密度,因为连续,特定点的概率必须为0,只能密度和变量范围积分得到概率)写成:

\[p(x_i|\theta)=\theta^{x_i}(1-\theta)^{1-x_i},\quad x_i\in\{0,1\}\]

左边的 \(p(\cdot|\theta)\) 里的 \(p\) 是“概率分布/概率质量函数”的记号, \(\theta\) 是模型参数,也就是“正面概率”。很多教材会把参数也记成 \(p\),写成 \(p(x_i|p)\);这并不算错,因为参数本身就是一个概率,但两个 \(p\) 同时出现时很容易视觉混淆,所以这里改用 \(\theta\) 来区分“模型符号”和“参数符号”。

当 \(x_i=1\) 时,

\[p(x_i=1|\theta)=\theta^1(1-\theta)^0=\theta\]

当 \(x_i=0\) 时,

\[p(x_i=0|\theta)=\theta^0(1-\theta)^1=1-\theta\]

如果 10 次里看到 7 次正面、3 次反面,那么整批数据的似然就是:

\[p(D|\theta)=\theta^7(1-\theta)^3\]

对应的对数似然是

\[\ell(\theta)=7\log \theta+3\log(1-\theta)\]

plot-binomial-loglik

我们现在要最大化似然,需要对 \(\theta\) 求导并令导数为 0:

\[\frac{d\ell(\theta)}{d\theta}=\frac{7}{\theta}-\frac{3}{1-\theta}=0\Rightarrow \theta=0.7\]

所以 \(\hat{\theta}_{\mathrm{MLE}}=0.7\)。即“在所有候选 \(\theta\) 里, \(\theta=0.7\) 最能让 7 正 3 反这份数据显得不奇怪”。

在机器学习里,损失函数往往不是独立拍脑袋指定出来的,而是由概率建模假设(Probabilistic Modeling Assumption)诱导出来的。只要先写下观测数据在参数 \(\theta\) 下的概率模型,例如监督学习中的条件分布 \(p_\theta(y|x)\),或者更具体地写成“输出误差/观测噪声服从某种分布”,那么训练集上的负对数似然(Negative Log-Likelihood, NLL)就成为一个关于 \(\theta\) 的函数;当训练目标恰好选为这个 NLL 时,最小化损失就等价于最大化似然。

这也解释了常见损失函数为什么会有明确的概率来源。高斯噪声(Gaussian Noise)假设会导出平方误差(Squared Error);拉普拉斯噪声(Laplacian Noise)假设会导出绝对误差(Absolute Error);伯努利分布(Bernoulli)和类别分布(Categorical)假设会导出二分类或多分类交叉熵(Cross-Entropy)。因此,更严谨的说法是:给定数据生成分布假设后,训练集的负对数似然会诱导出相应的损失函数。

这里被评分的始终是已观测训练数据,而不是模型额外“生成出来”的一份预测样本。训练集中的 \((x_i,y_i)\) 已经固定,参数 \(\theta\) 才是变量;式子 \(p_\theta(y_i|x_i)\) 评估的是“在参数 \(\theta\) 下,真实观测到的 \(y_i\) 在给定 \(x_i\) 时是否足够合理”。在高斯回归这类模型里, \(f_\theta(x_i)\) 通常充当条件分布的均值或位置参数,残差 \(y_i-f_\theta(x_i)\) 则刻画观测值相对该中心的偏离;它并不是把模型预测值本身当成新的观测数据,而是在用模型输出来参数化观测数据的条件分布。

高斯分布的MLE

在监督回归(Supervised Regression)里,训练集通常写成 \(D=\{(x_i,y_i)\}_{i=1}^N\):其中 \(x_i\) 是已观测的输入特征,\(y_i\) 是已观测的(即训练集中的真实值)输出标签。机器学习里做 MLE 时,最常见的做法是把 \(x\) 当作给定条件,只为输出建模条件分布(Conditional Distribution)\(p_\theta(y|x)\),然后选参数 \(\theta\) 让“在这些 \(x_i\) 上看到 \(y_i\)”这件事尽可能不意外:

\[\hat\theta_{\mathrm{MLE}}=\arg\max_{\theta}\prod_{i=1}^{N}p_\theta(y_i|x_i)\]

注意这里的参数 \(\theta\) 不在 \(x_i\) 里,而是出现在假设函数\(f_\theta(x)\) 里。例如线性回归(Linear Regression)可写成 \(f_\theta(x)=\mathbf{w}^\top x+b\),其中 \(\theta=(\mathbf{w},b)\)。

“高斯噪声(Gaussian Noise)”在回归里指的是残差(Residual)服从高斯分布。具体假设是:

\[y_i=f_\theta(x_i)+\varepsilon_i,\quad \varepsilon_i\sim\mathcal{N}(0,\sigma^2)\ \text{i.i.d.}\]

等价写成条件分布:

\[y_i\,|\,x_i \sim \mathcal{N}(f_\theta(x_i),\sigma^2)\]

上式的意思是:在给定输入 \(x_i\) 的条件下,输出 \(y_i\) 不再被视为确定值,而被建模为随机变量,并且服从均值为 \(f_\theta(x_i)\)、方差为 \(\sigma^2\) 的一维高斯分布(Gaussian Distribution),当然,这里的不确定性就是模型引入的。根据高斯分布的概率密度公式,并结合 i.i.d. 假设(联合似然为逐样本似然的乘积),整批数据的似然为

\[p(D|\theta,\sigma^2)=\prod_{i=1}^{N}\frac{1}{\sqrt{2\pi\sigma^2}}\exp\left(-\frac{(y_i-f_\theta(x_i))^2}{2\sigma^2}\right)\]

取负对数似然(Negative Log-Likelihood, NLL)得到训练时真正被最小化的量:

\[-\log p(D|\theta,\sigma^2)=\frac{N}{2}\log(2\pi\sigma^2)+\frac{1}{2\sigma^2}\sum_{i=1}^{N}(y_i-f_\theta(x_i))^2\]

当 \(\sigma^2\) 视为常数时,第一项与 \(\theta\) 无关,因此最小化 NLL 关于 \(\theta\) 等价于最小化平方误差和(Sum of Squared Errors, SSE):

\[\hat\theta_{\mathrm{MLE}}=\arg\min_\theta\sum_{i=1}^{N}(y_i-f_\theta(x_i))^2\]

把残差(Residual)记为 \(r_i=y_i-f_\theta(x_i)\),则上式就是最小化 \(\sum_i r_i^2\)。因此,在“高斯噪声 + 固定方差”的回归假设下,最大化似然(等价最大化对数似然)就是最小化残差平方和。

这就是“最小二乘(Least Squares)”为什么会从概率建模里自然出现;均方误差(Mean Squared Error, MSE)只是把 SSE 再除以 \(N\),不改变最优解。

如果 \(\sigma^2\) 也未知,则 MLE 会同时估计 \((\theta,\sigma^2)\)。在固定 \(\theta\) 时,对 \(\sigma^2\) 的 MLE 为

\[\hat\sigma^2_{\mathrm{MLE}}=\frac{1}{N}\sum_{i=1}^{N}(y_i-f_\theta(x_i))^2\]

注意这里是 \(1/N\)(MLE),而不是无偏估计常用的 \(1/(N-1)\)。

顺带一提:把回归模型退化为“常数预测” \(f_\theta(x)\equiv \mu\),就回到“在高斯噪声下估计均值 \(\mu\)”,其 MLE 是样本均值。这也是很多教材先从 \(x_i=\mu+\varepsilon_i\) 入手的原因:那是回归的一个最小特例(此时 \(\theta=\mu\))。

最大后验估计(MAP)

最大后验估计(Maximum A Posteriori, MAP)在 MLE 的“数据解释能力”之外,再加入参数的先验(Prior)信息。它选择后验概率(Posterior)最大的参数:

\[\hat{\theta}_{\mathrm{MAP}}=\arg\max_{\theta}p(\theta|D)\]

根据贝叶斯定理:

\[p(\theta|D)=\frac{p(D|\theta)p(\theta)}{p(D)}\]

其中 \(p(D|\theta)\) 是似然(Likelihood), \(p(\theta)\) 是先验, \(p(D)\) 是证据(Evidence)。因为 \(p(D)\) 与参数 \(\theta\) 无关,所以在求最大值时它只是常数,可以直接忽略:

\[\hat{\theta}_{\mathrm{MAP}}=\arg\max_{\theta}p(D|\theta)p(\theta)=\arg\max_{\theta}\big(\log p(D|\theta)+\log p(\theta)\big)\]

这个式子清楚地说明了 MAP 的结构: \(\log p(D|\theta)\) 负责拟合数据, \(\log p(\theta)\) 负责约束参数不要偏离先验认知。若改写成最小化形式,则有

\[\hat{\theta}_{\mathrm{MAP}}=\arg\min_\theta\big(-\log p(D|\theta)-\log p(\theta)\big)\]

因此,MAP 可以理解为“负对数似然 + 先验诱导的惩罚项(Penalty)”。这也是为什么很多正则化(Regularization)能够从贝叶斯视角解释:L2 正则通常对应高斯先验,L1 正则通常对应拉普拉斯先验。若先验在可行域内与 \(\theta\) 无关(例如均匀先验: \(p(\theta)=c\)),则 \(\log p(\theta)=\log c\) 是关于 \(\theta\) 的常数;在 \(\arg\max_\theta\) 中加上或去掉这一项都不改变最优点,因此 MAP 与 MLE 给出同一组参数(若均匀先验还隐含“只在某个范围内为常数、范围外为 0”,则等价于在该范围约束下做 MLE)。

继续用抛硬币解释。现在参数已经统一记作 \(\theta\),因此先验也写成 \(p(\theta)\),而不再写 \(p(p)\)。若对 \(\theta\) 设 Beta 分布(Beta Distribution)先验

Beta 分布是定义在区间 \([0,1]\) 上的连续分布,最常用来描述“某个概率值本身的不确定性”,因此非常适合作为伯努利参数 \(\theta\) 的先验。

\[p(\theta)\propto \theta^{\alpha-1}(1-\theta)^{\beta-1},\quad 0\le \theta\le 1\]

这里 \(\propto\) 表示“正比于”,意思是左边真正的概率密度函数还差一个归一化常数(Normalization Constant),这个常数负责保证密度在区间 \([0,1]\) 上积分为 1。对 MAP 而言,这个常数不影响最大值位置,所以通常省略不写。

参数 \(\alpha\) 和 \(\beta\) 控制分布形状: \(\alpha\) 越大,分布越偏向较大的 \(\theta\); \(\beta\) 越大,分布越偏向较小的 \(\theta\)。例如 \(\mathrm{Beta}(2,2)\) 会把概率质量更多放在中间区域,表达“更倾向认为硬币接近公平”; \(\mathrm{Beta}(8,2)\) 则更偏向 \(\theta\) 接近 1。

那么它表达的是:在看到数据之前,我们已经对“硬币正面概率应该落在什么范围”有一个先验偏好。

把这个先验与 7 正 3 反的似然 \(p(D|\theta)=\theta^7(1-\theta)^3\) 相乘,得到后验:

\[p(\theta|D)\propto \theta^{7+\alpha-1}(1-\theta)^{3+\beta-1}\]

这说明后验仍然是 Beta 分布:

\[p(\theta|D)=\mathrm{Beta}(7+\alpha,3+\beta)\]

众数(Mode)指的是概率密度函数最高的那个位置,也就是“这个分布最偏好的参数值”。因为 MAP 的定义本来就是寻找后验概率/后验密度最大的参数,所以当后验分布已经写出来时,MAP 估计就是这个后验分布的众数。

因为后验与 \(\theta^{7+\alpha-1}(1-\theta)^{3+\beta-1}\) 成正比,所以只需最大化这个函数。取对数后,等价目标变成

\[(7+\alpha-1)\log \theta+(3+\beta-1)\log(1-\theta)\]

对 \(\theta\) 求导并令导数为 0:

\[\frac{7+\alpha-1}{\theta}-\frac{3+\beta-1}{1-\theta}=0\]

移项并整理可得

\[(7+\alpha-1)(1-\theta)=(3+\beta-1)\theta\Rightarrow \hat{\theta}_{\mathrm{MAP}}=\frac{7+\alpha-1}{10+\alpha+\beta-2}\]

因此,当 \(\alpha,\beta>1\) 时,Beta 分布的众数(Mode)也就是 MAP 估计。

若取 \(\mathrm{Beta}(2,2)\) 先验,则

\[\hat{\theta}_{\mathrm{MAP}}=\frac{7+2-1}{10+2+2-2}=\frac{8}{12}=\frac{2}{3}\]

它比 MLE 的 \(0.7\) 更靠近 \(0.5\)。原因很具体: \(\mathrm{Beta}(2,2)\) 可以理解为在真实观测之外,先额外放入了“1 次正面 + 1 次反面”的温和偏好,所以最终估计不会被7正3反的样本完全带着走。样本很少时,先验的影响明显;样本很多时,数据项占主导,MAP 会逐渐逼近 MLE。

在机器学习里,MAP 与正则化(Regularization)本质上是同一件事的两种表述。不是“随意加一个惩罚项”,而是:一旦你给参数指定先验,取负对数后,这个先验就会自动变成优化目标里的正则项。

先看一般形式。MAP 最大化的是后验概率 \(p(\theta|D)\),等价于最小化负对数后验:

\[-\log p(\theta|D)=-\log p(D|\theta)-\log p(\theta)+\mathrm{const}\]

第一项 \(-\log p(D|\theta)\) 是数据拟合项,第二项 \(-\log p(\theta)\) 就是先验带来的惩罚项。因此“正则化”并不是凭空发明出来的工程技巧,而是贝叶斯先验在优化问题里的直接体现。

若参数向量 \(\theta\) 服从零均值各向同性高斯先验(Isotropic Gaussian Prior),可以写成

\[p(\theta)\propto \exp\left(-\frac{1}{2\tau^2}\|\theta\|_2^2\right)\]

这里 \(\tau^2\) 控制先验方差:方差越小,越强地偏好参数靠近 0。对它取负对数得到

\[-\log p(\theta)=\frac{1}{2\tau^2}\|\theta\|_2^2+\mathrm{const}\]

把常数 \(\frac{1}{2\tau^2}\) 记成 \(\lambda\),就得到熟悉的目标:

\[-\log p(D|\theta)+\lambda\|\theta\|_2^2\]

这正是 \(L_2\) 正则。它的作用可以理解为:先验认为“大权重不太可信”,所以优化时不仅要拟合数据,还要为过大的参数付出代价。由于高斯先验在 0 附近平滑、尾部衰减快,它通常会把参数整体压小,但不特别鼓励大量参数精确等于 0。

若先验改成拉普拉斯(Laplacian)分布:

\[p(\theta)\propto \exp\big(-\lambda\|\theta\|_1\big)\]

则负对数先验变成

\[-\log p(\theta)=\lambda\|\theta\|_1+\mathrm{const}\]

于是 MAP 等价于最小化

\[-\log p(D|\theta)+\lambda\|\theta\|_1\]

这就是 \(L_1\) 正则。它与 \(L_2\) 的关键区别在于:拉普拉斯先验在 0 处尖得更厉害,因此更强地偏好很多参数直接变成 0,也就是产生稀疏性(Sparsity)。

所以可以把对应关系记成一条很清楚的链:高斯先验对应 \(L_2\),拉普拉斯先验对应 \(L_1\);正则项的形状,本质上就是先验密度形状的负对数。很多看起来像“人为添加的惩罚项”,其实都可以解释为“在做 MAP”。

regularization-distribution-assumptions

这里的分布假设有两个不同落点。若假设的是数据误差或残差 \(\epsilon\) 的分布,它进入的是似然 \(p(D|\theta)\),决定数据拟合项的形状;若假设的是参数 \(\theta\) 自身的分布,它进入的是先验 \(p(\theta)\),决定正则项的形状。前者回答“数据会怎样围绕模型波动”,后者回答“参数本身更可能落在什么区域”。

因此,高斯和拉普拉斯并不只用于描述数据集。高斯残差假设会把负对数似然化成平方误差,拉普拉斯残差假设会把负对数似然化成绝对误差;与此同时,零均值高斯参数先验会把负对数先验化成 \(L_2\) 正则,零均值拉普拉斯参数先验会把负对数先验化成 \(L_1\) 正则。它们使用的是同一类分布族,但一个作用在数据项 \(p(D|\theta)\),一个作用在参数项 \(p(\theta)\)。

大数定律与中心极限定理
大数定律(Law of Large Numbers, LLN)

大数定律说明:当独立同分布样本越来越多时,样本平均会稳定地靠近真实期望(Expectation)。若 \(X_1,\dots,X_n\) 独立同分布,且 \(\mathbb{E}[X]\) 存在,则

\[\frac{1}{n}\sum_{i=1}^{n}X_i \to \mathbb{E}[X],\quad n\to\infty\]

这里的重点是“平均值会稳定下来”,而不是“每一次新观测都会让结果更接近真值”。它描述的是长期趋势:样本量越大,随机波动在平均过程中被不断抵消,样本平均就越不容易偏离真实期望太远。

最经典的例子是抛公平硬币。设正面记为 1、反面记为 0,则单次试验的期望是 \(\mathbb{E}[X]=0.5\)。前几次抛掷时,正面比例可能是 1、0、0.67、0.25,波动很大;但抛掷次数达到几百、几千次后,样本平均 \(\bar{X}\) 会越来越稳定地靠近 0.5。大数定律回答的是“为什么频率会稳定到概率附近”。

中心极限定理(Central Limit Theorem, CLT)

中心极限定理讨论的不是“均值会不会收敛”,而是样本均值在真值附近如何波动,以及这种波动的分布长什么样。在独立同分布且方差有限的条件下,标准化后的样本均值近似服从均值为 0、方差为 1 的正态分布:

\[\frac{\sqrt{n}(\bar{X}-\mu)}{\sigma}\Rightarrow \mathcal{N}(0,1)\]

这里 \(\mu=\mathbb{E}[X]\) 是总体均值, \(\sigma^2=\mathrm{Var}(X)\) 是总体方差。所谓标准化(Standardization),就是先减去均值 \(\mu\),把中心移到 0;再除以标准差 \(\sigma\),把尺度统一成“多少个标准差”;再乘上 \(\sqrt{n}\),把样本均值随着样本量增大而缩小的波动重新放回可比较的尺度。标准化之后,不同样本量下的波动可以放到同一个参考系里比较。

所谓方差有限,就是随机变量的波动强度不是无限大,满足 \(\mathrm{Var}(X)<\infty\)。直观上,这意味着样本虽然会波动,但不会被极端值以“无限强”的方式主导。像伯努利分布、二项分布、泊松分布、均匀分布和高斯分布都满足这个条件;而某些重尾分布则可能不满足,因此不能直接套用最基础的 CLT 表述。

为什么要乘上 \(\sqrt{n}\)?因为样本均值的波动规模大约是 \(\sigma/\sqrt{n}\):样本越多,均值越稳定。如果不乘 \(\sqrt{n}\),当 \(n\) 增大时, \(\bar{X}-\mu\) 会越来越接近 0,看不出其分布形状;乘上 \(\sqrt{n}\) 后,波动被拉回到常数量级,才会显现出稳定的正态极限。

继续看硬币例子。设 \(X_i\in\{0,1\}\) 且正面概率为 0.5,则 \(\mu=0.5\), \(\sigma^2=0.25\),标准差 \(\sigma=0.5\)。CLT 说的是:

\[\frac{\sqrt{n}(\bar{X}-0.5)}{0.5}\Rightarrow \mathcal{N}(0,1)\]

例如当 \(n=100\) 时,正面比例 \(\bar{X}\) 的标准差大约是 \(0.5/\sqrt{100}=0.05\)。这意味着正面比例通常会落在 \(0.5\pm 0.1\) 这一量级附近;更精确地,用正态近似可写成

\[\bar{X}\approx \mathcal{N}\left(0.5,\frac{0.25}{100}\right)=\mathcal{N}(0.5,0.0025)\]

plot-clt

上图是样本量分别为1, 5, 20, 100的Bernoulli(0.5)分布,分别进行了30000轮测试,绘制的(每轮)标准化后的分布,可以看到样本量足够多时,其均值倾向于向中心(未标准化前的0.5对应此伯努利分布的总体均值)靠近。

所以 CLT 回答的是“为什么很多统计量在样本足够大时会近似高斯”,而 LLN 回答的是“为什么样本平均会逼近真值”。前者给出分布近似,后者给出收敛结论。置信区间、显著性检验、A/B test 和 mini-batch 梯度噪声分析,主要依赖的是 CLT 提供的近似正态性。

置信度与置信区间

置信度(Confidence Level)与置信区间(Confidence Interval)属于统计推断(Statistical Inference)中的区间估计(Interval Estimation)。它们处理的不是“样本本身长什么样”,而是在只看到一批有限样本时,怎样给未知总体参数画出一个有覆盖保证的范围。在机器学习实验、A/B test、离线评测和指标报表里,样本均值、准确率、点击率、转化率和误差率后面常跟着一个区间,这个区间就是区间估计的产物。

若目标是估计总体均值 \(\mu\),样本均值为 \(\bar{X}\),且样本量足够大或总体近似正态,那么基于中心极限定理,可以构造近似的双侧置信区间:

\[\bar{X}\pm z_{1-\alpha/2}\frac{\sigma}{\sqrt{n}}\]

若总体标准差 \(\sigma\) 未知,而样本来自正态总体或样本量适中且使用样本标准差 \(s\) 近似,则常写作:

\[\bar{X}\pm t_{1-\alpha/2,\,n-1}\frac{s}{\sqrt{n}}\]

这里每个元素的含义分别是:

  • \(\bar{X}\):样本均值(Sample Mean),是当前样本对总体均值的点估计(Point Estimate)。
  • \(n\):样本量(Sample Size)。样本越多,区间通常越窄。
  • \(\sigma\):总体标准差(Population Standard Deviation);若未知,常用样本标准差 \(s\) 替代。
  • \(\frac{\sigma}{\sqrt{n}}\) 或 \(\frac{s}{\sqrt{n}}\):标准误(Standard Error),表示样本均值本身的波动尺度,而不是单个样本点的波动。
  • \(\alpha\):显著性水平(Significance Level)。若置信度为 95%,则 \(\alpha=0.05\)。
  • \(z_{1-\alpha/2}\):标准正态分布的分位数(Quantile);95% 置信度时大约是 \(1.96\)。
  • \(t_{1-\alpha/2,\,n-1}\):Student t 分布的分位数,带有 \(n-1\) 个自由度(Degrees of Freedom),用于总体方差未知时。

在这个表达式里,置信区间 指的是最终得到的区间本身,例如 \([1.8,2.4]\);置信度 指的是构造这个区间的方法在重复抽样下的长期覆盖率,例如 95%、99%。因此,95% 置信区间的严格含义是:如果用同一种抽样方式和同一种区间构造公式反复重复实验,那么大约 95% 的区间会覆盖真实参数。

这一定义有一个极其重要的解释边界。总体参数 \(\mu\) 在经典频率学派(Frequentist)统计里被视为固定但未知的常数;随机的是样本,因此随机的是区间端点。样本一旦观察完成,这次得到的区间要么覆盖 \(\mu\),要么不覆盖,概率意义已经不再施加在参数本身上。于是,95% 置信度描述的是区间构造程序的长期可靠性,而不是“参数有 95% 概率落在这次区间里”的后验概率表述。

置信度并不局限于连续分布。它的定义依赖的是“重复抽样下的覆盖率”,而不是总体分布是否连续。对伯努利分布(Bernoulli Distribution)、二项分布(Binomial Distribution)、泊松分布(Poisson Distribution)这类离散分布,同样可以对参数构造 95% 或 99% 的区间估计。例如对二项分布中的成功概率 \(p\),就可以根据观测到的成功次数构造 \(p\) 的置信区间;若参数或目标对象不是一维连续量,更宽泛的名称则是置信集合(Confidence Set)。

离散分布与连续分布的差别不在“能不能谈置信度”,而在于区间构造的细节。连续情形下,区间端点可以较平滑地调节到目标覆盖率附近;离散情形下,统计量只能取离散值,覆盖率往往无法恰好等于名义值,例如正好 95%,而常常只能做到“不低于 95%”。因此,离散分布里的精确区间常带有一定保守性(Conservativeness):区间更宽一些,但覆盖保证更稳。这也是为什么在离散统计推断里,除了近似正态区间外,还常见 Clopper–Pearson 这类精确区间构造方法。

一个具体例子最容易说明这两个概念。设某模型在 100 次独立测试中的平均准确率估计为 \(\bar{X}=0.82\),样本标准差为 \(s=0.10\)。若采用近似 95% 置信区间,可写成:

\[0.82\pm 1.96\times \frac{0.10}{\sqrt{100}}=0.82\pm 0.0196\]

于是区间约为:

\[[0.8004,\ 0.8396]\]

这里 \([0.8004,0.8396]\) 是置信区间,95% 是置信度。它表示:按这种抽样和构造方式长期重复下去,约 95% 的此类区间会覆盖真实平均准确率;这次具体得到的这个区间只是其中一个实现结果。

区间宽度主要由三个因素共同决定:

  • 样本波动越大,即 \(\sigma\) 或 \(s\) 越大,区间越宽。
  • 样本量越大,即 \(n\) 越大,标准误越小,区间越窄。
  • 置信度越高,例如从 95% 提高到 99%,对应分位数更大,区间也会变宽。

因此,置信区间不是“模型不确定性的一个装饰性数字”,而是在样本有限时对参数估计可靠性的定量表达;而置信度则是这套区间构造方法愿意给出的覆盖承诺。两者必须一起理解:只有区间没有置信度,范围没有统计保证;只有置信度没有区间,覆盖承诺也无法落到具体参数估计上。

随机过程

前面讨论的随机变量(Random Variable)通常只对应一次不确定试验,例如抛一次硬币、测一次身高、抽取一个样本标签。随机过程(Stochastic Process)则讨论一串彼此有关、按时间或空间索引起来的随机变量。它适合描述会随时间演化的不确定系统,例如天气变化、股价波动、队列长度、用户行为序列、传感器读数,以及自然语言中的 token 序列。

形式上,随机过程可记为:

\[\{X_t\}_{t\in T}\]

这里 \(T\) 是索引集合(Index Set),常表示时间; \(X_t\) 是时刻 \(t\) 的随机变量。若 \(T=\{0,1,2,\dots\}\),过程是离散时间(Discrete-time)的;若 \(T=[0,\infty)\),过程则是连续时间(Continuous-time)的。每个 \(X_t\) 都有自己的分布,但更重要的是这些随机变量之间的联合分布(Joint Distribution)与依赖结构,因为随机过程关心的不是“某一时刻单独会怎样”,而是“整个序列怎样一起变化”。

从结果形态看,一次随机过程的实现不再是一个点,而是一条轨迹(Trajectory)或样本路径(Sample Path)。例如,设 \(X_t\) 表示第 \(t\) 天的气温,那么一次观测得到的是一整段温度序列 \((X_1,X_2,\dots,X_T)\);若 \(X_t\) 表示语言模型在位置 \(t\) 生成的 token,那么一次实现就是一整句文本。

随机过程之所以在机器学习里重要,是因为很多任务天生就是时序问题。时间序列预测关心未来值如何演化,隐马尔可夫模型(Hidden Markov Model, HMM)关心隐藏状态如何随时间转移,强化学习关心状态—动作—奖励序列怎样展开,自回归语言模型则是在建模 token 序列的联合概率。因此,随机过程可以看作“把单个随机变量扩展到整条时间轴上的概率建模语言”。

马尔可夫性与马尔可夫过程

马尔可夫性(Markov Property)讨论的是随机过程中的“记忆如何被压缩”。它刻画这样一种情形:如果当前状态已经把与未来演化有关的信息概括完整,那么预测下一步时就不再需要显式回看更久的历史。在这种表示下,过去对未来的影响已经通过当前状态被浓缩进来了。

设随机过程为 \(\{X_t\}_{t=0}^{\infty}\),其中 \(X_t\) 表示时刻 \(t\) 的随机状态。若它满足一阶马尔可夫性,则有:

\[P(X_{t+1}\mid X_t,X_{t-1},\dots,X_0)=P(X_{t+1}\mid X_t)\]

这条式子的含义是:在已经知道当前状态 \(X_t\) 的前提下,再额外知道更早的历史 \(X_{t-1},\dots,X_0\),不会改变对下一时刻 \(X_{t+1}\) 的条件分布判断。左边是“条件在完整历史上的下一步分布”,右边是“条件在当前状态上的下一步分布”;两者相等,正是马尔可夫性的定义。

一个直接例子是天气变化。若把每天的天气记作随机变量 \(X_t\),状态空间为 \(\{\text{晴},\text{阴},\text{雨}\}\),那么常见建模假设是:明天是否下雨主要由今天的天气决定,而不需要把更早几天的天气逐项保留。此时“当前天气”就扮演了压缩历史信息的状态摘要。若今天是雨天,明天继续下雨的概率可以较大;若今天是晴天,明天下雨的概率可以较小。这种“只通过当前状态决定下一步分布”的结构,就是马尔可夫性。

满足马尔可夫性的随机过程,称为马尔可夫过程(Markov Process)或马尔可夫链(Markov Chain,离散时间、有限或可数状态时的常见名称)。因此,马尔可夫性是一个性质,马尔可夫过程是满足该性质的一类随机过程。若状态空间有限,常把一步转移概率写成转移矩阵(Transition Matrix) \(P\),其中:

\[P_{ij}=P(X_{t+1}=j\mid X_t=i)\]

这里 \(P_{ij}\) 表示“当前在状态 \(i\) 时,下一步转移到状态 \(j\) 的概率”。矩阵的每一行对应当前状态固定后的下一步分布,因此每一行元素都非负,且行和为 1。

马尔可夫过程之所以重要,是因为它把一个潜在上非常复杂的时序依赖问题,压缩成了局部转移规律。隐马尔可夫模型(Hidden Markov Model, HMM)、马尔可夫决策过程(Markov Decision Process, MDP)、很多时间序列状态模型,以及强化学习中的环境状态转移,都建立在这一思想之上。它们的差别不在于是否使用马尔可夫性,而在于:状态是否可见、是否存在动作、是否附带奖励,以及是否只关心下一步还是关心长期回报。

马尔可夫性是一种建模假设,不是自然界自动保证的真理。若“当前状态”定义得不充分,历史信息就没有被真正压缩进去,此时过程在这个状态表示下就不具有马尔可夫性。例如,仅用“当前股价”预测明天走势通常不够,因为成交量、市场情绪、宏观事件等信息并未包含在状态中;但若把更完整的市场状态向量一并纳入,马尔可夫近似会更合理。因此,马尔可夫性的关键不只是公式,而是当前状态是否足以成为过去对未来影响的充分摘要。

信息论
熵(Entropy)

熵(Entropy)刻画一个概率分布的不确定性(Uncertainty)。对离散分布 \(p\):

\[H(p)=-\sum_i p_i\log p_i\]

把 \(-\log p(x)\) 理解为“事件 \(x\) 的信息量(Information Content)/惊奇”,熵就是它的期望值:越均匀的分布越难预测,熵越大;越尖锐(某个事件概率接近 1)的分布越确定,熵越小。

例:若 \(p\) 在 \(K\) 个类别上均匀(\(p_i=1/K\)),则

\[H(p)=\log K\]

对数底决定单位:以 \(\log_2\) 为底单位是比特(Bits),以自然对数为底单位是纳特(Nats)。

语言也能帮助建立对熵的直觉。以字符为单位时,汉字集合更大,单个常用字符的平均出现概率往往更低,因此 \(-\log p(x)\) 更大;同时,汉语序列里的下一字符通常也更难直接预测,所以常给人“字符级信息更密、熵更高”的直觉。对比之下,韩语的字符系统更小,序列模式也通常更规则,下一字符更容易预测,因此字符级冗余感更强、熵的直觉更低。

若再做一个极粗略的字符级估算:把常用汉字集合近似看作 \(V=3000\)、把韩文字母集合近似看作 \(V=40\),并暂时假设“下一字符”在各自词表上均匀分布,则最大熵分别约为 \(\log_2 3000\approx 11.55\) bits 与 \(\log_2 40\approx 5.32\) bits。这对应的就是:词表越大、单符号平均概率越低,单位符号的潜在信息量上界越高。

KL 散度

KL 散度(Kullback–Leibler Divergence)衡量两个分布之间的“相对熵”(Relative Entropy)。对离散分布 \(p,q\):

\[D_{\mathrm{KL}}(p\|q)=\sum_i p_i\log\frac{p_i}{q_i}\]

它满足 \(D_{\mathrm{KL}}(p\|q)\ge 0\),且当且仅当 \(p=q\) 时取 0;但它一般不对称(Asymmetric),即 \(D_{\mathrm{KL}}(p\|q)\ne D_{\mathrm{KL}}(q\|p)\)。信息论解释是:用 \(q\) 的码本去编码来自 \(p\) 的样本,会额外多付出多少平均码长。

在机器学习里,KL 常作为正则项出现,例如把新策略/新模型约束在参考分布附近(KL Regularization)。

交叉熵

交叉熵(Cross Entropy)是信息论里衡量“用分布 \(q\) 去编码来自分布 \(p\) 的样本”所需平均信息量的量。这里 \(p\) 是真实分布(True Distribution)/数据分布, \(q\) 是模型分布(Model Distribution)/预测分布:

\[H(p,q)=-\sum_{i} p_i\log q_i\]

当 \(p\) 固定时,最小化 \(H(p,q)\) 等价于最小化 KL 散度(Kullback–Leibler Divergence):

\[H(p,q)=H(p)+D_{\mathrm{KL}}(p\|q)\]

分类问题里,真实标签通常用 one-hot 分布表示,这会把交叉熵简化成对“真实类别概率”的负对数:交叉熵损失(Cross-Entropy Loss)本质上就是负对数似然(Negative Log-Likelihood)。

“信息量为什么和概率有关?”因为在最优编码(Optimal Coding)里,一个事件 \(x\) 的最短平均码长与 \(-\log p(x)\) 同阶;以 \(\log_2\) 为底时单位是比特(Bits),以自然对数为底时单位是纳特(Nats)。熵(Entropy)就是期望信息量。

一个具体例子:设真实分布 \(p=(0.5,0.5)\),模型分布 \(q=(0.9,0.1)\),则

\[H(p,q)=-0.5\log 0.9-0.5\log 0.1\approx 1.204\ (\text{nats})\]

而真实熵 \(H(p)=-0.5\log 0.5-0.5\log 0.5\approx 0.693\),两者的差就是 \(D_{\mathrm{KL}}(p\|q)\approx 0.511\):模型越“错得自信”,KL 越大:

plot_entropy_cross

惊奇(Surprise)

惊奇(Surprise)/信息量是针对单个事件的度量:若事件 \(x\) 的概率为 \(p(x)\),则

\[\mathrm{Surprise}(x)=-\log p(x)\]

概率越小,惊奇越大;概率越大,惊奇越小。在语言建模里,若当前模型参数已经固定,那么真实 token 的 \(-\log p_\theta(y_t|c_t)\) 本质上是该 token 的负对数概率,也就是它的“惊奇”。这里 \(c_t\) 表示当前位置之前的上下文, \(y_t\) 表示当前位置真实出现的 token。若把同一个式子看成关于参数 \(\theta\) 的函数,它又是该 token 对参数的负对数似然(Negative Log-Likelihood, NLL)。因此这里的“惊奇”和 token-level NLL 在数值上是同一个对象,只是视角不同。如果再按各个事件的真实概率对这种“惊奇”做加权平均,得到的就是熵(Entropy):\(H(X)=\mathbb{E}[-\log p(X)]\)。换句话说,惊奇是单个事件的信息量,熵是这种信息量在整个分布下的期望。

困惑度(Perplexity)

困惑度(Perplexity)把“平均惊奇”指数化,得到一个更直观的尺度:可把它理解为模型在每一步预测时的“有效分支数(Effective Branching Factor)”。对长度为 \(N\) 的 token 序列,模型给出的条件概率是 \(q(x_t|x_{<t})\),则平均 NLL(也就是交叉熵)为:

\[\mathrm{NLL}=-\frac{1}{N}\sum_{t=1}^{N}\log q(x_t|x_{<t})\]

若使用自然对数,困惑度定义为:

\[\mathrm{PPL}=\exp(\mathrm{NLL})\]

因此:分布越均匀(更不确定),熵越高,平均惊奇越大,困惑度也越高。注意困惑度强烈依赖 tokenization 与评测语料,跨不同分词器/词表直接比较往往没有意义。

常用算法
基础数据结构和算法

这一节处理的核心问题是:当面对搜索、更新、统计、调度、最短路径、依赖分析或训练流水线等任务时,数据应该怎样组织,操作应该怎样执行,才能既正确又高效。数据结构(Data Structure)决定“数据在内存里如何表示”,算法(Algorithm)决定“在这种表示上如何完成查询、插入、删除、遍历、排序与优化”。很多系统性能问题,本质上不是算力不足,而是底层组织方式与操作方式不匹配。

可以把它理解成“仓库布局与搬运规则”的组合:同样一批货物,若排成连续货架、串成链式节点、组织成树状目录,或连接成路网,后续的查找、插入、合并与运输成本会完全不同。现代 AI 工程虽然把注意力集中在模型上,但数据加载器、特征流水线、参数缓存、向量检索、计算图调度、图学习和索引系统,最终都建立在这些基础结构之上。

结构 / 算法 核心能力 典型复杂度 常见场景
数组 / 动态数组 按下标随机访问;顺序扫描效率高 访问 \(O(1)\);中间插入/删除 \(O(n)\) 张量、批数据、embedding、排序、滑动窗口
链表 已知位置后插入/删除代价低 局部插删 \(O(1)\);查找 \(O(n)\) LRU、任务拼接、频繁重排的序列
栈(Stack) 后进先出(LIFO) push / pop / top 均为 \(O(1)\) 递归展开、表达式解析、单调栈
队列(Queue) 先进先出(FIFO) enqueue / dequeue 均为 \(O(1)\) BFS、任务队列、流式缓冲
哈希表(Hash Table) 按键快速索引 平均查找/插入/删除 \(O(1)\) 字典、词表、缓存、去重
Bloom Filter 近似集合成员查询 插入/查询均为 \(O(k)\) 缓存预检查、去重预过滤、存储层键存在性判断
树(Tree) 表达层次关系与有序结构 平衡查找常为 \(O(\log n)\) 索引、优先队列、前缀匹配、规则分裂
图(Graph) 表达任意对象之间的关系 遍历通常为 \(O(|V|+|E|)\) 社交网络、知识图谱、路线规划、依赖分析

复杂度表只给出渐近上界,不能直接替代工程判断。真实系统还要同时考虑缓存友好性(Cache Locality)、常数项、并发开销、内存占用和实现复杂度。例如链表在理论上支持常数时间插入,但它对 CPU 缓存并不友好;数组在理论上中间插入较慢,但顺序扫描极快,因此在现代硬件上经常更有优势。

数组与动态数组

数组(Array)处理的核心问题是:当元素类型一致、数量可以按顺序编号时,如何支持最低成本的随机访问与批量扫描。它的关键性质是连续内存(Contiguous Memory)。若每个元素大小为 \(s\),首地址为 \(\text{base}\),则第 \(i\) 个元素地址为

\[\text{addr}(a_i)=\text{base}+i\cdot s\]

这个式子说明数组访问为何是 \(O(1)\):位置可以直接计算,不需要沿指针逐步跳转。矩阵、张量、mini-batch、时间序列缓存、本地特征块和 embedding 表中的一行,本质上都依赖这种“地址可算”的结构。

数组的代价也非常明确:若在中间插入或删除元素,后面的元素必须整体搬移,因此复杂度通常是 \(O(n)\)。这意味着数组适合“读多写少、顺序稳定”的任务,不适合“在任意位置频繁插入”的任务。

动态数组(Dynamic Array)是在数组上的工程扩展:容量不足时申请更大的连续空间,把原有元素整体拷贝过去,再继续追加。一次扩容代价很高,但若容量按倍数增长,则追加操作的均摊(Amortized)复杂度仍可视为 \(O(1)\)。Python 的 list、C++ 的 vector、Java 的 ArrayList 都遵循这一思想。

直觉上,数组像按编号排好的货架:拿第 137 件货非常快,但若要把一件货塞进中间,后面整排货物都要整体后移。

链表

链表(Linked List)处理的是另一类问题:当序列顺序经常变化时,能否避免数组那样的大规模搬移。链表不要求连续内存,而是让每个节点(Node)保存数据和指向下一个节点的指针(Pointer);双向链表(Doubly Linked List)还会额外保存前驱指针。

若已经拿到某个节点的位置,那么在其前后插入或删除节点只需要调整局部指针,代价通常是 \(O(1)\)。但链表无法像数组那样通过下标直接定位第 \(i\) 个元素,查找往往必须从头逐个走过去,因此通常是 \(O(n)\)。

链表适合做“结构改动频繁、定位方式不是按下标而是按已有节点句柄”的任务。例如 LRU 缓存中,经常需要把刚访问的元素移到头部;若配合哈希表记录节点位置,链表就能高效完成重排。

链表像一串用绳子串起来的标签。改顺序很方便,但想直接摸到第 500 个标签,就只能沿着绳子一个个数过去。

栈(Stack)

栈(Stack)定义的是一种后进先出(Last In First Out, LIFO)的访问约束。它处理的问题不是“怎样存更多数据”,而是“怎样强制最近进入的状态最先退出”。典型操作包括入栈 push、出栈 pop 与查看栈顶 top,它们都发生在同一端,因此实现代价通常是 \(O(1)\)。

函数调用栈、递归回溯、表达式求值、括号匹配、深度优先搜索中的显式状态保存,都依赖这种结构。其本质是把“尚未处理完的上下文”按嵌套顺序压起来,等内部任务结束后再按相反顺序恢复。

单调栈(Monotonic Stack)是栈在算法中的重要变体。它通过维护一个单调递增或单调递减的栈,把“下一个更大元素”“柱状图最大矩形”等问题从 \(O(n^2)\) 降到 \(O(n)\)。原因在于每个元素最多入栈和出栈各一次。

队列(Queue)

队列(Queue)定义的是先进先出(First In First Out, FIFO)的访问约束。进入得早的元素先被处理,后来进入的元素排在尾部等待。它适合表达“任务排队、波前扩张、按到达顺序消费”的过程。

广度优先搜索(Breadth-First Search, BFS)之所以使用队列,正是因为 BFS 要按距离层层扩展:先处理距离起点为 1 的节点,再处理距离为 2 的节点。这个“分层推进”机制与 FIFO 完全一致。

循环队列(Circular Queue)通过把底层数组首尾相连,可以避免频繁搬移;双端队列(Deque)则允许两端都做插入和删除,因此能够支持滑动窗口最值、0-1 BFS 等更复杂的算法模式。

哈希表(Hash Table)

哈希表(Hash Table)处理的核心问题是:当数据按“键(Key)”组织,而不是按位置组织时,如何快速找到对应的值(Value)。其思想是先通过哈希函数(Hash Function)把键映射成一个整数,再把这个整数映射到桶(Bucket)或槽位(Slot)上。

若哈希函数分布均匀,且装载因子(Load Factor)控制合理,则查找、插入和删除的平均复杂度都可接近 \(O(1)\)。这正是词表映射、去重、缓存索引、参数名字典和特征 ID 映射大量采用哈希表的原因。

哈希表的难点在冲突(Collision)处理。多个键可能映射到同一位置,常见解决方案包括链地址法(Separate Chaining)和开放定址法(Open Addressing)。因此“哈希表平均 \(O(1)\)”并不意味着永远常数时间,它依赖于哈希函数质量、负载控制和冲突处理策略。

Bloom Filter(布隆过滤器)

Bloom Filter 本质上属于概率型数据结构(Probabilistic Data Structure),更准确地说,是一种近似集合成员查询结构(Approximate Membership Query, AMQ)。它解决的问题并不是“把元素精确存下来”,而是“用极小内存快速判断某元素是否可能出现过”。因此它通常作为哈希表、数据库索引或缓存系统之前的一层预过滤结构。

Bloom Filter 由一个长度为 \(m\) 的比特数组 \(B\in\{0,1\}^m\) 和 \(k\) 个哈希函数 \(h_1,\dots,h_k\) 构成,其中每个哈希函数都把元素 \(x\) 映射到区间 \(\{0,1,\dots,m-1\}\) 中的一个位置。插入元素 \(x\) 时,执行

\[B[h_1(x)]=B[h_2(x)]=\cdots=B[h_k(x)]=1\]

查询元素 \(x\) 时,检查 \(B[h_1(x)],\dots,B[h_k(x)]\)。只要其中至少有一个位置为 0,就可以断定 \(x\) 一定不在集合中;若这些位置全部为 1,则只能说明 \(x\) 可能在集合中。

这一定义直接带来 Bloom Filter 最重要的判定性质:它允许假阳性(False Positive),但不允许假阴性(False Negative)。原因在于,不同元素可能把同一批 bit 位置反复置为 1,于是一个从未插入过的元素也可能“碰巧”命中全 1;但只要某个位置仍为 0,就说明没有任何已插入元素覆盖过这条哈希路径,因此该元素一定不存在。

设一共插入了 \(n\) 个元素,则某个 bit 在所有插入结束后仍为 0 的概率近似为 \(\left(1-\frac{1}{m}\right)^{kn}\approx e^{-kn/m}\)。于是查询一个未出现元素时, \(k\) 个位置恰好都为 1 的假阳性概率近似为

\[p\approx \left(1-e^{-kn/m}\right)^k\]

这里 \(m\) 是 bit 数组长度, \(n\) 是已插入元素数, \(k\) 是哈希函数数目, \(p\) 是假阳性概率。这个公式揭示了 Bloom Filter 的基本权衡: \(m\) 越大,冲突越少; \(n\) 越大,数组越接近被“染满”; \(k\) 太小会降低区分能力,太大则会过度占满 bit 位。固定 \(m\) 与 \(n\) 时,常见的近似最优选择是

\[k\approx \frac{m}{n}\ln 2\]

直觉上,Bloom Filter 像一排共享的指示灯。每来一个元素,就按亮若干盏灯;查询时,只要对应灯中有一盏没亮,就可以确认它从未出现过。若全部亮着,也只能说明“这些灯曾被某些元素点亮过”,却不能保证就是当前这个元素点亮的。

Bloom Filter 最适合用于“先快速排除绝大多数不存在项,再把少量可疑项交给精确结构复核”的场景。例如缓存系统可先判断某个 key 是否可能在缓存中,若 Bloom Filter 直接给出“不在”,就可以避免无意义回源;LSM-Tree 存储系统可用它判断某个键是否可能存在于某个 SSTable;爬虫去重、黑名单预过滤、向量检索候选预筛都大量使用这一思想。

Bloom Filter 的边界也很明确。第一,它不保存原始元素,因此不能枚举集合内容,也不能像哈希表那样返回关联值。第二,标准 Bloom Filter 不支持安全删除,因为把某个 bit 清零可能误伤其他元素留下的痕迹;若确实需要删除,通常要改用计数 Bloom Filter(Counting Bloom Filter)。第三,当假阳性代价非常高、系统需要完全精确的成员判断时,应优先使用哈希表、B 树或其他精确索引结构。

bloom

树(Tree)

树(Tree)处理的是“层次结构”和“递归划分”问题。树中的节点之间具有父子关系,除了根节点(Root)外,每个节点都有唯一父节点。它天然适合表达目录层级、决策分裂、区间划分、优先级组织与前缀共享。

树之所以重要,在于它把原本线性的搜索空间组织成递归结构,使很多操作能通过“向左还是向右”“进入哪个子树”逐步缩小问题规模。若每次都能把候选空间缩小到原来的一半,复杂度就会从线性级下降到对数级。

二叉树与遍历

二叉树(Binary Tree)规定每个节点至多有两个孩子。前序遍历(Preorder)、中序遍历(Inorder)、后序遍历(Postorder)和层序遍历(Level-order)分别对应不同的信息读取顺序:前序适合序列化结构,中序适合读取二叉搜索树中的有序键,后序适合先处理子问题再合并,层序适合按深度观察整体形状。

二叉搜索树与平衡树

二叉搜索树(Binary Search Tree, BST)在每个节点上保持“左子树键值更小、右子树键值更大”的顺序约束,因此查找、插入和删除都可以沿着比较路径进行。若树高度为 \(h\),这些操作的复杂度一般与 \(O(h)\) 成正比。

问题在于普通 BST 在极端情况下会退化成链表,此时 \(h=n\)。平衡树(Balanced Tree)如 AVL 树、红黑树(Red-Black Tree)通过旋转(Rotation)维护高度受控,使 \(h=O(\log n)\),从而把查找、插入和删除稳定在对数复杂度。数据库索引和有序映射容器大量依赖这一思想。

堆与优先队列

堆(Heap)不是“完全有序树”,而是只维护局部顺序:在最小堆(Min-Heap)中,每个父节点都不大于子节点,因此根节点始终是全局最小值;最大堆(Max-Heap)则相反。它通常用数组实现,父子下标关系可以直接计算。

堆最适合实现优先队列(Priority Queue):每次都要快速取出当前最重要、最小或最大的元素时,插入和弹出都只需 \(O(\log n)\)。Dijkstra、A* 搜索、任务调度、Top-K 维护和流式中位数都大量依赖优先队列。

Trie 与前缀结构

Trie 树(Prefix Tree)把字符串按前缀共享组织起来。若插入单词集合 \(\{w_1,\dots,w_m\}\),公共前缀只存一次,因此“是否存在某个前缀”“以某前缀开头的词有多少”都可以沿字符路径直接完成。

Trie 特别适合词典匹配、自动补全、敏感词过滤和子词切分。它牺牲了一部分空间,换来按字符长度而非按词典规模进行搜索的能力。

图(Graph)

图(Graph)处理的是最一般的关系结构。若顶点集合为 \(V\),边集合为 \(E\),则图可写成 \(G=(V,E)\)。树本质上是图的一个特殊子类,但图允许环、允许多条连接、允许方向和权重,因此能表达社交关系、知识链接、网页跳转、道路网络、依赖图与神经网络计算图。

图的常见表示方式有邻接矩阵(Adjacency Matrix)和邻接表(Adjacency List)。前者适合稠密图,能 \(O(1)\) 判断两点是否相连;后者适合稀疏图,空间复杂度更低,遍历邻居更高效。

BFS 与 DFS

广度优先搜索(BFS)与深度优先搜索(DFS)是图遍历的两种基本组织方式。BFS 使用队列按层推进,适合无权最短路、层次扩展与最少步数问题;DFS 使用递归或显式栈沿一条路径尽量走深,适合回溯、环检测、拓扑排序、强连通分量与树形动态规划。

对邻接表表示的图,两者的时间复杂度通常都是 \(O(|V|+|E|)\)。区别不在渐近复杂度,而在访问顺序:BFS 保证按距离层层扩展,DFS 更擅长描述“先深入、后回退”的结构性问题。

最短路径

最短路径(Shortest Path)问题处理的是:从起点到终点,总代价最小的路径是什么。若图无权,BFS 就能得到边数最少的路径;若边权非负,常用 Dijkstra 算法。它每次从优先队列中取出当前距离估计最小的顶点,并尝试松弛(Relax)相邻边。

Dijkstra 的核心更新为

\[\mathrm{dist}[v]=\min\big(\mathrm{dist}[v],\mathrm{dist}[u]+w(u,v)\big)\]

其中 \(\mathrm{dist}[u]\) 是当前已知的从源点到 \(u\) 的最短距离估计, \(w(u,v)\) 是边权。这个公式表达的是最短路的本质:若“先到 \(u\),再走到 \(v\)”更便宜,就更新对 \(v\) 的距离认知。

拓扑排序

拓扑排序(Topological Sort)处理的是有向无环图(Directed Acyclic Graph, DAG)中的依赖顺序。若边 \(u\to v\) 表示“\(u\) 必须先于 \(v\)”,那么拓扑序就是一种满足全部先后约束的线性排列。

课程先修关系、编译依赖、工作流调度、神经网络计算图执行次序,本质上都属于这一问题。拓扑排序的价值不只是“排出一个顺序”,而是把依赖图转成一条能够实际执行的流水线。

最小生成树(Minimum Spanning Tree, MST)

最小生成树(Minimum Spanning Tree, MST)处理的是这样的问题:给定一个连通无向带权图 \(G=(V,E)\),需要从边集合 \(E\) 中选出一部分边,把所有顶点连成一个整体,同时不产生环,并使总权重最小。若把所有生成树的集合记为 \(\mathcal{T}(G)\),则标准形式可以写成

\[T^*=\arg\min_{T\in \mathcal{T}(G)}\sum_{e\in T} w(e)\]

其中 \(T^*\) 是最优生成树;\(w(e)\) 是边 \(e\) 的权重;\(\sum_{e\in T} w(e)\) 表示树中全部边的总代价。这里的“生成树”有三个同时成立的约束:第一, \(T\subseteq E\);第二,图在边集 \(T\) 下必须连通;第三, \(T\) 不能含环,因此边数必然满足 \(|T|=|V|-1\)。

这个定义明确了 MST 不是“找一棵看上去便宜的树”,而是在所有能够覆盖全部顶点的无环连通方案中做全局最小化。只强调“连通”会多出冗余边,只强调“边权小”又可能导致图不连通;MST 同时满足这两个条件。

mst-graph

直觉上,可以把 MST 理解成“以最低总造价把一组城市接通,但不修多余的回路”。如果形成了环,说明这条网络中至少有一条边是重复支出;如果某些城市没有接入,说明方案根本不可用。MST 就是在“全覆盖”和“最低成本”之间取得最紧的平衡。

MST 成立的核心理论基础是割性质(Cut Property):把顶点集切成两个不相交部分后,跨越这个切分的最小权边,一定存在于某棵最小生成树中。这个性质的含义是:局部最便宜的“安全边(Safe Edge)”可以被逐步加入,而不会破坏全局最优性。Prim 与 Kruskal 虽然组织方式不同,但本质上都在不断选择这样的安全边。

Prim 算法的思路是“从一个起点向外生长一棵树”。设当前已经纳入树中的顶点集合为 \(S\),则 Prim 每一步都在所有满足 \(u\in S,\ v\notin S\) 的边中,选择权重最小的一条,把新顶点接入当前树。这个过程像不断把新城市接入已经建好的主干网,因此特别适合用优先队列维护“当前边界上最便宜的边”。若图用邻接表存储并配合二叉堆实现优先队列,时间复杂度通常为 \(O(|E|\log |V|)\)。

Kruskal 算法的思路是“按全图范围从便宜到昂贵依次选边”。它先对所有边按权重升序排序,然后从小到大扫描:若当前边连接的是两个不同连通块,就把它加入结果;若会在当前结构中形成环,就跳过。为了高效判断“两个端点是否已经连通”,Kruskal 通常配合并查集(Disjoint Set Union, DSU)。排序代价主导总复杂度,因此复杂度通常写成 \(O(|E|\log |E|)\),与 \(O(|E|\log |V|)\) 在数量级上接近。

两种算法解决的是同一个优化问题,但适合的工程语境不同。Prim 更像“从局部网络不断扩张”,适合稠密图或从某个核心节点逐步向外建设的场景;Kruskal 更像“全局看所有候选边,再逐一合并连通块”,在边集天然可排序、图较稀疏时实现尤其直接。

一个最小例子可以把公式和过程连起来。设四个顶点 \(A,B,C,D\),边权为: \(w(A,B)=1\), \(w(B,C)=2\), \(w(A,C)=4\), \(w(B,D)=3\), \(w(C,D)=5\)。Kruskal 会先按边权排序: \((A,B),(B,C),(B,D),(A,C),(C,D)\)。前 3 条边分别把 \(A\) 与 \(B\)、 \(B\) 与 \(C\)、 \(B\) 与 \(D\) 连起来,此时已经得到 \(|V|-1=3\) 条边,且图连通无环,于是生成树为

\[T=\{(A,B),(B,C),(B,D)\}\]

其总代价为

\[\sum_{e\in T}w(e)=1+2+3=6\]

若改选边集 \(\{(A,B),(A,C),(B,D)\}\),总代价是 \(1+4+3=8\);若再加入 \((B,C)\),虽然成本局部看不高,但边数会超过 \(|V|-1\) 并形成环,因此不再是树。这个例子把“最低成本”“连通”“无环”三项约束如何同时生效展示得很清楚。

MST 常见于网络布线、电力传输、骨架路网设计、图像分割、聚类和图压缩。层次聚类中的单链接(Single Linkage)就可以通过图的最小生成树来理解:先把点看成顶点,把样本间距离看成边权,再在 MST 上剪断最长的若干条边,就得到若干连通簇。这也是为什么 MST 不只是图论题型,而是很多数据分析与机器学习方法的底层结构。

MST 也有明确边界。它只适用于无向、连通、带权图上的“全连通最低总成本”问题;若任务要求的是“从源点到其余点的最短路”,应使用最短路径算法;若图有方向,目标就不再是普通 MST,而会进入最小树形图(Minimum Arborescence)等更复杂的问题。

动态规划(Dynamic Programming, DP)
背景和问题定义

动态规划(Dynamic Programming, DP)处理的是这样一类问题:目标是求一个全局最优值、最优路径,或所有路径的总和,但如果直接把所有可能性全部枚举出来,计算量会迅速爆炸。它常见于序列决策、路径规划、字符串匹配、图搜索,以及隐马尔可夫模型(HMM)、条件随机场(CRF)这类结构化预测模型。

这类问题通常有两个共同特征。第一,重叠子问题(Overlapping Subproblems):同一个中间子问题会被反复计算。第二,最优子结构(Optimal Substructure):大问题的最优解可以由小问题的最优解递推得到。例如,在长度为 \(T\) 的序列上,若每一步有 \(|\mathcal{S}|\) 个可能状态,直接枚举所有状态路径往往需要考虑 \(|\mathcal{S}|^T\) 条候选路径;当 \(T\) 稍大时,这种暴力方法几乎不可用。

核心思想

动态规划的核心不是“把问题拆小”这么简单,而是:先定义能够代表子问题的状态,再写出状态之间的递推关系,并把已经算过的结果缓存下来复用。因此,它本质上是一种计算组织方式,而不是某个固定公式。

一个直观比喻是出差换乘。设想要从起点出发,经过很多站点,最终到达目的地。暴力法会把“到达每一站的所有走法”全部记下来;动态规划不会这样做。它只会为每个中间站保留一份最有价值的摘要,例如“到达这个站的最低成本”或“到达这个站的最大得分”。当继续前往下一站时,系统只需要查这份账本,而不必回头展开所有历史路径。

因此,动态规划通常包含四个步骤:定义状态、定义边界条件、写出转移方程、确定计算顺序。状态定义决定“中间结果要存什么”;边界条件决定“第一步从哪里开始”;转移方程决定“当前结果如何从更小问题得到”;计算顺序则保证所有依赖项在使用前已经计算完毕。

dp

为什么局部次优前缀不会漏掉全局最优

动态规划能够丢弃大量“暂时看起来不够好”的前缀路径,前提不是“这些路径永远不可能翻盘”,而是状态(State)已经完整刻画了未来决策所需的全部信息。一旦这个条件成立,到达同一状态的两条前缀路径,未来能够接上的可行后缀集合完全相同,因此只需要保留其中更优的那一条。

设两条前缀路径都到达同一状态 \(s\),其当前累计代价分别为 \(f_1(s)\) 与 \(f_2(s)\),且 \(f_1(s)\le f_2(s)\)。若从状态 \(s\) 出发,后续任意可行决策产生的附加代价记为 \(g(s)\),并且这个附加代价只由当前状态决定,而不再依赖此前的完整历史,则有

\[f_1(s)+g(s)\le f_2(s)+g(s)\]

这个不等式表明:在同一状态上,较差的前缀会被较优前缀完全支配(Dominated)。无论后面接哪一段后缀路径,较差前缀都不可能反超。因此 Bellman 最优性原理允许动态规划只保留“到达该状态的最优值”,而不必保留全部历史路径。

所谓“一个当前次优的路径,后来却通向全局最优”,本质上对应另一种情形:这条路径与当前更优路径虽然看起来到达了同一个位置,但它们对未来的可行动作并不相同。此时它们实际上并不属于同一个状态,而是状态定义缺失了关键信息。

一个典型例子是带资源约束的路径规划。若状态只写成当前位置 \((i,j)\),那么两条到达同一格子的路径会被合并;但若其中一条还保留一次传送机会,另一条已经把传送用掉,则它们未来的决策空间显然不同。正确的状态应扩展为 \((i,j,\mathrm{used})\) 或 \((i,j,\mathrm{fuel})\) 这类更完整的形式。只有在状态把“剩余资源、上一步动作、已使用预算、是否持仓”等会影响未来的因素都编码进去后,动态规划的剪枝才是安全的。

因此,动态规划处理“局部次优可能导向全局最优”的方式,不是保留所有看起来有潜力的路径,而是通过正确设计状态,使真正会影响未来的差异体现在不同状态上。同一状态内部只保留最优前缀;不同状态之间分别递推。动态规划的正确性,最终依赖的正是这一点:未来只依赖当前状态,而不依赖通向当前状态的完整历史。

公式和详细解释

若记 \(t\) 为阶段或时间步, \(s\) 为当前状态,一个非常典型的动态规划写法是:

\[\mathrm{DP}[t,s]=\max_{s'\in \mathrm{Prev}(s)}\left(\mathrm{DP}[t-1,s']+\mathrm{score}(s',s,t)\right)\]

这条式子表达的是:要得到“第 \(t\) 步处于状态 \(s\) 时的最优值”,不必重新枚举所有完整路径,而是只需查看所有能够转移到 \(s\) 的前驱状态 \(s'\),并在它们已有的最优值基础上,加上这一步的局部得分,再从中取最大。

  • \(\mathrm{DP}[t,s]\):第 \(t\) 步、状态为 \(s\) 的最优子问题值。
  • \(\mathrm{Prev}(s)\):所有可以转移到状态 \(s\) 的前驱状态集合。
  • \(\mathrm{score}(s',s,t)\):从 \(s'\) 转移到 \(s\) 时,在第 \(t\) 步新增的局部得分或代价。
  • \(\max\):表示当前任务要找“最好的一条路径”。若任务目标是最小代价,则可改为 \(\min\);若任务目标是把所有路径概率加总,则可改为 \(\sum\)。

边界条件通常写成:

\[\mathrm{DP}[1,s]=\mathrm{init}(s)+\mathrm{local}(s,1)\]

其中 \(\mathrm{init}(s)\) 表示序列从状态 \(s\) 开始的初始代价或初始分数, \(\mathrm{local}(s,1)\) 表示第一步在该状态产生的局部贡献。没有这个起点,后续递推就无从展开。

动态规划真正带来的收益来自复杂度压缩。以一阶序列模型为例,若每一步有 \(|\mathcal{S}|\) 个候选状态、总长度为 \(T\),暴力枚举往往需要考虑 \(|\mathcal{S}|^T\) 条完整路径;而若采用“时间步 + 当前状态”的动态规划状态定义,则通常只需在每个时间步枚举所有前驱状态,计算复杂度可以降为 \(O(T|\mathcal{S}|^2)\)。这种从指数级到多项式级的下降,正是动态规划在序列模型中不可替代的原因。

若任务不仅要求最优值,还要求恢复最优路径,则通常还会额外保存“当前最优值来自哪个前驱状态”的回溯信息(Backpointer)。这意味着动态规划不仅能回答“最优值是多少”,还能回答“这条最优路径具体怎么走”。

更重要的是,动态规划并不只对应一种运算。对于最优路径问题,递推中的核心运算往往是 \(\max\) 或 \(\min\);对于总概率、配分函数这类问题,核心运算则是 \(\sum\)。这也是为什么 HMM 的维特比算法、前向算法,以及 CRF 的前向后向算法,虽然目标不同,但都属于动态规划。

应用实例

在 HMM 中,动态规划最典型地体现在两类问题上。第一类是维特比算法(Viterbi Algorithm):它要求“给定观测序列后,哪一条隐藏状态路径最可能”,因此递推中的核心运算是 \(\max\)。第二类是前向算法(Forward Algorithm):它要求“所有隐藏状态路径合起来,总概率是多少”,因此递推中的核心运算是 \(\sum\)。两者使用的是同一张状态网格,只是“每一步如何聚合前驱信息”不同。

在 CRF 中,动态规划同样是核心计算工具。训练时,需要对所有可能标签路径做归一化,这对应配分函数(Partition Function)的计算;解码时,需要找得分最高的那条标签路径,这对应最优路径搜索。在线性链 CRF 中,这两件事都可以通过“时间步 + 当前标签”的动态规划状态来高效完成,否则若直接枚举所有标签序列,计算量会随序列长度呈指数增长。

因此,在机器学习语境里,动态规划可以概括为:把原本必须整体枚举的结构化问题,改写成一系列局部状态上的递推计算,并通过缓存中间结果把重复计算消掉。一旦看到“序列路径很多、局部决策可递推、同类子问题会重复出现”这三个信号,通常就应该优先考虑动态规划。

例子 1:编辑距离(Edit Distance)

设字符串 \(A=a_1a_2\dots a_m\) 与 \(B=b_1b_2\dots b_n\)。编辑距离要回答的问题是:至少经过多少次插入、删除、替换,才能把 \(A\) 变成 \(B\)。若直接枚举所有编辑序列,可能性会指数增长;但若定义 \(\mathrm{DP}[i,j]\) 表示“把 \(A\) 的前 \(i\) 个字符变成 \(B\) 的前 \(j\) 个字符所需的最小编辑次数”,问题就能递推解决。

\[\mathrm{DP}[i,j]=\min\begin{cases}\mathrm{DP}[i-1,j]+1\\ \mathrm{DP}[i,j-1]+1\\ \mathrm{DP}[i-1,j-1]+\mathbf{1}(a_i\ne b_j)\end{cases}\]

这里三项分别对应:删除 \(a_i\)、插入 \(b_j\)、或把 \(a_i\) 替换成 \(b_j\)(若本来相同,则替换代价为 0)。边界条件是 \(\mathrm{DP}[0,j]=j\)、\(\mathrm{DP}[i,0]=i\),因为空串变成长度为 \(j\) 的串需要做 \(j\) 次插入,反之需要做 \(i\) 次删除。这个例子非常典型地体现了动态规划:状态是前缀长度,转移是三种编辑操作,目标是求最小总代价。

例子 2:网格最短路径(Grid Shortest Path)

设一个 \(m\times n\) 网格,每个格子 \((i,j)\) 都有进入代价 \(w_{i,j}\),只能向右或向下移动。问题是:从左上角走到右下角的最小总代价是多少。若定义 \(\mathrm{DP}[i,j]\) 表示“到达格子 \((i,j)\) 的最小总代价”,则递推很直接:

\[\mathrm{DP}[i,j]=w_{i,j}+\min\big(\mathrm{DP}[i-1,j],\mathrm{DP}[i,j-1]\big)\]

因为到达 \((i,j)\) 只有两种可能:从上方 \((i-1,j)\) 走下来,或从左侧 \((i,j-1)\) 走过来。边界条件是第一行与第一列只能沿单一路径累计。这个例子说明,动态规划并不局限于字符串或序列模型;只要问题具有“局部来源有限、全局目标可递推”的结构,就可以用同样的思路求解。

贪心算法(Greedy Algorithm)
背景和问题定义

贪心算法(Greedy Algorithm)处理的是这样一类问题:希望快速构造一个全局可行解,并且每一步都只做当前看来最优的局部选择,而不回头修改已经作出的决定。它广泛出现在排序、调度、压缩、近似优化,以及许多机器学习训练与推断流程中。

核心思想

贪心的核心假设是:当前最好的局部选择,能够导向全局最优,或至少导向足够好的近似解。它像走山路时每一步都先选眼前最高、最稳的落脚点,而不是先把整座山的所有路径都完全规划出来。贪心的优势是快、简单、容易实现;风险是局部最优未必等于全局最优。

公式和详细解释

若记第 \(t\) 步可选动作集合为 \(\mathcal{A}_t\),一个抽象的贪心选择可写为:

\[a_t^*=\arg\max_{a\in\mathcal{A}_t}\ \mathrm{score}(a\mid \text{current state})\]

这里 \(\mathrm{score}(a\mid \text{current state})\) 是当前状态下动作 \(a\) 的局部收益;\(\arg\max\) 表示从所有可选动作里挑出得分最高的那个。贪心算法关心的是“眼下哪一步最好”,而不是“未来所有步骤联合起来后哪条完整路径最好”。

因此,贪心方法是否正确,取决于问题本身是否满足贪心选择性质(Greedy-choice Property)。如果这个性质成立,局部最优就能拼成全局最优;如果不成立,贪心通常只能作为启发式方法或近似算法。

应用实例

决策树训练就是一个典型例子。每个节点都不会提前规划整棵树的全局最优结构,而是只在当前节点上选择信息增益、基尼下降或误差下降最大的切分。这个过程本质上就是贪心:每一步都先把当前最值得切的地方切开。它训练快、解释性强,但也正因为是局部选择,单棵树通常不是全局最优树结构。

分治算法(Divide and Conquer)
背景和问题定义

分治算法(Divide and Conquer)处理的是“大问题可以被拆成若干个同结构小问题”的场景。它广泛出现在排序、搜索、矩阵运算、索引构建,以及大规模数据处理与并行计算中。

核心思想

分治的思想可以概括为三步:分解(Divide)— 递归求解(Conquer)— 合并(Combine)。它像整理一大堆文档时,先按主题拆成若干小堆,再分别处理,最后再合并成有序结果。与动态规划不同,分治更强调“子问题相互独立”,而不是“子问题结果需要反复复用”。

公式和详细解释

分治算法的时间复杂度常写成递推式:

\[T(n)=aT\left(\frac{n}{b}\right)+f(n)\]

这里 \(n\) 是问题规模;\(a\) 表示被拆成多少个子问题;\(n/b\) 是每个子问题的规模;\(f(n)\) 是“分解 + 合并”本身的额外代价。这个式子不告诉我们具体怎么做,但它准确描述了分治算法的结构骨架。

例如,归并排序(Merge Sort)把长度为 \(n\) 的数组分成两个规模约为 \(n/2\) 的子数组,递归排好序后再线性合并,因此它的复杂度递推就是 \(T(n)=2T(n/2)+O(n)\)。

应用实例

在机器学习工程中,分治思想常见于大规模近邻索引构建。例如构建 kd-tree 时,算法会按某个维度把样本集递归切成两半,再在左右子集上继续构树。这样得到的层次化空间划分,能显著加速后续的近邻搜索。它的本质并不是“学习一个模型”,而是通过递归拆分把原本需要全表扫描的搜索过程组织得更高效。

图搜索与最短路径
背景和问题定义

许多软件与机器学习问题都可以抽象成图(Graph):节点(Node)表示状态、样本、词、网页或知识实体,边(Edge)表示转移、相似性、依赖关系或可达关系。图搜索与最短路径算法要回答的问题是:如何从起点高效找到目标节点,或找到总代价最小的一条路径。

核心思想

图搜索的核心是“沿着边扩展状态空间,但尽量避免无意义的重复探索”。无权图最短路径常用广度优先搜索(BFS),因为它按层扩展,第一次到达目标通常就是步数最少的路径;带非负权图常用 Dijkstra,因为它总是优先扩展当前总代价最小的候选节点。

公式和详细解释

带权最短路径算法里的基本更新步骤通常写成“松弛(Relaxation)”:

\[\mathrm{dist}(v)=\min\big(\mathrm{dist}(v),\ \mathrm{dist}(u)+w(u,v)\big)\]

这里 \(\mathrm{dist}(u)\) 是当前已知从起点到节点 \(u\) 的最小代价, \(w(u,v)\) 是边 \(u\rightarrow v\) 的权重, \(\mathrm{dist}(u)+w(u,v)\) 则是“先到 \(u\) 再走到 \(v\)”这条新候选路径的总代价。若它比当前记录的 \(\mathrm{dist}(v)\) 更小,就更新。

这个式子看起来和动态规划很像,原因是二者都在做“由已知子结果递推新结果”。区别在于:图搜索更强调如何选择下一个要扩展的节点,以及如何在一般图结构中避免重复访问。

应用实例

在语音识别、机器翻译和图搜索推断中,解码过程经常会把候选状态组织成图或格(Lattice)。此时,寻找最优输出序列本质上就是图上的路径搜索问题。很多动态规划解码器也可以从“图上最优路径”的角度理解,因此图搜索是连接通用软件算法与结构化机器学习推断的重要桥梁。

二分查找(Binary Search)
背景和问题定义

二分查找(Binary Search)处理的是“搜索空间有序,或可行性判断具有单调性”的问题。它不仅用于有序数组查找,也广泛用于阈值搜索、参数调优、数值逼近和工程系统中的边界定位。

核心思想

二分查找的核心是:每次利用单调性砍掉一半搜索空间。它像猜数字游戏:如果知道答案一定在某个区间里,而且中点左侧和右侧满足不同性质,那么每问一次都能把候选范围减半。

公式和详细解释

若当前搜索区间为 \([l,r]\),中点通常取:

\[\mathrm{mid}=\left\lfloor\frac{l+r}{2}\right\rfloor\]

接着依据单调判定函数 \(\mathrm{check}(\mathrm{mid})\) 缩小区间:

  • 若 \(\mathrm{check}(\mathrm{mid})\) 为真,说明答案在左半边或恰好是中点,则令 \(r=\mathrm{mid}\)。
  • 若为假,说明答案在右半边,则令 \(l=\mathrm{mid}+1\)。

算法正确性的关键不在于公式本身,而在于维护区间不变式(Invariant):在每一步更新后,真正的答案仍然留在当前区间中。

应用实例

在机器学习里,二分查找常用于阈值定位。例如,当需要找到“使召回率至少达到某个目标值的最小分类阈值”时,只要阈值越大召回率越低这一单调关系成立,就可以在阈值区间上做二分查找,而不必逐点穷举。类似地,很多数值求根、超参数边界搜索、分位数定位问题也都可写成二分框架。

随机采样(Random Sampling)
背景和问题定义

随机采样(Random Sampling)处理的是这样一类问题:总体太大、精确计算太贵,或者目标本身就是概率性的,因此只能通过抽样近似整体行为。它是统计学习、蒙特卡洛估计、bootstrap、自助重采样、mini-batch 训练和负采样的共同基础。

核心思想

随机采样的核心是:不必每次都看完整总体,而是通过足够有代表性的随机子样本估计总体性质。它像民意调查:不可能每天逐个询问所有人,但若抽样方式合理,少量样本也能给出相对稳定的总体估计。

公式和详细解释

若目标是估计随机变量 \(X\) 下某个函数 \(f(X)\) 的期望 \(\mathbb{E}[f(X)]\),最常见的蒙特卡洛估计写为:

\[\hat{\mu}=\frac{1}{n}\sum_{i=1}^{n} f(x_i),\qquad x_i\sim p(x)\]

这里 \(x_i\sim p(x)\) 表示样本 \(x_i\) 是按分布 \(p(x)\) 随机抽到的; \(n\) 是样本数; \(\hat{\mu}\) 是用样本均值近似真实期望的估计量。样本越多,估计通常越稳定,但代价也越高。

这一思想在机器学习里非常普遍:SGD 不是每次都在全量数据上算梯度,而是用 mini-batch 的样本均值近似全数据梯度;negative sampling 不是对所有负类都求和,而是随机抽一小部分负样本近似完整目标。

应用实例

bootstrap 是一个很典型的例子。随机森林训练时,会对原始训练集做有放回采样,得到多份不同的 bootstrap 子集,再分别训练多棵树。这里真正起作用的不是“树”本身,而是随机采样制造了多个略有差异的数据视角,从而让集成后的模型更稳。

机器学习基础概念

机器学习基础概念(Machine Learning Foundations)回答四类核心问题:数据从哪里来、模型在学什么、模型为什么能泛化、结果该如何评价。把这些问题分开看,会比死记算法名称更有效:学习范式决定监督信号来自哪里,假设空间与归纳偏置决定模型愿意相信什么,数据集工程决定模型实际看到了什么,模型评估决定这些学习结果是否真的能迁移到未见样本。

假设/目标/代价/损失

这四个词描述的是同一条“训练=优化”的概念链,但位于不同层级。把层级理清后,公式与实现会自然对齐:模型 \(f_\theta\) 先给出预测,再用损失函数把预测变成数值误差,最后把误差在数据集上汇总成代价函数,并加入正则/约束得到最终的目标函数。

假设函数(Hypothesis Function)

假设函数(Hypothesis Function)也常被直接称为模型(Model)或预测函数(Predictor),记作 \(f_\theta\)。它回答的问题是:给定输入 \(x\),模型输出什么。参数 \(\theta\) 决定这条映射的具体形状。

线性回归(Linear Regression)的假设函数是最经典的例子:

\[\hat y=f_\theta(x)=\mathbf{w}^\top x+b,\quad \theta=(\mathbf{w},b)\]
目标函数(Objective Function)

目标函数(Objective Function)记作 \(J(\theta)\),是优化器真正要优化的函数。工程上最常见、也最清晰的写法是:目标函数 = 代价函数 + 正则化项(没有正则化时可视为正则项为 0,因此 \(J(\theta)=L(\theta)\))。

\[J(\theta)=L(\theta)+\lambda\,\Omega(\theta)\]

在线性回归里,若用 L2 正则(Ridge / Weight Decay),常见目标函数可以写成:

\[J(\theta)=L(\theta)+\lambda\|\mathbf{w}\|_2^2\]

把 \(L(\theta)\) 展开后,就是:

\[J(\theta)=\frac{1}{N}\sum_{i=1}^{N}(\mathbf{w}^\top x_i+b-y_i)^2+\lambda\|\mathbf{w}\|_2^2\]
代价/成本函数(Cost Function)

代价函数/成本函数(Cost Function)记作 \(L(\theta)\),通常指把样本损失在训练集上做平均或求和后的整体量,也就是经验风险(Empirical Risk)。不少教材会把它直接称为训练损失(training loss),并且在不引起歧义时把它与目标函数混用。

在线性回归里,常用“均方误差的平均”作为代价函数:

\[L(\theta)=\frac{1}{N}\sum_{i=1}^{N}\ell_i(\theta)\]

把 \(\ell_i(\theta)\) 取为平方误差后,等价写法是:

\[L(\theta)=\frac{1}{N}\sum_{i=1}^{N}(\mathbf{w}^\top x_i+b-y_i)^2\]
损失函数(Loss Function)

损失函数(Loss Function)记作 \(\ell\),通常定义在单个样本上,把“预测与目标的差距”映射为一个标量。它回答的问题是:这一条样本我错了多少。

在线性回归里,最常见的单样本损失是平方误差:

\[\ell_i(\theta)=\ell(\hat y_i,y_i)=(\hat y_i-y_i)^2,\quad \hat y_i=f_\theta(x_i)\]
学习范式

这里需要先分清两个维度。监督学习(Supervised Learning)、无监督学习(Unsupervised Learning)、自监督学习(Self-supervised Learning)和强化学习(Reinforcement Learning)主要按监督信号从哪里来划分;迁移学习(Transfer Learning)与少样本学习(Few-shot Learning)则更像训练设置或能力诉求,讨论的是模型如何复用已有知识、以及在样本极少时如何适配新任务。对比学习(Contrastive Learning)也不是与前几者并列的“学习方式”,而是一类训练目标,最常见于自监督表示学习,但也可以用于监督学习、多模态学习和度量学习(Metric Learning)。因此下面这些概念不是互斥关系,完全可以组合出现,例如“自监督 + 对比学习预训练 + 迁移学习微调 + few-shot 适配”就是现代深度学习中很常见的工作流。

监督学习

监督学习(Supervised Learning)使用带标签的数据对 \((x,y)\) 训练模型:输入 \(x\) 是特征(Feature),输出 \(y\) 是目标或标签(Label)。模型学习的不是“记住答案”,而是学习一个映射 \(f_\theta:x\to y\),使它对新样本也能给出合理预测。

但“学一个映射”还不够,训练时还必须回答另一个更具体的问题:怎样才算模型学得好。监督学习里最常见的回答,是在训练集上逐个比较预测与真实标签的差距,再把这些差距汇总成一个总体目标;这就导向经验风险最小化(Empirical Risk Minimization, ERM)。

经验风险最小化的典型目标写成:

\[\frac{1}{N}\sum_{i=1}^{N}\ell\big(f_\theta(x_i),y_i\big)\]

这里 \(N\) 是样本数, \(f_\theta(x_i)\) 是模型预测, \(y_i\) 是真实标签, \(\ell\) 是损失函数(Loss Function)。这条式子的含义不是抽象求和,而是:逐个样本计算“预测错了多少”,再取平均,把平均错误压到尽可能小。

例:垃圾邮件分类里, \(x\) 可以是邮件文本特征, \(y\in\{0,1\}\) 表示“正常/垃圾”;房价预测里, \(x\) 可以是面积、地段、楼龄, \(y\) 是价格。前者是分类(Classification),后者是回归(Regression),但“有标签地学映射、再用损失函数衡量误差”这一训练逻辑完全一致。

分类任务

分类任务(Classification)要预测的是离散类别,也就是样本属于哪一类。输出可以是一个类别 id,也可以是一组类别概率。例如二分类里常见输出 \(P(y=1|x)\),表示“给定特征 \(x\) 时,样本属于正类的概率”。

垃圾邮件识别、肿瘤良恶性判断、情感分析、图像里的猫狗识别都属于分类任务。它更像“做选择题”:模型最终要在有限候选里做判断。训练时常配合交叉熵(Cross-Entropy)这类损失,因为模型不仅要选对类别,还要给正确类别足够高的置信度。

回归任务

回归任务(Regression)要预测的是连续数值,也就是标签不是几个固定类别,而是在某个数值区间内连续变化。输出通常直接是一个实数,或一个多维连续向量。

房价预测、销量预测、温度预测、广告点击率中的停留时长估计都属于回归任务。它更像“做填空题”:模型不能只说“高”或“低”,而必须给出具体数值。训练时常配合均方误差(MSE)或平均绝对误差(MAE),因为关心的是预测值与真实值到底差了多少。

分类与回归都属于监督学习,因为它们都有标签;真正的区别在于标签空间的形状:分类的标签空间是离散集合,回归的标签空间是连续区间。这个区别会直接决定模型输出层形式、损失函数选择以及评估指标。

无监督学习

无监督学习(Unsupervised Learning)只有输入 \(x\),没有人工标签 \(y\)。它的目标不是拟合“标准答案”,而是从数据中发现结构(Structure),例如聚类(Clustering)、降维(Dimensionality Reduction)、密度估计(Density Estimation)与异常检测(Anomaly Detection)。

一个直观类比是:监督学习像“拿着答案册做题”,无监督学习像“没有答案册,只能自己把一堆材料按相似性归类”。例如电商用户没有现成“用户类型”标签,但可以根据浏览、购买、停留时间等行为聚成“价格敏感型”“冲动购买型”“高价值复购型”等群体,用于运营分层。

自监督学习

自监督学习(Self-supervised Learning)介于监督与无监督之间:原始数据没有人工标签,但任务标签可以由数据本身自动构造出来。核心思想是从数据内部制造预测任务,让模型在完成这些任务的过程中学到可迁移表示(Representation)。

语言模型的下一个 token 预测就是最典型的自监督任务:前文是输入,后一个 token 是由原始文本自动给出的“监督信号”。图像领域里,旋转预测、遮挡恢复、不同增强视角匹配也属于同一路线。

对比学习

对比学习(Contrastive Learning)通过“拉近正样本、推远负样本”学习表示。这里的关键不是类别标签,而是样本之间的相对关系:哪些应该相似,哪些应该区分。

一个常见形式是 InfoNCE 损失:

\[-\log \frac{\exp(\mathrm{sim}(z_i,z_i^+)/\tau)}{\sum_{j}\exp(\mathrm{sim}(z_i,z_j)/\tau)}\]

其中 \(z_i\) 是当前样本表示, \(z_i^+\) 是与它匹配的正样本表示, \(\mathrm{sim}(\cdot,\cdot)\) 是相似度函数(常用余弦相似度), \(\tau\) 是温度参数(Temperature),控制分布尖锐程度。这个公式的直觉是:让正确配对在所有候选中拿到最高分。类比来看,它像“人脸识别训练”——同一个人的两张照片应靠近,不同人的照片应拉开。

掩码预测

掩码预测(Masked Prediction)把输入中的一部分信息故意遮住,再要求模型恢复。例如 BERT 会把句子中的部分 token 替换成特殊标记 \([MASK]\),模型要根据上下文预测被遮住的词。

类比来看,这像完形填空:你不是死记整句,而是学会根据上下文推断缺失信息。它迫使模型同时利用左侧和右侧上下文,因此特别适合编码器(Encoder)型表示学习。

迁移学习

迁移学习(Transfer Learning)讨论的是:先在数据更丰富、任务更通用的源任务上学到参数或表示,再把这些知识迁移到目标任务。它不是按监督信号划分出来的独立“学习方式”,而是一种跨任务复用知识的训练策略。现代大模型先预训练、再微调,本质上就是迁移学习。

它与对比学习不在同一层面。对比学习回答的是“预训练阶段该用什么目标来学表示”;迁移学习回答的是“学到的表示如何迁到新任务”。两者经常配合出现:例如先在海量无标签图像上用对比学习预训练视觉编码器,再把该编码器迁移到医学影像分类、工业缺陷检测或小样本识别任务上。

少样本学习

少样本学习(Few-shot Learning)处理的是“每个任务只有极少标注样本”时如何仍然快速泛化。它通常建立在迁移学习或预训练模型之上:模型先学到一套通用表示,再在很少示例下快速适配新任务。困难不在于单个任务本身,而在于模型必须把以往经验迁移到新任务上。直觉上,它更像“学会如何快速学习”,而不是“把一个任务彻底学透”。

零样本(Zero-shot)

零样本(Zero-shot)指模型在目标任务上没有任何专门示例,也能凭借已有知识完成任务。大语言模型通过指令理解实现的很多能力都属于这一类。例:不给任何情感分类样例,只写“判断下面评论是正面还是负面”,模型仍可能完成分类。

单样本(One-shot)

单样本(One-shot)指只给 1 个示例。这个示例的价值不是提供统计规律,而是告诉模型“输出格式、任务边界和你想要的判别标准”。例如先给一条“商品评论 → 正面”的例子,再让模型判断下一条评论。

K 样本(K-shot)

K 样本(K-shot)指给每类或每任务提供 \(K\) 个示例。随着 \(K\) 增大,模型更容易对任务意图和判别标准形成稳定估计。工程上,prompt 中的 few-shot 示例本质上就是在上下文窗口里做一种“临时任务适配”。

元学习(Meta-learning / MAML)

元学习(Meta-learning)研究“让模型更快适应新任务”。MAML(Model-Agnostic Meta-Learning)的核心不是直接学一个最终答案,而是学一个好的初始化参数 \(\theta\),使模型只需少量梯度更新就能适配新任务。

MAML 的外层目标可概括为:

\[\min_\theta \sum_{\mathcal{T}} \mathcal{L}_{\mathcal{T}}\big(\theta-\alpha\nabla_\theta \mathcal{L}_{\mathcal{T}}(\theta)\big)\]

其中 \(\mathcal{T}\) 表示一个任务, \(\alpha\) 是内层更新步长。读法是:先用当前参数在某任务上走一步,再看更新后的参数在该任务上的表现好不好;如果“一步后就变好”,说明初始化是好的。类比来看,MAML 训练的不是“会做每道题的学生”,而是“只要老师讲一遍就能迅速举一反三的学生”。

原型网络(Prototypical Networks)

原型网络(Prototypical Networks)把每个类别表示成嵌入空间中的一个“类中心(Prototype)”。对类别 \(k\),其原型定义为该类支持集(Support Set)样本嵌入的平均:

\[c_k=\frac{1}{|S_k|}\sum_{(x_i,y_i)\in S_k,\ y_i=k} f_\theta(x_i)\]

这里 \(f_\theta(x_i)\) 是样本的向量表示, \(S_k\) 是类别 \(k\) 的支持样本集合。分类时,把新样本映射到嵌入空间,看它离哪个原型最近。直觉上,这像“每一类先算一个代表点,新样本按离哪个代表点最近来归类”。在 few-shot 图像分类中,这种方法往往比直接训练复杂分类头更稳。

强化学习

强化学习(Reinforcement Learning, RL)最容易把人劝退的地方,是一上来就堆术语:马尔可夫、时序差分、优势函数、策略梯度……但把这些词全去掉后,它讲的其实只是一个极其朴素的故事:一个智能体在环境里反复试错,慢慢学会怎样长期拿到更多奖励。

监督学习像“做题立刻对答案”:你给模型输入 \(x\),同时给它正确标签 \(y\)。强化学习不是这样。它更像玩一整局游戏:你只能一边行动,一边看后果,一边修正打法。当前这一步看起来对不对,往往要过很多步以后才知道。

核心循环:迷宫游戏

可以把强化学习先想成一个小机器人走迷宫。这个故事里有六个最核心的角色:

  • 智能体(Agent):做决策的主体,也就是那个小机器人。
  • 环境(Environment):机器人所处的外部世界,例如迷宫、棋盘、游戏地图、推荐系统或对话上下文。
  • 状态(State, \(s\)):机器人当前看到的局面,例如“前面是墙,右边有路”。
  • 动作(Action, \(a\)):机器人此刻可以做的选择,例如左转、右转、前进。
  • 奖励(Reward, \(r\)):环境给这一步行动的反馈,例如捡到金币加 1,掉进陷阱减 1。
  • 策略(Policy, \(\pi\)):机器人脑子里的“通关秘籍”,也就是在什么状态下该怎么行动的规则。

于是强化学习的目标可以直接翻译成一句人话:不断修改这本“通关秘籍”,让整局游戏玩下来拿到的总分尽可能高。

rl

为什么这里不只看即时奖励,而要看“整局总收益”?因为很多任务里,奖励会延迟出现。下棋时,一步好棋未必立刻得分,但可能为十步后的胜利铺路;推荐系统里,一次推荐是否合理,也要看用户后续点击、停留和转化。因此强化学习常用于游戏对战、机器人控制、资源调度、广告竞价、推荐排序,以及大模型对齐等场景。

为了衡量“从现在开始,这套打法最终值不值得”,强化学习定义长期回报(Return,也常称累计回报):

\[G_t=\sum_{k=0}^{\infty}\gamma^k r_{t+k+1},\quad \max_\pi\ \mathbb{E}_\pi[G_t]\]

这条式子不要硬背,可以直接按故事来读。前半部分 \(G_t=\sum_{k=0}^{\infty}\gamma^k r_{t+k+1}\) 说的是“从当前时刻开始,整局游戏最终能拿多少分”: \(r_{t+k+1}\) 是未来第 \(k+1\) 步得到的奖励, \(\gamma\) 是折扣因子(Discount Factor),表示未来奖励要不要打折。它的直觉很像“现在的 100 块通常比一年后的 100 块更值钱”:当 \(\gamma\) 越接近 1,模型越重视长期收益;当它更小,模型就更短视。后半部分 \(\max_\pi\ \mathbb{E}_\pi[G_t]\) 则是在说:在所有可能的策略 \(\pi\) 里,去寻找那个能让期望长期回报最大的策略。这里的 \(\mathbb{E}_\pi\) 是期望,后面的方括号 \([G_t]\) 只是表示“取期望的对象是 \(G_t\) 这个随机回报”,并不是额外的新符号。之所以要写期望,是因为同一个策略在同一个环境里重复运行,过程里往往带有随机性——例如环境可能有随机事件,策略本身也可能按概率选动作。所以强化学习真正优化的不是“某一次刚好打得特别好”的偶然结果,而是“长期重复玩这局游戏时,平均下来能拿到的总分”尽可能高。

把故事写成数学:MDP

马尔可夫决策过程(Markov Decision Process, MDP)不是额外的新东西,它只是把上面的迷宫故事写成数学记号。最常见的写法是五元组 \((\mathcal{S},\mathcal{A},P,R,\gamma)\):

  • \(\mathcal{S}\):状态空间(State Space),也就是所有可能局面的集合。
  • \(\mathcal{A}\):动作空间(Action Space),也就是所有可选动作的集合。
  • \(P(s'|s,a)\):状态转移概率,表示在状态 \(s\) 做动作 \(a\) 后,到达下一状态 \(s'\) 的概率。
  • \(R(s,a)\) 或 \(R(s,a,s')\):奖励函数,表示这一步能拿到什么反馈。
  • \(\gamma\):折扣因子,决定未来奖励在总目标里占多大比重。

“马尔可夫”这个词听着吓人,意思其实很简单:如果当前状态已经把关键信息都概括好了,那么未来只取决于当前状态和当前动作。像下棋时,只看当前棋盘局面就足够,不必把每一步历史都原样背下来。

理解了这个核心循环后,主流强化学习算法其实只是三大门派:价值派、策略派,以及在大模型时代出现的对齐派。它们不是在解决不同问题,而是在用不同方式学习同一件事:怎样改进策略。

价值派:Q-Learning 与 DQN

价值派(Value-Based)的思路像一个精打细算的记账员。它不直接记“现在该怎么做”,而是先问一个更根本的问题:如果我在当前状态下做这个动作,从长期看到底划不划算。这个“划算程度”的估计,就是动作价值函数(Action-value Function) \(Q(s,a)\)。

这里最容易混淆的是: \(Q(s,a)\) 不是“这一步眼前立刻拿到的奖励”,也不是单独指“这一步的成本”。它表示的是:在状态 \(s\) 下先执行动作 \(a\),然后后面继续尽量做好选择,最终总共大约能拿到多少长期回报。如果某个动作会消耗时间、体力、资源或带来风险,这些通常会被写进奖励函数里,表现成负奖励;因此 \(Q(s,a)\) 看的是长期净效果,而不是只看眼前奖励,也不是只看单独成本。

Q-Learning 之所以叫这个名字,是因为它要学习的对象就是动作价值函数 \(Q(s,a)\) 的估计(Q 源自 quality,表示动作在某状态下的“好坏程度”)。Q-Learning 的直觉是:如果我在状态 \(s\) 下选择动作 \(a\),环境会先立刻返还一个即时奖励 \(r\),然后把我带到下一状态 \(s'\)。这里的 \(r\) 只是在给“这一步刚刚发生了什么”打分;而 \(Q(s,a)\) 想学的则是“这一步连同后面整局走势一起看,最终值多少”。所以 Q-Learning 做的事情,不是把即时奖励直接当成答案,而是用这一步新看到的结果,回头修正账本里对 \(Q(s,a)\) 的动作价值估计:

\[Q(s,a)\leftarrow Q(s,a)+\alpha\Big(r+\gamma\max_{a'}Q(s',a')-Q(s,a)\Big)\]

这条更新式最好逐项拆开看:

  • 更新式左边的 \(Q(s,a)\) 表示“这次更新后,要重新写回账本的那个值”。
  • 箭头右边最后那个 \(Q(s,a)\) 表示“更新前账本里原来记着的旧估计”。同一个符号在箭头两边都出现,是因为它表示的是同一个账本位置更新前后的值。
  • \(s\) 是当前状态,例如“机器人现在站在岔路口,左边是墙,右边能走”。
  • \(a\) 是当前状态 \(s\) 下刚刚执行的那个动作,例如“向右走一步”。
  • \(r\) 是执行动作 \(a\) 后,环境立刻返还的即时奖励。例如这一步踩到金币就加 1,踩到陷阱就减 1。
  • \(s'\) 是执行完当前动作 \(a\) 之后到达的下一状态。这里的撇号只是表示“下一个状态”,不是别的特殊运算。
  • \(a'\) 表示在下一状态 \(s'\) 中任意一个可选动作。它带撇号,只是为了和当前动作 \(a\) 区分开。
  • \(Q(s',a')\) 表示:如果机器人已经来到下一状态 \(s'\),此时选择动作 \(a'\),那么从那以后预期长期回报大约是多少。
  • \(\max_{a'}Q(s',a')\) 的意思是:把下一状态 \(s'\) 里所有可选动作 \(a'\) 的长期价值都估一遍,再挑出其中最大的那个估计。它回答的问题是:如果我已经走到了下一状态,并且从下一步开始尽量做最好的选择,后面大概还能再拿到多少长期回报。
  • \(\gamma\max_{a'}Q(s',a')\) 表示把“未来还能拿到的最好长期回报”按折扣因子 \(\gamma\) 打折后算回来,因为越远的未来通常权重越小。
  • \(r+\gamma\max_{a'}Q(s',a')\) 是新的目标值(TD target):它把“这一步立刻拿到的即时奖励”与“从下一步开始最好情况下还能拿到的折扣后长期回报”加在一起。
  • \(r+\gamma\max_{a'}Q(s',a')-Q(s,a)\) 是新目标与旧估计之间的差,也就是时序差分误差(TD error)。如果这个差为正,说明原来低估了;如果这个差为负,说明原来高估了。
  • \(\alpha\) 是学习率,控制这次修正到底改多少。 \(\alpha\) 大,账本改得快但更容易抖;小则更稳,但学得更慢。

把整条式子连起来看,就是:先记录“当前这一步实际拿到了多少即时奖励”,再估计“到了下一状态后,如果接下来尽量做最好的选择,还能拿到多少折扣后长期回报”,把这两部分合成一个新的目标值,然后用它去修正旧账本里对 \(Q(s,a)\) 的动作价值估计。这就是 Q-Learning 的核心。

DQN(Deep Q-Network)并没有改变这个思路,它只是把“小本子记账”升级成“让神经网络来记账”。当状态非常大时,例如 Atari 游戏的原始像素画面,手工建一个巨大 Q 表几乎不可能,这时就用深度网络直接输入状态,输出每个动作的价值估计。DQN 的本质不是新的哲学,而是:让价值派能处理高维感知输入。

用迷宫里的“死胡同”再对照一遍,会更容易把这件事和更新式对上。常见有两种奖励设计:

  • 如果每走一步都有即时奖励(很多任务里是每步一个小的负奖励,表示时间或能量成本),那么一旦走进死胡同,哪怕还没走到尽头,后续回退/绕路的每一步都会继续累积这些代价。沿着死胡同走得越深,后续必然要付出的额外代价越多,于是死胡同深处的状态会先学到更低的 \(\max_{a'}Q(s,a')\);再通过更新式里的 \(\gamma\max_{a'}Q(s',a')\) 把“更差的未来”逐步回传到入口处,最终拉低“最开始走进死胡同那一步”的 \(Q(s,a)\)。
  • 如果奖励非常稀疏:只有到达终点那一刻给一次奖励,其余步奖励为 0,那么走进死胡同本身不会产生额外的负奖励,它的影响来自“把终点奖励推迟了”。假设终点奖励为 \(R_{\mathrm{goal}}\),到达终点的时间为 \(T\),则从时刻 \(t\) 起的长期回报约为 \(G_t=\gamma^{T-t-1}R_{\mathrm{goal}}\):走到终点越晚,\(\gamma<1\) 时折扣越多,回报越小。这会表现为:越靠近终点的状态动作对先学到较大的 Q,越远的状态动作对学到的 Q 会多乘几个 \(\gamma\)。若环境还有最大步数上限(time limit),超过上限视为失败并给 0 回报,那么绕进死胡同也可能把轨迹拖到上限之外,使得许多状态动作对的 TD target 直接变为 0,从而把入口处那一步的 \(Q(s,a)\) 也压低。
策略派:Policy Gradient 与 PPO

策略派(Policy-Based)觉得记账太麻烦,尤其当动作不是“左转/右转”这种离散选项,而是“方向盘打多少角度”“机械臂关节转多少度”这种连续动作时,根本不适合把每个动作都列成账本。于是它选择直接练本能:给定状态,直接输出动作概率分布,这个分布本身就是策略 \(\pi_\theta(a|s)\)。

策略梯度(Policy Gradient)的核心思想非常直白:凡是最终带来高回报的动作,就提高它以后再次发生的概率;凡是带来低回报的动作,就降低它的概率。它的基本形式写成

\[\nabla_\theta J(\theta)=\mathbb{E}\big[\nabla_\theta \log \pi_\theta(a_t|s_t)\,G_t\big]\]

这条式子同样最好逐项拆开看:

  • \(J(\theta)\) 是策略的总体目标,也就是“让整条策略长期回报尽可能大”这件事。
  • \(\nabla_\theta J(\theta)\) 表示“如果我想把总目标 \(J(\theta)\) 变大,参数 \(\theta\) 应该往哪个方向改”。
  • \(\theta\) 是策略模型的参数。在机器人里它可能是控制器参数,在神经网络里它就是网络权重。
  • \(s_t\) 是时刻 \(t\) 的状态,也就是当前看到的局面。
  • \(a_t\) 是时刻 \(t\) 真正执行的那个动作。
  • \(\pi_\theta(a_t|s_t)\) 是“在状态 \(s_t\) 下,策略给动作 \(a_t\) 分配了多大概率”。它不是奖励,也不是价值,而是策略本身的偏好强弱。
  • \(\log \pi_\theta(a_t|s_t)\) 不是又引入了一个神秘对象,它只是对这个概率取对数。这样做的主要原因是数学上更容易求导,并且能把一整条轨迹上的概率乘积改写成对数求和。
  • \(\nabla_\theta \log \pi_\theta(a_t|s_t)\) 表示:如果想让动作 \(a_t\) 在状态 \(s_t\) 下更容易再次发生,参数 \(\theta\) 应该朝哪个方向改。它给的是“增大该动作概率的方向”。
  • \(G_t\) 是从时刻 \(t\) 开始,这次动作后面最终带来的长期回报。它在这里扮演“事后评分”的角色:若 \(G_t\) 高,说明这次动作最终效果好;若低,说明效果差。
  • \(\nabla_\theta \log \pi_\theta(a_t|s_t)\,G_t\) 这项可以直观理解为:先找到“怎样让这次动作更常发生”的方向,再用 \(G_t\) 来决定这个方向该被强化多少。动作后果越好,就推得越用力;后果越差,就反过来压制。
  • \(\mathbb{E}[\cdot]\) 表示对很多次采样结果取期望,因为单次轨迹有随机性。策略梯度真正优化的不是“某一次刚好运气好”的结果,而是长期平均表现。

把整条式子连起来看,就是:先执行一个动作,等整段后果出来后,再回头问“这次动作究竟值不值”。如果值,就提高它以后再次出现的概率;如果不值,就降低它的概率。这就是策略派“直接练本能”的本质。

PPO(Proximal Policy Optimization)是在策略梯度上加护栏。纯策略梯度的问题是:如果某一步更新太猛,策略可能一下子学歪,训练直接崩掉。PPO 的核心就是限制“这次别改太多”:

\[\min\Big(r_t(\theta)A_t,\ \mathrm{clip}(r_t(\theta),1-\epsilon,1+\epsilon)A_t\Big)\]

这条式子也可以逐项拆开看:

  • \(r_t(\theta)=\frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{\mathrm{old}}}(a_t|s_t)}\) 是新旧策略对同一动作概率的比值。若它接近 1,说明这次更新前后,策略对这个动作的看法变化不大;若它远离 1,说明改动已经很大。
  • \(\pi_{\theta_{\mathrm{old}}}(a_t|s_t)\) 是更新前旧策略给这个动作的概率; \(\pi_\theta(a_t|s_t)\) 是更新后新策略给它的概率。
  • \(A_t\) 是优势函数(Advantage)。它回答的问题不是“这次总共拿了多少分”,而是“这个动作比当前状态下的平均水平到底好多少”。若 \(A_t>0\),说明这步动作比平均更好;若 \(A_t<0\),说明更差。
  • \(r_t(\theta)A_t\) 可以理解成“如果完全按这次新旧概率比去更新,那么这个动作会被奖励或惩罚多少”。
  • \(\mathrm{clip}(r_t(\theta),1-\epsilon,1+\epsilon)\) 是 PPO 最关键的护栏:它强行规定概率比不要偏离 1 太远。 \(\epsilon\) 就是护栏宽度。
  • 外面的 \(\min(\cdot,\cdot)\) 表示:原始更新和“截断后的保守更新”两者里,只取更保守的那个。这样即使优化器很激进,也不会让策略一步跳太远。

所以 PPO 的本质可以直接说成人话:方向仍然按“好的动作多做,差的动作少做”来改,但每次只允许小步微调,防止策略训练失控。这也是它在机器人控制和大模型对齐里都非常常用的原因。

大模型对齐:RLHF、DPO 与 GRPO

语言模型本来做的是下一个 token 预测:给定前文,猜下一个词最可能是什么。这很像一只会续写的鹦鹉。大模型对齐(Alignment)要解决的问题是:怎样让它不只是“会接话”,还要更有帮助、更安全、更符合人类偏好。

把语言模型放进强化学习视角后,整个映射会立刻清楚起来:用户输入的 prompt 加上当前已生成前缀 \((x,c_t)\) 就是状态;当前要选的下一个 token \(y_t\) 就是动作;整段最终回答 \(y\) 就是一条完整轨迹;而模型本身给出的下一个 token 条件概率分布 \(\pi_\theta(y_t|c_t,x)\),就是所谓生成策略(Generation Policy)。所以“修改生成策略”并不神秘,本质上就是:修改模型在每个上下文里更倾向说哪些 token。

RLHF(Reinforcement Learning from Human Feedback)的做法是:先收集人类偏好数据,例如“回答 A 比回答 B 更好”;再训练一个奖励模型 \(r_\phi(x,y)\),让它学会像裁判一样给回答打分;最后用 PPO 这类策略优化方法,把高分回答的概率调高、低分回答的概率调低。一个常见目标写成

\[\max_\pi\ \mathbb{E}_{y\sim \pi(\cdot|x)}\big[r_\phi(x,y)-\beta\,\mathrm{KL}(\pi(\cdot|x)\|\pi_{\mathrm{ref}}(\cdot|x))\big]\]

这里 \(\pi_{\mathrm{ref}}\) 是参考模型,通常是监督微调(SFT)后的初始模型;KL 项的作用是防止模型为了讨好奖励模型而“跑偏”太远。可以把 RLHF 理解成:先找人类裁判总结出一套评分标准,再让模型在这套标准下稳步调整说话方式。

DPO(Direct Preference Optimization)认为这套流程有点重:既要训练奖励模型,又要跑强化学习优化。它利用偏好数据做了数学改写,直接把“回答 A 优于回答 B”的信息作用到策略本身,跳过了显式奖励模型与完整 RL 回路。直观地说,DPO 像是把“裁判打分 + 再训练”合成一步,工程更简单,训练也更稳定。

GRPO(Group Relative Policy Optimization)则进一步强调“相对好坏”而不是绝对打分。它让模型针对同一个问题先生成一组候选答案,再在组内比较谁更好、谁更差,然后根据这个相对排名更新策略。它的直觉很像班级作文比赛:不是先给每篇作文一个绝对分,而是先把同一组作文排个名次,再让模型朝更优答案的方向调整。GRPO 的优势在于省掉了沉重的价值网络(Critic),因此特别适合数学推理、代码生成这类可以比较优劣、但很难稳定打绝对分的任务。

假设空间、容量与归纳偏置

同一份训练数据,之所以会被不同模型学出完全不同的规律,根源在于每个模型都自带一套“允许学什么、不允许学什么”的结构约束。假设空间(Hypothesis Space)、模型容量(Model Capacity)与归纳偏置(Inductive Bias)共同描述的,就是这套约束。

假设空间

假设空间(Hypothesis Space)是模型可表达函数的集合,常记为 \(\mathcal{H}\):

\[\mathcal{H}=\{f_\theta:\theta\in\Theta\}\]

这里 \(f_\theta\) 是由参数 \(\theta\) 决定的预测函数, \(\Theta\) 是参数可取的范围。这个定义的关键不在于“参数有多少”,而在于模型最终允许出现哪些映射形状。例如,一元线性回归的假设空间只包含直线;二次多项式回归的假设空间包含抛物线;深度神经网络的假设空间则更大,能表示复杂得多的非线性函数。

因此,训练并不是在所有可能函数中盲目搜索,而是在某个特定假设空间里找一个最合适的函数。假设空间太小,真实规律可能根本装不进去;假设空间太大,模型又容易把偶然噪声也解释成模式。

模型容量

模型容量(Model Capacity)描述的是假设空间的表达能力有多强,也就是模型能拟合多复杂规律。容量高,不代表一定更好;它只表示模型“有能力”表示复杂函数。是否真的学得好,还取决于数据量、正则化、优化过程和任务本身。

容量可以从多个角度理解。参数更多通常意味着容量更高,但这不是唯一标准;树的深度、核方法的核函数形式、特征维度、网络层数、隐藏维度、注意力头数,都会改变容量。工程上常用一个朴素判断:如果模型连训练集主要结构都拟合不了,容量偏低;如果训练集几乎完美、验证集却明显变差,容量往往偏高或约束不足。

容量与复杂度控制始终是一组平衡。表格数据上的浅层树模型可能已经足够;图像、语音、自然语言这类高度复杂任务,则通常需要更高容量的模型族。容量本身不是缺点,关键在于它是否与数据规模和任务难度匹配。

归纳偏置

归纳偏置(Inductive Bias)是模型在有限样本下从已见数据推广到未见数据时,默认采用的结构性偏好。只靠训练集上有限个点,无法唯一确定整个输入空间上的函数;模型之所以还能做出泛化判断,是因为它隐含地偏好某些解释,而排斥另一些解释。

把学习目标写成经验风险最小化时,这一点会更清楚:

\[\hat f=\arg\min_{f\in\mathcal{H}}\hat R_n(f),\qquad \hat R_n(f)=\frac{1}{n}\sum_{i=1}^{n}\ell(f(x_i),y_i)\]

这里 \(\hat R_n(f)\) 是经验风险(Empirical Risk),表示函数 \(f\) 在训练集上的平均损失; \(\hat f\) 是最终选出的模型。关键约束正是 \(f\in\mathcal{H}\):优化并不是在所有可能函数中找最优解,而是在一个被模型结构预先限制过的空间里找解。这个限制本身就是归纳偏置。

归纳偏置的来源很多。线性模型偏好线性关系;KNN(K-Nearest Neighbors)偏好局部相似样本给出相似输出;卷积神经网络(CNN)偏好局部连接与平移等变(Translation Equivariance);树模型偏好分段常数的轴对齐切分;Transformer 则偏好通过注意力在 token 之间建立可变依赖。正则化、数据增强、参数共享、预训练初始化、优化器的更新轨迹,也都会进一步塑造模型的归纳偏置。

表示聚合与池化

池化(Pooling)可以先按一句人话来理解:把一组相邻或相关的特征,压缩成更短、更稳定、更容易继续处理的摘要。它不是重新发明新特征,而是对已有特征做聚合(Aggregation)或下采样(Downsampling)。这里的下采样指:沿某些维度减少位置数或采样点数,让表示尺寸变小、分辨率变粗。例如把 \(4\times 4\) 的特征图压成 \(2\times 2\),或把一长段序列压成更短的摘要向量,都属于下采样。

若把一组输入特征记为 \(x_1,\dots,x_k\),则池化可以抽象写成

\[y=\mathrm{Pool}(x_1,\dots,x_k)\]

这里 \(\mathrm{Pool}\) 可以是最大值(Max Pooling)、平均值(Average Pooling)、求和(Sum Pooling)或更复杂的加权聚合。它们做的事不同,但主线一致:把“多个位置/多个元素的表示”变成“更少的表示”。

池化之所以重要,是因为很多任务并不需要保留每个细节位置的完整分辨率。图像分类不一定关心边缘恰好落在第 17 个还是第 18 个像素;句子分类也不一定要求记住某个情绪词出现在第 6 个还是第 7 个 token。此时,把局部细节适度压缩,往往能提升稳定性、降低计算量,并让后续层更关注“有没有出现模式”,而不是“模式的坐标是否一模一样”。

最常见的几种池化

最大池化(Max Pooling)保留一组特征里最强的那个响应。若某个窗口里有一个边缘、某个关键词或某个邻居信号特别强,最大池化会把它留下来。它更像在问:这一小块区域里,最显著的模式有没有出现。

平均池化(Average Pooling)对一组特征取平均,更强调整体趋势而不是最强局部点。它更像在问:这一块区域总体上激活强不强、语义平均水平如何。

求和池化(Sum Pooling)常见于图网络和集合建模,用于累积总量信息。若节点数量本身有意义,求和会把“有多少邻居/总共多强”也编码进去;平均池化则更强调归一化后的平均强度。

全局池化(Global Pooling)表示不再只看局部窗口,而是直接把整张特征图、整段序列或整个节点集合压成一个向量。例如全局平均池化(Global Average Pooling, GAP)会把一整个空间维度平均掉,得到“每个通道在全局上的平均响应”。自适应池化(Adaptive Pooling)则把输出尺寸预先固定,例如无论输入特征图多大,最终都压成 \(1\times 1\) 或 \(7\times 7\)。

不同网络里的含义

在卷积神经网络(CNN)里,池化最经典的含义是沿空间维度做局部下采样。例如一张特征图经过 \(2\times 2\) 最大池化后,宽高会缩小,局部最强响应被保留下来。它的直接收益有三点:减小特征图尺寸、扩大后续层的感受野(Receptive Field)、并降低模型对小幅平移和局部扰动的敏感度。

在时序模型和文本模型里,池化更常表示沿时间或序列长度维度做聚合。例如把所有 token 表示做平均池化,得到整句向量;把一段音频帧表示做最大池化,得到“这一整段里最强的模式”。这里池化的重点不再是二维空间下采样,而是把变长序列压成固定长度表示,方便做分类、检索或相似度计算。

在图神经网络(GNN)里,池化有两层常见含义。第一层是邻域聚合(Neighborhood Aggregation):一个节点把邻居表示做均值、求和或最大值,再更新自己;这可以理解为“节点级局部池化”。第二层是图级读出(Graph-level Readout):把整张图的节点表示再做一次全局聚合,得到整个图的表示,用于图分类、图回归等任务。

在 Transformer 里,池化通常不再以“池化层”这一模块形式高频出现,但概念仍然存在。句子分类常取 \([\mathrm{CLS}]\) 位置表示,或对所有 token 做平均池化;Embedding 模型也常对最后一层隐藏状态做 mean pooling / max pooling 得到句向量。进一步看,注意力(Attention)本身也可以理解成一种带内容依赖的加权聚合:区别只在于普通池化的规则通常固定,而注意力的权重是由输入动态决定的。

池化到底保留了什么、丢掉了什么

池化保留的是摘要信息,丢掉的是更精细的位置细节。最大池化更偏向“是否出现过显著模式”,平均池化更偏向“整体平均状态如何”,求和池化则更偏向“总量有多大”。因此,池化总带有一种 trade-off:表示更紧凑、更稳、更省算力,但精确定位能力会下降。

这也是为什么不同任务会选择不同聚合方式。图像分类往往欢迎一定程度的位置不敏感,因此池化很自然;语义检索希望一整句压成一个句向量,因此句级池化很常见;但像语义分割、目标检测、序列标注这类任务,输出本身依赖逐位置判断,就不能过早把位置信息池掉,否则细粒度边界会被抹平。

上采样、插值与转置卷积

若说下采样(Downsampling)是在压缩表示,那么上采样(Upsampling)就是反过来把较粗的表示扩展回更细的空间分辨率。它做的不是凭空创造新信息,而是把低分辨率特征重新铺回更高分辨率的位置网格中,方便恢复空间结构、边界或局部细节。

插值(Interpolation)是最直接的上采样方式。最邻近插值(Nearest Neighbor Interpolation)相当于把原像素或原特征直接复制到更密的网格里,速度快、实现简单,但边界可能显得生硬;双线性插值(Bilinear Interpolation)则按周围位置做平滑加权,结果更连续,但也更容易把边界抹平。它们的共同特点是:上采样规则是固定的,不需要学习参数。

转置卷积(Transposed Convolution)则是可学习的上采样。它不是“把普通卷积矩阵简单转置后就 magically 还原图像”,而是指:若把普通卷积看作一个线性算子,转置卷积对应的是这个线性算子的转置形式,因此能够把较小的特征图映射到较大的特征图。因为它带有可学习卷积核,所以模型可以学习“该怎样把粗特征展开成更适合任务的细特征”。

在视觉任务里,这三者的分工很常见。语义分割、图像生成、超分辨率、U-Net 解码器、扩散模型解码器都需要上采样:有时先用插值把尺寸放大,再接普通卷积细化;有时直接用转置卷积一步完成“放大 + 学习性重组”。前者通常更稳、更少棋盘格伪影(Checkerboard Artifacts),后者表达力更强,但更依赖实现细节与核大小、步幅(Stride)设置。

泛化、过拟合与偏差—方差

机器学习真正关心的不是训练集上错多少,而是模型离开训练集之后还能否维持稳定表现。泛化(Generalization)、过拟合(Overfitting)、欠拟合(Underfitting)与偏差—方差权衡(Bias–Variance Tradeoff)描述的,就是这件事。

泛化

泛化(Generalization)指模型在未见样本上的表现。若训练数据与未来输入都来自同一数据分布 \(P(X,Y)\),则模型的总体风险可写成:

\[R(f)=\mathbb{E}_{(x,y)\sim P}\big[\ell(f(x),y)\big]\]

这里 \(R(f)\) 是真实风险(Population Risk),表示模型 \(f\) 在整个真实分布上的平均损失; \(\ell(f(x),y)\) 是单样本损失;期望 \(\mathbb{E}\) 表示对所有可能样本做平均。训练时真正能看到的只有有限样本,因此优化的通常是经验风险 \(\hat R_n(f)\),而不是这个理想化的总体风险。

训练误差与测试误差之间的差距,常称为泛化间隙(Generalization Gap)。间隙小说明模型在未见数据上比较稳定;间隙大则说明模型过度依赖训练样本中的偶然细节。

过拟合与欠拟合

欠拟合(Underfitting)表示模型过于简单,连训练集里的主结构都学不出来;过拟合(Overfitting)表示模型对训练集学得过细,把噪声、异常点和偶然波动也当成了规律。两者都属于泛化失败,只是失败方式不同。

判断时通常同时看训练误差与验证误差。欠拟合时,训练误差和验证误差都偏高;过拟合时,训练误差可能很低,但验证误差明显更高。前者更像“模型看不懂题”,后者更像“模型把练习册答案背熟了,却没有真正掌握规律”。

过拟合并不只由参数多导致。高维稀疏特征、标签噪声、样本量不足、分布偏移、数据泄露、过长训练时间和过弱正则化,都会放大过拟合风险。欠拟合则常见于模型容量不足、特征表达太弱、训练尚未收敛,或者任务本身需要非线性而模型只允许线性表达。

偏差与方差

偏差(Bias)与方差(Variance)是分析泛化误差来源的经典视角。对平方损失(Squared Loss),常见分解写成:

\[\mathbb{E}\big[(Y-\hat f(X))^2\big]=\mathrm{Bias}^2+\mathrm{Variance}+\sigma^2\]

左边的 \(\mathbb{E}[(Y-\hat f(X))^2]\) 是模型的平均平方误差; \(\mathrm{Bias}^2\) 表示模型平均预测与真实函数之间的系统性偏离; \(\mathrm{Variance}\) 表示模型对训练样本波动的敏感度; \(\sigma^2\) 是数据本身不可约的噪声(Irreducible Noise),即使模型和训练过程都完美,也无法完全消除。

高偏差通常对应模型表达能力不足,例如用直线去拟合强非线性关系;高方差通常对应模型过于敏感,例如少量训练样本变化就会让决策边界大幅摆动。工程上,降低偏差常靠更强模型、更好特征和更充分训练;降低方差常靠更多数据、正则化、数据增强、早停(Early Stopping)和集成学习(Ensemble Learning)。很多建模决策,本质上都是在这两类误差之间做权衡。

经验风险最小化与正则化

大部分监督学习训练都可以概括成同一条主线:先定义单样本损失,再在训练集上取平均形成经验风险,最后通过优化算法把它压低。正则化(Regularization)是在这条主线之上加入额外约束,用来控制复杂度并改善泛化。

经验风险最小化

经验风险最小化(Empirical Risk Minimization, ERM)是统计学习的基本训练原则。设训练集为 \(\mathcal{D}=\{(x_i,y_i)\}_{i=1}^{n}\),则经验风险定义为:

\[\hat R_n(f)=\frac{1}{n}\sum_{i=1}^{n}\ell(f(x_i),y_i)\]

这里 \(n\) 是样本数, \(f(x_i)\) 是模型对第 \(i\) 个样本的预测, \(y_i\) 是真实标签, \(\ell\) 是损失函数。经验风险最小化就是在假设空间 \(\mathcal{H}\) 中寻找让这条平均损失最小的函数:

\[\hat f_{\mathrm{ERM}}=\arg\min_{f\in\mathcal{H}}\hat R_n(f)\]

这条原则覆盖范围极广。线性回归最小化的是平方误差经验风险,逻辑回归和多分类神经网络最小化的是交叉熵经验风险,序列标注模型最小化的是序列级条件对数似然。算法形式不同,骨架是一致的。

正则化

正则化(Regularization)是在经验风险之外,再加入一个偏好“更简单、更平滑、更稳定”解的约束项。常见写法是:

\[\hat f=\arg\min_{f\in\mathcal{H}}\hat R_n(f)+\lambda\,\Omega(f)\]

这里 \(\Omega(f)\) 是正则项(Regularizer),刻画模型复杂度; \(\lambda\) 是正则化强度,决定“拟合训练集”和“控制复杂度”之间的权衡。 \(\lambda\) 越大,模型越保守;越小,模型越自由。

L2 正则(L2 Regularization)偏好较小权重,常写成 \(\Omega(f)=\|\mathbf{w}\|_2^2\);L1 正则(L1 Regularization)偏好稀疏解,常写成 \(\Omega(f)=\|\mathbf{w}\|_1\)。更广义地看,早停、Dropout、数据增强、权重共享、标签平滑、参数冻结、低秩适配,都是在不同层面对模型自由度施加约束,因此都可以看作正则化思想的工程实现。

IID 与分布偏移

机器学习中的很多训练与评估结论,都建立在一个默认前提上:训练样本与未来样本来自同一统计机制。这个前提通常写成 IID(Independent and Identically Distributed,独立同分布)假设。只要这个前提破坏,训练集表现与线上表现之间就可能出现明显断裂。

IID 假设

设样本对 \((x_i,y_i)\) 来自某个联合分布 \(P(X,Y)\),IID 假设写成:

\[(x_1,y_1),\dots,(x_n,y_n)\overset{\mathrm{iid}}{\sim}P(X,Y)\]

这里“独立(Independent)”表示一个样本是否出现,不影响另一个样本的生成;“同分布(Identically Distributed)”表示所有样本都来自同一个联合分布 \(P(X,Y)\)。这个假设让训练集平均损失能够作为总体风险的近似,也让交叉验证、置信区间和很多泛化理论成立。

IID 是理想化近似,而不是自然界的铁律。时间序列、推荐系统、金融交易、医疗数据、A/B 实验日志、用户行为数据,常常都存在相关性、群组效应、时间漂移或采样偏差,因此不能机械套用 IID 设定。

分布偏移

当训练分布与测试分布不一致时,就发生了分布偏移(Distribution Shift):

\[P_{\mathrm{train}}(X,Y)\neq P_{\mathrm{test}}(X,Y)\]

分布偏移有几种常见形式。协变量偏移(Covariate Shift)指 \(P(X)\) 变化,而 \(P(Y|X)\) 基本稳定;例如线上用户年龄结构变了,但“给定用户画像时是否点击”的规律没明显变。标签偏移(Label Shift)指 \(P(Y)\) 变化,例如欺诈率在促销期突然上升。概念漂移(Concept Drift / Concept Shift)指 \(P(Y|X)\) 本身发生变化,例如垃圾邮件发送策略升级后,原来有效的文本模式不再可靠。

因此,训练集、验证集与测试集的切分不能只追求随机均匀,还必须尽量模拟未来部署环境。若线上是时间推进场景,测试集就应按时间后移;若线上按用户或设备泛化,切分就应按实体隔离;若业务分布持续漂移,还需要做持续监控、重训和再校准。分布偏移不是评估里的边角问题,而是机器学习系统走向生产后的主要失效来源之一。

数据集工程

数据集工程(Dataset Engineering)决定了模型看到什么、以什么尺度看到、又会被哪些偏差误导。很多所谓“模型问题”,根源其实是数据问题:标签噪声、分布漂移、类别极不均衡或特征泄漏,都会直接扭曲训练结果。

数据划分

数据划分的目标,是把学参数、做模型选择、汇报最终结果这三件事严格隔离开。若同一批数据既用来训练参数,又用来调超参数,最后还拿来汇报效果,评估结果通常会乐观得不真实,因为模型已经间接“看过”了答案。

从统计学习角度看,这三类数据分别承担三种不同职责:训练集负责让模型学习参数;验证集负责帮助人或训练流程做工程决策;测试集负责模拟真正的未知数据,给出最后一次、尽量无偏的泛化评估。三者分工清楚,模型评估才有可信度。

训练集

训练集(Training Set)用于更新模型参数。监督学习中,训练集包含输入 \(x\) 与标签 \(y\);模型在这批样本上计算损失(Loss)、反向传播梯度(Gradient)并更新参数,因此训练集直接决定“模型学到了什么”。它回答的问题是:在已观测样本上,模型有没有学会输入与输出之间的对应关系。

训练集通常应占数据的大头,因为参数学习需要足够多的样本来稳定估计模式。实践中常见比例是 70% 到 80%,但这不是固定规则:若数据总量非常大,训练集比例可以更高;若数据本来就少,则往往需要把更多精力放在交叉验证(Cross Validation)而不是死守固定比例。

训练集上的误差通常是三者里最低的,这并不说明模型已经具有泛化能力。一个模型完全可能在训练集上表现极好,却只是记住了样本中的噪声与偶然性。训练集成绩更多反映“拟合能力”,而不是“真实上线表现”。

验证集

验证集(Validation Set)用于模型选择(Model Selection)和超参数调优(Hyperparameter Tuning)。它不直接参与参数更新,但会影响训练流程中的关键决策,例如学习率(Learning Rate)、正则化强度、模型深度、树的数量、batch size、阈值选择,以及是否执行 Early Stopping。

验证集回答的问题不是“模型能不能学会”,而是:在若干候选配置里,哪一个更可能在新数据上表现最好。因此,验证集像训练过程中的“模拟考试”:它不是最终成绩单,但会决定你在训练期间如何改模型、如何调参数、何时停止训练。

验证集通常占总数据的 10% 到 15% 左右。若数据量很小,单独留出一份验证集的代价会较高,此时更常见的做法是使用 \(K\) 折交叉验证,让每个样本轮流充当验证数据,以减少一次随机划分带来的偶然性。交叉验证的细节放在后面的“模型评估”部分展开。

测试集

测试集(Test Set)用于最终评估模型的泛化能力(Generalization)。它应尽量只在方案冻结之后使用:模型结构、超参数、训练策略、阈值和后处理规则都不再修改时,才在测试集上做一次最终评估。它回答的问题是:如果把模型部署到真实世界,它在新样本上的表现大致会怎样。

测试集通常占总数据的 10% 到 15%。它的重要性不在于比例有多大,而在于它必须保持“未参与决策”。如果开发过程中反复查看测试集结果,并据此继续改模型,那么测试集就已经被污染,不再是独立评测,而变成了另一个隐性的验证集。

因此,测试集更像真正的“高考卷”或“盲测集”:它的价值在于最后一次、尽量无偏的评估,而不是参与训练流程本身。

如何划分数据集

最常见的简单划分是训练集 / 验证集 / 测试集 = 70% / 15% / 15%,或 80% / 10% / 10%。这种划分适合样本量较大、类别分布较稳定的任务,因为单次随机切分已经足以给出相对稳定的训练与评估结果。

当数据量较小、类别极不平衡、或者不同子群体差异明显时,划分策略就必须更谨慎。分类任务常采用分层抽样(Stratified Split),确保训练、验证、测试三部分的类别比例大致一致;时间序列任务则必须按时间顺序切分,避免未来信息泄漏到过去;用户级、设备级、病人级任务常需要按实体分组切分,防止同一实体的样本同时出现在训练集和测试集中,造成过于乐观的结果。

因此,“如何划分”本身就是建模的一部分。划分方式若与真实部署场景不一致,即使指标很好,也可能只是评估设定过于宽松,而不是真正泛化能力强。

数据泄露

数据泄露(Data Leakage)指测试集或验证集中的信息以直接或间接方式进入训练过程,从而导致模型评估结果虚高。它的危险不在于“代码报错”,而在于模型会表现得看似极好,却无法在真实新数据上复现。

最常见的数据泄露有几类。第一类是先对全量数据做预处理,再切分数据,例如先用全量数据计算标准化均值和方差,再划分训练 / 测试集;这样测试集的信息已经进入了训练流程。第二类是用测试集反复调参,例如每改一次模型就看一次测试集成绩,直到测试集最好看为止。第三类是特征中混入未来或标签信息,例如用预测时不可能知道的字段做输入,或把目标变量的某种变形偷偷带进特征。

避免数据泄露的原则只有一句:任何依赖数据分布统计量、特征构造规则、模型选择决策或阈值选择的步骤,都只能在训练集内部完成,再把同样的变换应用到验证集和测试集。标准化、特征选择、缺失值填补、目标编码(Target Encoding)、降维(PCA)和重采样(Resampling)都要遵守这一原则。

因此,数据集划分不只是“把数据分三份”这么简单,而是整个实验设计(Experimental Design)的一部分。只有训练集、验证集、测试集的职责边界清晰,交叉验证使用得当,且数据泄露被严格控制,模型指标才具有解释价值和可复现实验意义。

归一化与标准化

归一化(Normalization)与标准化(Standardization)都在解决“不同特征量纲和尺度差异过大”问题,但含义不同。最常见的最小-最大归一化把数据映射到固定区间:

\[x'=\frac{x-x_{\min}}{x_{\max}-x_{\min}}\]

它把特征压到 \([0,1]\),适合像像素值、比例值这类天然有上下界的量。标准化则是减去均值、再除以标准差:

\[z=\frac{x-\mu}{\sigma}\]

标准化后的特征均值为 0、标准差为 1,更适合线性模型、距离模型和很多神经网络优化过程。类比来看,归一化像“把不同长度的尺子都缩到同一长度区间”;标准化像“先平移到共同中心,再按波动尺度统一单位”。

特征工程

特征工程(Feature Engineering)是把原始数据加工成更利于模型学习的表示。它不是“多造点列”这么简单,而是在把领域知识编码进输入空间。例:时间戳可以拆成小时、星期、是否节假日;用户行为日志可以构造近 7 天点击次数、转化率、时间衰减统计;文本可以做 TF-IDF、n-gram 或实体抽取。

类比来看,特征工程像做菜前的备料:同样的原料,如果已经切片、去骨、配好比例,后续烹饪会顺畅得多。经典机器学习对特征工程高度依赖;深度学习则把一部分特征学习自动化了,但在表格数据、推荐、广告和风控里,特征工程仍然决定上限。

类别不平衡处理

类别不平衡(Class Imbalance)指某些类别样本远多于另一些类别。欺诈检测、故障检测、医学筛查里最典型:正类往往极少。如果不处理,模型可能通过“永远预测多数类”获得看似不错的 Accuracy,却在关键少数类上彻底失效。

常见处理方法包括:重采样(过采样少数类、欠采样多数类)、类别加权(Class Weighting)、阈值调整(Threshold Tuning)和使用更合适的指标(如 Precision、Recall、PR-AUC)。例如在信用卡欺诈场景中,正类只占 0.1%,此时“全判正常”会有 99.9% Accuracy,但业务价值几乎为 0。

模型评估

模型评估(Model Evaluation)回答的不是“模型能不能在训练集上做对”,而是“模型在新数据上是否可靠,以及错误代价如何”。不同任务对应的指标重点不同:分类关心类别区分,回归关心数值偏差,排序关心相对顺序。

交叉验证

交叉验证(Cross Validation)在数据较少时特别重要。最常见的 \(K\) 折交叉验证把数据分成 \(K\) 份:每次用其中 1 份做验证、其余 \(K-1\) 份训练,循环 \(K\) 次,最后对 \(K\) 个验证结果取平均。

它的作用像“轮流把不同一份数据拿出来当模拟考试卷”,从而降低一次随机划分带来的偶然性。对小数据集而言,单次划分可能刚好“运气好或坏”;交叉验证则给出更稳定的泛化估计。

校准

校准(Calibration)讨论的是:模型给出的概率值,是否真的能当概率解释。分类模型不只输出“判成哪一类”,还常输出一个置信分数,例如 \(0.9\)。若一个模型在所有“预测概率约为 0.9”的样本子集上,最终真的有约 90% 预测正确,那么它就是校准良好的;若它经常把只有 60% 把握的样本说成 90%,就属于过度自信(Overconfident)。

二分类中,若模型输出正类概率 \(\hat p(x)\in[0,1]\),理想校准条件可写成:

\[P(Y=1\mid \hat p(X)=p)=p\]

这里左边表示:在所有预测概率等于 \(p\) 的样本中,真实为正类的条件概率;右边的 \(p\) 是模型自己报出的概率。两者相等时,概率输出就与真实频率一致。多分类场景下,常把模型最大类别概率当作置信度,并检验“报 80% 置信度的样本,是否真的大约 80% 正确”。

校准与准确率不是同一件事。一个模型可以分类很准,但概率不可靠;也可以概率尺度较准,但分类边界并不最优。前者常见于深层神经网络:argmax 分类结果不错,但 softmax 概率偏尖,置信度系统性偏高。涉及风险控制、医学筛查、自动驾驶、检索重排、多阶段决策时,概率是否可信往往和“分对多少”同样重要,因为阈值决策、人工复核和代价加权都依赖这个概率尺度。

校准的可视化工具通常是可靠性图(Reliability Diagram)。做法是把预测置信度分成若干区间,例如 \([0.0,0.1),[0.1,0.2),\dots\),然后对每个区间分别计算平均置信度与真实准确率。若图上的点接近对角线 \(y=x\),说明校准较好;若点普遍落在对角线下方,说明模型报得比实际更自信;若点在对角线上方,则说明模型偏保守。

常用数值指标是期望校准误差(Expected Calibration Error, ECE):

\[\mathrm{ECE}=\sum_{m=1}^{M}\frac{|B_m|}{n}\,\big|\mathrm{acc}(B_m)-\mathrm{conf}(B_m)\big|\]

这里 \(M\) 是置信度分箱数, \(B_m\) 是第 \(m\) 个置信度区间中的样本集合, \(|B_m|\) 是该区间样本数, \(n\) 是总样本数, \(\mathrm{acc}(B_m)\) 是该区间的实际准确率, \(\mathrm{conf}(B_m)\) 是该区间的平均预测置信度。ECE 的含义很直接:把每个置信区间里“说得多准”和“实际多准”的差值取绝对值,再按样本占比加权平均。ECE 越小,表示整体校准越好。

另一类常见指标是 Brier Score。对二分类,它定义为:

\[\mathrm{Brier}=\frac{1}{n}\sum_{i=1}^{n}(\hat p_i-y_i)^2\]

这里 \(\hat p_i\) 是第 \(i\) 个样本的预测正类概率, \(y_i\in\{0,1\}\) 是真实标签。它既惩罚分类错误,也惩罚概率刻度不准,因此兼顾区分能力与概率质量。与单纯 Accuracy 不同,Brier Score 会区分“错得有多离谱”:把一个负样本报成 \(0.51\) 和报成 \(0.99\),代价并不相同。

工程上最常见的后处理方法是温度缩放(Temperature Scaling)。设原始 logits 为 \(z_i\),则缩放后的 softmax 概率写成:

\[p_i=\frac{\exp(z_i/T)}{\sum_j \exp(z_j/T)}\]

这里 \(T>0\) 是温度参数。 \(T>1\) 会把分布拉平,降低过度自信; \(T<1\) 会把分布压尖,提高置信度。温度参数通常在验证集上通过最小化负对数似然(Negative Log-Likelihood, NLL)来拟合,然后固定用于测试或部署阶段。它不会改变类别排序,因此常能在几乎不影响 Accuracy 的前提下改善概率校准。

分类指标

分类指标通常从混淆矩阵(Confusion Matrix)出发。设正类预测结果统计为真阳性 \(TP\)、假阳性 \(FP\)、真阴性 \(TN\)、假阴性 \(FN\)。不同指标本质上是在回答不同问题:是看“总共判对多少”,还是看“判成正类时有多准”,还是看“真实正类抓到了多少”。

Accuracy

准确率(Accuracy)定义为

\[\mathrm{Accuracy}=\frac{TP+TN}{TP+TN+FP+FN}\]

它衡量“总体上判对了多少比例”,适合类别相对平衡、不同错误代价接近的场景。但在类别极不平衡时会误导:例如癌症筛查里,99% 都是阴性时,模型全判阴性也可能有 99% Accuracy,却毫无检测价值。

Precision

精确率(Precision)定义为

\[\mathrm{Precision}=\frac{TP}{TP+FP}\]

它回答的是:“所有被模型判成正类的样本里,有多少真的为正。”当误报成本很高时,Precision 特别重要。例:垃圾邮件过滤里,如果把正常邮件误判成垃圾邮件代价很高,就要关心 Precision。

Recall

召回率(Recall)定义为

\[\mathrm{Recall}=\frac{TP}{TP+FN}\]

它回答的是:“所有真实正类里,有多少被模型找出来了。”当漏报成本很高时,Recall 更关键。例:医学筛查里漏掉患者可能比多做一次复检更危险,因此 Recall 往往比 Precision 更重要。

F1 Score

F1 值(F1 Score)是 Precision 与 Recall 的调和平均:

\[F_1=\frac{2\cdot \mathrm{Precision}\cdot \mathrm{Recall}}{\mathrm{Precision}+\mathrm{Recall}}\]

之所以用调和平均而不是普通平均,是因为它会惩罚“一高一低”的不平衡情况。若一个模型 Precision 极高但 Recall 很低,它并不能拿到高 F1。F1 适合正负样本不平衡、且希望兼顾漏报与误报的场景。

AUC-ROC

AUC-ROC 衡量模型在不同分类阈值下区分正负样本的整体能力。ROC 曲线横轴是假阳性率(False Positive Rate),纵轴是真阳性率(True Positive Rate)。AUC 是曲线下面积,范围在 \([0,1]\);越接近 1,说明模型越能把正样本排在负样本前面。

它不依赖某一个固定阈值,因此适合比较“排序能力”。但在极端不平衡数据上,PR 曲线(Precision-Recall Curve)常更敏感,因为 ROC 容易被大量真阴性“冲淡”。

回归指标

回归指标(Regression Metrics)衡量预测值与真实值之间的数值偏差。它们关注的不是“判对类别”,而是“偏差有多大、对大误差是否敏感、模型解释了多少波动”。以房价预测为例,预测 300 万和真实 320 万之间的差距,就是典型回归误差。

MAE

平均绝对误差(Mean Absolute Error, MAE)定义为

\[\mathrm{MAE}=\frac{1}{N}\sum_{i=1}^{N}|\hat y_i-y_i|\]

它直接度量“平均差了多少个原始单位”,解释最直观。若房价单位是万元,MAE=12 就表示平均误差约 12 万元。由于使用绝对值,MAE 对离群点没有 MSE 那么敏感。

MSE

均方误差(Mean Squared Error, MSE)定义为

\[\mathrm{MSE}=\frac{1}{N}\sum_{i=1}^{N}(\hat y_i-y_i)^2\]

平方会放大大误差,因此 MSE 对离群点更敏感。它常用于你希望“大错要被重罚”的场景。高斯噪声假设下,最小化 MSE 还对应最大似然估计,因此它不仅是工程指标,也是概率建模结果。

RMSE

均方根误差(Root Mean Squared Error, RMSE)是

\[\mathrm{RMSE}=\sqrt{\mathrm{MSE}}\]

它保留了 MSE 对大误差更敏感的性质,同时把单位拉回原始量纲,因此更易解释。若房价 RMSE 为 20 万元,可以直接理解为“典型误差量级约 20 万元”。

R²

\[R^2\](决定系数,Coefficient of Determination)回答的是:相比于最朴素的瞎猜基线,你的回归模型到底把预测提升了多少。要理解它,只需要在脑子里放两条线:一条是“什么都不知道时只能猜平均值”的水平线,另一条是模型给出的预测曲线。

先看最朴素的基线。假设你要预测一批房子的价格,但你手里没有面积、地段、楼龄这些特征,别人却逼着你给出预测。此时最不容易挨打的办法,不是胡乱报一个数字,而是对所有房子都猜样本平均价 \(\bar y\)。在散点图上,这对应一条横向的水平线。

真实房价 \(y_i\) 会散落在这条平均线的上下。每个点到平均线的垂直距离 \(y_i-\bar y\),就是“瞎蒙平均值”时犯下的误差。把这些误差平方后全部加起来,就得到

\[\sum_i(y_i-\bar y)^2\]

这就是公式里的分母。它衡量的不是模型误差,而是这批数据本身原来就有多分散、多混乱。也可以把它理解为目标变量的总波动、总混沌程度,或者说“在完全不用特征时,世界原本有多少东西解释不了”。

现在再看你的模型。你训练出一个回归模型,它根据输入特征给出预测 \(\hat y_i\)。在图上,这不再是那条死板的水平线,而是一条试图穿过散点云中心的预测曲线。模型当然不可能完美,所以每个真实值 \(y_i\) 与预测值 \(\hat y_i\) 之间仍会有垂直误差,这个误差就是残差(Residual)。

把这些模型仍然没解释掉的误差平方后加起来,就得到

\[\sum_i(\hat y_i-y_i)^2\]

这就是公式里的分子,也叫残差平方和(Residual Sum of Squares, RSS)。它代表模型已经尽力之后,世界上依然残存的混沌。分子越小,说明模型越贴近真实数据;分子越大,说明模型虽然复杂,但其实没把问题解释清楚。

于是

\[R^2=1-\frac{\sum_i(\hat y_i-y_i)^2}{\sum_i(y_i-\bar y)^2}\]

这条式子就可以直接读成一句大白话:先看模型还剩下多少解释不了的波动,再除以最开始总共有多少波动,得到“模型搞不定的比例”;最后用 1 减掉它,剩下的就是模型成功解释掉的波动比例。

因此,若 \(R^2=0.8\),意思不是“正确率 80%”,而是目标变量原本有 100 份波动,模型大约解释掉了其中 80 份,只剩 20 份还没解释;若 \(R^2=0\),说明你的模型折腾半天,效果和“永远预测平均值”完全一样;若 \(R^2<0\),则表示模型比这个最朴素基线还差,常见原因是模型设错了、特征没信息,或实现上有 bug。

从老板视角看, \(R^2\) 的灵魂拷问其实只有一句:相比直接拿平均值糊弄事,你这个复杂回归模型到底多解释了多少真实波动。这也是为什么 \(R^2\) 特别适合回答“模型有没有真正利用特征学到东西”,但它不能替代 MAE、RMSE——因为 \(R^2\) 讲的是解释比例,而不是误差到底有多少个原始单位。

优化算法

优化算法(Optimization Algorithms)解决的问题非常朴素:模型参数该往哪个方向改,才能让损失函数持续下降。只要训练目标能写成“最小化某个损失函数”,背后就需要一套更新参数的规则。线性回归、逻辑回归、神经网络、大语言模型训练,本质上都绕不开这个问题。

这里要先分清两件事。优化(Optimization)关心的是“训练损失能不能降下来”;泛化(Generalization)关心的是“模型在新样本上好不好”。一个优化器可能把训练集拟合得很好,但泛化依然一般;反过来,一个优化器如果连训练损失都压不下去,模型通常也谈不上有效。因此优化算法决定的是你如何走向一个解,而不是直接保证这个解一定最好。

梯度下降

梯度下降(Gradient Descent)是最核心的一阶优化思想。设损失函数为 \(L(\theta)\),参数为 \(\theta\),则梯度 \(\nabla_\theta L(\theta)\) 给出“损失上升最快的方向”。既然梯度指向上坡,那么要让损失下降,就应沿着它的反方向更新参数:

\[\theta_{t+1}=\theta_t-\eta\,\nabla_\theta L(\theta_t)\]

这里 \(\theta_t\) 是第 \(t\) 步的参数, \(\eta\) 是学习率(Learning Rate),决定每一步走多大; \(\nabla_\theta L(\theta_t)\) 是当前位置的斜率信息。学习率太大,容易一步跨过谷底甚至震荡发散;学习率太小,又会下降得极慢。它像蒙着雾下山:梯度告诉你脚下哪边更陡,学习率决定你每次迈多大步。

为什么很多模型不直接“解公式”,而要反复迭代?因为在深度学习里,参数维度极高,损失面又往往非凸(Non-convex),通常没有漂亮的闭式解(Closed-form Solution)。这时最现实的办法不是一次算出全局最优,而是利用局部斜率,一步一步把损失往下压。

当总损失是逐样本损失的平均时,梯度下降还可以写得更具体:

\[L(\theta)=\frac{1}{N}\sum_{i=1}^{N}\ell(\theta;x_i)\] \[\nabla_\theta L(\theta)=\frac{1}{N}\sum_{i=1}^{N}\nabla_\theta \ell(\theta;x_i)\]

这也回答了“为什么可以批量喂输入”:梯度对求和是线性的,整体梯度等于逐样本梯度的平均,所以可以并行算每个样本的梯度,再求平均后统一更新参数。

满足这种“逐样本求和/求平均”结构的损失函数其实非常多。典型例子包括:线性回归里的均方误差(MSE)、平均绝对误差(MAE),二分类里的 logistic loss / binary cross-entropy,多分类里的交叉熵(Cross-Entropy),语言模型训练里的负对数似然(Negative Log-Likelihood, NLL)。它们都可以写成“每个样本先各自算一份损失,再在整个数据集上取平均”的形式,因此天然适合 mini-batch 训练。

但并不是所有目标都能严格写成这种完全独立的逐样本平均。若损失显式依赖样本之间的相对关系,情况就会复杂一些。例如排序学习里的 pairwise/listwise loss、度量学习中的 triplet loss,以及对比学习里的 InfoNCE,都会让一个样本的损失依赖同一个 batch 中的其他样本。此时虽然仍然可以按 batch 计算梯度,但它已经不是“每个样本各算各的、最后简单平均”那么干净的分解了。

工程上还常见另一种情况:目标函数可以写成“逐样本平均损失 + 正则项(Regularization)”。例如

\[L(\theta)=\frac{1}{N}\sum_{i=1}^{N}\ell(\theta;x_i)+\lambda\Omega(\theta)\]

其中 \(\Omega(\theta)\) 可以是 \(\|\theta\|_2^2\) 这类参数惩罚项。前半部分仍然按样本分解,后半部分则是直接作用于参数本身,而不对应某一个单独样本。很多现代训练目标,本质上都是这两部分的组合。

几个常用训练量需要先分清:

  • 批大小(Batch Size):一次更新使用多少个样本。
  • 步(Step / Iteration):一次参数更新。
  • 轮(Epoch):完整遍历一次训练集。

若训练集大小为 \(N\),batch size 为 \(B\),则每个 epoch 的步数约为 \(\lceil N/B\rceil\)。工程里经常会说“训练了多少 step”,因为真正发生参数变化的是 step,而不是 epoch 这个更粗的计数单位。

批量梯度下降(BGD)

批量梯度下降(Batch Gradient Descent, BGD)每次都用整个训练集来计算一次精确梯度,再更新参数。这里的 batch 指的不是现代深度学习里常说的一个 mini-batch,而是“整批训练数据”。它的优点是方向最稳定、梯度方差最小;缺点是每一步都很贵,数据一大就几乎不可用。它更适合小数据集、凸优化问题,或教材里说明“梯度下降原理”时使用。

随机梯度下降(SGD)

随机梯度下降(Stochastic Gradient Descent, SGD)每次只用一个样本的梯度做更新。它的方向噪声很大,看起来像“跌跌撞撞地下山”,但每一步极便宜、更新极频繁,因此在数据流式到来或样本极多时很有价值。

  • 优点:更新快、内存开销小、天然适合在线学习(Online Learning)与流式数据(Streaming Data)。
  • 优点:梯度噪声有时反而是好事,更容易离开鞍点(Saddle Point)和较差的局部极小。
  • 缺点:轨迹抖动大,若学习率控制不好,训练容易不稳定。

它像店长根据每一位新顾客的反馈立刻调价:反应很快,但也容易被个别顾客带偏。

适用场景:当你需要用最新样本尽快产生参数更新时,SGD(batch size=1)是最直接的选择,典型包括:

  • 在线学习(Online Learning)/流式数据(Streaming Data):样本持续到来,要求增量更新,而不是离线反复扫全量数据。
  • 分布漂移(Distribution Shift)与非平稳(Non-stationary)环境:用户偏好、市场、策略对抗等持续变化,需要快速跟踪新分布。
  • 低延迟更新需求:例如广告/推荐/风控的在线校准,需要“见到一条新反馈就更新一点”。
  • 资源受限或样本极大:内存无法容纳大 batch 或无法频繁计算全量梯度时,用单样本更新换取更低的每步计算与存储成本。

在现代深度学习里,若使用 GPU/TPU 训练,大多数时候会用小批量梯度下降来兼顾吞吐与稳定性;纯 SGD 更常出现在在线/增量训练与部分强化学习(Reinforcement Learning, RL)设置中。

小批量梯度下降(Mini-batch SGD)

小批量梯度下降(Mini-batch SGD)是在 BGD 与 SGD 之间折中:每次用一个 batch 的平均梯度更新。它既能利用 GPU 的并行算力,又保留一定梯度噪声,因此现代深度学习几乎都在这个范式下训练。

batch 太小,梯度估计噪声会很大;batch 太大,虽然每步更稳定,但显存压力更高、更新频率更低,有时还会让优化和泛化都变钝。因此 batch size 不是“越大越好”,而是吞吐、稳定性、显存和泛化之间的折中。

动量法(Momentum)

单纯的梯度下降在“峡谷形”损失面里很容易左右来回震荡:沿陡峭方向上下摆动,沿真正有用的谷底方向前进却很慢。动量法(Momentum)的直觉是:不要只看当前这一脚的斜率,而要把过去几步的方向累积成一种“惯性”。

\[v_{t+1}=\beta v_t+(1-\beta)g_t,\quad \theta_{t+1}=\theta_t-\eta v_{t+1}\]

其中 \(g_t\) 是当前梯度, \(v_t\) 是累计出来的速度, \(\beta\in[0,1)\) 控制“记住过去多少信息”。 \(\beta\) 越大,方向越平滑、惯性越强;越小,则越接近普通梯度下降。类比来看,它像推一个有重量的小球下山:不会因为脚下的微小凸凹就频繁改道,而会沿长期更一致的下降方向滚动。

momentum

AdaGrad / RMSProp

AdaGrad 与 RMSProp 属于自适应学习率(Adaptive Learning Rate)方法。它们的核心思想是:不同参数的梯度尺度不同,不应该所有维度都用同一个固定步长。历史上梯度很大的维度,后续步子要缩小;梯度稀疏或很小的维度,则可以走得更积极。

AdaGrad 累积历史平方梯度:

\[s_{t+1}=s_t+g_t\odot g_t,\quad \theta_{t+1}=\theta_t-\eta\,\frac{g_t}{\sqrt{s_{t+1}}+\epsilon}\]

其中 \(g_t\odot g_t\) 表示逐元素平方, \(\epsilon\) 是数值稳定项。这样一来,历史上梯度一直很大的维度会被自动缩小学习率。AdaGrad 在稀疏特征(Sparse Features)任务里很有效,例如早期的文本与推荐场景;但它的问题是 \(s_t\) 只增不减,训练到后期学习率可能衰减得过头,参数几乎不再动。

RMSProp 用指数滑动平均替代“无限累积”,缓解这个问题:

\[s_{t+1}=\rho s_t+(1-\rho)(g_t\odot g_t),\quad \theta_{t+1}=\theta_t-\eta\,\frac{g_t}{\sqrt{s_{t+1}}+\epsilon}\]

这样历史信息会逐步“遗忘”,使学习率缩放更关注近期梯度尺度。可以把 AdaGrad 理解成“终身记账”,而 RMSProp 更像“滚动记账”。

Adam

Adam(Adaptive Moment Estimation)把动量法(Momentum)的一阶矩估计与 RMSProp 的二阶矩估计结合起来,因此它同时解决优化中的两个核心痛点:方向感(往哪走)与节奏感(每步走多大)。直觉上,可以把它理解为“带惯性的方向盘 + 自动变速箱”:方向由平均梯度决定,步长由梯度的尺度自动缩放。

一阶矩:方向感(Momentum)
\[m_{t+1}=\beta_1 m_t+(1-\beta_1)g_t\]
  • 索引约定:第 \(t\) 次更新先在 \(\theta_t\) 处计算 \(g_t\),再把它并入动量得到 \(m_{t+1}\);下标 \(t+1\) 表示“更新后状态”,不是未来信息。
  • \(m_{t+1}\):并入 \(g_t\) 后的一阶矩(动量)估计。
  • 右边第一项 \(\beta_1 m_t\):把历史动量按系数 \(\beta_1\) 保留下来,表示“历史方向对新方向的贡献”。
  • 右边第二项 \((1-\beta_1)g_t\):把当前梯度按系数 \(1-\beta_1\) 注入动量,表示“当前观测对新方向的贡献”。
  • \(g_t\):第 \(t\) 步的梯度,通常由当前 mini-batch 估计得到(\(g_t=\nabla_\theta L(\theta_t)\))。
  • \(m_t\):一阶矩估计的滑动平均(动量项),可理解为“平均梯度方向”。
  • \(\beta_1\in[0,1)\):动量衰减系数,越大表示记忆越长、方向越平滑。

两项系数满足 \(\beta_1+(1-\beta_1)=1\),因此这是指数滑动平均(Exponential Moving Average, EMA,越近发生的事情,参考价值越大;越久远的事情,参考价值越小)。当 \(m_0=0\) 时,可把它展开为:

\[m_{t+1}=(1-\beta_1)\sum_{k=0}^{t}\beta_1^{t-k}g_k\]

上式说明:越久远的梯度 \(g_k\) 权重按 \(\beta_1^{t-k}\) 指数衰减;经验上可把有效记忆长度理解为 \(O\!\left(\frac{1}{1-\beta_1}\right)\)。因此 \(\beta_1\) 越大,平均窗口越长,方向越平滑但响应越慢;\(\beta_1\) 越小,平均窗口越短,方向更敏捷但更易受噪声影响。

二阶矩:节奏感(RMSProp)

RMSProp(Root Mean Square Propagation)用梯度平方的指数滑动平均(Exponential Moving Average, EMA)来估计每个参数维度的“尺度”,再用该尺度对当前梯度做逐元素归一化,从而把更新步伐控制在更稳定的量级。

\[v_{t+1}=\beta_2 v_t+(1-\beta_2)(g_t\odot g_t),\quad \tilde g_t=\frac{g_t}{\sqrt{v_{t+1}}+\epsilon}\]
  • 索引约定:第 \(t\) 次更新先在 \(\theta_t\) 处计算 \(g_t\),再用它更新得到 \(v_{t+1}\);用 \(v_{t+1}\) 缩放 \(g_t\) 表示“用本次更新后的尺度估计做归一化”,不涉及未来信息。
  • \(v_t\):上一轮更新结束后的二阶原点矩估计(EMA 状态,“更新前的尺度缓存”)。
  • \(v_{t+1}\):梯度的二阶原点矩(Second Raw Moment)估计,逐(梯度)维近似 \(\mathbb{E}[g^2]\),刻画“历史梯度大小”的典型尺度。
  • \(g_t\odot g_t\):当前梯度的逐元素平方(\(\odot\) 为 Hadamard 乘积),只保留幅度信息。
  • \(\sqrt{v_{t+1}}\):均方根(Root Mean Square, RMS)尺度;平方使量纲变为 \(g^2\),开方把量纲还原到 \(g\),从而可与 \(g_t\) 相除。
  • \(\tilde g_t\):按 RMS 尺度归一化后的梯度;分式表示逐元素相除(每个参数维度各自缩放)。
  • \(\beta_2\in[0,1)\):衰减系数,控制尺度估计的记忆长度;越大表示对历史尺度更“长记忆”。
  • \(\epsilon\):数值稳定项,避免分母为 0 或过小。

该缩放把“方向”和“尺度”解耦:方向仍由 \(g_t\) 给出;步长由 \(\sqrt{v_{t+1}}\) 自适应调节。若某维长期梯度偏大,则 \(\sqrt{v_{t+1}}\) 变大、该维更新被压小;若某维长期梯度偏小,则分母较小、该维相对步子更大。

若把 RMSProp 作为独立优化器使用,参数更新可写为 \(\theta_{t+1}=\theta_t-\eta\,\tilde g_t\)。在 Adam 中,同样的 RMS 缩放作用在一阶矩估计上:用 \(\hat m_{t+1}\) 替代 \(g_t\) 作为分子,并在下一节通过偏置修正得到 \(\hat v_{t+1}\) 作为分母。

偏置修正:冷启动校正(Bias Correction)

因为 \(m_0=v_0=0\),训练初期的滑动平均会系统性偏小(“没热起来”)。Adam 用偏置修正把它拉回合理尺度:

\[\hat m_{t+1}=\frac{m_{t+1}}{1-\beta_1^{t+1}},\quad \hat v_{t+1}=\frac{v_{t+1}}{1-\beta_2^{t+1}}\]
  • \(\hat m_{t+1},\hat v_{t+1}\):偏置修正后的估计,用来抵消初始化为 0 导致的早期偏小。
  • 分母 \(1-\beta^{t+1}\):校正“冷启动偏小”的缩放因子。由于初始化为 0,指数滑动平均在经历 \(t+1\) 次更新时只积累了约 \(1-\beta^{t+1}\) 的有效权重,因此会偏小;除以它相当于把估计值按同样比例放大回去。

更严格地说:若假设 \(\mathbb{E}[g_t]=\mu\) 近似稳定,则由递推可得 \(\mathbb{E}[m_{t+1}]=(1-\beta_1^{t+1})\mu\),因此 \(\hat m_{t+1}=\frac{m_{t+1}}{1-\beta_1^{t+1}}\) 是把它改成近似无偏估计。同理可得 \(\hat v_{t+1}\) 的修正。

参数更新:方向 ÷ 尺度
\[\theta_{t+1}=\theta_t-\eta\,\frac{\hat m_{t+1}}{\sqrt{\hat v_{t+1}}+\epsilon}\]
  • \(\theta_t\):第 \(t\) 步参数(权重向量/张量)。
  • \(\eta\):学习率(全局步长系数)。
  • \(\sqrt{\hat v_{t+1}}\):逐元素开方;整项 \(\frac{\hat m_{t+1}}{\sqrt{\hat v_{t+1}}+\epsilon}\) 表示逐元素相除。
  • \(\epsilon\):数值稳定项,避免除以 0 或极小数。

分子给方向,分母给节奏。一个极端例子能看出为什么 Adam 用 \(\mathbb{E}[g^2]\) 而不是方差:若某维梯度连续很多步都是 \(g_t=10\),方差为 0 会导致除法不稳定;但 \(\mathbb{E}[g^2]\approx 100\) 给出稳定尺度,最终更新量级约为 \(10/\sqrt{100}=1\)(再加 \(\epsilon\) 保底)。

Adam 往往更易调参、早期收敛更快,因此在 Transformer、扩散模型和很多深度网络里是默认起点。但它并不是无条件最好:有些任务上,最终泛化仍可能不如精心调过的 SGD。实践中,配合权重衰减(Weight Decay)时,通常会使用 AdamW,把权重衰减从梯度自适应缩放里解耦出来,效果更稳。

AdamW

AdamW(Adam with Decoupled Weight Decay)把权重衰减(Weight Decay)从 Adam 的自适应梯度缩放里解耦出来。原因是:在 Adam 这类自适应方法里,如果你把 L2 正则化写进损失(等价于把 \(\lambda\theta\) 加到梯度里),这个正则项也会被二阶矩 \(\hat v_t\) 的缩放影响,从而导致不同参数维度的“衰减强度”不再可控。

正则化本来应该是一个可控的、与梯度尺度无关的收缩力度;解耦后 \(\lambda\) 的含义更稳定。

对比两种写法会更清楚:

  • 把 L2 正则化并入目标(常被口语化地称为“weight decay”,但在自适应优化器里并不等价):先算 \(g_t=\nabla_\theta L(\theta_t)+\lambda\theta_t\),再把这个 \(g_t\) 送入 Adam 的 \(m_t,v_t\) 与自适应步长。
  • AdamW(解耦权重衰减):先算纯数据梯度 \(g_t=\nabla_\theta L(\theta_t)\) 并完成 Adam 的自适应更新,然后单独对参数做一次权重衰减。

AdamW 的参数更新可写成:

\[\theta_{t+1}=\theta_t-\eta\,\frac{\hat m_{t+1}}{\sqrt{\hat v_{t+1}}+\epsilon}-\eta\,\lambda\,\theta_t\]
  • 前半段 \(-\eta\,\frac{\hat m}{\sqrt{\hat v}+\epsilon}\):Adam 的自适应梯度更新(由数据损失驱动)。
  • 后半段 \(-\eta\,\lambda\,\theta_t\):解耦的 weight decay(参数按比例收缩),其中 \(\lambda\) 是衰减强度。

其中第一项是 Adam 的自适应更新,第二项是独立的权重衰减(等价于每步把权重按比例拉向 0)。这种分离让 \(\lambda\) 更像一个真正可解释的“收缩强度”,在 Transformer 等模型上通常更稳定、更好调。工程实现里常见做法是:对 bias 与归一化层参数(如 LayerNorm 的 \(\gamma,\beta\))不做 weight decay,以免对尺度/偏置项造成不必要的收缩。

Muon

Muon 是一种面向神经网络隐藏层(Hidden Layer)权重矩阵(Weight Matrix)的优化器。它与 Adam/AdamW 的根本差异在于:AdamW 会为每个参数维度单独估计更新尺度,并对梯度/更新量做逐元素(Element-wise)归一化;Muon 则把一个二维权重张量视为一个整体,直接利用矩阵结构来塑造更新方向。因此,Muon 更像一种矩阵感知(Matrix-aware)的优化器。

它的核心做法不是改变“沿梯度下降”这个大方向,而是改变“更新张量应该具有什么几何形状”。典型写法可以概括为:先对梯度做动量(Momentum)累积,再把这个矩阵更新做一次正交化(Orthogonalization)后处理,然后才真正更新参数:

\[M_{t+1}=\beta M_t+(1-\beta)G_t\] \[\Delta W_t=\mathrm{Orth}(M_{t+1}),\quad W_{t+1}=W_t-\eta\,\Delta W_t\]

这里 \(G_t\) 是当前梯度矩阵, \(M_t\) 是动量缓冲, \(\mathrm{Orth}(\cdot)\) 表示把更新矩阵变换到更“接近正交(Orthogonal)”的形状。工程实现里,这一步通常用 Newton-Schulz 迭代(Newton-Schulz Iteration)高效近似完成,因此 Muon 常被概括为“对动量更新做正交化”。

  • 优势:对线性层/MLP/注意力里的二维权重矩阵,Muon 往往能给出更结构化的更新方向;在一些大模型训练设定下,它的训练效率与收敛速度优于 AdamW。
  • 边界:Muon 不是全参数通吃的默认方案。它通常只用于隐藏层的二维参数;embedding、bias、归一化参数、输出层等非二维或语义不同的参数,实践中常继续交给 AdamW。
  • 工程特征:它强调更新矩阵的谱结构(Spectral Structure),而不是单个坐标的独立缩放;因此超参数分组与参数类型划分比 AdamW 更重要。

可以把 AdamW 与 Muon 的差别记成一句话:AdamW 解决“每个参数该走多大步”,Muon 进一步关心“整个矩阵应该以什么形状移动”。因此 Muon 更像是隐藏层矩阵优化的专用工具,而不是对所有参数一视同仁的通用默认项。

学习率调度

学习率(Learning Rate)往往是最敏感的超参数之一。即使优化器相同,只要学习率设错,训练就可能完全失败。学习率调度(Learning Rate Scheduling)/退火(Annealing)的核心思想是:前期用相对大的步长快速下降,后期逐渐减小步长做精细收敛。

常见调度方式包括:

  • Step decay:按 epoch 或 step 乘以固定因子衰减,简单直接。
  • Linear decay:线性下降到较小值或 0,常用于大模型训练后段。
  • Warmup + decay:先小步热身,再进入正常学习率,最后逐步衰减;对 Transformer 和大 batch 训练尤其常见。
  • 余弦退火(Cosine Annealing):将学习率从较大值逐步衰减到较小值,把优化从“高温探索”过渡到“低温收敛”,在训练后期降低梯度噪声(gradient noise)与过冲(overshoot)风险,使参数能在极小值附近稳定细化。余弦曲线在起点与终点的一阶导数为 0,避免阶梯式衰减的突变,因而衰减更平滑、后期更柔和。

Warmup 为什么有用?因为训练刚开始时,参数还处在一个非常“生”的区域,梯度统计不稳定,若一上来就用很大学习率,模型容易发散。先用较小步长热身几百或几千步,再拉到目标学习率,通常更稳。

余弦退火的典型写法(从 \(\eta_{\max}\) 衰减到 \(\eta_{\min}\))为:

\[\eta(t)=\eta_{\min}+\frac{1}{2}(\eta_{\max}-\eta_{\min})\left(1+\cos\left(\pi\frac{t}{T}\right)\right)\]
  • \(\eta(t)\):第 \(t\) 步使用的学习率。
  • \(\eta_{\max}\) / \(\eta_{\min}\):一个退火周期内的最大学习率与最小学习率。
  • \(t\):当前步数(通常从 0 开始计),\(T\):该周期的总步数。

这个公式可以直接做两次代入来验证边界:当 \(t=0\) 时,\(\cos(0)=1\),所以 \(\eta(0)=\eta_{\max}\);当 \(t=T\) 时,\(\cos(\pi)=-1\),所以 \(\eta(T)=\eta_{\min}\)。中间学习率按半个余弦周期平滑下降。

通过余弦(Cosine)提供了一个非常干净的端点平滑(smooth endpoints)性质:在起点和终点处变化率为 0。对上式求导可得

\[\frac{d\eta}{dt}=-\frac{1}{2}(\eta_{\max}-\eta_{\min})\frac{\pi}{T}\sin\left(\pi\frac{t}{T}\right)\]

因此 \(\sin(0)=\sin(\pi)=0\),学习率在周期开始与结束都不会出现突兀的“拐点”。相比之下,step decay 有不连续跳变,linear decay 在末端通常会突然到达下限并停止变化(出现不光滑的折点)。在非凸深度网络里,这种平滑退火往往更稳:前期保持较大步长便于探索,后期自然减小步长便于精细收敛。

工程上常见扩展是余弦重启(Cosine Annealing with Warm Restarts, SGDR):把训练过程切成多个周期,每个周期把 \(t\) 重新从 0 开始计(并可逐周期拉长 \(T\))。在标准 SGDR 中,学习率在周期边界是不连续的:它会在一个周期末端衰减到 \(\eta_{\min}\),并在下一个周期起点从 \(\eta_{\max}\) 重新开始(参数 \(\theta\) 不会重置)。

这种“重启”的作用不是为了制造噪声,而是把优化过程从“后期小步精修”短暂切回“较大步长探索”,以应对非凸问题中的平台区(plateau)与次优盆地(suboptimal basin)。学习率拉高会增大每步更新幅度与梯度噪声(gradient noise)的有效影响,帮助轨迹跳出当前区域并探索新的吸引域;而如果当前区域确实是更稳健的平坦极小值(flat minimal),后续退火通常会把参数再次拉回并在附近更精细地收敛。工程上常见做法是把 \(\eta_{\max}\) 设在“不会破坏稳定性”的范围内;若重启瞬间仍担心不稳定,也可以在每次重启后加一个很短的 warmup,让学习率在少量步数内从较小值爬升到 \(\eta_{\max}\)。

没有一种调度策略对所有任务都最好。真正有效的做法是结合损失曲线、梯度稳定性、验证集表现和训练预算一起看:如果前期降不动,往往学习率偏小;如果剧烈震荡甚至发散,往往学习率偏大;如果后期长期卡在平台区,通常需要更细的衰减策略。

sgdr

集成策略(Ensemble Learning)

集成学习(Ensemble Learning)的核心思想是:不要只信一个模型,而是让多个模型共同投票或共同修正。它背后的统计直觉是:不同模型的误差如果不完全一致,组合后往往比单个模型更稳。类比来看,这像让多个医生会诊:一个人可能看偏,但几个人的综合意见通常更可靠。

Bagging

Bagging(Bootstrap Aggregating)的核心做法是对训练集进行多次自助采样(bootstrap sampling),即反复执行有放回采样(sampling with replacement)生成多个训练子集,并在这些子集上分别训练基模型,以降低方差(Variance)。由于每个模型见到的数据子集略有差异,学到的决策边界不会完全一致;最后对预测结果做平均或多数投票,可抵消一部分过拟合噪声。

例:如果单棵决策树很容易被训练集中的偶然样本带偏,那么训练 100 棵在不同 bootstrap 样本上的树,再投票,通常会比只用 1 棵树稳定得多。这也是随机森林的核心直觉。

Boosting

Boosting 的思路与 Bagging 相反:它不是“并行训练很多彼此独立的模型”,而是“串行训练一串弱学习器(Weak Learners),让后一个模型专门修正前一个模型没做好的部分”。因此它更像“老师批改作业”:每一轮都盯着上轮最容易出错的题继续强化。

以加法模型视角看,Boosting 逐步构造

\[F_M(x)=\sum_{m=1}^{M}\alpha_m h_m(x)\]

其中 \(h_m(x)\) 是第 \(m\) 个弱学习器, \(\alpha_m\) 是它的权重。公式不是为了堆符号,而是在表达:最终模型是“很多个简单模型的加权和”,每一轮都往当前模型上加一小块“修正项”。

Stacking

Stacking(堆叠集成)不只是平均多个模型输出,而是再训练一个元学习器(Meta-Learner)去学习“什么时候该信哪个模型”。例如一个基模型擅长处理稀疏文本特征,另一个擅长处理数值特征,Stacking 可以学会在不同样本上动态加权它们。

它像“专家会诊 + 总负责人”:若文本模型和表格模型各有专长,元模型就负责综合判断谁在当前病例上更可信。

机器学习编程

机器学习编程(Machine Learning Programming)处理的核心问题是:当一个模型被写成代码并真正运行起来时,谁负责组织训练流程,谁负责表达数学操作,谁又负责在具体硬件上把这些操作算快。这三层通常分别对应编程框架(Framework)、算子(Operator)和内核(Kernel)。理解这三个层次,有助于把“模型公式”与“工程实现”连接起来。

它们不是彼此独立的三个名词,而是一条自上而下的执行链。研究者或工程师先在框架里定义模型结构与训练流程;框架再把模型拆成一系列算子,例如矩阵乘法、卷积、归一化、激活、softmax;每个算子最终还需要落到某个硬件相关的内核实现上,才能在 CPU、GPU、TPU 或其他加速器上真正执行。因此,框架决定开发体验,算子决定计算图语义,内核决定实际运行效率。

框架(Framework)

框架(Framework)并不是单一层次的概念。在现代机器学习工程里,至少要区分两层:一层是基础框架(Foundational Framework),负责张量(Tensor)、自动求导(Automatic Differentiation)、算子调度与底层执行;另一层是高层框架(High-level Framework),负责把某一类模型、某一类训练范式或某一类工程流程封装成更直接的接口。前者提供“地基”,后者提供“脚手架”和“现成结构”。

因此,PyTorch、TensorFlow、JAX 这类系统更适合放在基础框架层;而 Transformers、DeepSpeed、ModelScope、Lightning 这类工具,则更适合放在高层框架层。它们之间不是替代关系,而是典型的上下层关系:高层框架通常建立在基础框架之上,用更强的任务抽象、更少的模板代码和更完整的工程能力,把常见训练与推理流程直接组织起来。

常见框架简介

从工程使用频率看,开发者最常接触的通常不是“从零写张量系统”,而是先接触一组已经按职责分层的常见框架:高层框架负责组织训练与推理流程,基础框架负责真正执行张量计算,某些系统还进一步偏向执行优化与部署。把这些名字放回分层结构里理解,比孤立记忆框架名称更清楚。

高层框架(High-level Framework)

高层框架的核心价值在于,它们不重新发明张量计算和自动求导,而是在基础框架之上增加更强的任务语义、训练编排、模型生态或分布式能力。很多工程里,开发者日常接触最多的其实是这一层。

高层框架 主要依赖的基础框架 核心定位 替你封装了什么 最适合的场景 与基础框架的关系
Transformers 以 PyTorch 为主,也支持 TensorFlow 与 JAX / Flax 预训练 Transformer 模型与任务头生态 模型定义、权重加载、tokenizer / processor、Trainer、pipeline、任务头 NLP、LLM、多模态模型的微调与推理 通常不是自己实现底层训练系统,而是调用底层框架完成张量计算与反向传播
DeepSpeed 主要建立在 PyTorch 之上 大模型训练与推理优化框架 ZeRO、参数分片、优化器状态管理、分布式训练编排、推理加速 超大模型训练、多卡 / 多机扩展、显存受限训练 本质上是对 PyTorch 训练过程的增强与重写,而不是替代 PyTorch
Unsloth 主要建立在 PyTorch 之上,并与 Transformers、PEFT、TRL 等 Hugging Face 生态深度协同 面向 LLM 微调与对齐的性能导向高层框架 快速加载与训练配方、QLoRA / DoRA / RL 配置、量化微调、长上下文训练、导出到 GGUF / Ollama / vLLM / Hugging Face 单卡或少卡进行 LLM 微调、偏好对齐、消费级显卡上的高性价比实验 它不替代 PyTorch 或 Transformers,而是在它们之上把“高效微调 + 导出部署”这条链路进一步封装并做性能优化
ModelScope 主要建立在 PyTorch 之上,也兼容其他学习框架与平台能力 模型社区 + SDK + 训练 / 推理工作流 模型获取、pipeline、训练入口、评测、部署衔接、领域模型集成 中文生态、多模态任务、快速调用开源模型并做微调 更像“模型平台层 + 高层开发框架”,下层训练仍要落到基础框架执行
PyTorch Lightning PyTorch 训练流程组织框架 Trainer、设备放置、日志、checkpoint、验证循环、分布式训练模板 希望保留 PyTorch 灵活性,同时减少训练样板代码 把 PyTorch 代码组织得更规范,但底层模型与梯度仍然是 PyTorch
Accelerate PyTorch 分布式训练与多设备执行抽象 多 GPU / 多机启动、混合精度、设备管理、统一训练脚本适配 想在尽量少改代码的前提下把 PyTorch 训练扩展到分布式环境 不取代 PyTorch 训练代码,而是让同一份 PyTorch 代码更容易跨设备运行
Keras 3 可运行在 TensorFlow、JAX、PyTorch 之上,推理还可对接 OpenVINO 高层模型开发接口 Layer / Model 抽象、训练接口、callback、分布式 API、生态组件 需要高层建模接口且希望在多后端之间切换 处于基础框架之上,强调统一建模接口,而不是直接取代底层后端
Sentence Transformers 主要建立在 Transformers 与 PyTorch 之上 Embedding 与 reranker 高层框架 文本向量化、相似度训练、检索 / rerank 训练器、评测工具 语义检索、向量召回、文本匹配、reranking 属于面向特定任务族的高层框架,下层依赖 Transformers 与 PyTorch
MMEngine / OpenMMLab 主要建立在 PyTorch 之上 通用训练引擎与视觉算法框架底座 Runner、Hook、Config、数据流、训练 / 验证 / 测试流程组织 检测、分割、姿态估计等视觉任务 用统一工程抽象组织 PyTorch 训练,尤其适合复杂视觉实验体系

这一层最容易让人产生“它自己就能训练模型”的直觉,但从执行链条看,它们大多只是把训练过程组织得更高级。以 Transformers 为例,Trainer 可以发起训练,但底层的张量、梯度、优化器、自动求导与设备执行,通常仍然由 PyTorch 负责;Lightning、Accelerate、DeepSpeed 也是同样的逻辑,只是它们封装的侧重点不同。

Unsloth

Unsloth 最适合放在高层框架这一层理解。它并不重新定义 Tensor、自动求导(Autograd)或底层计算图,而是在 PyTorch、Transformers、PEFT、TRL 这一整套既有生态之上,把大语言模型(Large Language Model, LLM)的高频训练流程重新组织成更偏性能导向的开发体验。它解决的核心问题不是“怎样从零实现神经网络”,而是怎样在尽可能小的显存和尽可能少的工程样板下,把 LLM 微调、对齐、导出与部署这条链路跑通。

从开发者视角看,Unsloth 的典型工作流通常仍然是“加载 Hugging Face 模型 → 挂接 PEFT 适配器 → 用监督微调(SFT)或强化学习(RL)训练 → 导出到下游推理栈”。它的价值在于把这条链上几个最痛的环节一起压平:第一,量化微调(如 LoRA / QLoRA)与长上下文训练更容易直接落地;第二,针对 GRPO 等对齐训练给出更直接的入口;第三,把训练后的模型或适配器导出到 GGUF、Ollama、vLLM、SGLang、Hugging Face 等下游环境的路径做得更短。换言之,Unsloth 不是另起炉灶,而是把已有生态串得更紧,并对其中最贵的显存、最长的上下文和最复杂的导出环节做专项优化。

它与其他高层框架的边界也需要分清。Transformers 的优势在于模型家族与任务头生态最通用;Accelerate 更像多设备执行抽象;DeepSpeed 更偏分布式训练、参数分片与大规模集群优化;Unsloth 则把重心压在“单机到小规模多卡场景下,如何更快、更省显存地完成 LLM 微调与对齐”。因此,它尤其适合消费级 GPU、本地实验、小团队快速验证、Notebook 驱动的训练流程,以及以 LoRA / QLoRA / RL 为主的大模型增量训练。若任务是超大规模集群预训练或需要复杂的跨机并行策略,DeepSpeed / Megatron 一类系统通常仍然更中心;若任务是通用模型调用与标准微调,Transformers 仍然是最基础的入口。

工程上可以把 Unsloth 看成“面向 LLM 微调的高性能工作台”。它一端连接 Hugging Face 模型与适配器生态,另一端连接本地推理、GGUF、Ollama、vLLM、SGLang 等部署路径,中间则用一套更偏性能调优的训练封装把它们粘起来。对初学者,它降低的是上手门槛:少改几处配置就能跑通量化微调或 RL;对熟悉生态的工程师,它降低的是试验成本:同样的显存预算下,能尝试更长上下文、更复杂的对齐流程,或更快地把训练结果导出到不同推理栈。它的本质依然是高层工程抽象,而不是底层深度学习框架的替代品。

比较维度 Transformers DeepSpeed Unsloth
核心目标 统一模型与任务接口 放大训练规模与显存效率 压低 LLM 微调 / 对齐门槛并提升单机效率
最擅长的问题 模型加载、任务头、Trainer、pipeline ZeRO、分布式并行、大模型集群训练 QLoRA、GRPO、长上下文、快速导出部署
典型使用者 几乎所有 NLP / LLM 开发者 大模型平台与多机训练团队 本地实验者、个人开发者、小团队 LLM 微调工程师
与 PyTorch 的关系 调用其张量与训练能力 增强其训练与并行系统 在其之上重组 LLM 微调与导出流程
基础框架(Foundational Framework)

基础框架直接定义张量运算、计算图、自动求导、优化器、算子调度与设备执行能力。它们离硬件更近,也离“神经网络真正怎样被算出来”更近。高层框架能否存在,首先取决于这一层是否提供了足够稳定和强大的底座。

基础框架 核心抽象 主要优势 最适合的场景 典型局限
PyTorch Tensor、 nn.Module、autograd、动态图(Dynamic Computation Graph) 灵活、直观、研究生态最强,训练与调试体验优秀 研究、论文复现、大模型训练、需要自定义训练逻辑的任务 如果完全手写训练循环,工程样板代码较多,部署链路常需额外工具配合
TensorFlow Tensor、Layer / Model、自动求导、图执行与编译 训练与部署体系完整,服务化、端侧与工业链路成熟 企业级生产环境、需要完整训练到部署闭环的场景 研究阶段的编码与调试直观性通常不如 PyTorch
JAX 数组(Array)+ 函数变换 + XLA 编译 编译优化强,函数式表达清晰,适合大规模并行数值计算 需要强编译能力、自定义并行策略、科研数值实验的任务 函数式编程习惯要求更高,工程生态相对更偏高级用户
PaddlePaddle Tensor、动态图 / 静态图、训练与产业工具链 中文生态与产业落地支持强,训练推理工具链完整 产业应用、教育场景、中文任务与本土化生态 国际社区规模与通用论文实现数量通常少于 PyTorch

如果把机器学习工程比作建楼,那么基础框架提供的是钢筋、水泥、电路和承重结构。高层框架之所以能让开发速度显著提升,正是因为底层这些张量、梯度和算子能力已经由基础框架稳定提供。

执行与部署系统(Execution and Deployment Stack)

除了高层框架和基础框架,还存在一类经常与“框架”混称、但职责不同的系统:执行与部署系统。它们的核心目标不是让用户更方便地写模型,而是让已经定义好的模型在特定硬件上更快、更省、更稳定地运行。

系统 主要定位 最常见作用 典型场景 与前两层的关系
ONNX Runtime 跨框架推理执行系统 加载 ONNX 图,做图优化、算子调度与多后端执行 统一部署、跨框架导出后的推理执行 位于模型定义之后,更接近运行时(Runtime)而不是训练框架
TensorRT NVIDIA GPU 推理优化系统 图优化、层融合、量化与 kernel 自动选择 低延迟在线推理、高吞吐批量服务 通常接收上层框架导出的模型,再做更深的硬件侧优化
OpenVINO Intel 硬件推理栈 模型转换、图优化、Intel CPU / iGPU / VPU 推理 Intel 服务器与边缘设备部署 更接近部署后端,而不是通用训练框架
TVM 深度学习编译栈 自动调优、代码生成、异构硬件适配 边缘部署、自定义芯片、性能工程 站在算子和内核之间,为不同硬件生成更优执行实现

因此,讨论“框架”时最好先分清是哪一层:高层框架负责把任务和流程组织起来,基础框架负责把张量与梯度真正算出来,执行与部署系统负责把已经定义好的模型在目标硬件上跑到更优。这三层一旦混在一起,很多看似相近的名词就会失去边界。

算子(Operator)

算子(Operator)是计算图(Computation Graph)的基本运算单元。它定义一个明确的数学变换:输入什么张量(Tensor)、输出什么张量、张量的形状(Shape)和数据类型(Data Type)如何变化,以及反向传播时梯度如何计算。框架层写出的模块、层、网络块,最终都会被拆解成一串更细粒度的算子。

从工程实现上看,算子这一层负责表达“数学语义”。例如一个线性层(Linear Layer)会被拆成 MatMul 与 Bias Add;一个自注意力(Self-Attention)模块会被拆成 Q/K/V 投影、MatMul、Scale、Mask、Softmax、再一次 MatMul、Dropout、LayerNorm 等。高层模块能否被编译优化,本质上取决于这些算子能否被识别、融合与高效执行。

常用算子可以分成四大类:线性代数与张量形状类、神经网络前向计算类、序列与索引操作类、训练与优化类。下面的表格按这一方式展开。

线性代数与张量形状类
算子 核心作用 常见输入 / 输出 典型出现位置 实现与使用要点
MatMul / GEMM 矩阵乘法,完成线性投影与特征混合 二维或更高维张量,输出新的线性组合 全连接层、注意力投影、MLP 最核心的高密度算子之一,常直接决定训练吞吐
Batch MatMul 批量矩阵乘法,多个矩阵对并行相乘 三维及以上张量 多头注意力(Multi-Head Attention) 常与转置、缩放、mask 连用
Add / Bias Add 逐元素加法 两个可广播张量 残差连接、偏置项、特征融合 常被融合到前后算子中减少访存
Sub / Mul / Div 逐元素减法、乘法、除法 逐元素张量运算 归一化、门控、缩放 广播规则必须和张量形状匹配
Scale 用常数或向量对张量缩放 输入张量与标量 / 向量 attention 中的 \(1/\sqrt{d_k}\) 缩放 经常被编译器与前后算子融合
Transpose / Permute 重排维度顺序 输入张量到相同元素、不同布局的张量 NCHW / NHWC 转换,多头维度重排 逻辑上不改值,但常改变内存访问模式
Reshape / View 改变张量形状而不改变元素总数 同样的数据,不同 shape 展平、分头、合并头、batch 展开 若内存不连续,可能触发额外复制
Expand / BroadcastTo 按广播规则扩展维度 低维张量扩展为高维张量 偏置广播、mask 扩展 逻辑扩展不一定真实复制数据
Squeeze / Unsqueeze 删除或插入长度为 1 的维度 维度数变化,数据值不变 batch / channel 维调整 常用于接口对齐和算子拼接
Concat / Stack 拼接多个张量 多个同类型张量合并为一个 多特征合并、多分支网络 Concat 沿已有维度拼接,Stack 会新增维度
Split / Chunk 将一个张量拆成多个子张量 一个张量拆成若干块 Q/K/V 切分、多分支路径 与 Concat、Stack 常成对出现
ReduceSum / ReduceMean / ReduceMax 沿某些维度做聚合 高维张量压缩成低维张量 池化、loss 聚合、统计量计算 归约(Reduction)通常对并行实现要求较高
EinSum 用爱因斯坦求和规则表达复合张量运算 多个张量到一个张量 复杂线性代数、注意力原型实现 表达力强,但实际性能往往依赖后端是否能分解优化
神经网络前向计算类
算子 核心作用 常见输入 / 输出 典型出现位置 实现与使用要点
Convolution 局部感受野加权求和 特征图与卷积核,输出新的特征图 CNN、视觉 backbone、语音模型 步幅、填充、分组卷积会显著影响性能与感受野
Depthwise / Group Convolution 按通道组或单通道卷积 特征图到特征图 MobileNet、轻量视觉网络 减少计算量,但对 kernel 实现要求更高
Pooling(Max / Avg) 局部下采样与聚合 特征图压缩为空间更小的特征图 CNN、时序聚合 降低分辨率与计算量,也带来信息损失
Adaptive Pooling 把输入压到固定输出尺寸 任意空间尺寸到固定尺寸 视觉分类头、全局池化 方便不同输入尺寸统一到下游全连接层
ReLU 负值截断为 0 的激活函数 逐元素非线性变换 MLP、CNN、分类头 实现简单,稀疏性强
GELU 平滑激活,保留小负值的连续变化 逐元素非线性变换 Transformer、LLM MLP 现代语言模型最常见的激活之一
SiLU / Swish 输入与 sigmoid 门控的乘积 逐元素非线性变换 高性能视觉与语言模型 平滑、效果稳定,常见于新型 backbone
Sigmoid 把实数映射到 \((0,1)\) 逐元素概率化 门控单元、二分类输出、多标签任务 饱和区梯度小,深层网络中通常不作主激活
Tanh 把实数映射到 \((-1,1)\) 逐元素非线性变换 早期 RNN、门控结构 零中心,但同样存在饱和问题
Softmax 把一组分数归一化为概率分布 类别分数到概率 多分类头、attention 权重 常与交叉熵和 mask 配合,数值稳定性关键
LayerNorm 对单个样本的最后若干维做归一化 输入张量到同 shape 张量 Transformer、LLM 不依赖 batch 统计量,适合变长序列
BatchNorm 利用 batch 统计量做归一化 输入张量到同 shape 张量 CNN、视觉任务 训练与推理行为不同,小 batch 时效果可能下降
RMSNorm 基于均方根做归一化 输入张量到同 shape 张量 许多现代大语言模型 比 LayerNorm 更简洁,计算更轻
Attention / SDPA 基于相似度对值向量加权聚合 Q、K、V 到上下文表示 Transformer、跨模态模型 高层看是算子族,底层常映射到 FlashAttention 等 kernel
Embedding Lookup 根据离散索引查表取向量 token id 到 embedding 向量 NLP、推荐系统、类别特征 本质是参数矩阵的索引读取,不是普通 MatMul
序列与索引操作类
算子 核心作用 常见输入 / 输出 典型出现位置 实现与使用要点
Gather 按给定索引抽取元素或切片 源张量与索引张量 embedding、beam search、采样 访问模式离散,容易受内存带宽限制
Scatter / ScatterAdd 按索引写回或累加 目标张量、索引、更新值 图神经网络、稀疏更新 并发写冲突和原子操作代价常是性能瓶颈
Index Select 按某一维选取指定位置 张量与一维索引 子序列抽取、类别筛选 语义上比通用 gather 更窄,但常更清晰
Slice / Narrow 截取连续区间 大张量切出子张量 窗口注意力、局部特征抽取 若数据连续,可几乎零开销视图化
Mask Fill / Select 按布尔掩码选择或填充值 张量与 mask attention mask、padding 屏蔽 对变长序列与非法位置处理非常关键
Where 按条件在两个值之间选择 条件张量与候选张量 条件计算、loss 屏蔽、数值裁剪 本质是逐元素条件分支
Argmax / Argmin 返回最大 / 最小值所在索引 张量到索引 分类预测、贪心解码 输出是位置而非概率,通常不可导
TopK 返回前 \(k\) 个值及其索引 张量到值与索引 检索、beam search、采样截断 常与排序、候选筛选结合
Sort / Argsort 排序并返回顺序 张量到排序结果 排序损失、候选重排 复杂度高,尽量只在必要路径中使用
Pad 在边界补零或补指定值 原张量到更大张量 卷积前处理、batch 对齐、序列补齐 padding 策略会影响有效计算比例
Pack / Unpack Sequence 压缩或还原变长序列表示 变长序列与紧凑表示之间转换 RNN、语音与时序模型 用于减少 padding 带来的无效计算
Position Encoding Add 注入位置信息 token 表示与位置编码 Transformer、序列模型 绝对位置、相对位置、RoPE 在实现形式上不同
训练与优化类
算子 核心作用 常见输入 / 输出 典型出现位置 实现与使用要点
Dropout 训练时随机失活部分单元 输入张量到稀疏化后的张量 MLP、attention、分类头 训练和推理行为不同,推理阶段通常关闭
Cross-Entropy Loss 衡量预测分布与真实类别的差距 logits 与标签到标量损失 分类、语言模型、token 分类 实现中常与 log-softmax 融合提高稳定性
NLL Loss 负对数似然损失 对数概率与标签到损失 分类任务、序列建模 通常接在 log-softmax 之后
MSE Loss 均方误差 预测值与目标值到损失 回归、蒸馏、表示对齐 对异常值较敏感
L1 / SmoothL1 Loss 绝对误差或平滑绝对误差 预测值与目标值到损失 目标检测、鲁棒回归 比 MSE 对异常值更稳
KL Divergence 衡量两个分布之间的差异 两个概率分布到标量 知识蒸馏、VAE、分布对齐 输入通常需要是概率或对数概率
Backward / Gradient 沿计算图反向传播梯度 损失到各参数梯度 所有训练流程 框架自动求导的核心能力就体现在这里
Gradient Clip 限制梯度范数或幅值 梯度到裁剪后梯度 RNN、大模型训练 控制梯度爆炸,提升训练稳定性
Optimizer Step(SGD / Adam / AdamW) 根据梯度更新参数 参数、梯度、状态到新参数 每一步训练迭代 常被实现为 fused optimizer kernel 以减少开销
Weight Decay 对参数施加正则化收缩 参数到受约束更新 分类、语言模型、视觉模型 现代实现常与 AdamW 解耦
AllReduce 跨设备聚合梯度或统计量 多卡张量到同步后的张量 数据并行训练 严格说更接近通信算子,但在训练图中极常见
AllGather / ReduceScatter 跨设备收集或切分张量 多设备张量通信 张量并行、序列并行、ZeRO 大模型分布式训练不可缺少

因此,算子层是连接“模型定义”和“底层执行”的语义中枢。看懂模型实际调用了哪些算子,基本就等于看懂了它在做哪些数学步骤,以及这些步骤能否被进一步融合和加速。

内核(Kernel)

内核(Kernel)是算子的底层实现。它规定了某个算子如何映射到具体硬件:线程如何组织、数据如何分块、是否使用共享内存(Shared Memory)、是否调用向量化指令、是否走 Tensor Core、是否把多个小算子融合成一次执行。若说算子定义的是“做什么”,那么内核定义的就是“怎样在这台机器上把它做快”。

从性能工程角度看,内核层回答的是:同一个数学算子,针对不同硬件、数据形状、精度格式和访存模式,哪种实现最优。这也是为什么表面上同样是 MatMul、LayerNorm 或 Attention,不同框架和后端的速度会相差很大。

常见内核或内核族可以按下表理解:

内核 / 内核族 主要服务的算子 典型硬件 / 后端 核心优化手段 最典型的收益 常见场景
cuBLAS GEMM kernel MatMul、Linear、Batch MatMul NVIDIA GPU tile blocking、Tensor Core、流水线、寄存器复用 把矩阵乘法做到接近硬件峰值吞吐 全连接层、attention 投影、MLP
cuDNN Convolution kernel Convolution、Pooling、部分归一化与激活 NVIDIA GPU direct convolution、im2col + GEMM、Winograd、FFT 自动选择 按输入形状自动切换最优卷积路径 CNN、视觉 backbone、语音前端
oneDNN / MKL kernel MatMul、Convolution、Normalization x86 CPU SIMD 向量化、cache blocking、线程并行 提升 CPU 推理与训练效率 服务器 CPU 推理、无 GPU 环境
NCCL communication kernel AllReduce、AllGather、ReduceScatter、Broadcast NVIDIA 多 GPU 环形通信(Ring)、树形通信(Tree)、链路拓扑优化 降低多卡同步开销 数据并行、张量并行、大模型训练
FlashAttention kernel Scaled Dot-Product Attention NVIDIA GPU 及其他支持相应实现的加速器 分块、在线 softmax、kernel fusion、减少 HBM 访存 把 attention 从显存瓶颈拉回到更接近计算瓶颈 Transformer、LLM、长序列建模
Fused LayerNorm / RMSNorm kernel LayerNorm、RMSNorm、Bias Add、Residual Add GPU / CPU 后端 多步逐元素运算融合为一次访存 显著降低 memory-bound 算子的开销 Transformer block、LLM 推理
Fused MLP kernel Bias Add、GELU / SiLU、Dropout、Residual GPU 把连续逐元素算子合并,减少中间张量写回 减少 kernel launch 次数与显存读写 MLP block、前馈网络
Triton custom kernel 任意自定义算子或 fused operator GPU 开发者手写 tile、访存布局与并行策略 在通用库缺少最优实现时获得定制性能 大模型训练、研究型性能优化、自定义融合
TensorRT generated kernel 部署图中的卷积、MatMul、激活、归一化、量化路径 NVIDIA GPU 图优化、层融合、低精度选择、kernel autotuning 显著降低推理时延并提升吞吐 在线推理服务、边缘推理
XLA generated kernel JAX / TensorFlow 图中的可融合算子子图 GPU、TPU 等 图级融合、静态形状分析、编译生成目标代码 让一串算子整体下沉为更大的执行单元 JAX 训练、TPU 训练、编译型执行场景
TVM generated kernel 自定义张量表达式对应的算子 CPU、GPU、边缘加速器 自动调度、自动搜索、代码生成 跨异构硬件获得针对性实现 端侧部署、自定义芯片适配
PagedAttention / KV-cache kernel 增量解码中的 attention 与缓存访问 LLM 推理后端 分页管理 KV cache、优化随机访问和 batch 合并 提升长上下文与多请求并发推理效率 大语言模型在线推理

理解内核时最重要的一点是:一个算子并不对应唯一实现。同样是卷积,可以选 direct convolution、Winograd 或 FFT;同样是 attention,可以选普通分步实现、FlashAttention 或推理场景下的 paged attention。真正的差异往往不在数学定义,而在访存方式、融合策略、并行粒度和硬件利用率上。

因此,内核并不是建模阶段最先暴露给用户的对象,却往往决定模型最终的吞吐、时延、显存占用、能耗和成本。模型结构决定“上限在哪里”,内核质量决定“这个上限能兑现多少”。

三者关系

把三者串起来看,一个卷积层或注意力层的执行路径通常是这样的:开发者先在 PyTorch 或 JAX 中写出一个模块;框架把它拆成若干算子,例如 MatMul、Softmax、LayerNorm 或 Convolution;运行时再为每个算子选择对应硬件上的 kernel,例如 cuBLAS 的 GEMM kernel、cuDNN 的 convolution kernel,或 Triton 写成的自定义 fused kernel。整个训练与推理过程由框架负责调度,算子负责表达数学语义,内核负责把语义变成高性能机器代码。

可以用一个具体例子来理解。若在 PyTorch 中定义一个卷积层,那么:

  1. PyTorch 作为框架负责接收模块定义、组织张量、记录梯度关系并调度执行。
  2. 卷积(Convolution)作为算子表示“输入特征图与卷积核做局部加权求和”这一数学操作。
  3. 底层可能调用 cuDNN 提供的卷积 kernel,在 GPU 上以高度优化的方式完成真正计算。

同样地,在 Transformer 中写一层自注意力时,框架会组织前向与反向图;MatMul、Softmax、Mask、LayerNorm 等作为算子组成计算链;而 FlashAttention、fused LayerNorm、paged attention 这类高性能实现,则属于内核或 kernel-level optimization 的范畴。

因此,这三个层次的关系可以概括为:框架管理整个建模与执行流程,算子定义模型中的数学步骤,内核负责把这些步骤在具体硬件上高效落地。从研究到工程落地的能力鸿沟,往往正体现在能否同时理解这三层。

经典机器学习
选型指南

经典机器学习的模型选择,本质上是在任务形式、数据规模、特征形态、可解释性要求、训练与推断成本之间做匹配。只要先判断“有没有标签”“输出是什么类型”“样本量有多大”“特征是不是稀疏或非线性”“是否需要概率或规则解释”,大多数任务都可以迅速缩小到少数几个候选模型。

本章中的模型并不是按“先进程度”排序,而是按建模假设来区分。线性模型假设边界或关系接近线性;树模型更擅长表格数据中的非线性交互;概率模型更强调分布解释;近邻模型依赖局部相似性;聚类与降维模型关注无监督结构;HMM(Hidden Markov Model, HMM)和条件随机场(Conditional Random Field, CRF)则处理序列标签之间存在依赖的结构化预测问题。

下面的表格不是概览式罗列,而是直接服务于选型。每一行都回答五个问题:什么情况下优先选它、它最依赖什么数据条件、它能解决什么核心诉求、为什么它在该场景里合适、以及什么情况下应当换模型。在大多数工程场景里,先按这些表格缩小范围,再进入具体模型细节,效率最高。

任务类型:分类
模型 优先选择条件 数据与特征前提 最主要价值 不建议优先使用的情况
逻辑回归 需要稳定强基线、需要概率输出、需要解释每个特征如何影响类别 特征可以线性分离到一定程度;高维稀疏特征尤其合适,如 one-hot、词袋、统计特征 训练快、概率自然、权重可解释,适合作为第一版可上线模型 类别边界高度非线性、特征交互复杂且没有显式特征工程时
支持向量机(SVM) 样本中小规模、类别边界较清晰、希望用最大间隔提升泛化稳健性 特征需要做尺度统一;核 SVM 更适合中小规模,不适合超大样本 对边界样本建模强,在线性不可分但结构仍较规整时往往优于纯线性模型 数据量很大、需要快速训练与部署、或者必须输出天然概率时
决策树 需要把模型直接解释成规则路径,或业务天然是“按阈值分流”的形式 表格特征、混合数值与类别特征都可;不强依赖标准化 规则可视化最直接,便于和业务规则、审计规则对齐 追求最稳泛化性能时;单树通常方差高,容易过拟合
随机森林 表格分类需要稳健基线、希望少调参、担心单棵树过拟合 适合中等规模表格数据;对噪声、缺失和特征尺度通常更宽容 比单树稳定,通常先于复杂 boosting 模型给出可靠结果 追求表格任务的极致精度,或需要很小的模型体积时
梯度提升树(GBDT) 表格分类精度优先,特征中存在明显非线性与交互效应 适合结构化特征,不要求线性关系;通常需要一定调参 能逐轮修正前一轮错误,在中等规模表格任务上常是强力基线 需要极快训练、极少调参,或数据已经极大到串行 boosting 成本明显偏高时
XGBoost 工业表格分类、竞赛任务、缺失值与正则化处理都很重要 适合中大规模结构化数据;对特征工程和超参数较敏感,但工程支持成熟 精度高、鲁棒、缺失值处理成熟,是很多表格分类任务的首选之一 极端大规模、极度强调训练速度与内存效率时,LightGBM 往往更优先
LightGBM 大规模表格分类、高维稀疏特征、需要更快训练与更低内存消耗 适合样本量大、特征维度高的结构化任务;对类别特征和稀疏特征较友好 训练快、工程效率高,在工业 CTR、风控、推荐特征场景很常见 数据量较小且噪声较大时;叶子生长策略若不控制,容易过拟合
朴素贝叶斯 需要极快文本分类基线、小样本启动、希望先验证特征是否有判别力 最适合词袋、词频、计数类高维稀疏特征;默认接受条件独立近似 训练和推断都极快,在垃圾邮件、主题粗分类等任务上常有效 强依赖复杂特征相关性、类别边界非线性明显、或需要高精度概率校准时
K 近邻(KNN) 样本规模小、相似样本应有相似标签、希望不做显式训练 距离度量必须有意义;所有特征应标准化,且维度不能过高 局部模式直观,适合做小数据原型验证或相似样本检索式分类 高维稀疏特征、大规模数据、低延迟在线推断场景
线性判别分析(LDA) 有监督分类同时希望压缩特征维度,且类别统计结构较稳定 更适合每类近似高斯、类内协方差可估计的情况;样本数不能太少 把“降维”和“分类判别”结合起来,适合先压缩再分类的流程 类别分布非常复杂、强非高斯、强非线性时
任务类型:回归
模型 优先选择条件 数据与特征前提 最主要价值 不建议优先使用的情况
线性回归 需要连续值预测、希望建立可解释、可审计、可稳定复现的基线 目标与特征大致满足线性关系,或经过变换后接近线性 系数解释直观,便于分析“哪个因素把目标推高或拉低” 目标关系明显呈现复杂分段、交互或强非线性时
Lasso(L1 正则化) 特征很多、怀疑只有少数特征真正有效、希望模型自动做变量筛选 高维特征尤其适合;允许部分权重被压到 0 回归同时完成特征选择,适合构建更稀疏、更简洁的模型 大量强相关特征共同起作用时;它可能只保留其中部分特征
岭回归 / L2 正则化 特征共线性明显、担心普通线性回归权重不稳定 适合多个相关特征共同解释目标,而不希望稀疏淘汰其中一部分 通过收缩权重降低方差,使模型在相关特征场景下更稳定 首要目标是做特征筛选、希望很多系数直接变成 0 时
Elastic Net(L1 + L2 正则化) 既想做特征选择,又不希望在相关特征组上过于不稳定 高维、相关特征并存的回归任务最常见 综合 Lasso 与岭回归的优点,在稀疏性和稳定性之间折中 特征数量不多、模型目标非常简单时;其调参成本高于纯 L1 或 L2
决策树 目标值与输入关系近似分段函数,或业务逻辑天然围绕阈值展开 表格特征、混合类型特征都可;不需要严格线性假设 能学出“满足什么条件时预测值跳到哪个区间”的规则 希望预测曲线平滑、稳定,或希望泛化误差尽可能低时
随机森林 希望回归稳健、抗噪声、少调参,先拿到可靠效果 表格回归场景最常见;对特征尺度和局部异常较稳 综合多个树模型平均结果,通常比单树更不容易过拟合 要求外推能力强,或希望模型极度轻量、延迟极低时
梯度提升树(GBDT) 表格回归精度优先,目标和特征之间存在复杂非线性 适合异构表格特征;对异常值和长尾目标通常也较有韧性 在房价、评分、收益、风险等典型表格回归中常是强基线 算力非常紧、需要极低训练成本时
XGBoost / LightGBM 工业级表格回归、大规模特征、希望兼顾精度与工程效率 适合结构化数据;XGBoost 更稳健成熟,LightGBM 更强调速度与规模 常作为表格回归默认候选,能直接处理大量非线性和特征交互 数据关系本来就简单线性、并且强依赖系数解释时
K 近邻(KNN) 局部相似样本的目标值应当接近,希望用邻域平均直接预测 小数据、低维、有意义的距离度量是前提 局部平滑性强时实现简单有效,适合作为相似样本回归基线 高维、大样本、分布稀疏或在线延迟敏感时
任务类型:聚类
模型 优先选择条件 数据与特征前提 最主要价值 不建议优先使用的情况
K-Means 需要快速把样本分成若干组,并且预期每组都围绕某个均值中心展开 簇大致是球形或凸形;欧氏距离有意义;需要先给定 \(K\) 速度快、实现简单,适合作为无监督分群第一选择 簇形状复杂、密度差异大、离群点很多或无法预先估计簇数时
层次聚类 不仅想得到分组结果,还想知道各组是如何逐层合并成层级结构的 更适合中小规模数据;需要能接受 \(O(N^2)\) 级别距离矩阵成本 能输出树状图,适合做群体结构分析与多粒度解释 数据量很大、只关心最终聚类标签、不关心层级关系时
DBSCAN 希望识别任意形状簇,并把稀疏孤立点单独作为噪声剔除 密度尺度相对统一;距离度量有意义;参数 \(\epsilon\) 邻域半径和最小点数可估计 不需要预设簇数,能自然处理非凸簇和离群点 不同区域密度差异很大时;单一密度阈值难兼顾所有簇
HDBSCAN 簇的密度明显不一致,希望保留 DBSCAN 的密度思想但更自适应 数据存在多密度结构;仍需合理距离度量 比 DBSCAN 更能处理“有的簇很密、有的簇较松”的真实数据 只需要一个快速、简单、可复现的基础分群结果时
高斯混合模型(GMM) 希望得到软聚类结果,或者认为每个簇更像椭球形概率团块 连续特征较适合;默认每个簇可近似为一个高斯成分 不仅给簇标签,还给每个样本属于各簇的概率 簇形状非常复杂、非高斯、多峰结构难用少量高斯逼近时
任务类型:降维与可视化
模型 优先选择条件 数据与特征前提 最主要价值 不建议优先使用的情况
主成分分析(PCA) 希望做线性降维、压缩冗余特征、去噪或为下游模型降成本 主要结构能由少数线性主方向解释;不依赖标签 保留最大方差方向,是最稳健、最常用的无监督降维起点 真正关心的是类别判别性而不是总体方差,或数据结构强非线性时
线性判别分析(LDA) 有标签并希望把不同类别拉开后再做分类或可视化 类别标签可靠;类内散度与类间散度都可稳定估计 直接围绕“可分性”找投影,比 PCA 更贴近分类目标 没有标签、类别边界强非线性、或类别数太少导致可降维空间有限时
t-SNE 想把高维嵌入压到二维或三维,只为看局部邻域是否形成簇 更适合可视化,不适合直接做可逆特征压缩 局部邻域展示能力强,适合分析表征是否把相似样本聚到一起 需要把降维结果直接送入生产模型,或需要保留严格全局距离关系时
UMAP 希望做更快的大规模可视化,兼顾局部结构与部分全局连通性 适合高维嵌入、文本向量、图表示等复杂表征 通常比 t-SNE 更快,也更容易保留大体流形结构 需要线性可解释主方向,或需要结果完全稳定可重复到坐标级别时
任务类型:异常检测
模型 优先选择条件 数据与特征前提 最主要价值 不建议优先使用的情况
孤立森林(Isolation Forest) 通用表格异常检测,希望先得到一个稳健、扩展性好的异常分数 适合中大规模数据;不要求明确概率分布形式 通过随机切分隔离少数样本,通常是异常检测第一基线 异常定义依赖非常精细的局部密度差异时
局部异常因子(LOF) 异常并不是全局离群,而是“在本地邻域里显得稀疏” 距离度量必须合理;样本规模不宜过大 能发现那些整体位置不极端、但局部密度明显偏低的点 高维距离失真严重、或需要高吞吐在线检测时
单类支持向量机(One-Class SVM) 只有正常样本,目标是学习正常数据的封闭边界 特征需标准化;更适合中小规模;核方法对边界形状有帮助 适合“正常类定义清楚、异常类没有稳定样本”的场景 数据量很大、特征维度很高、参数难以稳定选择时
高斯混合模型(GMM) 希望把异常定义为低概率区域,并明确得到似然分数 连续数据更合适;分布能用若干高斯混合近似 异常判定有明确概率语义,适合风险评分和阈值分析 数据分布非常复杂、非高斯、或异常并不等价于低密度时
任务类型:序列标注与结构化预测
模型 优先选择条件 数据与特征前提 最主要价值 不建议优先使用的情况
隐马尔可夫模型(HMM) 序列较短、转移规律明显、希望在较小数据和较强先验下完成基础序列建模 状态转移与观测发射假设大致成立;问题适合生成式描述 结构清晰、推断高效,适合作为经典序列建模入门和小规模基线 标签强依赖全局上下文、特征复杂、需要大量判别式特征时
条件随机场(CRF) 输出不是单点分类而是整条标签序列,并且相邻标签的合法性非常关键 一维链式序列最合适;上游特征或表示需要至少能提供较强局部证据 通过整体解码约束标签转移,使最终标签序列更一致、更符合任务结构 长距离语义主要由强表征模型决定、标签约束作用很弱,或任务更适合 span 建模时
任务类型:密度估计与概率建模
模型 优先选择条件 数据与特征前提 最主要价值 不建议优先使用的情况
朴素贝叶斯 希望快速得到后验概率分类器,并接受条件独立近似 高维稀疏离散特征最合适,如文本词频、词出现计数 概率形式直接、估计简单,适合快速建模和在线系统 特征依赖结构复杂、需要精细表达联合分布时
高斯混合模型(GMM) 希望显式建模连续数据分布,或需要软聚类与密度估计统一完成 连续数据、多峰分布、可近似为若干高斯成分 每个样本都能得到各成分责任概率,解释和阈值分析都较自然 分布极端复杂、重尾严重、或高斯成分数难合理确定时
隐马尔可夫模型(HMM) 不仅要建模观测分布,还要建模隐藏状态在时间上的转移机制 观测是序列,且状态依赖主要体现在相邻时刻 把“序列生成机制”和“时序转移规律”统一到一个概率模型里 长程依赖很强、局部马尔可夫假设明显不成立时

若只是要一个工程上可执行的默认起点,可以进一步压缩成如下规则:表格分类与回归优先从随机森林、GBDT、XGBoost、LightGBM 和线性模型里选;文本高维稀疏分类优先看逻辑回归和朴素贝叶斯;无监督分群先看 K-Means,再根据簇形状和噪声情况转向 DBSCAN、HDBSCAN 或 GMM;需要可视化时先区分是要线性压缩还是只要展示结构,再在 PCA、LDA、t-SNE、UMAP 中选择;涉及标签序列依赖时再进入 HMM 与 CRF。

线性模型

线性模型(Linear Models)的核心不是“世界一定是线性的”,而是先用一个可解释、可优化、常常足够强的基线去刻画输入与输出的关系。很多复杂模型也可以看作“在线性读出层之前先做更强的特征变换”。

线性回归

线性回归(Linear Regression)在回归任务中建模“输入特征的加权求和如何产生连续输出”。它的价值在于:可解释(权重直接对应特征影响)与可优化(凸问题,训练稳定)。

模型与符号

给定训练集 \(\{(\mathbf{x}_i,y_i)\}_{i=1}^{N}\),其中 \(\mathbf{x}_i\in\mathbb{R}^d\) 是第 \(i\) 个样本的特征向量, \(y_i\in\mathbb{R}\) 是对应标签。线性回归假设单样本预测为:

\[\hat y_i=\mathbf{w}^\top \mathbf{x}_i+b\]
  • \(\hat y_i\):对 \(y_i\) 的预测。
  • \(\mathbf{w}\in\mathbb{R}^d\):权重向量(每个维度对应一个特征)。
  • \(b\in\mathbb{R}\):偏置(Bias),用于整体平移。
  • \(\mathbf{w}^\top \mathbf{x}_i\):内积(Dot Product),表示“按特征加权求和”。

把全部样本写成矩阵形式。令设计矩阵(Design Matrix)\(\mathbf{X}\in\mathbb{R}^{N\times d}\) 的第 \(i\) 行为 \(\mathbf{x}_i^\top\),标签向量 \(\mathbf{y}\in\mathbb{R}^{N}\) 的第 \(i\) 个分量为 \(y_i\),全 1 向量 \(\mathbf{1}\in\mathbb{R}^{N}\)。则:

\[\hat{\mathbf{y}}=\mathbf{X}\mathbf{w}+b\mathbf{1}\]

直觉类比:它像“按因素打分再加总”。例如房价预测里,面积、地段评分、楼龄都可作为特征;权重正负决定影响方向,绝对值大小决定影响强弱。

目标函数(最小二乘)

最常见的训练目标是最小化均方误差(Mean Squared Error, MSE)的总和(或平均):

\[\min_{\mathbf{w},b}\ J_{\text{EN}}(\mathbf{w},b)=\frac{1}{N}\|\mathbf{y}-\mathbf{X}\mathbf{w}-b\mathbf{1}\|_2^2+\lambda_1\|\mathbf{w}\|_1+\lambda_2\|\mathbf{w}\|_2^2\]

这个目标可以拆成三部分理解:第一项 \(\frac{1}{N}\|\mathbf{y}-\mathbf{X}\mathbf{w}-b\mathbf{1}\|_2^2\) 是数据拟合误差,其中 \(\mathbf{y}-\mathbf{X}\mathbf{w}-b\mathbf{1}\) 是所有样本的残差向量;第二项 \(\lambda_1\|\mathbf{w}\|_1\) 倾向把一部分权重直接压到 0;第三项 \(\lambda_2\|\mathbf{w}\|_2^2\) 倾向把权重整体缩小得更平滑。这里 \(N\) 是样本数, \(\lambda_1,\lambda_2\) 是正则化强度。若两者都取 0,就退化为普通最小二乘。

  • \(J(\mathbf{w},b)\):目标函数(Objective)。
  • \(\|\cdot\|_2\):二范数(Euclidean Norm),向量的长度。

平方项会对大残差施加更大惩罚,因此训练会优先修正“偏得很离谱”的样本。并且在高斯噪声假设下,最小二乘等价于最大似然估计(Maximum Likelihood Estimation, MLE)导出的解。

解析解(正规方程)

把偏置吸收到特征中更方便:定义增广特征 \(\tilde{\mathbf{x}}_i=[\mathbf{x}_i;1]\in\mathbb{R}^{d+1}\),增广参数 \(\tilde{\mathbf{w}}=[\mathbf{w};b]\in\mathbb{R}^{d+1}\),增广矩阵 \(\tilde{\mathbf{X}}=[\mathbf{X},\mathbf{1}]\in\mathbb{R}^{N\times(d+1)}\)。则 \(\hat{\mathbf{y}}=\tilde{\mathbf{X}}\tilde{\mathbf{w}}\),目标为 \(\min_{\tilde{\mathbf{w}}}\|\mathbf{y}-\tilde{\mathbf{X}}\tilde{\mathbf{w}}\|_2^2\)。若 \(\tilde{\mathbf{X}}^\top\tilde{\mathbf{X}}\) 可逆,则正规方程(Normal Equation)给出闭式解:

\[\tilde{\mathbf{w}}^*=\left(\tilde{\mathbf{X}}^\top\tilde{\mathbf{X}}\right)^{-1}\tilde{\mathbf{X}}^\top\mathbf{y}\]

这里 \(\tilde{\mathbf{w}}^*\) 表示最优增广参数,前 \(d\) 维对应原权重 \(\mathbf{w}\),最后一维对应偏置 \(b\)。 \(\tilde{\mathbf{X}}^\top\tilde{\mathbf{X}}\) 汇总了特征之间的相关结构, \(\tilde{\mathbf{X}}^\top\mathbf{y}\) 汇总了特征与标签之间的相关程度,因此这个闭式解本质上是在“用整体相关关系一次性解出最优线性系数”。

  • \(\tilde{\mathbf{X}}^\top\tilde{\mathbf{X}}\in\mathbb{R}^{(d+1)\times(d+1)}\):Gram 矩阵,度量特征之间的相关性。
  • \((\cdot)^{-1}\):矩阵逆;不可逆时通常用伪逆(Pseudo-inverse)或加正则化处理。

工程实现中,直接求逆并不推荐;更稳定的做法是解线性方程组或用 QR/SVD 分解。

实例:把公式算一遍

用一维数据拟合 \(y\approx wx+b\)。给定三点 \((x,y)\in\{(0,1),(1,3),(2,5)\}\)。构造增广矩阵与标签:

\[\tilde{\mathbf{X}}=\begin{bmatrix}0 & 1\\ 1 & 1\\ 2 & 1\end{bmatrix},\quad \mathbf{y}=\begin{bmatrix}1\\ 3\\ 5\end{bmatrix}\]

这个增广矩阵的每一行对应一个样本;第一列是原始特征 \(x\),第二列固定为 1,用来把偏置 \(b\) 并入矩阵乘法。标签向量 \(\mathbf{y}\) 则把三个样本的真实输出按顺序堆叠起来。

计算:

\[\tilde{\mathbf{X}}^\top\tilde{\mathbf{X}}=\begin{bmatrix}5 & 3\\ 3 & 3\end{bmatrix},\quad \tilde{\mathbf{X}}^\top\mathbf{y}=\begin{bmatrix}13\\ 9\end{bmatrix}\]

左边的矩阵可以看成所有样本在“特征与偏置”两个方向上的二阶统计量: \(5\) 来自 \(0^2+1^2+2^2\), \(3\) 来自 \(0+1+2\),右边向量 \(\tilde{\mathbf{X}}^\top\mathbf{y}\) 则分别对应 \(\sum_i x_i y_i\) 与 \(\sum_i y_i\)。这正是正规方程所需要的汇总量。

解线性方程 \(\left(\tilde{\mathbf{X}}^\top\tilde{\mathbf{X}}\right)\tilde{\mathbf{w}}=\tilde{\mathbf{X}}^\top\mathbf{y}\),即:

\[\begin{cases}5w+3b=13\\ 3w+3b=9\end{cases}\Rightarrow w=2,\ b=1\]

这组方程的未知量只有两个:斜率 \(w\) 和偏置 \(b\)。解出 \(w=2\) 表示特征每增加 1,预测值增加 2;解出 \(b=1\) 表示当 \(x=0\) 时,模型基线输出为 1。

因此预测为 \(\hat y=2x+1\),恰好穿过三点。这个例子展示了:正规方程把“最小化平方误差”的优化问题,转换成一个线性方程组。

适用场景
  • 需要可解释的特征贡献(权重)与可校验的线性关系。
  • 表格数据(Tabular)中,关系接近线性或可通过特征变换/交互项线性化。
  • 作为强基线:先用线性模型定位数据问题、特征质量与噪声水平,再决定是否需要更复杂模型。
  • 高维稀疏特征(如 one-hot、文本 bag-of-words)下,配合正则化可获得稳定解。

当特征很多、共线性(Collinearity)强或数据量相对不足时,普通最小二乘(Ordinary Least Squares, OLS)会出现高方差:训练集拟合很好、验证集误差上升。正则化(Regularization)通过惩罚参数规模,把“拟合训练误差”与“控制模型复杂度”写进同一个目标函数。

Lasso(L1 正则化)

Lasso 把参数惩罚写成一范数(\(L_1\) Norm):

\[\min_{\mathbf{w},b}\ J_{\text{lasso}}(\mathbf{w},b)=\frac{1}{N}\left\|\mathbf{y}-\mathbf{X}\mathbf{w}-b\mathbf{1}\right\|_2^2+\lambda\|\mathbf{w}\|_1\]

这个式子里,前半部分仍然是拟合误差,衡量预测和真实标签之间差多少;后半部分 \(\lambda\|\mathbf{w}\|_1\) 是稀疏惩罚,其中 \(\|\mathbf{w}\|_1=\sum_j |w_j|\) 会优先把不重要的权重压成 0。于是 Lasso 不只是“把权重变小”,而是经常顺带完成特征选择。

  • \(\lambda\ge 0\):正则化强度(Regularization Strength)。越大表示越强的收缩。
  • \(\|\mathbf{w}\|_1=\sum_{j=1}^{d}|w_j|\):一范数,鼓励稀疏(Sparsity)。
  • 通常不惩罚偏置 \(b\);否则会把整体均值也一起往 0 拉。
  • Lasso 由于 \(|\cdot|\) 在 0 点不可导,一般没有像岭回归那样简洁的闭式解;常用坐标下降(Coordinate Descent)、近端梯度(Proximal Gradient)或 LARS 等算法求解。

Lasso 的关键作用不是均匀缩小全部权重,而是让一部分权重被压到精确 0。它更像给参数设置了一个阈值:弱相关、贡献不足以抵消惩罚的特征,会被直接剔除。因此 Lasso 同时完成复杂度控制与特征选择(Feature Selection)。

几何上,在相同训练误差轮廓线下, \(L_1\) 约束对应菱形/正八面体;这些尖角更容易与最优点相交在坐标轴上,因此常出现某些 \(w_j=0\) 的解。

  • 适合高维稀疏特征、希望自动筛特征的场景,例如广告、推荐、文本 one-hot 特征。
  • 当特征高度相关时,Lasso 往往只保留其中少数几个,因此解的稳定性通常弱于岭回归。
岭回归 / L2 正则化

岭回归把参数惩罚写成二范数平方(\(L_2\) Norm Squared):

\[\min_{\mathbf{w},b}\ J_{\text{ridge}}(\mathbf{w},b)=\frac{1}{N}\left\|\mathbf{y}-\mathbf{X}\mathbf{w}-b\mathbf{1}\right\|_2^2+\lambda\|\mathbf{w}\|_2^2\]

岭回归的结构与普通线性回归相同,只是在误差项之外额外加入了 \(\lambda\|\mathbf{w}\|_2^2\)。这里 \(\|\mathbf{w}\|_2^2=\sum_j w_j^2\) 会连续惩罚过大的权重,因此它更擅长缓解共线性和过拟合,而不是像 Lasso 那样主动做稀疏选择。

  • \(\lambda\ge 0\):正则化强度。越大表示越强的收缩。
  • \(\|\mathbf{w}\|_2^2=\sum_{j=1}^{d}w_j^2\):二范数平方,连续惩罚大权重。
  • 通常不惩罚偏置 \(b\);否则会把整体均值也一起往 0 拉。

从梯度角度看,惩罚项 \(\lambda\|\mathbf{w}\|_2^2\) 对单个参数 \(w_j\) 的梯度贡献是 \(2\lambda w_j\)。这就是 \(L_2\) 正则化在深度学习中被称为权重衰减(Weight Decay)的原因:它持续把权重按比例拉回 0。若取 \(\lambda=1\),当 \(w_j=10\) 时,梯度为 \(20\);优化器会施加强烈收缩,把这个大权重猛拉回去。当 \(w_j=0.1\) 时,梯度只有 \(0.2\);往 0 拉的力量就很弱。也就是说,参数一旦变大, \(L_2\) 惩罚立刻增强;参数已经很小时,它几乎不再干预。

岭回归仍是凸二次问题,并有闭式解(忽略/已中心化处理 \(b\) 的情况):

\[\mathbf{w}^*=\left(\mathbf{X}^\top\mathbf{X}+N\lambda\mathbf{I}\right)^{-1}\mathbf{X}^\top\mathbf{y}\]

与普通最小二乘相比,这里多出来的 \(N\lambda\mathbf{I}\) 是沿对角线加入的一项稳定化修正。 \(\mathbf{I}\) 是单位矩阵,它不会改变特征之间的相对结构,但会让矩阵更容易求逆,因此在特征高度相关时更稳定。

  • \(\mathbf{I}\in\mathbb{R}^{d\times d}\):单位矩阵(Identity Matrix)。
  • \(\mathbf{X}^\top\mathbf{X}+N\lambda\mathbf{I}\):对角线上加了 \(N\lambda\) 的稳定项,缓解共线性导致的病态(Ill-conditioning)。

用一个最小可算的例子说明 \(\lambda\) 如何改变解。考虑无偏置的一维回归 \(\hat y=wx\),目标为:

\[J(w)=\sum_{i=1}^{N}(y_i-wx_i)^2+\lambda w^2\]

这是单变量岭回归的简化形式。前一项把所有样本的平方误差加总,后一项 \(\lambda w^2\) 惩罚过大的斜率。它清楚展示了岭回归的核心:既要求拟合数据,又限制参数不要长得太大。

对 \(w\) 求导并令其为 0 得:

\[\frac{\mathrm{d}J}{\mathrm{d}w}=-2\sum_{i=1}^{N}x_i(y_i-wx_i)+2\lambda w=0\Rightarrow w^*=\frac{\sum_{i=1}^{N}x_i y_i}{\sum_{i=1}^{N}x_i^2+\lambda}\]

这个结果说明岭回归解和普通最小二乘解非常接近,只是分母里多了一个 \(\lambda\)。它会把估计值往 0 方向收缩: \(\lambda\) 越大,分母越大,得到的 \(w^*\) 就越保守。

可见 \(\lambda\) 直接进入分母,把 \(w^*\) 持续拉向 0。岭回归不会像 Lasso 那样大量制造精确 0,而是把所有权重更平滑地压小,因此更像“把所有旋钮都往小一点拧”,让模型整体更保守、更稳健。

  • 适合特征高度相关、希望保留全部特征但降低方差的场景;常见于经济学、医学和一般表格数据。
  • 当既希望稀疏,又希望在强相关特征间保持稳定时,Elastic Net(\(L_1+L_2\))通常比纯 Lasso 更稳。
Elastic Net(L1 + L2 正则化)

Elastic Net 把 \(L_1\) 与 \(L_2\) 惩罚合并到同一个目标中:

\[\min_{\mathbf{w},b}\ J_{\text{EN}}(\mathbf{w},b)=\frac{1}{N}\|\mathbf{y}-\mathbf{X}\mathbf{w}-b\mathbf{1}\|_2^2+\lambda_1\|\mathbf{w}\|_1+\lambda_2\|\mathbf{w}\|_2^2\]

它同时保留两类效应: \(L_1\) 项负责产生稀疏性(Sparsity),把一部分弱特征压到 0; \(L_2\) 项负责平滑收缩,在特征高度相关时提高解的稳定性。因此 Elastic Net 通常用于“既希望自动做特征选择,又不希望在强相关特征之间选得过于激进”的场景。

  • 当 \(\lambda_2=0\) 时,退化为 Lasso。
  • 当 \(\lambda_1=0\) 时,退化为岭回归(Ridge Regression)。
  • 当特征高度相关且维度很高时,Elastic Net 往往比纯 Lasso 更稳,也比纯岭回归更稀疏。
逻辑回归

逻辑回归(Logistic Regression)是二分类的标准基线:它先用线性函数产生打分,再把该打分通过 sigmoid(Logistic Function)映射到 \((0,1)\),从而得到条件概率模型。

模型、概率与 logit

对二分类,令标签随机变量(Random Variable)\(Y\in\{0,1\}\),其中 \(1\) 表示正类, \(0\) 表示负类。给定输入 \(\mathbf{x}\) 后,先定义线性打分:

\[z=\mathbf{w}^\top\mathbf{x}+b\]

再定义 sigmoid 函数:

\[\sigma(z)=\frac{1}{1+e^{-z}}\]

于是,在给定输入 \(\mathbf{x}\) 的条件下,标签取正类的条件概率写成:

\[p(Y=1\mid \mathbf{x})=\sigma(z)=\sigma(\mathbf{w}^\top\mathbf{x}+b)\]

这里 \(\mid\) 表示“在给定……条件下”;左侧 \(Y=1\) 表示事件“标签随机变量取值为正类 1”。因此这个式子表示:在输入 \(\mathbf{x}\) 已知时,事件 \(Y=1\) 发生的概率。

相应地,负类概率为:

\[p(Y=0\mid \mathbf{x})=1-\sigma(z)\]
  • \(\mathbf{x}\in\mathbb{R}^d\):特征向量。
  • \(\mathbf{w}\in\mathbb{R}^d\):权重向量(Weight Vector)。
  • \(b\in\mathbb{R}\):偏置(Bias)。
  • \(z\in\mathbb{R}\):线性打分;它也是 logit(对数几率,log-odds)。
  • \(\sigma(\cdot)\):把任意实数映射到 \((0,1)\) 的非线性函数。

logit 的含义来自恒等式:

\[\log\frac{p(Y=1\mid \mathbf{x})}{1-p(Y=1\mid \mathbf{x})}=z=\mathbf{w}^\top\mathbf{x}+b\]

这里的 \(\frac{p(Y=1\mid \mathbf{x})}{1-p(Y=1\mid \mathbf{x})}\) 称为几率(Odds),表示“正类概率与负类概率之比”;再对它取对数,就得到 logit(对数几率,log-odds):\(\log\frac{p}{1-p}\)。因此上式的含义不是再引入一个无关的新量,而是说明:逻辑回归把正类概率的对数几率建模为输入特征的线性函数。

换言之,在二分类逻辑回归里, \(z=\mathbf{w}^\top\mathbf{x}+b\) 就是线性部分的原始输出值,而这个原始输出值恰好等于 logit。它本身不是概率,可以取任意实数;经过 sigmoid 之后才变成 \((0,1)\) 内的概率。多分类情形中,softmax 之前那一组线性输出通常统称为 logits。

因此 \(w_j\) 可以被解释为:特征 \(x_j\) 增加一个单位,会把对数几率增加 \(w_j\)(在其他特征不变时)。这就是逻辑回归的核心可解释性。

logistic

训练目标(NLL / Cross-Entropy)

给定训练集 \(\{(\mathbf{x}_i,y_i)\}_{i=1}^{N}\),记 \(p_i=\sigma(\mathbf{w}^\top\mathbf{x}_i+b)\)。逻辑回归通过最大化似然(Likelihood)训练;等价地,它最小化负对数似然(Negative Log-Likelihood, NLL),也即二分类交叉熵(Binary Cross-Entropy):

\[\min_{\mathbf{w},b}\ L(\mathbf{w},b)=-\sum_{i=1}^{N}\left(y_i\log p_i+(1-y_i)\log(1-p_i)\right)\]
  • \(\log p_i\):当 \(y_i=1\) 时,鼓励 \(p_i\) 变大。
  • \(\log(1-p_i)\):当 \(y_i=0\) 时,鼓励 \(p_i\) 变小。

加入 \(L_2\) 正则化时,常见形式为 \(L(\mathbf{w},b)+\lambda\|\mathbf{w}\|_2^2\)(通常不惩罚 \(b\))。该目标是凸的,因此不存在“坏局部最优”的训练不稳定问题。

梯度:公式如何驱动参数更新

把样本堆叠成矩阵 \(\mathbf{X}\)、标签向量 \(\mathbf{y}\),预测概率向量 \(\mathbf{p}\)(第 \(i\) 个分量为 \(p_i\))。则无正则项时梯度为:

\[\nabla_{\mathbf{w}}L=\mathbf{X}^\top(\mathbf{p}-\mathbf{y}),\quad \frac{\partial L}{\partial b}=\mathbf{1}^\top(\mathbf{p}-\mathbf{y})\]

这两个梯度式子都围绕同一个误差向量 \(\mathbf{p}-\mathbf{y}\) 展开:它表示“模型给出的正类概率”和“真实标签”之间的偏差。 \(\mathbf{X}^\top(\mathbf{p}-\mathbf{y})\) 表示把这种偏差按特征方向汇总起来,从而告诉每个权重该往哪个方向改; \(\mathbf{1}^\top(\mathbf{p}-\mathbf{y})\) 则把所有偏差直接相加,用来更新偏置。

这两个式子揭示了训练机制:如果某个样本真实标签是 1 但模型给出小概率(\(p_i-y_i<0\)),则梯度会推动 \(\mathbf{w}\) 朝着增加该样本 logit 的方向更新;反之亦然。

实例:单样本算概率、算损失、算一次梯度

考虑一维特征 \(x=2\),参数 \(w=1,b=-1\),则 \(z=wx+b=1\),概率:

\[p=\sigma(1)=\frac{1}{1+e^{-1}}\approx 0.731\]

若真实标签 \(y=1\),该样本的负对数似然为:

\[\ell=-\log p\approx 0.313\]

该样本对 \(w\) 的梯度为(单样本形式):

\[\frac{\partial \ell}{\partial w}=(p-y)x=(0.731-1)\cdot 2\approx -0.538\]

用学习率 \(\eta\) 做一次梯度下降: \(w\leftarrow w-\eta\frac{\partial\ell}{\partial w}\)。由于梯度为负,更新会把 \(w\) 增大,从而增大 \(z\)、提升 \(p\),使模型更倾向把该样本判为正类。

适用场景
  • 二分类且需要概率输出/可校准阈值(例如欺诈检测、流失预测、医学风险评分)。
  • 高维稀疏特征(如 one-hot、文本 bag-of-words),逻辑回归常是强基线。
  • 对可解释性、训练稳定性要求高的工程场景(可用权重做审计/特征诊断)。
  • 当决策边界高度非线性且特征工程不足时,需要树模型或神经网络补上非线性。
支持向量机(SVM)

支持向量机(Support Vector Machine, SVM)不是“随便找一条能分开两类样本的直线/超平面”,而是要找那条对两类样本都留出最大安全缓冲区的边界。这个缓冲区叫间隔(Margin):边界离两类样本都越远,模型对噪声、标注扰动与局部数据波动通常越稳。

从数学形式看,SVM 最终会落到二次规划(Quadratic Programming, QP)。所谓二次规划,就是:目标函数是变量的二次函数,约束是线性等式或线性不等式。SVM 的目标是最小化 \(\frac{1}{2}\|\mathbf{w}\|_2^2\),约束则是每个样本都必须被放到正确一侧并留出至少 1 的函数间隔,因此它正好属于这一类优化问题。

svm

从结构上看,SVM 把三件事连在一起:

  1. 几何:先定义“什么叫分得开”,以及“什么叫分得最稳”。
  2. 优化:把“最稳的边界”写成一个可求解的凸二次规划。
  3. 对偶:把问题改写成只依赖样本内积的形式,从而自然导出核技巧(Kernel Trick)。
从几何直觉到“最大间隔”

对二分类任务,设标签 \(y_i\in\{-1,+1\}\)。线性分类器先计算一个打分函数(Score Function):

\[f(\mathbf{x})=\mathbf{w}^\top\mathbf{x}+b\]

这里最好先把“函数写法”和“几何边界写法”区分清楚。像 \(y=x\) 这样的形式,强调的是“给定自变量(Independent Variable) \(x\),应变量(Dependent Variable) \(y\) 如何变化”;但对分类器来说,更关键的问题不是“谁依赖谁”,而是哪些点恰好落在边界上,以及点位于边界哪一侧。因此同一条直线在几何里通常改写成隐式形式(Implicit Form) \(x-y=0\)。

一旦写成 \(x-y=0\),就能直接看成二维超平面方程 \(\mathbf{w}^\top\mathbf{x}+b=0\):令 \(\mathbf{x}=(x,y)^\top\)、\(\mathbf{w}=(1,-1)^\top\)、\(b=0\),便有 \(\mathbf{w}^\top\mathbf{x}+b=x-y\)。此时直线方向向量(Direction Vector)可以取 \(\mathbf{v}=(1,1)^\top\),因为沿这条线移动时 \(y\) 与 \(x\) 同时增加;而 \(\mathbf{w}^\top\mathbf{v}=1\cdot 1+(-1)\cdot 1=0\),说明 \(\mathbf{w}\) 与直线切向方向正交,所以它正是这条直线的法向量(Normal Vector)。更一般地,对任意边界 \(\mathbf{w}^\top\mathbf{x}+b=0\),系数向量 \(\mathbf{w}\) 都垂直于边界,因此天然决定“正侧、负侧”和距离的度量方向。

再用它的符号做判别:

\[\hat y=\mathrm{sign}(f(\mathbf{x}))=\mathrm{sign}(\mathbf{w}^\top\mathbf{x}+b)\]

这里 \(\mathbf{w}\) 是超平面的法向量(Normal Vector)。沿 \(\mathbf{w}\) 方向移动, \(f(\mathbf{x})\) 会增大;沿反方向移动, \(f(\mathbf{x})\) 会减小。因此:

  • \(f(\mathbf{x})=0\):点就在分类超平面上。
  • \(f(\mathbf{x})>0\):点落在法向量 \(\mathbf{w}\) 指向的那一侧。
  • \(f(\mathbf{x})<0\):点落在另一侧。

超平面把空间分成正半空间(Positive Half-space)与负半空间(Negative Half-space);分数的正负号直接给出样本位于哪一侧。

令 \(\mathcal{H}=\{\mathbf{x}:\mathbf{w}^\top\mathbf{x}+b=0\}\) 表示超平面,令单位法向量(Unit Normal Vector)为 \(\mathbf{n}=\mathbf{w}/\|\mathbf{w}\|_2\)。对样本 \(\mathbf{x}_i\),记 \(\mathbf{x}_{\Pi,i}\) 为它在超平面 \(\mathcal{H}\) 上的正交投影点(Orthogonal Projection),因此 \(\mathbf{w}^\top\mathbf{x}_{\Pi,i}+b=0\),且 \(\mathbf{x}_i-\mathbf{x}_{\Pi,i}\) 与 \(\mathbf{w}\) 平行。点 \(\mathbf{x}_i\) 到超平面的带符号距离(Signed Distance)定义为该位移在单位法向量方向上的投影长度:

\[\mathrm{dist}_{\pm}(\mathbf{x}_i,\mathcal{H})=\mathbf{n}^\top(\mathbf{x}_i-\mathbf{x}_{\Pi,i})=\frac{\mathbf{w}^\top\mathbf{x}_i+b}{\|\mathbf{w}\|_2}\]

分子 \(\mathbf{w}^\top\mathbf{x}_i+b\) 衡量点在法向量方向上偏离超平面的代数量;分母 \(\|\mathbf{w}\|_2\) 对法向量做归一化,去掉“同一个超平面可写成不同倍数方程”的尺度影响;符号保留样本位于超平面哪一侧的信息。

带符号距离区分了超平面的两侧,但正类样本与负类样本的正确侧相反。将标签 \(y_i\in\{-1,+1\}\) 乘入后,得到几何间隔(Geometric Margin):

\[\gamma_i=\frac{y_i(\mathbf{w}^\top\mathbf{x}_i+b)}{\|\mathbf{w}\|_2}\]

几何间隔是用标签修正后的带符号距离。因此:

  • \(\gamma_i>0\):样本在正确一侧,被正确分类。
  • \(\gamma_i=0\):样本正好压在边界上。
  • \(\gamma_i<0\):样本落到错误一侧,被误分类。

SVM 的目标是让所有训练样本中最小的那个 \(\gamma_i\) 尽可能大,即最大化“最坏样本到边界的正确方向距离”:

\[\gamma=\min_i \gamma_i\]

这就是最大间隔(Maximum Margin)的含义:不是让“平均样本”离边界远,而是让最危险、最靠近边界的样本也尽量安全。

硬间隔 SVM(Hard-margin SVM)原始问题

先看线性可分(Linearly Separable)的情形。所谓线性可分,就是存在某个 \((\mathbf{w},b)\),使每个样本都在与自己标签一致的一侧。这件事可以统一写成:

\[y_i(\mathbf{w}^\top\mathbf{x}_i+b)>0,\quad \forall i\]

为什么这里是 \(>0\)?因为它等价于“符号一致”:当 \(y_i=+1\) 时,要求 \(\mathbf{w}^\top\mathbf{x}_i+b>0\),即正类样本必须落在正半空间;当 \(y_i=-1\) 时,要求 \(\mathbf{w}^\top\mathbf{x}_i+b<0\),即负类样本必须落在负半空间。若只等于 0,则样本恰好压在分类边界上,不属于严格可分,因为此时它没有任何安全间隔,符号判别也处在临界点。

不过, \(y_i(\mathbf{w}^\top\mathbf{x}_i+b)\) 还不是几何距离,因为把 \((\mathbf{w},b)\) 同时乘以任意正常数 \(t>0\),超平面 \(\mathbf{w}^\top\mathbf{x}+b=0\) 完全不变,但这个量会整体乘上 \(t\)。因此它只是一个未归一化的间隔量,通常称为函数间隔(Functional Margin)。

为了消掉这个缩放自由度,SVM 采用一个标准定标:强制所有样本的最小函数间隔等于 1,也就是要求

\[y_i(\mathbf{w}^\top\mathbf{x}_i+b)\ge 1,\quad \forall i\]

这条约束把两类样本同时编码进来:当 \(y_i=+1\) 时,它变成 \(\mathbf{w}^\top\mathbf{x}_i+b\ge 1\);当 \(y_i=-1\) 时,它变成 \(\mathbf{w}^\top\mathbf{x}_i+b\le -1\)。于是分类边界两侧又出现两条平行的“间隔边界”(Margin Boundaries):

\[\mathbf{w}^\top\mathbf{x}+b=+1,\quad \mathbf{w}^\top\mathbf{x}+b=-1\]

因为平行超平面 \(\mathbf{w}^\top\mathbf{x}+b=c_1\) 与 \(\mathbf{w}^\top\mathbf{x}+b=c_2\) 之间的距离是 \(|c_1-c_2|/\|\mathbf{w}\|_2\),所以这两条间隔边界之间的宽度为

\[\frac{|(+1)-(-1)|}{\|\mathbf{w}\|_2}=\frac{2}{\|\mathbf{w}\|_2}\]

在这个定标下,离分类边界最近的样本几何间隔恰好是

\[\gamma=\min_i \frac{y_i(\mathbf{w}^\top\mathbf{x}_i+b)}{\|\mathbf{w}\|_2}=\frac{1}{\|\mathbf{w}\|_2}\]

因此,最大化几何间隔就等价于最小化 \(\|\mathbf{w}\|_2\);为了得到标准的凸二次目标,通常写成:

\[\min_{\mathbf{w},b}\ \frac{1}{2}\|\mathbf{w}\|_2^2\quad \text{s.t.}\quad y_i(\mathbf{w}^\top \mathbf{x}_i+b)\ge 1\]

这就是硬间隔 SVM 的原始问题(Primal Problem)。现在“二次规划”这个术语也具体了:目标函数 \(\frac{1}{2}\|\mathbf{w}\|_2^2\) 是关于参数的凸二次函数,而约束 \(y_i(\mathbf{w}^\top \mathbf{x}_i+b)\ge 1\) 对 \((\mathbf{w},b)\) 是线性的,所以这是一个凸二次规划,并且可以求到全局最优解。

拉格朗日函数与 KKT:为什么只剩少数“支持向量”

这一段只回答一个问题:训练集中明明有很多样本,为什么最后真正决定分类边界的,往往只有少数几个点。这个结论的严格来源是 KKT 条件,但它的直观含义并不抽象:只有那些真正把最大间隔边界“卡住”的样本,才会在最优解里留下非零权重。

硬间隔 SVM 的原始问题是:

\[\min_{\boldsymbol{w},b}\frac{1}{2}\|\boldsymbol{w}\|_2^2\quad \text{s.t.}\quad y_i(\boldsymbol{w}^\top \boldsymbol{x}_i+b)\ge 1,\ \forall i\]

这里目标函数 \(\frac{1}{2}\|\boldsymbol{w}\|_2^2\) 想把边界做得尽量“简单”,也就是让法向量尽量短,从而把间隔做大;而每个训练样本都在提出自己的硬约束:它不仅要被分对,还必须距离边界至少有 1 个单位的函数间隔。把这两股力量写到同一个式子里,就得到拉格朗日函数(Lagrangian):

\[\mathcal{L}(\boldsymbol{w},b,\boldsymbol{\alpha})=\frac{1}{2}\|\boldsymbol{w}\|_2^2-\sum_{i=1}^{N}\alpha_i\big(y_i(\boldsymbol{w}^\top \boldsymbol{x}_i+b)-1\big),\quad \alpha_i\ge 0\]

其中 \(\alpha_i\) 是第 \(i\) 个样本对应的拉格朗日乘子(Lagrange Multiplier)。在 SVM 里,可以把它直接理解为“第 \(i\) 个样本对当前分类边界施加了多大压力”。压力越大,说明这个样本越在真正影响边界的位置;压力为 0,说明这个样本虽然在训练集里,但最优边界并不需要它来支撑。

这个问题的读法可以想成一个“边界往外推、样本往回顶”的平衡过程:

  • 模型一侧 想让 \(\|\boldsymbol{w}\|_2\) 尽量小,从而把间隔尽量做大。
  • 约束一侧 则由每个样本通过 \(\alpha_i\) 施加压力:谁越接近边界、越可能破坏间隔,谁就越值得保留权重。

于是,离边界很远的样本会发生什么,就变得非常直观。若某个样本满足

\[y_i(\boldsymbol{w}^\top\boldsymbol{x}_i+b)>1\]

说明它不仅分对了,而且还有额外安全余量。这个点对“边界能否继续外推”没有形成真正阻碍,因此最优时它对应的 \(\alpha_i\) 会被压到 0。相反,若某个样本恰好满足

\[y_i(\boldsymbol{w}^\top\boldsymbol{x}_i+b)=1\]

它就正贴在间隔边界上,是“再往外推一点就会出问题”的临界点。这样的样本才有资格在最优解中保留非零权重。

KKT 条件(Karush–Kuhn–Tucker Conditions)把这个直觉写成严格公式。第一条来自驻点条件(Stationarity):

\[\nabla_{\boldsymbol{w}}\mathcal{L}=0\Rightarrow \boldsymbol{w}=\sum_{i=1}^{N}\alpha_i y_i \boldsymbol{x}_i\]

这条式子的含义非常重要。它说明最终的法向量 \(\boldsymbol{w}\) 并不是由全部样本平均决定的,而是由训练样本的加权和决定的。这里:

  • \(\boldsymbol{x}_i\) 是第 \(i\) 个训练样本;
  • \(y_i\alpha_i\) 是它的“带符号权重”;
  • 若 \(\alpha_i=0\),该样本就完全不会出现在 \(\boldsymbol{w}\) 的表达式里。

第二条关键条件是互补松弛(Complementary Slackness):

\[\alpha_i\big(y_i(\boldsymbol{w}^\top \boldsymbol{x}_i+b)-1\big)=0\]

这条式子可以直接逐项阅读:

  • \(\alpha_i\) 是第 \(i\) 个样本对边界施加的压力;
  • \(y_i(\boldsymbol{w}^\top \boldsymbol{x}_i+b)-1\) 是该样本相对于间隔边界的“松弛量”;当它大于 0 时,说明样本在安全区里;当它等于 0 时,说明样本正好贴边。

由于这两个量的乘积必须等于 0,所以只可能出现两种情况:

  • 若 \(y_i(\boldsymbol{w}^\top \boldsymbol{x}_i+b)-1>0\),说明该样本有安全余量,那么必须有 \(\alpha_i=0\)。
  • 若 \(\alpha_i>0\),说明该样本仍在对边界施压,那么必须有 \(y_i(\boldsymbol{w}^\top \boldsymbol{x}_i+b)=1\)。

这就是支持向量(Support Vector)的严格定义来源:在硬间隔 SVM 中,只有恰好贴在间隔边界上的样本,才可能对应非零 \(\alpha_i\);这些样本共同决定最终超平面的位置。其余样本虽然被正确分类,但因为离边界还有余量,所以在最优解里不再起作用。

如果继续沿着这个结论往下看,就会发现 SVM 的稀疏性完全不是偶然现象,而是 KKT 的直接产物。训练集里可以有大量“安全样本”,但最优边界只需要被少数临界样本支撑起来。名字“支持向量”说的正是这件事:这些点不是普通数据点,而是真正在几何上把边界撑住的点。

对偶问题(Dual):把“求边界”改写成“给样本分权重”

前面已经看到:KKT 让 \(\alpha_i\) 变成了“谁在真正顶住边界”的刻度。但如果这里只停在 KKT,还是会留下一个疑问:对偶问题到底是怎么从原始问题里长出来的?关键动作只有一步:先把 \(\alpha_i\) 固定住,把拉格朗日函数当成关于 \(\mathbf{w},b\) 的函数来最小化;然后再回过头,只对 \(\alpha\) 做最大化。

也就是说,原始问题里我们直接求“哪条边界最好”:

\[\min_{\mathbf{w},b}\ \frac{1}{2}\|\mathbf{w}\|_2^2\quad \text{s.t.}\quad y_i(\mathbf{w}^\top\mathbf{x}_i+b)\ge 1\]

而引入拉格朗日乘子之后,可以先看下面这个函数:

\[\mathcal{L}(\mathbf{w},b,\alpha)=\frac{1}{2}\|\mathbf{w}\|_2^2-\sum_{i=1}^{N}\alpha_i\Big(y_i(\mathbf{w}^\top \mathbf{x}_i+b)-1\Big),\quad \alpha_i\ge 0\]

对固定的 \(\alpha\),它就是一个关于 \(\mathbf{w},b\) 的凸函数。于是我们先做内层最小化:

\[g(\alpha)=\min_{\mathbf{w},b}\ \mathcal{L}(\mathbf{w},b,\alpha)\]

这里的 \(g(\alpha)\) 就叫对偶函数(Dual Function)。它表示:假设每个样本的施压强度已经给定,边界那一侧最好的回应会是什么。

这一步的好处是, \(\mathbf{w},b\) 可以被显式消掉。对 \(\mathbf{w}\) 和 \(b\) 求驻点条件,有:

\[\frac{\partial \mathcal{L}}{\partial \mathbf{w}}=0\Rightarrow \mathbf{w}=\sum_{i=1}^{N}\alpha_i y_i\mathbf{x}_i\] \[\frac{\partial \mathcal{L}}{\partial b}=0\Rightarrow \sum_{i=1}^{N}\alpha_i y_i=0\]

这两条式子非常关键:第一条说明法向量 \(\mathbf{w}\) 完全由训练样本线性组合出来;第二条说明正负两类样本的“总施压”必须平衡。把它们代回去,原来依赖 \(\mathbf{w},b\) 的问题就变成只依赖 \(\alpha\) 的问题:

\[\max_{\alpha}\ \sum_{i=1}^{N}\alpha_i-\frac{1}{2}\sum_{i=1}^{N}\sum_{j=1}^{N}\alpha_i\alpha_j y_i y_j\,\mathbf{x}_i^\top\mathbf{x}_j\] \[\text{s.t.}\quad \alpha_i\ge 0,\quad \sum_{i=1}^{N}\alpha_i y_i=0\]

这就是 SVM 的对偶问题(Dual Problem)。现在可以看出它为什么叫“对偶”:它没有再直接问“\(\mathbf{w},b\) 应该是多少”,而是改问“每个样本应该分到多大的权重 \(\alpha_i\),才能共同把最优边界顶出来”。

这样改写有两个直接收益。第一,支持向量为什么稀疏会变得一眼可见:若某个样本最终 \(\alpha_i^*=0\),它就自动从 \(\mathbf{w}=\sum_i \alpha_i y_i\mathbf{x}_i\) 里消失。第二,对偶目标里出现的样本方式只剩内积 \(\mathbf{x}_i^\top\mathbf{x}_j\),这正是后面引入核函数(Kernel)的入口。

把最优权重 \(\alpha_i^*\) 求出来后,分类器可以直接写成:

\[f(\mathbf{x})=\mathrm{sign}\left(\sum_{i=1}^{N}\alpha_i^* y_i\,\mathbf{x}_i^\top \mathbf{x}+b^*\right)\]

这个式子的含义很具体:新样本 \(\mathbf{x}\) 会与训练样本做内积(Inner Product),也就是计算相似度;每个训练样本按自己的类别符号 \(y_i\) 和影响系数 \(\alpha_i^*\) 投一票;最后把这些票加总,再加上偏置 \(b^*\),看结果落在哪一侧。

由于绝大多数样本的 \(\alpha_i^*=0\),真正参与这次投票的通常只有支持向量。因此 SVM 的预测阶段常带有一个很强的稀疏性(Sparsity):不是所有训练样本都在持续发声,真正起作用的只是边界附近那一小部分点。

偏置 \(b^*\) 可以用任一支持向量恢复。若 \(\mathbf{x}_k\) 是一个支持向量,则它满足 \(y_k(\mathbf{w}^{*\top}\mathbf{x}_k+b^*)=1\),因此

\[b^*=y_k-\mathbf{w}^{*\top}\mathbf{x}_k\]
核函数(Kernel):把“线性边界”搬到更合适的空间

对偶问题真正重要的地方,不只是“把变量从 \(\mathbf{w},b\) 换成了 \(\alpha_i\)”,而是它把 SVM 的全部数据依赖压缩成了样本之间的内积(Inner Product):

\[\mathbf{x}_i^\top\mathbf{x}_j\]

这一步非常关键,因为它说明:SVM 在对偶形式里并不需要直接看到样本坐标本身,它只需要知道样本彼此有多相似。只要这种“相似度”还能写成某个空间里的内积,SVM 的训练与预测公式就都可以照搬。

于是核技巧(Kernel Trick)的引入就变得自然了。设有一个特征映射(Feature Map)\(\phi(\mathbf{x})\),它把原始样本送到更高维、甚至无限维的特征空间(Feature Space)。如果我们真的显式去算这个高维向量,代价往往很大;但对偶形式只关心内积,因此只要能直接计算

\[K(\mathbf{x}_i,\mathbf{x}_j)=\phi(\mathbf{x}_i)^\top\phi(\mathbf{x}_j)\]

就等价于“隐式地”在特征空间里做线性 SVM,而不必真的把 \(\phi(\mathbf{x})\) 写出来。这个直接在原空间里计算特征空间内积的技巧,就叫核函数(Kernel Function)或核技巧(Kernel Trick)。

这也解释了为什么 kernel 是从 dual 里长出来的,而不是额外拼上去的:若你还停留在原始问题里,眼前看到的仍是显式参数 \(\mathbf{w}\);而一旦进入对偶形式,表达式里只剩 \(\mathbf{x}_i^\top\mathbf{x}_j\),把它替换成别的“合法相似度”就成了最自然的一步。

于是决策函数从

\[f(\mathbf{x})=\mathrm{sign}\left(\sum_{i=1}^{N}\alpha_i^* y_i\,\mathbf{x}_i^\top \mathbf{x}+b^*\right)\]

变成

\[f(\mathbf{x})=\mathrm{sign}\left(\sum_{i=1}^{N}\alpha_i^* y_i\,K(\mathbf{x}_i,\mathbf{x})+b^*\right)\]

要点是:特征空间里仍然是线性超平面;只是映回原空间后,边界看起来变成了弯的。因此 kernel 不是“把线性 SVM 换成非线性模型”,而是“先把数据换到更容易线性可分的表示里,再继续做线性 SVM”。

从直觉上看,核函数本质上是在重新定义“两个样本像不像”。线性核(Linear Kernel)比较原始方向是否一致;多项式核(Polynomial Kernel)强调特征之间的组合关系;RBF / Gaussian 核更强调局部邻近性,因此很容易形成局部、弯曲的决策边界。

  • 线性核(Linear Kernel):\(K(\mathbf{x},\mathbf{z})=\mathbf{x}^\top\mathbf{z}\)。
  • 多项式核(Polynomial Kernel):\(K(\mathbf{x},\mathbf{z})=(\mathbf{x}^\top\mathbf{z}+c)^d\)。
  • RBF / Gaussian 核:\(K(\mathbf{x},\mathbf{z})=\exp(-\gamma\|\mathbf{x}-\mathbf{z}\|_2^2)\)。

一个典型例子是“同心圆”二分类:在二维平面里,内圈和外圈无法用一条直线分开;但如果映射到包含半径平方等特征的空间,类别就可能被一个超平面分开。核方法的价值就在这里:原空间里看到的是弯曲边界,特征空间里做的仍然是线性分类。

软间隔 SVM(Soft-margin SVM):允许少量违约,但要付代价

现实数据通常含噪声、离群点(Outlier)或类别重叠。若仍然要求“所有点都必须在间隔之外”,硬间隔 SVM 很可能根本无解,或者被少数异常点强行拉歪。软间隔 SVM(Soft-margin SVM)因此引入松弛变量(Slack Variable)\(\xi_i\ge 0\),允许个别样本违反间隔约束:

\[\min_{\mathbf{w},b,\xi}\ \frac{1}{2}\|\mathbf{w}\|_2^2+C\sum_{i=1}^{N}\xi_i\quad \text{s.t.}\quad y_i(\mathbf{w}^\top \mathbf{x}_i+b)\ge 1-\xi_i,\ \xi_i\ge 0\]

这个式子只表达一件事:边界仍然希望尽量大,但违约要交罚款,罚款强度由 \(C\) 决定。对单个样本, \(\xi_i\) 的含义可以直接按大小来读:

  • \(\xi_i=0\):样本分类正确,且在间隔边界上或之外。
  • \(0<\xi_i\le 1\):样本仍在正确一侧,但已经挤进了间隔内部。
  • \(\xi_i>1\):样本跨过了分类边界,已经被误分。

\(C\) 控制的是“对违约有多敏感”:

  • \(C\) 大:更重视把训练集分对,边界更硬,对噪声也更敏感。
  • \(C\) 小:更重视大间隔和整体稳定性,允许少量训练误差。

软间隔下,支持向量的范围也更宽:不仅贴着间隔边界的点重要,落在间隔内部甚至被误分的点也会直接影响最优解。对应到对偶变量,常见情形是 \(0<\alpha_i<C\) 的点贴在间隔上,而 \(\alpha_i=C\) 的点往往是间隔内样本或误分类样本。

把松弛变量消去后,软间隔 SVM 还可以写成更常见的合页损失(Hinge Loss)形式:

\[\min_{\mathbf{w},b}\ \frac{1}{2}\|\mathbf{w}\|_2^2+C\sum_{i=1}^{N}\max\big(0,\ 1-y_i(\mathbf{w}^\top \mathbf{x}_i+b)\big)\]

第一项限制模型复杂度,第二项惩罚分类违约。SVM 因此可以被看作“大间隔 + 违约惩罚”的组合,而支持向量则是这两股力量平衡后仍然留在最前线的样本。

树模型与集成方法

这一类方法处理的核心问题是:当输入与输出之间存在明显非线性、阈值效应与高阶特征交互时,线性模型往往表达力不足,但工程上仍然希望模型具备较强可解释性、对表格数据友好、并且训练稳定。树模型通过递归切分(Recursive Partitioning)把输入空间划成若干局部区域;集成方法则进一步通过 Bagging 或 Boosting 提升泛化能力与精度。

决策树

决策树(Decision Tree)把预测过程写成一串逐层切分的规则:内部节点负责提问,边负责根据答案分流,叶节点负责输出最终结果。它的优势不在于公式复杂,而在于模型结构与业务规则天然同构:每一条从根到叶的路径,都对应一条可读的判断链。

决策树、分类树、回归树的关系

决策树是总称;分类树(Classification Tree)与回归树(Regression Tree)是它在两类监督学习任务上的具体形式。三者共享同一种树结构,但目标变量、切分准则与叶子输出不同。

概念 预测目标 叶子输出 常用切分准则
决策树(Decision Tree) 树模型的总称 取决于具体任务 取决于具体任务
分类树(Classification Tree) 离散标签(如“流失/不流失”) 类别或类别概率 基尼不纯度(Gini)、熵(Entropy)、信息增益(Information Gain)
回归树(Regression Tree) 连续数值(如“价格”“时长”) 一个数值常数 平方误差(Squared Error)、MSE / SSE 下降

因此不要把“决策树”和“分类树”当成并列概念。更准确的表述是:分类树与回归树都是决策树;前者预测类别,后者预测数值。

结构与统一公式

设某个节点上落入的样本集合为 \(S\),大小为 \(|S|\)。对某个候选切分(Split)\(\phi\),例如“第 \(j\) 个特征 \(x_j\le t\)”,样本会被分成左右两个子节点:

\[S_L(\phi)=\{(\mathbf{x}_i,y_i)\in S:\ x_{i,j}\le t\},\quad S_R(\phi)=S\setminus S_L(\phi)\]

其中 \(S_L\) 是满足切分条件的样本集合,\(S_R\) 是剩余样本集合。树在每个节点都会尝试多个候选切分 \(\phi\),并保留收益最大的那个。

为了避免分别记忆分类树与回归树的训练目标,可以先写成统一形式。设 \(I(S)\) 表示“节点 \(S\) 当前有多乱”或“在该节点上预测误差有多大”,则一次切分的收益可统一写成:

\[\mathrm{Gain}(S,\phi)=I(S)-\frac{|S_L(\phi)|}{|S|}I\!\left(S_L(\phi)\right)-\frac{|S_R(\phi)|}{|S|}I\!\left(S_R(\phi)\right)\]

这条式子的含义非常直接:

  • \(I(S)\):切分前,这个节点有多混乱。
  • \(I(S_L),I(S_R)\):切分后,左右子节点各自还有多混乱。
  • \(\frac{|S_L|}{|S|},\frac{|S_R|}{|S|}\):左右子节点占父节点样本的比例。要乘这个比例,是因为大子节点对总体误差的影响更大,小子节点不能和大子节点拥有同样权重。
  • \(\mathrm{Gain}(S,\phi)\) 越大,说明这次切分越有效。

分类树与回归树的差别,正体现在 \(I(S)\) 具体取什么。

决策树:一个整体例子

在贷款审批(Loan Approval)场景中,决策树可以直接写成规则链。根节点先按负债收入比(Debt-to-Income Ratio)切分;若负债收入比过高,再看是否有逾期记录;若负债收入比正常,再看信用评分(Credit Score)与近 6 个月收入稳定性。最终某个叶节点可能对应“直接通过”,另一个叶节点对应“人工复核”,再另一个叶节点对应“拒绝”。这就是决策树最重要的工程价值:它不只是给出一个分数,还给出一条可追溯的判断路径。

分类树:目标、公式与含义

分类树的目标是让每个叶节点里的标签尽量单一。若一个节点里几乎都是同一类样本,这个节点就“纯”;若各类样本混在一起,这个节点就“不纯”。

设类别集合为 \(\mathcal{K}\),类别 \(k\) 在节点 \(S\) 中的占比记为:

\[p_k(S)=\frac{\text{节点 }S\text{ 中标签为 }k\text{ 的样本数}}{|S|}\]

常用的不纯度(Impurity)有两种。

基尼不纯度(Gini Impurity):

\[G(S)=1-\sum_{k\in\mathcal{K}}p_k(S)^2\]

它可以读成“随机抽两个样本时,标签不一致的倾向有多强”。若节点里全是同一类,则某个 \(p_k=1\)、其余为 0,此时 \(G(S)=0\),说明节点已经纯净;若二分类里两类各占一半,则 \(G(S)=1-(0.5^2+0.5^2)=0.5\),说明混杂程度较高。

熵(Entropy):

\[H(S)=-\sum_{k\in\mathcal{K}}p_k(S)\log p_k(S)\]

熵衡量的是“不确定性”。若节点里全是同一类,则不需要再猜,熵为 0;若各类比例接近,说明不确定性高,熵也更大。

信息增益(Information Gain)就是“切分前的不确定性”减去“切分后的加权不确定性”:

\[\mathrm{IG}(S,\phi)=H(S)-\frac{|S_L(\phi)|}{|S|}H\!\left(S_L(\phi)\right)-\frac{|S_R(\phi)|}{|S|}H\!\left(S_R(\phi)\right)\]

这条公式的每一部分都对应一个明确动作:

  • 第一项 \(H(S)\) 是切分前的混乱程度。
  • 后两项是切分后左右子节点各自的混乱程度,并按样本占比加权求和。
  • 两者相减,就是这次切分让节点“变纯”了多少。

有些实现使用基尼下降而不是信息增益,本质上是同一件事:选择那个能让子节点更纯、让标签更集中的切分。

分类树:实际例子——用户流失预警

设任务是预测“一个用户未来 30 天是否流失”。标签只有两类:流失 / 未流失,因此这是典型分类树问题。候选特征可以包括:最近 7 天登录次数、最近 30 天是否投诉、是否还有未使用优惠券、最近一次下单距今天数。

假设根节点先尝试切分“最近 7 天登录次数 < 2”。这次切分后,左子节点里的用户大多已经很久不活跃,且流失比例显著升高;右子节点里的用户则活跃度更高、留存率更好。此时无论用基尼还是熵计算,左右节点的加权不纯度都会明显低于父节点,因此这会成为一个高质量切分。

继续往下,左子节点还可以再按“最近 30 天是否投诉”切分:低活跃且有投诉的用户,叶节点里可能出现“82% 最终流失”;低活跃但无投诉的用户,叶节点里可能是“61% 流失”。此时叶子不只给出类别,还可给出经验概率。工程上,这样的输出就能直接用于运营动作:高风险叶子推召回优惠券,中风险叶子推客服回访,低风险叶子不干预。

descision-tree-1

回归树:目标、公式与含义

回归树处理的是连续数值目标,例如价格、时长、销量、能耗。它不追求“类别更纯”,而追求“同一个叶节点里的数值尽量接近”。

若某个叶节点 \(S\) 最终只输出一个常数 \(c\),那么在平方误差(Squared Error)下,最优输出不是中位数,而是均值:

\[c^*(S)=\arg\min_c\sum_{(\mathbf{x}_i,y_i)\in S}(y_i-c)^2=\frac{1}{|S|}\sum_{(\mathbf{x}_i,y_i)\in S}y_i\]

之所以是均值,是因为平方误差会把所有偏差向两边拉平,而均值正是使平方偏差和最小的那个常数。

在这个叶节点上,最小平方误差和(Sum of Squared Errors, SSE)为:

\[\mathrm{SSE}(S)=\sum_{(\mathbf{x}_i,y_i)\in S}\left(y_i-c^*(S)\right)^2\]

它表示节点里所有样本值围绕叶子预测值 \(c^*(S)\) 的总波动。SSE 越大,说明这个节点里的样本值越分散,单用一个常数代表它们的效果越差。

因此一次切分的目标是让切分后的总误差尽量小,也可写成误差下降尽量大:

\[\Delta(S,\phi)=\mathrm{SSE}(S)-\mathrm{SSE}\!\left(S_L(\phi)\right)-\mathrm{SSE}\!\left(S_R(\phi)\right)\]

若更喜欢看平均误差,也可以把它写成 MSE(Mean Squared Error)形式:

\[\mathrm{MSE}(S)=\frac{1}{|S|}\mathrm{SSE}(S)\]

等价地,也可以最小化切分后的加权平均误差:\[\frac{|S_L|}{|S|}\mathrm{MSE}(S_L)+\frac{|S_R|}{|S|}\mathrm{MSE}(S_R)\]

两种写法完全等价:SSE 强调总误差,MSE 强调平均误差;本质都是寻找让子节点内部数值更集中的切分。

回归树:实际例子——外卖配送时长预测

设任务是预测一笔订单从接单到送达需要多少分钟。这是连续数值目标,因此属于回归树。候选特征可以包括:配送距离、是否下雨、是否晚高峰、商家出餐速度、骑手当前手中订单数。

根节点可能先按“配送距离是否大于 3 公里”切分。因为近距离订单与远距离订单的时长分布差异很大,这一步通常能显著降低节点内部方差。对远距离子节点,再按“是否下雨”切分;下雨天路况更慢、波动更大。对近距离子节点,则可能按“是否处于午晚高峰”切分。

假设某个叶节点对应“距离 > 3 公里、下雨、晚高峰”这类订单,这个叶节点里的训练样本平均送达时长是 47 分钟,那么该叶子的预测值就是 47。另一个叶节点若对应“距离 < 2 公里、不下雨、非高峰”,其平均时长可能只有 18 分钟。回归树的预测逻辑不是拟合一条全局直线,而是把不同业务情境分段,再在每段内给出一个局部平均值。

decision-tree-2

适用场景
  • 需要把模型输出翻译成可审计规则,例如风控、审批、运营分层、客服分流。
  • 数据以表格(Tabular)为主,且存在显著非线性、阈值效应或特征交互。
  • 希望同时处理连续特征与离散特征,并保留较强可解释性。
  • 注意:单棵树方差高、容易过拟合,通常需要限制最大深度、最小叶子样本数或配合集成方法。
随机森林

随机森林(Random Forest)是 Bagging(Bootstrap Aggregating)在树模型上的经典实现:用 bootstrap 采样生成多份训练子集,训练多棵通常偏差较低、但对训练数据扰动高度敏感(高方差)的决策树,再把它们的输出聚合,以显著降低整体方差并提升鲁棒性。

这里的“高方差(High Variance)”指模型的估计方差(Estimator Variance)或预测方差(Prediction Variance):如果训练集稍有变化,单棵树学到的分裂结构与最终预测就可能明显变化。随机森林利用多棵树的平均/投票,把这种由数据扰动带来的波动相互抵消。

random-forest

算法与符号

给定训练集 \(D=\{(\mathbf{x}_i,y_i)\}_{i=1}^{N}\)。对 \(m=1,\dots,M\):

  1. bootstrap 采样:从 \(D\) 有放回采样 \(N\) 次得到 \(D_m\)。所谓“有放回(Sampling with Replacement)”,是指每次抽到一个样本后,都先把它放回原数据集,再进行下一次抽样;因此同一个样本可能被重复抽中,而有些样本在这一轮里一次也没有被抽到。
  2. 训练一棵树 \(T_m\):每个节点分裂时,只在随机选取的 \(d'\) 个特征上搜索最优切分(特征子采样,feature subsampling)。

预测时,回归取平均,分类取多数投票:

\[\hat y_{\text{reg}}(\mathbf{x})=\frac{1}{M}\sum_{m=1}^{M}T_m(\mathbf{x}),\quad \hat y_{\text{clf}}(\mathbf{x})=\mathrm{mode}\left(\{T_m(\mathbf{x})\}_{m=1}^{M}\right)\]

这里 \(T_m(\mathbf{x})\) 表示第 \(m\) 棵树对样本 \(\mathbf{x}\) 的预测。回归任务把所有树的输出做平均,以减少波动;分类任务取众数 \(\mathrm{mode}(\cdot)\),也就是票数最多的类别。随机森林的稳定性正来自这种“多棵树共同决定”的聚合机制。

  • \(M\):树的数量。
  • \(d'\):每次分裂考虑的特征数(常见经验:分类用 \(\sqrt{d}\),回归用 \(d/3\))。
为什么有效:方差下降与“去相关”

若单棵树预测的方差为 \(\sigma^2\),不同树之间的相关系数近似为 \(\rho\)(\(0\le\rho\le 1\)),则平均后的方差近似为:

\[\mathrm{Var}\!\left(\frac{1}{M}\sum_{m=1}^{M}T_m(\mathbf{x})\right)\approx \sigma^2\left(\rho+\frac{1-\rho}{M}\right)\]

这个近似式子把随机森林为什么有效说得很清楚: \(\sigma^2\) 是单棵树自身的预测波动, \(\rho\) 是树与树之间的相关性, \(M\) 是树数。树越多, \(\frac{1-\rho}{M}\) 越小;树之间越不相似, \(\rho\) 越低,最终平均后的波动就越小。

因此随机森林有两条主线:

  • 增加 \(M\) 降低 \((1-\rho)/M\) 项。
  • 通过 bootstrap + 特征子采样降低相关性 \(\rho\),让集成真正“互补”。
OOB:不用额外验证集的误差估计

bootstrap 采样会重复抽到某些样本。对固定样本 \(i\),一次采样中没被抽到的概率为 \((1-\frac{1}{N})^N\approx e^{-1}\approx 0.368\)。因此每棵树大约有 36.8% 的样本是袋外(Out-of-Bag, OOB)样本,可用它们评估该树对未见数据的表现,并对全森林给出近似验证误差。

这里 \((1-\frac{1}{N})\) 表示“一次抽样没抽到某个固定样本”的概率,连续做 \(N\) 次后得到 \((1-\frac{1}{N})^N\)。当 \(N\) 足够大时,它逼近 \(e^{-1}\),也就是约 36.8%。这就是为什么随机森林天然拥有一批“没参与这棵树训练”的 OOB 样本。

适用场景
  • 表格数据(Tabular)的强默认基线:非线性、特征交互、缺失值与尺度不一致都较鲁棒。
  • 对超参数不敏感、训练稳定;可用特征重要性(Feature Importance)做解释与特征筛查。
  • 当需要极致精度时,GBDT 家族往往更强;当需要更快推理/更小模型时,线性/浅层模型更合适。
梯度提升树(GBDT)

梯度提升树(Gradient Boosting Decision Tree, GBDT)是一类按序叠加回归树的加法模型(Additive Model)。模型从简单的初始预测 \(F_0\) 出发,在每一轮加入一棵新树,用于修正当前模型尚未拟合好的部分,从而逐步降低训练集上的经验风险(Empirical Risk)。

每一轮新增的树都对应一个修正函数(Correction Function)。它不直接重新学习标签 \(y\),而是拟合当前模型输出与目标之间尚未被解释的差异。多轮修正连续叠加后,模型会从粗糙预测逐步逼近目标函数。

一个直观比喻是:GBDT 像一组按顺序接手的阅卷老师。第一位老师先给出一个粗略分数,后面的每一位老师都不重做整张卷子,只专门检查前面模型错得最明显的地方,并在这些地方补上修正意见。树一棵接一棵叠加后,最终预测会越来越接近真实值。

这里每棵小树都不是独立完成任务的“大模型”,而是一个局部纠错器。它关心的是当前模型还没解释好的误差:哪些样本被高估了,哪些被低估了,以及这些误差集中出现在哪些特征区域。“梯度”对应当前损失下降最快的修正方向,“提升”则表示把这些小修正持续累加成一个更强的整体模型。

gbdt

目标:最小化经验风险

GBDT 背后的目标非常直接:寻找一个函数 \(F\),使训练集上的总损失最小:

\[
\min_F\ \sum_{i=1}^{N}\ell\big(y_i,F(\mathbf{x}_i)\big)
\]

这里 \(\ell(y,F(\mathbf{x}))\) 是单样本损失函数,平方损失、对数损失等都可以放进来。难点在于:函数 \(F\) 不是一个普通标量参数,而是一个复杂的预测函数;如果一次性同时优化所有树的结构和叶子输出,组合空间过大,几乎不可直接求解。

因此 GBDT 采用前向分步加法(Forward Stagewise Additive Modeling):不一次求整个 \(F\),而是把它写成逐步累加的形式,只在第 \(m\) 轮新增一个修正函数 \(f_m\):

\[
F_M(\mathbf{x})=F_0(\mathbf{x})+\nu\sum_{m=1}^{M}f_m(\mathbf{x})
\]

这里 \(F_M(\mathbf{x})\) 表示:模型经过总共 \(M\) 轮提升后,对输入样本 \(\mathbf{x}\) 输出的最终预测值。下标 \(M\) 表示“已经累计做了 \(M\) 次修正”,不是幂次,也不是某一棵单独的树。GBDT 的最终模型是许多轮小修正叠加后的总结果。

  • \(\mathbf{x}\):一个输入样本的特征向量。
  • \(F_0(\mathbf{x})\):初始模型对样本 \(\mathbf{x}\) 的预测,常取常数 \(c\) 使 \(\sum_i \ell(y_i,c)\) 最小。它可以理解为模型在还没有长出任何树之前给出的第一版粗略判断。
  • \(f_m(\mathbf{x})\):第 \(m\) 轮新增的回归树在样本 \(\mathbf{x}\) 上给出的修正值,负责弥补当前模型尚未拟合好的部分。
  • \(\sum_{m=1}^{M}f_m(\mathbf{x})\):把前 \(M\) 轮所有修正树的输出加起来,得到总修正量。
  • \(\nu\in(0,1]\):学习率(Shrinkage),控制每一步修正只走多大。它的作用不是改变方向,而是缩小步长,使训练更稳定、泛化更好。

这个公式也可以按“底稿 + 反复批改”来理解: \(F_0(\mathbf{x})\) 是第一版预测,后面的每个 \(f_m(\mathbf{x})\) 都是在已有结果上补一小笔修正,最终的 \(F_M(\mathbf{x})\) 就是经历 \(M\) 次修正后的版本。

\[
f_m=\arg\min_f\sum_{i=1}^{N}\ell\big(y_i,F_{m-1}(\mathbf{x}_i)+f(\mathbf{x}_i)\big)
\]

这条式子表示:在第 \(m\) 轮,模型要寻找一个新的修正函数 \(f_m\),使它加到旧模型 \(F_{m-1}\) 上之后,训练集的总损失尽可能小。这里的 \(\arg\min_f\) 可以读作“在所有候选函数 \(f\) 里,找出那个能让目标最小的函数”。因此,求出来的不是一个数,而是当前这一轮最合适的新树。

  • \(F_{m-1}(\mathbf{x}_i)\):前 \(m-1\) 轮模型在第 \(i\) 个样本上的当前预测值。
  • \(f(\mathbf{x}_i)\):候选新树在第 \(i\) 个样本上的修正值。
  • \(F_{m-1}(\mathbf{x}_i)+f(\mathbf{x}_i)\):把新树加进去之后,这个样本的新预测值。
  • \(\ell\big(y_i,F_{m-1}(\mathbf{x}_i)+f(\mathbf{x}_i)\big)\):该样本在新预测下的损失。
  • \(\sum_{i=1}^{N}\ell(\cdot)\):把所有样本的损失加总,得到这一轮希望尽量压低的整体目标。

这一轮之所以写成 \(F_{m-1}+f\),而不是重新求一个全新的 \(F_m\),原因在于 GBDT 采用的是逐步修正策略:旧模型已经学到的部分先保留,新树只负责补上当前还没有拟合好的误差。这样每一轮只解决一个更小的局部问题,计算上更可行,也更符合“不断纠错”的直觉。

第 \(m\) 轮只优化新增的修正函数 \(f_m\),而把已有模型 \(F_{m-1}\) 视为固定量。这样做把原本难以整体求解的函数优化问题,拆成了一系列可逐步求解的局部优化问题。

负梯度的来源

上面的子问题仍然不容易直接做,因为“最佳新树”本身还是一个复杂的函数搜索问题。GBDT 的关键近似是:在当前模型 \(F_{m-1}\) 附近,对损失做一阶展开,只看局部下降方向。

对单个样本 \(i\),把新增修正记为 \(f(\mathbf{x}_i)\),则有:

\[
\ell\big(y_i,F_{m-1}(\mathbf{x}_i)+f(\mathbf{x}_i)\big)
\approx
\ell\big(y_i,F_{m-1}(\mathbf{x}_i)\big)
+
\frac{\partial \ell(y_i,F(\mathbf{x}_i))}{\partial F(\mathbf{x}_i)}\Big|_{F=F_{m-1}} f(\mathbf{x}_i)
\]

一阶展开表明,新增函数 \(f\) 的最优局部方向由损失对模型输出的负梯度决定。因此第 \(m\) 轮的伪残差(Pseudo-residual)定义为:

\[
r_i^{(m)}=-\left.\frac{\partial \ell\left(y_i,F(\mathbf{x}_i)\right)}{\partial F(\mathbf{x}_i)}\right|_{F=F_{m-1}}
\]

接下来的动作就自然了:不用树直接拟合标签 \(y_i\),而是用一棵回归树去拟合这些伪残差 \(r_i^{(m)}\)。这棵树学到的,就是“当前模型在输入空间不同区域里,应该往哪个方向、修正多大”的分段常数近似。

模型更新写成:

\[
F_m(\mathbf{x})=F_{m-1}(\mathbf{x})+\nu f_m(\mathbf{x})
\]

“梯度提升”这一名称对应的正是上述更新方式:优化对象不是有限维参数向量,而是预测函数本身;每一轮更新都沿着损失在函数空间中的负梯度方向加入一个新的修正函数。

平方损失下的残差形式

若损失取平方损失

\[
\ell(y,F)=\frac{1}{2}(y-F)^2
\]

则对模型输出求导:

\[
\frac{\partial \ell(y,F)}{\partial F}=F-y
\]

因此第 \(m\) 轮的负梯度为:

\[
r_i^{(m)}=-\left(F_{m-1}(\mathbf{x}_i)-y_i\right)=y_i-F_{m-1}(\mathbf{x}_i)
\]

这正是当前预测与真实值之间的残差(Residual)。所以在回归任务里,人们常把 GBDT 说成“不断拟合残差”;这并不是另一套经验规则,而是平方损失下负梯度公式的直接结果。

树作为局部修正器

因为树天然产生分段常数(Piecewise Constant)的局部修正。若某一轮中,一棵树把样本空间切成若干区域 \(R_1,\dots,R_J\),那么它输出的是:

\[
f_m(\mathbf{x})=\sum_{j=1}^{J}\gamma_j\mathbf{1}(\mathbf{x}\in R_j)
\]

这意味着:模型不是对整个输入空间统一加一个修正,而是在每个局部区域里分别加一个常数修正 \(\gamma_j\)。这正适合处理表格数据里的阈值效应、非线性和特征交互。

叶子输出的解析解

在平方损失下,若某个叶子覆盖的样本集合为 \(S\),并用常数 \(\gamma\) 拟合这一叶内的残差 \(r_i\),则该叶子的局部目标是:

\[
\min_{\gamma}\sum_{i\in S}(r_i-\gamma)^2
\]

对 \(\gamma\) 求导并令其为 0:

\[
\frac{d}{d\gamma}\sum_{i\in S}(r_i-\gamma)^2=-2\sum_{i\in S}(r_i-\gamma)=0
\]
\[
\sum_{i\in S}r_i-|S|\gamma=0
\]
\[
\gamma^*=\frac{1}{|S|}\sum_{i\in S}r_i
\]

因此叶子输出之所以是均值,不是经验设定,而是平方损失下这个局部最小二乘问题的解析解。每一轮加入一棵树,本质上是在每个局部区域里补上一段“平均残差修正”。

训练流程
  1. 初始化 \(F_0\),通常取使总体损失最小的常数模型。
  2. 对第 \(m\) 轮,计算所有样本的伪残差 \(r_i^{(m)}\)。
  3. 训练一棵回归树 \(f_m\) 去拟合 \((\mathbf{x}_i,r_i^{(m)})\)。
  4. 把这棵树按学习率 \(\nu\) 缩小后加到当前模型上。
  5. 重复多轮,直到验证集误差不再下降,或达到预设树数。

GBDT 的本质,是把复杂的函数优化问题拆成许多轮局部修正,并在每一轮用一棵小树逼近当前损失下降最快的方向。

适用场景
  • 结构化表格任务中的强模型:广告、推荐、风控、运营排序、传统特征工程场景。
  • 对特征尺度、非线性、缺失值较鲁棒;能自动学习高阶交互。
  • 注意:对超参数更敏感(树深、学习率、树数、采样比例);需要用验证集早停(Early Stopping)防止过拟合。
XGBoost
背景和问题定义

XGBoost(Extreme Gradient Boosting)是在梯度提升树(Gradient Boosting Decision Tree, GBDT)基础上的工程化强化版本。它关注的是:在保持高表达能力的同时,让树的生长过程更稳定、目标函数更明确、复杂度控制更系统。

核心思想

XGBoost 仍然采用加法模型(Additive Model):当前模型由多棵树的输出求和得到,第 \(t\) 轮只学习一棵新树 \(f_t\) 作为修正项。它的关键强化点有两条:第一,把新增树的学习写成显式的带正则优化问题;第二,对该目标做二阶近似,同时利用梯度(Gradient)和海森(Hessian)信息计算叶子输出与分裂增益。

算法公式和详细解释

设第 \(t\) 轮预测为 \(\tilde y_i^{(t)}=\tilde y_i^{(t-1)}+f_t(\boldsymbol{x}_i)\)。XGBoost 在第 \(t\) 轮优化的目标可写为:

\[\text{Obj}^{(t)}=\sum_{i=1}^{N} \ell(y_i,\tilde y_i^{(t)})+\Omega(f_t)+\text{const}\]

在这个目标里, \(\ell(y_i,\tilde y_i^{(t)})\) 衡量第 \(i\) 个样本在第 \(t\) 轮更新后的预测误差, \(\Omega(f_t)\) 惩罚新树本身的复杂度, \(\text{const}\) 则表示与当前轮新树无关的常数项。也就是说,XGBoost 每一轮都在平衡“把误差降下去”和“不要把树长得太复杂”。

其中正则项通常取:

\[\Omega(f)=\gamma T+\frac{\lambda}{2}\sum_{j=1}^{T}w_j^2\]

这里 \(T\) 是叶子数, \(\gamma T\) 惩罚“树长出太多叶子”, \(\frac{\lambda}{2}\sum_j w_j^2\) 惩罚“每个叶子的输出值过大”。前者控制结构复杂度,后者控制数值幅度,两者合起来让模型更稳。

这里 \(T\) 是叶子数, \(w_j\) 是第 \(j\) 个叶子的输出, \(\gamma\) 控制“新增一个叶子是否值得”, \(\lambda\) 控制叶子输出过大的代价。对损失在当前预测附近做二阶泰勒展开,定义:

\[g_i=\frac{\partial \ell(y_i,\tilde y_i)}{\partial \tilde y_i}\Big|_{\tilde y_i=\tilde y_i^{(t-1)}},\qquad h_i=\frac{\partial^2 \ell(y_i,\tilde y_i)}{\partial \tilde y_i^2}\Big|_{\tilde y_i=\tilde y_i^{(t-1)}}\]

\(g_i\) 是一阶导数,表示“当前这个样本朝哪个方向改,损失下降最快”; \(h_i\) 是二阶导数,表示“这个方向有多陡、多稳定”。XGBoost 同时使用这两项信息,所以比只用一阶梯度的做法更精细。

则近似目标为:

\[\tilde{\text{Obj}}^{(t)}\approx \sum_{i=1}^{N} \left(g_i f_t(\boldsymbol{x}_i)+\frac{1}{2}h_i f_t(\boldsymbol{x}_i)^2\right)+\Omega(f_t)\]

这条近似目标里, \(f_t(\boldsymbol{x}_i)\) 是新树在样本 \(i\) 上给出的修正值。线性项 \(g_i f_t(\boldsymbol{x}_i)\) 反映“沿当前方向修正是否有利”,二次项 \(\frac{1}{2}h_i f_t(\boldsymbol{x}_i)^2\) 反映“修正过大时会不会带来额外代价”。

若固定树结构,记落在叶子 \(j\) 的样本集合为 \(I_j\),并定义 \(G_j=\sum_{i\in I_j}g_i\)、\(H_j=\sum_{i\in I_j}h_i\),则该叶子的最优输出为:

\[w_j^*=-\frac{G_j}{H_j+\lambda}\]

这里 \(G_j\) 是第 \(j\) 个叶子里所有样本一阶梯度的总和, \(H_j\) 是二阶梯度总和。分子告诉模型这个叶子整体应该往哪个方向修正,分母则用二阶信息和正则项 \(\lambda\) 把修正幅度稳住。

某次分裂把父叶拆成左右两叶后的增益(Gain)为:

\[\text{Gain}=\frac{1}{2}\left(\frac{G_L^2}{H_L+\lambda}+\frac{G_R^2}{H_R+\lambda}-\frac{G^2}{H+\lambda}\right)-\gamma\]

这个增益式子比较的是“父叶不分裂”和“分成左右两叶”谁更划算。 \(G_L,H_L\) 与 \(G_R,H_R\) 分别是左右子叶的梯度统计量, \(G,H\) 是父叶统计量;最后减去 \(\gamma\),表示每多长一个叶子都要付复杂度代价。

这说明 XGBoost 的分裂同时考虑“收益”和“复杂度惩罚”,并以此控制结构扩张。

训练或推断流程
  1. 用当前模型计算每个样本的一阶梯度 \(g_i\) 与二阶梯度 \(h_i\)。
  2. 在候选特征与候选阈值上搜索分裂增益最大的切分。
  3. 固定树结构后,利用 \(w_j^*\) 计算每个叶子的最优输出。
  4. 把新树加入现有模型,继续下一轮迭代。
  5. 预测时把所有树的输出累加,再映射到分类或回归结果。
应用实例

在点击率预估(CTR Prediction)中,用户、广告和上下文之间往往存在复杂交互。XGBoost 可以通过逐轮加树自动学习“什么样的用户在什么时间、看到什么样的广告更容易点击”这类组合规则,因此在工业级表格任务中长期保持强竞争力。

优缺点与适用场景
  • 优点:表格数据表现强,目标函数清晰,正则化明确,工程生态成熟。
  • 局限:超参数较多;树深、学习率、树数、采样比例之间存在明显耦合。
  • 适用场景:风控、广告、推荐、排序与一般结构化表格建模。
LightGBM
背景和问题定义

LightGBM 是面向大规模数据与高维稀疏特征优化的 GBDT 实现。它关注的核心问题是:当样本量和特征维度都很大时,如何降低分裂搜索的时间与内存成本,同时尽量不牺牲精度。

核心思想

LightGBM 的两个关键设计是直方图分桶(Histogram Binning)和叶子优先生长(Leaf-wise Growth)。前者把连续特征离散到有限个桶上,后者每一步都继续分裂当前收益最大的叶子,从而在相同叶子预算下更快降低训练误差。

算法公式和详细解释

在优化目标上,LightGBM 与 GBDT / XGBoost 一致,仍然是逐轮加入树来降低损失。它的区别主要体现在计算方式:若某个连续特征被离散到 \(B\) 个桶,则算法只需在桶边界上搜索分裂点,而不必在所有实数取值上逐一枚举。这样,每个节点维护的是桶级梯度统计量,而非逐样本的原始实数值。

叶子优先生长意味着:算法始终选择当前分裂增益最大的叶子继续向下扩展。它通常比按层生长(Level-wise)更激进,因而在同样叶子数限制下更容易得到较低训练误差,但也更容易在局部区域长出很深的树。

训练或推断流程
  1. 将连续特征离散到有限个桶,并统计桶级梯度信息。
  2. 在每个节点上基于桶统计量搜索最优切分。
  3. 选择全局增益最大的叶子继续分裂。
  4. 使用最大深度、最大叶子数、最小叶子样本数等约束抑制过拟合。
  5. 预测时沿树路径到达叶子并累加所有树的输出。
应用实例

在大规模推荐粗排任务中,输入特征通常极高维且高度稀疏。LightGBM 能在保留较强拟合能力的同时显著缩短训练时间,因此非常适合需要频繁重训的工业流水线。

优缺点与适用场景
  • 优点:训练快、内存占用低,对大规模稀疏特征友好。
  • 局限:叶子优先策略若约束不足,局部树会过深,过拟合风险更高。
  • 适用场景:超大规模表格数据、稀疏特征建模、追求训练效率的工业场景。
概率模型

这一类方法处理的核心问题是:模型不仅要给出“预测是什么”,还要明确回答“这个结果有多可信、数据是如何生成的、隐藏结构是什么”。因此它们直接建模概率分布(Probability Distribution)、隐变量(Latent Variables)或序列依赖关系,在分类、密度估计、软聚类、序列推断与不确定性表达中具有统一优势。

朴素贝叶斯
背景和问题定义

朴素贝叶斯(Naive Bayes)用于分类问题。给定特征 \(\boldsymbol{x}\),它要估计样本属于每个类别 \(y\) 的后验概率 \(p(y|\boldsymbol{x})\)。该方法尤其适合高维稀疏、小样本或需要快速概率基线的任务。

核心思想

朴素贝叶斯的核心假设是:在给定类别 \(y\) 的条件下,各个特征条件独立(Conditional Independence)。这个假设通常并不严格成立,但它把高维联合分布的估计问题,转化为多个一维条件分布的估计问题。

算法公式和详细解释

由贝叶斯公式:

\[p(y|\boldsymbol{x})=\frac{p(\boldsymbol{x}|y)p(y)}{p(\boldsymbol{x})}\]

这个贝叶斯公式把后验概率拆成三部分: \(p(y|\boldsymbol{x})\) 是看到特征后属于类别 \(y\) 的概率; \(p(\boldsymbol{x}|y)\) 是该类别生成这组特征的可能性; \(p(y)\) 是类别先验; \(p(\boldsymbol{x})\) 则是对所有类别做归一化的总证据。

由于 \(p(\boldsymbol{x})\) 对所有类别相同,分类时只需比较:

\[p(y|\boldsymbol{x})\propto p(y)\prod_{j=1}^{d}p(x_j|y)\]

这里的 \(\propto\) 表示“成正比”。因为对同一个样本来说,分母 \(p(\boldsymbol{x})\) 对所有类别都相同,所以比较类别大小时只需看右边:先验 \(p(y)\) 乘上每个特征条件概率 \(p(x_j|y)\) 的连乘积。

其中 \(p(y)\) 是先验概率(Prior), \(p(x_j|y)\) 是条件似然(Likelihood)。根据特征类型不同,可以得到高斯朴素贝叶斯、伯努利朴素贝叶斯、多项式朴素贝叶斯等变体。

训练或推断流程
  1. 从训练集统计每个类别的先验概率 \(p(y)\)。
  2. 估计每个类别下各特征的条件分布 \(p(x_j|y)\)。
  3. 推断时计算各类别的对数后验分数 \(\log p(y)+\sum_j \log p(x_j|y)\)。
  4. 选择分数最大的类别作为预测输出。
应用实例

在垃圾邮件检测中,若某些词在垃圾邮件中显著更常见,那么这些词对应的条件概率会被估得更大,从而把包含这些词的邮件判到垃圾类别。

优缺点与适用场景
  • 优点:训练快、推断快、对高维稀疏特征友好。
  • 局限:条件独立假设常被破坏;概率校准有时较弱。
  • 适用场景:文本分类、垃圾邮件过滤、简单可靠的概率基线。
高斯混合模型(GMM)
背景和问题定义

高斯混合模型(Gaussian Mixture Model, GMM)处理的是“数据由多个潜在高斯成分混合生成”的建模问题。与 K-Means 只输出硬划分不同,GMM 希望估计每个样本属于各个簇的概率,并允许不同簇有不同的协方差结构。

核心思想

GMM 引入潜变量 \(z\) 表示样本来自哪一个高斯成分。整体分布由多个高斯分布按混合系数加权得到,因此每个样本对各个簇的归属是软的(Soft Assignment),并以概率形式表达。

一个直观比喻是:把数据想成混在一起的几类人群,只能看到每个人的外在特征,却看不到他原本属于哪一类。每一类人群都有自己的“中心位置”和“分散形状”,对应一个高斯成分;整个数据集则像这些人群按不同比例叠在一起形成的总体分布。与 K-Means 把每个样本硬塞进某一个簇不同,GMM 会给出“这个样本更像第 1 类,也有一部分像第 2 类”这样的软归属结果。

因此,混合系数 \(\pi_k\) 可以理解为各类人群在总体中的占比,均值 \(\boldsymbol{\mu}_k\) 是每类人群的中心,协方差 \(\boldsymbol{\Sigma}_k\) 描述该群体沿不同方向的扩散方式,而责任度 \(\gamma_{ik}\) 则表示“样本 \(i\) 有多大程度属于第 \(k\) 类”。这也是 GMM 比 K-Means 更灵活的原因:它允许边界模糊,也允许簇具有不同大小、方向和椭球形状。

算法公式和详细解释

对样本 \(\boldsymbol{x}\),GMM 的概率密度写为:

\[p(\boldsymbol{x})=\sum_{k=1}^{K} \pi_k \mathcal{N}(\boldsymbol{x}\mid \boldsymbol{\mu}_k,\boldsymbol{\Sigma}_k)\]

这条式子说明 GMM 的整体密度不是由单个高斯给出,而是 \(K\) 个高斯成分的加权和。 \(\pi_k\) 决定第 \(k\) 个成分在总体中的占比, \(\mathcal{N}(\boldsymbol{x}\mid \boldsymbol{\mu}_k,\boldsymbol{\Sigma}_k)\) 描述样本 \(\boldsymbol{x}\) 在该成分下有多典型。

其中 \(\pi_k\) 是混合系数,满足 \(\pi_k\ge 0\) 且 \(\sum_k \pi_k=1\)。给定样本后,其属于第 \(k\) 个成分的责任度(Responsibility)为:

\[\gamma_{ik}=p(z_i=k|\boldsymbol{x}_i)=\frac{\pi_k \mathcal{N}(\boldsymbol{x}_i\mid \boldsymbol{\mu}_k,\boldsymbol{\Sigma}_k)}{\sum_{j=1}^{K}\pi_j \mathcal{N}(\boldsymbol{x}_i\mid \boldsymbol{\mu}_j,\boldsymbol{\Sigma}_j)}\]

责任度 \(\gamma_{ik}\) 是“样本 \(i\) 属于成分 \(k\) 的后验概率”。分子表示“成分 \(k\) 解释这个样本的能力”,分母则把所有成分对该样本的解释能力加总起来做归一化,因此所有 \(\gamma_{ik}\) 加起来等于 1。

GMM 的参数通常通过期望最大化(Expectation-Maximization, EM)求解。E 步计算责任度,M 步更新参数:

\[N_k=\sum_{i=1}^{N}\gamma_{ik},\qquad \pi_k=\frac{N_k}{N}\]

这里 \(N_k\) 不是成分 \(k\) 的硬计数,而是软计数:每个样本只按自己的责任度贡献一部分。于是混合系数更新为 \(\pi_k=\frac{N_k}{N}\),表示第 \(k\) 个成分在总体中的相对权重。

\[\boldsymbol{\mu}_k=\frac{1}{N_k}\sum_{i=1}^{N}\gamma_{ik}\boldsymbol{x}_i,\qquad \boldsymbol{\Sigma}_k=\frac{1}{N_k}\sum_{i=1}^{N}\gamma_{ik}(\boldsymbol{x}_i-\boldsymbol{\mu}_k)(\boldsymbol{x}_i-\boldsymbol{\mu}_k)^\top\]

均值更新式说明:每个样本按责任度大小对中心 \(\boldsymbol{\mu}_k\) 做加权贡献;协方差更新式则是在该加权中心周围统计离散程度。责任度越大,样本对该成分的中心和形状影响越大。

训练或推断流程
  1. 初始化混合系数、均值和协方差。
  2. E 步:计算每个样本对各高斯成分的责任度。
  3. M 步:根据责任度更新参数。
  4. 重复 E / M,直到对数似然收敛。
应用实例

在用户分群中,若人群天然分成多个椭球状子群体,那么 GMM 不仅能给出簇划分,还能输出“某个用户属于每个群体的概率”,这比 K-Means 的硬分配更细致。

优缺点与适用场景
  • 优点:软聚类、概率解释清晰、能建模不同协方差形状。
  • 局限:对初始化敏感;高维时协方差估计代价高。
  • 适用场景:软聚类、密度估计、带概率解释的聚类分析。
隐马尔可夫模型(HMM)
背景和问题定义

隐马尔可夫模型(Hidden Markov Model, HMM)用于序列建模,尤其适合处理序列标注(Sequence Labeling)问题。序列标注的任务形式是:给定一个按时间或位置排列的输入序列,为序列中的每个位置分配一个标签。例如,在词性标注中,句子“我爱北京天安门”的每个词或字都需要对应一个词性标签;在语音识别中,一段连续声学信号需要对应到一串离散文字或音素标签。

HMM 是序列模型中的经典早期方法,在语音识别等领域长期具有重要地位。它的优势在于结构清晰、推断高效,能够以较低的计算成本处理序列决策;与此同时,它主要依赖局部状态转移和局部发射关系,所使用的上下文信息相对有限。

HMM 的建模方式是:观测序列 \(\boldsymbol{x}_{1:T}\) 可以看到,但生成这些观测的状态序列 \(\boldsymbol{z}_{1:T}\) 看不到。这里的隐藏状态通常对应词性、命名实体类别或发音状态等潜在标签。围绕这一模型,核心问题通常包括计算某段观测序列的概率、恢复最可能的隐藏状态路径,以及估计模型参数。

核心思想

HMM 假设隐藏状态满足一阶马尔可夫性(First-order Markov Property):当前状态只依赖前一个状态;同时每个观测只依赖当前状态。一个直接的比喻是:无法直接看到远方朋友每天所处的天气,但可以持续看到他发布的活动,例如“去游泳”“去逛街”或“在家睡觉”。在这个比喻里,天气是隐藏状态 \(z_t\),活动是观测 \(x_t\)。HMM 的生成逻辑正是先生成隐藏状态序列,再由每个状态发射对应观测。

如果今天是晴天,明天仍然晴天的概率通常较高;如果今天下雨,朋友在家休息的概率通常高于去游泳。这分别对应 HMM 中的状态转移概率 \(p(z_t|z_{t-1})\) 和发射概率 \(p(x_t|z_t)\)。因此,HMM 把序列建模为一个“剧本模拟器”:先按转移规律生成一条看不见的天气轨迹,再按照每一天的天气生成看得见的活动记录。

HMM 概念 比喻中的对应物 含义
隐藏状态 \(z_t\) 每天的天气 真实存在,但观察者不能直接看到。
观测 \(x_t\) 朋友圈里的活动 可以直接看到,用来反推隐藏状态。
初始分布 \(p(z_1)\) 第一天各种天气出现的概率 序列从什么状态开始。
转移概率 \(p(z_t|z_{t-1})\) 天气从今天到明天的变化规律 例如“晴天后仍是晴天”的概率较高。
发射概率 \(p(x_t|z_t)\) 某种天气下出现某种活动的概率 例如下雨时更可能“在家睡觉”。
隐藏状态序列 \(\boldsymbol{z}_{1:T}\) 整段天气变化轨迹 模型希望恢复的潜在过程。
观测序列 \(\boldsymbol{x}_{1:T}\) 整段活动记录 模型的输入数据。

这个比喻也解释了 HMM 的优势与局限。它简单、快速、可解释,因为联合概率能够拆成局部转移和局部发射的乘积,并可用动态规划高效推断。但它的条件独立假设也很强:某一天的活动只由当天的天气决定,不直接依赖前后活动。在词性标注等任务中,一个词的标签往往同时受左右上下文影响,这种假设就会限制表达能力。

算法公式和详细解释

HMM 的联合分布写为:

\[p(\boldsymbol{x}_{1:T},\boldsymbol{z}_{1:T})=p(z_1)\prod_{t=2}^{T}p(z_t|z_{t-1})\prod_{t=1}^{T}p(x_t|z_t)\]

这条联合分布把一整条序列拆成三部分: \(p(z_1)\) 是初始状态概率, \(\prod_{t=2}^{T}p(z_t|z_{t-1})\) 是状态转移链, \(\prod_{t=1}^{T}p(x_t|z_t)\) 是每个状态发射观测的概率。正因为有这种乘积分解,HMM 才能用动态规划高效求解。

若记初始分布为 \(\pi\),转移矩阵为 \(A\),发射分布为 \(B\),则前向算法(Forward Algorithm)的核心量为:

\[\alpha_t(j)=p(x_{1:t},z_t=j)\]

\(\alpha_t(j)\) 的含义是:看到前 \(t\) 个观测,同时当前时刻状态恰好是第 \(j\) 个状态的联合概率。它把“历史观测信息”和“当前落在哪个状态”压缩成一个可递推的中间量。

其递推为:

\[\alpha_t(j)=\left[\sum_i \alpha_{t-1}(i)A_{ij}\right]B_j(x_t)\]

递推式可以分成两步看:先对所有上一步状态 \(i\) 求和,用 \(A_{ij}\) 累积“从 \(i\) 转到 \(j\) 的可能性”;再乘上 \(B_j(x_t)\),表示当前状态 \(j\) 发射出观测 \(x_t\) 的概率。

最可能状态路径可由维特比算法(Viterbi Algorithm)求解;参数估计通常采用 Baum-Welch 算法,即 HMM 上的 EM。

训练或推断流程
  1. 定义状态空间、转移概率和发射概率。
  2. 若参数已知,用前向 / 后向算法做概率计算,用维特比算法做解码。
  3. 若参数未知,用 Baum-Welch 在训练集上迭代估计参数。
  4. 根据任务输出状态路径、序列概率或边缘状态分布。
应用实例

在词性标注中,观测是单词序列,隐藏状态是词性标签。HMM 会同时利用“某个词在某种词性下更常见”的发射规律和“词性之间如何转移”的序列规律完成整体解码。

例如,对序列“我 / 爱 / 北京 / 天安门”,模型看到的是词本身,看不到的是背后的标签序列。HMM 会比较多种候选路径,如“代词(Pronoun)→ 动词(Verb)→ 专有名词(Proper Noun)→ 专有名词(Proper Noun)”与其他不合理组合的概率。由于“我”更容易由代词状态发射,“爱”更容易由动词状态发射,而“代词后接动词、动词后接名词性成分”又符合常见转移规律,这条标签路径就会获得更高概率。这个过程可以理解为:模型一边根据词本身猜标签,一边检查整条词性路径是否顺畅。

hmm

优缺点与适用场景
  • 优点:序列结构清晰,动态规划推断高效,可解释性强。
  • 局限:一阶马尔可夫假设较强,表达能力有限。
  • 适用场景:基础序列标注、时间状态切换建模、中小规模序列任务。
条件随机场(CRF)
背景和问题定义

条件随机场(Conditional Random Field, CRF)主要用于结构化预测(Structured Prediction),尤其是序列标注。它处理的问题是:在给定输入序列 \(\boldsymbol{x}\) 的条件下,如何联合预测输出标签序列 \(\boldsymbol{y}\),并显式建模标签之间的依赖关系。

CRF 可以看作对 HMM 的进一步发展:它不再试图解释输入序列如何被生成,而是直接在给定输入的条件下预测最合理的标签结构。通过引入全局特征和更灵活的上下文依赖,CRF 缓解了 HMM 仅依赖局部独立假设所带来的信息不足。在深度学习广泛进入 NLP 之前,CRF 长期是各类标注任务中的核心方法。

核心思想

CRF 的核心不是描述数据如何生成,而是在给定观测序列的条件下,对整条标签序列进行全局评分。仍以天气和活动的比喻来理解:已知一整周的活动记录后,CRF 不会先假设天气如何一步步生成活动,而是把各种可能的天气序列都拿来比较,判断哪一种与这组活动整体最一致。它建模的是条件分布 \(p(\boldsymbol{y}|\boldsymbol{x})\),而不是 HMM 那样的联合分布 \(p(\boldsymbol{x},\boldsymbol{y})\)。

这种“全局把控”体现在两个层面。第一,CRF 的打分对象是完整的标签路径,而不是每个位置互相独立的局部决策;第二,打分依据可以是灵活定义的特征函数(Feature Function)。例如,若连续三天都出现“游泳”,对应“连续晴天”的标签组合就应得到更高分;若一周中出现“滑雪”这类活动,与“夏天”一致的天气标签组合就应被显著压低。特征函数可以同时利用当前位置、前后邻域以及相邻标签之间的组合关系。

因此,CRF 可以视为一个面向整条序列的打分系统:输入固定,模型比较不同标签序列的相对合理性,并选择得分最高的一条。它的优势是能够充分利用复杂上下文和标签依赖,在序列标注任务中通常比 HMM 更准确;代价是训练和推断都更重,需要计算整条序列上的归一化与动态规划。

算法公式和详细解释

线性链 CRF 的条件分布通常写为:

\[p(\boldsymbol{y}|\boldsymbol{x})=\frac{1}{Z(\boldsymbol{x})}\exp\left(\sum_{t=1}^{T}\sum_k \lambda_k f_k(y_{t-1},y_t,\boldsymbol{x},t)\right)\]

这个式子最好分三层看。先看最里面的 \(\sum_{t=1}^{T}\sum_k \lambda_k f_k(y_{t-1},y_t,\boldsymbol{x},t)\):它表示对整条标签序列逐位置累积特征得分。再看外面的指数 \(\exp(\cdot)\):它把“总得分”变成一个始终为正的数,而且总得分越大,这个数就越大。最后再除以 \(Z(\boldsymbol{x})\),把这些正数正规化成概率。因此,CRF 的计算顺序可以理解为:先打分,再变成正权重,最后归一化成概率。

为了看清楚 \(Z(\boldsymbol{x})\) 在做什么,可以先临时把分子记成一个“未归一化分数”:

\[\tilde{p}(\boldsymbol{y}|\boldsymbol{x})=\exp\left(\sum_{t=1}^{T}\sum_k \lambda_k f_k(y_{t-1},y_t,\boldsymbol{x},t)\right)\]

这里特意加波浪号,是为了强调它还不是概率。原因很简单:把所有可能标签序列的 \(\tilde{p}(\boldsymbol{y}|\boldsymbol{x})\) 加起来,结果一般不会恰好等于 1。它只是每条路径的相对权重,表达“这条标签路径有多合理”。

这时配分函数(Partition Function)就出现了:

\[Z(\boldsymbol{x})=\sum_{\boldsymbol{y}} \exp\left(\sum_{t=1}^{T}\sum_k \lambda_k f_k(y_{t-1},y_t,\boldsymbol{x},t)\right)\]

之所以你会觉得它“和上面那个公式一样”,是因为它确实就是把上式分子对所有可能的标签序列整体求和。上面的 \(p(\boldsymbol{y}|\boldsymbol{x})\) 针对的是某一条固定标签序列 \(\boldsymbol{y}\);而这里的 \(Z(\boldsymbol{x})\) 不是看某一条路径,而是把所有可能路径都算一遍,再全部加起来。所以它不是“另一条几乎一样的公式”,而是“分子在全标签空间上的总和”。

于是条件概率就变成:

\[p(\boldsymbol{y}|\boldsymbol{x})=\frac{\tilde{p}(\boldsymbol{y}|\boldsymbol{x})}{Z(\boldsymbol{x})}\]

现在这个式子就容易理解了:某条路径的概率,等于“这条路径自己的权重”除以“所有路径权重的总和”。这和 softmax 的归一化逻辑完全一致,只不过 softmax 是在有限个类别上归一化,而 CRF 是在所有可能的标签序列上归一化。

配分函数这个名字来自统计物理,但在这里不需要物理背景也能理解:它本质上就是一个归一化常数。没有它,模型只能说“路径 A 比路径 B 更合理”;有了它,模型才能进一步说“路径 A 的概率是多少”。也正因为 \(Z(\boldsymbol{x})\) 需要把所有可能标签路径都考虑进去,CRF 训练时才必须借助动态规划,而不能暴力枚举。

  • \(f_k(y_{t-1},y_t,\boldsymbol{x},t)\):第 \(k\) 个特征函数,描述当前位置、相邻标签和输入之间的某种局部模式。
  • \(\lambda_k\):该特征的权重;越大表示模型越重视这个模式。
  • \(\boldsymbol{x}\):固定输入序列;在讨论 \(Z(\boldsymbol{x})\) 时,它不变。
  • \(\boldsymbol{y}\):某一条候选标签序列;计算 \(Z(\boldsymbol{x})\) 时要对所有可能的 \(\boldsymbol{y}\) 求和。
  • \(\sum_{t=1}^{T}\sum_k \lambda_k f_k(\cdot)\):整条标签序列的总得分。
  • \(\exp(\cdot)\):把总得分映射成正权重,并放大高分路径与低分路径之间的差异。
  • \(Z(\boldsymbol{x})\):所有候选标签路径未归一化权重的总和,用于把相对权重变成概率。

训练时最大化条件对数似然,解码时用维特比算法寻找最优标签序列。

训练或推断流程
  1. 定义特征函数,描述输入与标签、标签与标签之间的关系。
  2. 用前向后向算法计算配分函数与梯度。
  3. 通过梯度法优化参数 \(\lambda_k\)。
  4. 推断时用维特比算法输出最优标签序列。
应用实例

在命名实体识别(NER)中,局部分类器可能会把某个词单独判成人名,但 CRF 会进一步考虑相邻标签是否合法,从而减少孤立的局部误判。这里“是否合法”指的不是语法合法,而是标签序列是否符合该任务定义下允许出现的邻接模式。例如,在常见的 BIO 标注体系中, \(B\) 表示 Begin,即实体开始; \(I\) 表示 Inside,即实体内部; \(O\) 表示 Outside,即不属于任何实体。也有一些任务使用 BIOES 标注体系,其中 \(E\) 表示 End, \(S\) 表示 Single。与 BIO 相比,BIOES 会把实体结束位置和单字实体显式标出来,因此边界信息更细。于是,标签 \(B\text{-}PER\) 表示一个人名实体的开始, \(I\text{-}PER\) 表示该人名实体的内部, \(O\) 表示不属于任何实体。于是, \(B\text{-}PER\rightarrow I\text{-}PER\) 是常见且合法的相邻转移, \(O\rightarrow B\text{-}PER\) 也合法;但 \(O\rightarrow I\text{-}PER\) 通常不合法,因为一个实体内部标签不能无缘无故直接开始,前面必须先有对应的开始标签。同样, \(B\text{-}LOC\rightarrow I\text{-}PER\) 这类“实体类型突然不一致”的连接也通常应被压低分数。

例如,在句子“张三 在 北京 工作”中,若任务要识别人名(PER)和地点(LOC),一个合理的 BIO 标注序列可能是“张三 / 在 / 北京 / 工作”对应 \(B\text{-}PER, O, B\text{-}LOC, O\)。这里首先需要区分两件事:某个位置更像哪一种实体类型,以及这些局部判断连起来是否构成一条合理的标签序列。前者主要来自输入本身提供的证据,例如“张三”在词形上很像中文人名,“北京”本身强烈像地点名词,而“在 北京 工作”这种上下文也会继续加强“北京是地点”的判断。传统 CRF 会把这些信息写成特征函数,例如“当前词是否常见于人名词表”“当前词是否带有地名后缀”“左邻词是否是介词‘在’”“右邻词是否是动作词‘工作’”等;每个特征都会给某个候选标签加分或减分。

CRF 的作用是在这些局部类型证据之上,再做一次全局一致性的联合解码。换言之,实体类型 A 还是 B,并不是和 CRF 完全无关;但也不是由 CRF 凭空决定的。更准确地说,实体类型的语义判断主要来自输入特征,CRF 负责把这些局部判断放到整条序列里统一协调。例如,如果“北京”这个位置单看局部证据时,对 LOC 的分数高于 PER,那么 CRF 会倾向保留“地点”这一判断;但它还会进一步检查,当前位置前后的标签连接是否自然。如果某条候选路径把“张三”切成 \(B\text{-}PER, O\),或者把“北京”接成 \(B\text{-}PER\rightarrow I\text{-}LOC\),即使某个局部位置的分数不低,整条路径仍会因为边界断裂或类型转移不一致而被整体压低。于是 CRF 做的不是单点分类,而是“局部类型打分 + 全局路径约束”的联合决策。

从工程实现上看,这个分工在不同年代的模型里表现形式不同。在传统 CRF 中,“局部类型打分”通常来自人工设计的特征模板,例如当前词、前后词、词性、字形、是否出现在人名词典或地名词典中;CRF 再把这些手工特征组合成整条序列的全局分数。在 BiLSTM-CRF 或 BERT-CRF 这类现代模型中,局部证据不再主要依赖手工模板,而是先由 BiLSTM 或 BERT 生成上下文化表示(Contextual Representation),再由线性层给出每个位置对各标签的局部分数,最后仍由 CRF 层负责建模标签转移和整条路径解码。也就是说,上游编码器主要回答“这个位置像什么类型”,CRF 层主要回答“这些位置判断拼在一起是否构成一条最合理的标签序列”。

crf-1

类似的全局打分思想也可以推广到依存句法分析(Dependency Parsing, DEP)这类结构化任务。句子中的每个词都需要找到自己的中心词(head),模型的目标不是孤立地决定“这个词连向谁”,而是评估整棵依存树是否合理。例如,在“她 喜欢 自然语言处理”中,“喜欢”通常更可能作为中心谓词,“她”依附到“喜欢”形成主谓关系,“自然语言处理”整体依附到“喜欢”形成宾语关系。若某个局部决策把“她”错误地连到“自然语言处理”,单看两个词的局部相似度未必很低,但放到整棵树的全局结构中就会显得不协调。CRF 的价值正体现在这里:它通过全局归一化和结构约束,偏好整体验证一致的输出结构,而不是一组彼此冲突的局部最优决策。

crf-2

优缺点与适用场景
  • 优点:适合结构化输出,能显式编码标签依赖。
  • 局限:训练与推断成本高于普通独立分类器。
  • 适用场景:序列标注、分词、命名实体识别等条件结构化预测任务。
近邻模型

这一类方法处理的核心问题是:在缺少可靠全局函数形式时,是否可以直接依赖“局部相似样本通常有相似输出”这一假设完成预测。近邻模型不急于学习一个显式参数化函数,而是把相似性度量(Similarity Metric)本身作为建模中心:先找邻居,再由邻居投票、平均或加权得到结果。

K 近邻(KNN)
背景和问题定义

K 近邻(K-Nearest Neighbors, KNN)用于分类与回归。给定一个待预测样本 \(\boldsymbol{x}\),它要根据训练集中与其最相似的样本来决定输出。

核心思想

KNN 的基本假设是局部平滑性(Local Smoothness):在特征空间中彼此接近的样本,往往具有相近的标签或数值。它不显式学习参数化模型,训练集本身就是局部比较的参照集。

算法公式和详细解释

给定距离函数 \(d(\boldsymbol{x},\boldsymbol{x}')\) 与邻居数 \(K\),若 \(N_K(\boldsymbol{x})\) 表示 \(\boldsymbol{x}\) 的 \(K\) 个最近邻,则分类时可写为:

\[\hat y=\mathrm{mode}\left(\{y_i:(\boldsymbol{x}_i,y_i)\in N_K(\boldsymbol{x})\}\right)\]

这里 \(N_K(\boldsymbol{x})\) 是样本 \(\boldsymbol{x}\) 的 \(K\) 个最近邻集合,花括号中收集的是这些邻居的标签, \(\mathrm{mode}(\cdot)\) 则返回出现次数最多的类别。也就是说,KNN 分类本质上就是“看最近的邻居们大多数是谁”。

回归时常取邻居标签平均:

\[\hat y=\frac{1}{K}\sum_{(\boldsymbol{x}_i,y_i)\in N_K(\boldsymbol{x})}y_i\]

回归版 KNN 只是把“多数投票”换成“数值平均”。 \(\frac{1}{K}\sum\) 表示把最近 \(K\) 个邻居的输出做均值,因此预测值会受到局部邻域中所有数值样本的共同影响。

若距离使用欧氏距离,则默认所有特征尺度可比,因此标准化(Standardization)通常是必要前处理。

训练或推断流程
  1. 训练阶段几乎不做参数学习,只保存全部训练样本。
  2. 推断时计算待测样本到训练样本的距离。
  3. 选出最近的 \(K\) 个样本。
  4. 分类取多数投票,回归取平均或距离加权平均。
应用实例

在简单的手写数字识别中,如果一张新图片与训练集中大量“3”的图像都很接近,而与“8”的图像明显更远,那么 KNN 会依据局部邻域投票把它判为 3。

优缺点与适用场景
  • 优点:概念简单、无需复杂训练、局部非线性表达能力强。
  • 局限:推断成本高;对特征尺度和无关特征敏感;维度灾难会削弱距离判别力。
  • 适用场景:中小规模数据、快速基线、基于相似度的简单分类与回归。
聚类

聚类处理的核心问题是:在没有标签的前提下,如何仅根据样本之间的几何关系、密度结构或层次关系,把数据自动分成若干组。这里不存在唯一正确的“簇”定义:K-Means 假设簇围绕中心分布,层次聚类强调多粒度组织结构,DBSCAN / HDBSCAN 则把簇理解为高密度连通区域。因此,聚类算法的选择本质上是在选择“什么样的结构应被视为同一类”。

K-Means
背景和问题定义

K-Means 处理的是无监督聚类问题:给定一组没有标签的样本,希望把它们分成 \(K\) 个簇,使同一簇内样本尽量接近,不同簇之间尽量分开。

核心思想

K-Means 用“每个簇由一个中心点代表”的方式近似数据分布。算法不断重复两件事:把样本分配给最近的中心;再用簇内样本均值更新中心。它本质上是在最小化簇内平方误差。

k-means

算法公式和详细解释

目标函数为:

\[\min_{\{c_k\},\{z_i\}} \sum_{i=1}^{N} \|\boldsymbol{x}_i-c_{z_i}\|_2^2\]

这个目标里, \(c_k\) 是第 \(k\) 个簇中心, \(z_i\) 表示样本 \(i\) 被分到哪个簇, \(\|\boldsymbol{x}_i-c_{z_i}\|_2^2\) 是样本到所属簇中心的平方距离。K-Means 想做的,就是让所有样本离各自中心都尽可能近。

其中 \(c_k\) 是第 \(k\) 个簇中心, \(z_i\in\{1,\dots,K\}\) 表示样本 \(\boldsymbol{x}_i\) 属于哪个簇。固定簇分配时,最优中心是该簇样本均值:

\[c_k=\frac{1}{|S_k|}\sum_{\boldsymbol{x}_i\in S_k} \boldsymbol{x}_i\]

这里 \(S_k\) 是第 \(k\) 个簇里所有样本的集合, \(|S_k|\) 是该簇样本数。这个更新式说明簇中心就是簇内样本的算术平均,因此 K-Means 的“中心”确实是均值意义上的代表点。

训练或推断流程
  1. 初始化 \(K\) 个簇中心。
  2. 分配步骤:把每个样本分到最近中心。
  3. 更新步骤:用各簇样本均值更新中心。
  4. 重复迭代直到簇分配稳定或目标下降很小。
应用实例

在用户分群中,若特征是消费频次与客单价,K-Means 往往会自动形成“高频低客单”“低频高客单”“中频中客单”等若干均值中心明确的群体。

优缺点与适用场景
  • 优点:实现简单、可扩展、训练速度快。
  • 局限:需要预先指定 \(K\);对初始化与离群点敏感;不适合非凸簇。
  • 适用场景:簇近似球形、需要快速聚类或作为预处理的任务。
层次聚类
背景和问题定义

层次聚类(Hierarchical Clustering)输出的是一个由粗到细的聚类层次结构,因此簇数可以在观察树状图后再决定。它适合需要观察“簇是如何逐步合并或拆分”的任务。

核心思想

凝聚式层次聚类(Agglomerative Clustering)从每个样本单独成簇开始,每一步合并当前最相近的两个簇;分裂式层次聚类则从一个大簇开始不断拆分。实践中更常见的是凝聚式版本。

h-clustering

算法公式和详细解释

关键在于定义簇间距离。常见联接准则(Linkage Criteria)包括:

\[d_{\text{single}}(A,B)=\min_{\boldsymbol{x}\in A,\boldsymbol{y}\in B} d(\boldsymbol{x},\boldsymbol{y})\]

单链距离只看两簇之间最近的那一对点,因此它很容易把“靠得最近的局部桥梁”连起来,适合发现链式结构,但也更容易被噪声点串联。

\[d_{\text{complete}}(A,B)=\max_{\boldsymbol{x}\in A,\boldsymbol{y}\in B} d(\boldsymbol{x},\boldsymbol{y})\]

完全链距离只看两簇之间最远的那一对点,因此它会避免把跨度过大的簇合并到一起,更偏好紧凑、直径较小的簇。

\[d_{\text{average}}(A,B)=\frac{1}{|A||B|}\sum_{\boldsymbol{x}\in A,\boldsymbol{y}\in B} d(\boldsymbol{x},\boldsymbol{y})\]

平均链则对两簇之间所有点对的距离取平均。这里 \(|A||B|\) 是点对总数,因此它不只看最近点或最远点,而是综合考虑两簇整体的平均接近程度。

不同联接方式对应不同簇形偏好:单链更容易形成链式簇,完全链更偏向紧凑簇,平均链则居中。

训练或推断流程
  1. 初始化每个样本为单独一个簇。
  2. 计算簇间距离矩阵。
  3. 反复合并距离最近的两个簇,并更新距离矩阵。
  4. 得到树状图(Dendrogram)后,在某个高度切开即可获得聚类结果。
应用实例

在文档聚类中,层次聚类不仅能区分“体育”“财经”“科技”等大类,还能进一步展示每一大类内部的细粒度层级关系。

优缺点与适用场景
  • 优点:无需预先指定簇数;可以输出多层次聚类结构。
  • 局限:计算与存储成本较高;早期合并错误通常无法回退。
  • 适用场景:中小规模数据、需要树状关系解释的聚类分析。
DBSCAN
背景和问题定义

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)用于识别任意形状的高密度簇,并显式发现噪声点。它尤其适合处理非球形簇与含离群点数据。

核心思想

DBSCAN 通过局部密度定义簇。若一个点周围半径 \(\epsilon\) 内有足够多的邻居,则它是核心点(Core Point);核心点可以把周围密度可达(Density-Reachable)的样本不断扩展成一个簇。既不够密、又不属于任何核心点邻域的样本被视为噪声。

dbscan

 

算法公式和详细解释

记 \(N_{\epsilon}(\boldsymbol{x})\) 为点 \(\boldsymbol{x}\) 的 \(\epsilon\) 邻域。若:

\[|N_{\epsilon}(\boldsymbol{x})|\ge \text{minPts}\]

判断核心点只需看两件事: \(N_{\epsilon}(\boldsymbol{x})\) 是点 \(\boldsymbol{x}\) 在半径 \(\epsilon\) 内的邻域集合, \(|N_{\epsilon}(\boldsymbol{x})|\) 是邻域里有多少点。只要这个数量不小于 \(\text{minPts}\),就说明该点周围密度足够高,可以作为簇扩张的核心。

则 \(\boldsymbol{x}\) 是核心点。若某点落在某个核心点邻域中但自身并非核心点,则为边界点(Border Point);不属于任何簇的点为噪声(Noise)。

训练或推断流程
  1. 遍历未访问样本,计算其 \(\epsilon\) 邻域。
  2. 若邻居数少于 \(\text{minPts}\),则暂记为噪声或边界候选。
  3. 若为核心点,则以它为起点递归扩展所有密度可达的点。
  4. 重复直到所有样本都被标记。
应用实例

在地理位置聚类中,餐馆、商圈、交通枢纽附近的点位通常形成形状复杂的密集区域。DBSCAN 可以识别这些非凸热点,同时把零散孤立点保留为噪声。

优缺点与适用场景
  • 优点:无需预设簇数;可识别任意形状簇;对离群点鲁棒。
  • 局限:对 \(\epsilon\) 和 \(\text{minPts}\) 敏感;难以同时适配不同密度簇。
  • 适用场景:空间聚类、热点区域发现、非凸簇与带噪声数据。
HDBSCAN
背景和问题定义

HDBSCAN(Hierarchical DBSCAN)用于缓解 DBSCAN 的单一密度阈值问题。它面对的核心困难是:真实数据中的簇密度常常并不一致,用一组固定的 \(\epsilon\) 和 \(\text{minPts}\) 很难同时兼顾所有簇。

核心思想

HDBSCAN 会在多个密度尺度上构建层次结构,再从中选出稳定簇(Stable Clusters)作为结果。这让它比 DBSCAN 更适合处理密度差异显著的数据。

hdbscan-intuition

算法公式和详细解释

给定参数 \(k\),先定义核心距离(Core Distance)为点到其第 \(k\) 近邻的距离,再定义互可达距离(Mutual Reachability Distance):

\[d_{\text{mreach},k}(\boldsymbol{x},\boldsymbol{y})=\max\big(\text{core}_k(\boldsymbol{x}),\text{core}_k(\boldsymbol{y}),d(\boldsymbol{x},\boldsymbol{y})\big)\]

互可达距离把三个量取最大值:点 \(\boldsymbol{x}\) 的核心距离、点 \(\boldsymbol{y}\) 的核心距离,以及它们之间的原始距离。这样做的效果是:低密度区域的点会被“拉远”,从而更清楚地暴露不同密度簇之间的结构边界。

随后算法在互可达图上构建最小生成树(Minimum Spanning Tree),再转成聚类层次,并依据簇稳定性选择最终输出。

训练或推断流程
  1. 计算所有点的核心距离。
  2. 基于互可达距离构造图并求最小生成树。
  3. 从图中得到随密度变化的层次聚类结构。
  4. 在压缩树(Condensed Tree)上选择稳定簇作为结果。
应用实例

在用户行为嵌入空间中,有些兴趣群体很紧密,有些较松散。HDBSCAN 可以同时保留这两类簇,而不需要强行用同一个密度阈值描述它们。

优缺点与适用场景
  • 优点:对多密度簇更稳健,仍保留噪声识别能力。
  • 局限:实现更复杂,计算与内存开销通常高于 DBSCAN。
  • 适用场景:嵌入聚类、用户分群、不同密度簇共存的数据。
升维

升维(Feature Expansion / Lifting)处理的问题,与降维正好互补。降维试图把高维表示压缩到更低维空间,以减少冗余、噪声与计算量;升维则试图把原始特征映射到一个更高维的表示空间,使原本难以表达、难以分离或难以拟合的结构,在新空间里变得更容易处理。它的目标不是“把维度变大本身”,而是通过增加表示自由度,把非线性关系改写为更容易由简单模型处理的形式。

背景和问题定义

许多经典机器学习模型本体是线性的,例如线性回归、逻辑回归、线性支持向量机(Support Vector Machine, SVM)。它们直接在原始输入空间中学习一个线性决策函数或线性预测函数。若数据关系本身高度非线性,那么模型能力可能不足。升维的思路因此是:先把输入映射为一个更高维的新表示,再在新表示上使用线性模型。模型形式仍然简单,但由于工作空间改变了,整体表达能力会显著提升。

更一般地,若原始输入为 \(\boldsymbol{x}\in \mathbb{R}^d\),则升维映射可写成:

\[\tilde{\boldsymbol{x}}=\phi(\boldsymbol{x}),\qquad \phi: \mathbb{R}^d\to \mathbb{R}^D,\qquad D>d\]

这里 \(\boldsymbol{x}\) 是原始输入; \(\tilde{\boldsymbol{x}}\) 是升维后的新特征; \(\phi(\boldsymbol{x})\) 是特征映射; \(D>d\) 表示新的表示空间维度高于原空间维度。若后续模型写成 \(f(\boldsymbol{x})=\boldsymbol{w}^\top \tilde{\boldsymbol{x}}+b\),那么它虽然在新空间中仍然是线性的,但在原始输入 \(\boldsymbol{x}\) 上通常已经对应一个非线性函数。

核心思想

升维的直观含义,是把原来“纠缠在一起”的关系展开。例如在二维平面里,某些数据可能无法被一条直线分开;但若把 \((x_1,x_2)\) 映射成 \((x_1,x_2,x_1^2,x_2^2,x_1x_2)\) 这样的更高维特征,原本的弯曲边界就可能对应高维空间中的一个超平面。于是复杂性并没有消失,而是被转移到了特征映射 \(\tilde{\boldsymbol{x}}=\phi(\boldsymbol{x})\) 上。

这也是经典机器学习里一个非常常见的套路:先做特征构造或特征展开,再用结构简单、优化稳定的线性模型。因此,升维常常并不以“升维”这个名字出现,而是以多项式特征、基函数展开、核方法、one-hot 编码、N-gram 稀疏特征、随机特征等形式出现。

公式和详细解释

升维后的线性模型通常写成:

\[f(\boldsymbol{x})=\boldsymbol{w}^\top \tilde{\boldsymbol{x}}+b\]

这里 \(\tilde{\boldsymbol{x}}\) 是由原始输入 \(\boldsymbol{x}\) 构造出来的高维特征向量; \(\boldsymbol{w}\in \mathbb{R}^D\) 是新空间中的参数; \(b\) 是偏置。关键点在于:模型在 \(\tilde{\boldsymbol{x}}\) 空间里仍然是线性的,但如果 \(\phi(\boldsymbol{x})\) 含有平方项、交叉项、基函数或核映射,那么 \(f(\boldsymbol{x})\) 相对于原始输入 \(\boldsymbol{x}\) 就会表现出非线性。

以二次多项式特征为例,若原始输入为 \(\boldsymbol{x}=(x_1,x_2)\),则可构造:

\[\tilde{\boldsymbol{x}}=(x_1,x_2,x_1^2,x_2^2,x_1x_2)\]

此时线性模型

\[f(\boldsymbol{x})=w_1x_1+w_2x_2+w_3x_1^2+w_4x_2^2+w_5x_1x_2+b\]

在参数上仍然是线性的,但在输入上已经能够表达二次曲面或二次决策边界。这正是升维最核心的数学作用:把原空间中的非线性关系,改写成高维空间中的线性关系。

常见升维方式
方式 升维形式 核心作用 典型场景
多项式特征 加入平方项、立方项、交叉项 把低阶线性模型扩展为可拟合非线性关系 线性回归、逻辑回归、线性分类器
基函数展开 高斯基、样条基、傅里叶基等 用一组预定义函数把局部或周期结构显式展开 回归、广义加性模型、核近似
核方法 通过核函数隐式映射到高维甚至无限维空间 在不显式展开特征的情况下提升可分性 SVM、核岭回归、核 PCA
One-hot 编码 把离散类别映射为高维稀疏向量 让类别变量进入线性模型并保持类别独立性 表格特征、推荐、广告、点击率预估
N-gram / 词袋 把文本映射为高维稀疏词项空间 显式展开局部共现与组合模式 传统文本分类、检索、朴素贝叶斯、线性 SVM
随机特征 用随机映射近似某些核空间 在显式高维表示与核方法之间做折中 Random Fourier Features、核近似

其中,核方法是经典机器学习里最有代表性的升维思想。以 SVM 为例,若定义特征映射 \(\tilde{\boldsymbol{x}}=\phi(\boldsymbol{x})\),则线性分类器可写成 \(f(\boldsymbol{x})=\boldsymbol{w}^\top \tilde{\boldsymbol{x}}+b\)。核技巧(Kernel Trick)并不显式构造 \(\tilde{\boldsymbol{x}}\),而是直接通过核函数

\[K(\boldsymbol{x},\boldsymbol{x}')=\phi(\boldsymbol{x})^\top \phi(\boldsymbol{x}')\]

计算升维后特征空间中的内积。这样既保留了高维映射的表达力,又避免了显式展开到巨大维度的代价。也正因为如此,SVM 是很多人最先感受到“升维威力”的经典模型。

应用实例

在圆形可分但线性不可分的数据中,原始二维平面上一条直线无法把内圈与外圈分开;但若加入半径相关的二次特征,例如 \(x_1^2+x_2^2\),则问题可以转写为更高维空间中的线性分离。文本任务里,N-gram 稀疏特征同样是一种典型升维:原始句子是离散序列,经过词袋或 N-gram 展开后,就变成了数万维甚至更高维的稀疏向量,随后再交给逻辑回归、朴素贝叶斯或线性 SVM 处理。

表格任务中的类别变量处理也体现了同样思想。一个城市字段看起来只是一个离散取值,但 one-hot 编码后,它会被展开成一个高维稀疏向量,使模型能够为每个类别学习独立参数。推荐系统、广告点击率预估、工业风控中的大规模离散特征,长期都高度依赖这种升维方式。

为什么经典机器学习更谨慎地升维

经典机器学习并不是很少使用升维,而是更谨慎。原因在于,维度一旦上去,过拟合风险、存储开销与计算开销都会迅速增加,这就是维度灾难(Curse of Dimensionality)的典型体现。于是经典方法常把“升维”与“控制复杂度”配套使用:一边通过特征展开提升表达能力,一边用正则化(Regularization)、特征选择(Feature Selection)或后续降维来抑制过拟合。

因此,在经典机器学习里,常见工作流并不是“只升维”或“只降维”,而是两者交替配合:先做有针对性的特征展开,让结构变得更容易表达;再通过正则化、筛选或压缩保留真正有效的部分。升维是在展开表达能力,降维是在压缩冗余信息,它们并不是对立操作,而是围绕表示空间做的两种互补控制。

维度灾难

维度灾难(Curse of Dimensionality)指的是:当特征维度不断升高时,许多在低维空间中直观、有效的统计与几何规律会迅速恶化,导致数据需求、计算成本与建模难度同时上升。它不是某一个单独问题,而是一组高维效应的统称,包括样本空间体积指数级膨胀、样本变得极其稀疏、局部邻域难以稳定估计、距离与密度统计的判别力下降,以及模型更容易用复杂边界去记忆训练集。

其中一个最重要的现象确实是:高维里距离往往会变得不再像低维那样有区分力。直观地说,当维度很多时,样本之间的最近距离和最远距离可能越来越接近,导致“谁是真正近邻”这件事变得没那么清晰。依赖距离或局部邻域的方法,例如 KNN、聚类、核密度估计、局部异常检测等,往往会因此退化。这也是为什么高维数据上,距离度量、标准化、特征筛选和嵌入学习会变得格外重要。

但“高维更容易过拟合”并不只因为距离失去意义。更根本的原因是:当维度升高后,表示空间的自由度与可容纳的划分方式急剧增加,而训练样本相对于整个空间显得越来越稀疏。模型于是更容易找到一些只对训练集成立、却不能推广到新样本的偶然边界或偶然相关性。换句话说,距离退化主要伤害的是邻域、相似度与密度估计;过拟合风险上升则更直接地来自空间稀疏化、参数自由度增加和有效样本覆盖不足。

这也是为什么经典机器学习在做升维时往往必须同步引入约束:一方面用特征展开提升表达能力,另一方面通过正则化(Regularization)、特征选择(Feature Selection)、降维(Dimensionality Reduction)或更强的数据先验,限制模型不要把高维空间当成“背题空间”。因此,维度灾难并不是在说“高维一定不好”,而是在提醒:维度每增加一层,模型就需要更多数据、更强归纳偏置和更谨慎的复杂度控制,才能让新增维度真正转化为有效表达能力。

和深度学习中的升维关系

深度学习中的很多操作,本质上也在做升维。Transformer 的前馈网络(Feed-Forward Network, FFN / MLP)常把 \(d_{\text{model}}\) 升到更大的 \(d_{\text{ff}}\),再降回原维度;这与经典机器学习里“先展开、再用简单变换处理”的思想是一脉相承的。差别在于,经典方法里的升维往往是人工设计或固定形式的,而深度学习中的升维通常是可学习的线性投影与非线性组合。

因此,若从表示学习角度看,升维在机器学习中并不罕见。SVM 的核空间、逻辑回归的多项式特征、文本的 N-gram 稀疏向量、推荐系统的 one-hot 离散展开,以及 Transformer MLP 中的中间维度扩张,本质上都属于同一条主线:把原本难以处理的关系,展开到一个更容易表达与分离的表示空间里。

降维

降维处理的核心问题是:高维数据往往包含冗余、相关性与噪声,既增加计算成本,也削弱可视化与建模稳定性。目标不是简单“删维度”,而是在压缩表示的同时尽量保留有用结构——这个“有用”可以是方差、类别可分性、局部邻域、全局流形,具体取决于所采用的方法。

主成分分析(PCA)
背景和问题定义

主成分分析(Principal Component Analysis, PCA)处理的是线性降维问题:在尽量保留数据主要变化信息的前提下,把高维样本映射到更低维空间。它常用于压缩维度、去相关、可视化与噪声抑制。

pca

核心思想

PCA 用方差(Variance)近似衡量信息量。若数据在某个方向上的投影变化很大,说明该方向承载了更多结构;于是 PCA 选择能最大化投影方差的一组正交方向作为新的表示基底。

算法公式和详细解释

给定中心化后的数据矩阵 \(\boldsymbol{X}_c\in\mathbb{R}^{N\times d}\),协方差矩阵为:

\[\boldsymbol{\Sigma}=\frac{1}{N}\boldsymbol{X}_c^\top \boldsymbol{X}_c\]

这里 \(\boldsymbol{X}_c\) 是已经减去均值后的数据矩阵, \(\boldsymbol{X}_c^\top \boldsymbol{X}_c\) 汇总了各个特征之间如何共同变化;再除以 \(N\),就得到平均意义下的协方差矩阵 \(\boldsymbol{\Sigma}\)。PCA 正是从这个矩阵里找“变化最大的方向”。

第一主成分对应的优化问题为:

\[\max_{\boldsymbol{u}} \quad \boldsymbol{u}^\top \boldsymbol{\Sigma}\boldsymbol{u} \quad \text{s.t.} \quad \|\boldsymbol{u}\|_2=1\]

\(\boldsymbol{u}\) 是候选投影方向, \(\boldsymbol{u}^\top \boldsymbol{\Sigma}\boldsymbol{u}\) 表示数据投影到该方向后的方差,约束 \(\|\boldsymbol{u}\|_2=1\) 则防止通过把向量无限放大来虚增方差。于是这个优化问题真正寻找的是“单位长度下最能保留变化信息的方向”。

其解是协方差矩阵最大特征值对应的特征向量。取前 \(k\) 个主成分组成矩阵 \(\boldsymbol{U}_k\) 后,样本 \(\boldsymbol{x}\) 的低维表示为:

\[\boldsymbol{z}=\boldsymbol{U}_k^\top(\boldsymbol{x}-\boldsymbol{\mu})\]

这里 \(\boldsymbol{\mu}\) 是原始数据均值, \(\boldsymbol{x}-\boldsymbol{\mu}\) 先把样本中心化, \(\boldsymbol{U}_k\) 由前 \(k\) 个主成分方向组成,最终 \(\boldsymbol{z}\) 就是样本在这组主方向上的低维坐标。

训练或推断流程
  1. 对数据做中心化,必要时再做标准化。
  2. 计算协方差矩阵或直接对数据矩阵做奇异值分解(SVD)。
  3. 取前 \(k\) 个主成分方向。
  4. 把数据投影到这些方向上得到低维表示。
应用实例

在人脸图像压缩中,大量像素变化往往由少数全局因素驱动。PCA 可以用少量主成分保留大部分有效变化,从而显著降低特征维度。

优缺点与适用场景
  • 优点:线性、稳定、可解释,常用作预处理和可视化。
  • 局限:只能捕捉线性结构;对异常值敏感。
  • 适用场景:线性降维、特征压缩、去相关与噪声过滤。
线性判别分析(LDA)
背景和问题定义

线性判别分析(Linear Discriminant Analysis, LDA)用于监督降维与分类。与 PCA 只看输入分布不同,LDA 利用类别标签寻找一个投影空间,使同类样本尽量聚集、异类样本尽量分开。

lda

核心思想

LDA 同时考虑类内散度(Within-class Scatter)和类间散度(Between-class Scatter)。好的投影方向应当让类间距离大、类内波动小,因此它优化的核心是判别性。

算法公式和详细解释

定义类内散度矩阵:

\[\boldsymbol{S}_W=\sum_{k=1}^{C}\sum_{\boldsymbol{x}_i\in \mathcal{C}_k}(\boldsymbol{x}_i-\boldsymbol{\mu}_k)(\boldsymbol{x}_i-\boldsymbol{\mu}_k)^\top\]

类内散度矩阵 \(\boldsymbol{S}_W\) 统计的是“同一类内部有多分散”。 \(\mathcal{C}_k\) 是第 \(k\) 类的样本集合, \(\boldsymbol{\mu}_k\) 是该类均值。若类内样本围绕各自均值分布得很紧, \(\boldsymbol{S}_W\) 就会较小。

类间散度矩阵:

\[\boldsymbol{S}_B=\sum_{k=1}^{C}N_k(\boldsymbol{\mu}_k-\boldsymbol{\mu})(\boldsymbol{\mu}_k-\boldsymbol{\mu})^\top\]

类间散度矩阵 \(\boldsymbol{S}_B\) 统计的是“各类中心彼此有多分开”。其中 \(\boldsymbol{\mu}\) 是全局均值, \(N_k\) 是第 \(k\) 类样本数,因此样本多的大类会对类间结构贡献更大权重。

LDA 寻找投影向量 \(\boldsymbol{w}\) 使 Fisher 判别准则最大:

\[J(\boldsymbol{w})=\frac{\boldsymbol{w}^\top \boldsymbol{S}_B \boldsymbol{w}}{\boldsymbol{w}^\top \boldsymbol{S}_W \boldsymbol{w}}\]

Fisher 准则的分子衡量“投影后类间有多分开”,分母衡量“投影后类内有多混在一起”。因此 \(J(\boldsymbol{w})\) 越大,说明方向 \(\boldsymbol{w}\) 越有助于把不同类别拉开、同时保持同类紧凑。

该问题可转化为广义特征值问题 \(\boldsymbol{S}_B\boldsymbol{w}=\lambda \boldsymbol{S}_W\boldsymbol{w}\)。对 \(C\) 类问题,最多能得到 \(C-1\) 个有效判别方向。

训练或推断流程
  1. 根据标签统计每一类的均值与全局均值。
  2. 构造类内散度矩阵和类间散度矩阵。
  3. 求解广义特征值问题,选择主要判别方向。
  4. 将样本投影到低维判别子空间中做分类或可视化。
应用实例

在手写数字分类中,LDA 关注的是“哪些方向最有助于把不同数字分开”,因此在有标签监督时,它往往比只最大化总体方差的 PCA 更适合分类前降维。

优缺点与适用场景
  • 优点:利用标签信息,投影方向更有判别性。
  • 局限:线性假设较强;类内散度矩阵可能奇异。
  • 适用场景:有标签监督的降维、分类前特征压缩、判别性可视化。
t-SNE
背景和问题定义

t-SNE(t-distributed Stochastic Neighbor Embedding)主要用于二维或三维可视化。它主要关注如何在低维图上尽量保留高维空间中的局部邻域关系。

核心思想

t-SNE 把“样本彼此接近”转写为概率相似度:在高维空间中,接近的样本应当有较大概率互为邻居;在低维嵌入中,也希望这种邻近关系继续成立。优化的目标是让两种邻域概率分布尽可能接近。

算法公式和详细解释

在高维空间中,先定义邻域概率 \(p_{ij}\);在低维空间中,对嵌入点 \(\boldsymbol{y}_i\) 定义:

\[q_{ij}=\frac{(1+\|\boldsymbol{y}_i-\boldsymbol{y}_j\|_2^2)^{-1}}{\sum_{a\ne b}(1+\|\boldsymbol{y}_a-\boldsymbol{y}_b\|_2^2)^{-1}}\]

这里 \(\boldsymbol{y}_i\) 和 \(\boldsymbol{y}_j\) 是低维嵌入坐标,分子把距离越近的点赋予越大的相似度,分母则把所有点对的相似度加总起来做归一化,因此 \(q_{ij}\) 可以被解释成低维空间里的邻域概率。

t-SNE 最小化高维邻域分布与低维邻域分布之间的 KL 散度:

\[\text{KL}(P\|Q)=\sum_{i\ne j} p_{ij} \log \frac{p_{ij}}{q_{ij}}\]

KL 散度衡量的是“低维邻域分布 \(Q\) 与高维邻域分布 \(P\) 相差多少”。若某对样本在高维里很近,即 \(p_{ij}\) 很大,但在低维里被拉得太开, \(q_{ij}\) 就会过小,从而产生较大惩罚。

低维中采用重尾 Student-t 分布,主要是为了缓解拥挤问题(Crowding Problem),使远处点更容易被拉开。

训练或推断流程
  1. 根据高维距离计算样本间的邻域概率。
  2. 随机初始化低维坐标。
  3. 计算低维相似度 \(q_{ij}\)。
  4. 通过梯度下降最小化 KL 散度并更新低维坐标。
应用实例

在词向量或图像嵌入可视化中,t-SNE 常把语义相近的样本压到局部团簇中,从而帮助研究者直观看到表示空间里是否出现了合理分群。

优缺点与适用场景
  • 优点:二维可视化效果强,局部邻域保持能力好。
  • 局限:全局距离与簇间相对位置不稳定;对超参数和随机初始化敏感。
  • 适用场景:嵌入可视化、表示质量诊断、探索性数据分析。
UMAP
背景和问题定义

UMAP(Uniform Manifold Approximation and Projection)同样用于低维可视化与非线性降维。它面对的任务与 t-SNE 类似,但更强调在保留局部结构的同时,尽量维持一定的全局几何关系,并提升速度与可扩展性。

umap

核心思想

UMAP 先在高维空间构建一个加权近邻图,把数据视为流形(Manifold)上的离散采样;随后在低维空间中寻找一张新图,使低维图与高维图的模糊连通结构尽量一致。它本质上是在匹配两张图的连通结构,而不只是在匹配两组欧氏距离。

这里的流形可以先从一个标准定义理解:设样本位于高维空间 \(\mathbb{R}^D\) 中,若它们实际上集中在某个低维集合 \(\mathcal{M}\subseteq\mathbb{R}^D\) 附近,并且对 \(\mathcal{M}\) 上任一点,都能在一个足够小的邻域内用 \(d\) 维坐标平滑描述,其中 \(d\ll D\),那么这个集合就可以看作一个 \(d\) 维流形。流形的关键性质不是“它弯不弯”,而是它在局部看起来像低维欧氏空间,在全局上则可以嵌入到更高维空间并发生弯曲、卷曲或拉伸。

在数据分析里,这个概念表示:虽然原始特征有很多维,但样本并没有真正填满整个高维空间,而是分布在某种低维结构附近。例如一组人脸图像在像素空间里维度极高,但由姿态、光照、表情等少数潜在因素变化时,样本往往只覆盖其中一个低维子区域。UMAP 的出发点正是:若数据主要几何结构由这个低维流形决定,那么局部近邻关系比“全局欧氏直线距离”更能反映真实结构。

“离散采样”则表示:真实流形 \(\mathcal{M}\) 本身是连续对象,但我们手里只有有限个样本点 \(\{x_i\}_{i=1}^N\)。UMAP 通过近邻图近似这些点在流形上的局部连通关系,再在低维空间中寻找一组坐标 \(\{y_i\}_{i=1}^N\),使这种局部连通关系尽量被保留下来。因此它不是直接恢复整张流形,而是在有限样本层面恢复流形的邻域结构。

与 t-SNE 相比,UMAP 更强调“样本来自某个低维流形,并且近邻图是在近似这个流形的局部连通结构”;t-SNE 的核心对象则更偏向“高维邻域概率分布与低维邻域概率分布的匹配”。两者都重视局部关系,但 UMAP 的表述更几何化,t-SNE 的表述更概率化。

算法公式和详细解释

若高维图边权为 \(p_{ij}\),低维图边权常写为:

\[q_{ij}=\frac{1}{1+a\|\boldsymbol{y}_i-\boldsymbol{y}_j\|_2^{2b}}\]

UMAP 用这个函数把低维距离转换成连通强度。 \(a\) 和 \(b\) 控制曲线形状:距离很近时 \(q_{ij}\) 接近 1,距离变远时迅速衰减到接近 0,因此它可以把“近邻关系”转写成平滑的图边权。

其中 \(a,b\) 决定低维距离与连接强度的映射形状。UMAP 的优化目标通常是高维图与低维图之间的交叉熵(Cross-Entropy):既鼓励高维中相连的点在低维中也靠近,也鼓励高维中不相连的点在低维中适当分开。

训练或推断流程
  1. 计算近邻图,并为边赋予模糊连通权重。
  2. 初始化低维坐标。
  3. 通过随机优化最小化高维图与低维图之间的交叉熵。
  4. 得到二维或三维嵌入用于可视化或下游分析。
应用实例

在单细胞测序、文本嵌入或推荐向量分析中,UMAP 常被用来把高维表示映射到二维平面,从而观察群体结构、类别分布与异常点。

优缺点与适用场景
  • 优点:通常比 t-SNE 更快,较好兼顾局部与部分全局结构。
  • 局限:嵌入结果仍依赖超参数与随机种子;二维距离不能机械等同于原空间距离。
  • 适用场景:大规模嵌入可视化、非线性降维、聚类前的低维表示。
异常检测

异常检测处理的核心问题是:正常样本通常大量存在,而异常样本稀少、形态多变、甚至在训练阶段根本拿不到完整标签。模型因此不再主要学习“类别之间如何区分”,而是学习“什么算正常”以及“偏离正常结构有多严重”。不同方法对“异常”的定义并不相同:有的依赖隔离难易度,有的依赖局部密度,有的学习正常区域边界。

什么叫异常

在业务语境里,“异常”并不等于“数值特别大”或“离均值很远”。更准确地说,异常是相对于当前业务规则、历史模式或同类群体而言,不应当出现、很少出现、或者一旦出现就值得额外关注的样本。因此异常是一个“相对概念”,必须依赖参照系:相对于谁、在哪个时间段、在什么上下文里、以什么代价衡量。

例如,单笔消费 5000 元在全国范围内不一定异常,但若这位用户平时只在本地便利店做几十元交易,而这次交易突然发生在异地、高风险设备、深夜时段,并伴随支付习惯突变,那么它在风控上就可能是异常。类似地,服务器 CPU 使用率 85% 在大促期间可能是正常负载,在凌晨低峰却可能意味着任务堆积;工厂传感器温度轻微升高若同时伴随振动模式变化,也可能预示故障正在形成。

这说明业务上的异常通常至少包含三类含义。第一类是统计稀有:样本落在低概率区域。第二类是行为失配:它与该对象自己的历史模式不一致。第三类是群体失配:它在全局上不一定极端,但相对于同类群体显著不同。异常检测算法的差异,本质上就在于它们分别更擅长刻画哪一种“失配”。

因此,做异常检测时首先要回答的不是“用哪种模型”,而是“业务到底把什么视为异常”。若异常意味着“明显稀少且容易与大部队分开”,隔离式方法更合适;若异常意味着“在本地邻域里显得稀疏”,应优先考虑密度比较;若正常样本边界清楚、异常样本类型杂乱,则更适合只学习正常区域。算法不是在定义业务,而是在实现业务已经确定的异常标准。

孤立森林(Isolation Forest)
背景和问题定义

孤立森林(Isolation Forest)用于无监督异常检测:在没有可靠异常标签时,仅根据数据分布本身识别“容易被孤立”的异常样本。它尤其适合高维表格数据与大规模检测场景。

核心思想

孤立森林利用一个非常直接的直觉:异常点通常更稀少、更孤立,因此在随机切分下更容易被提早隔离。路径越短,越可能是异常;路径越长,越像处于正常群体内部。若把正常样本理解为“扎堆生活在高密度区域里的大群体”,那么它们往往需要经过很多次随机切割才会被单独分离出来;而那些落在边缘、稀疏区域、或与主体分布明显脱节的样本,只需少量切分就会被单独留在某个叶节点里。

这种思路和距离或密度方法非常不同。K 近邻(K-Nearest Neighbors, KNN)或局部异常因子(Local Outlier Factor, LOF)会显式比较“离别人有多远”或“局部密度有多低”;孤立森林则直接把异常检测改写成一个更具操作性的判据:一个样本在随机树里平均多快会被单独隔开。因此它并不先估计复杂的概率分布,也不依赖全局距离结构,而是用“隔离难易度”来近似刻画异常性。

random-forest

图示解读

图中的示意数据由两个主要正常簇和若干离散分布的异常点构成。背景等高线展示的是孤立森林学到的“异常分数地形”:颜色越深,表示该区域样本平均路径长度越长,更接近模型眼中的正常高密度区域;颜色越浅,表示样本更容易在随机切分中被提早隔离,因此更接近潜在异常区域。

图中圆形点对应被模型判为正常的样本,它们主要聚集在两个深色中心附近;叉号对应被模型判为异常的样本,它们更多分布在边缘、簇间空白带或浅色区域。这种可视化非常适合帮助理解孤立森林的工作方式:它并不是在画一条严格的几何边界,而是在表达“哪里更容易被随机树迅速切出来”。因此,等高线的深浅更接近一种“隔离难度地图”,而不是传统分类器意义上的硬分类边界。

隔离树是什么

隔离树(Isolation Tree, iTree)可以理解成一棵专门为了“把样本逐步切开”而构造的随机二叉树。它与决策树(Decision Tree)在外形上相似,但目标完全不同:决策树是在找最有区分力的切分规则,隔离树则故意随机选择一个特征,再在该特征当前取值范围内随机选择一个切分点,把样本递归分到左右子节点。

设当前节点包含样本集合 \(S\),随机选到的特征为第 \(j\) 维,其切分阈值为 \(\tau\),则一次切分可写成

\[S_{\mathrm{left}}=\{\boldsymbol{x}\in S\mid x_j<\tau\},\qquad S_{\mathrm{right}}=\{\boldsymbol{x}\in S\mid x_j\ge \tau\}\]

递归继续进行,直到某个节点只剩下 1 个样本,或所有样本在当前节点上已经无法再被有效区分。对一个本来就远离主体、所在区域又很稀疏的样本而言,随机切分往往只需要很少几步就能把它单独留在某个叶节点中;而对处在高密度正常群体内部的样本,通常要经过更多次切分才能被单独隔离。隔离树因此并不显式估计概率密度,而是把“异常”转写为“被随机切分提早单独分离”的难易度。

算法公式和详细解释

对样本 \(\boldsymbol{x}\),记它在一棵隔离树中的路径长度为 \(h(\boldsymbol{x})\)。在多棵树上取平均路径长度 \(\mathbb{E}[h(\boldsymbol{x})]\) 后,异常分数定义为:

\[s(\boldsymbol{x},n)=2^{-\mathbb{E}[h(\boldsymbol{x})]/c(n)}\]

这里 \(h(\boldsymbol{x})\) 是样本在一棵树里被隔离所需的路径长度, \(\mathbb{E}[h(\boldsymbol{x})]\) 是在整片森林中的平均值, \(c(n)\) 是针对样本规模 \(n\) 的归一化常数。路径越短,指数里的值越小,异常分数 \(s(\boldsymbol{x},n)\) 就越接近 1。

其中 \(c(n)\) 是平均路径长度的归一化常数,用来把不同样本规模下的路径长度放到可比较的尺度上。它常写为 \(c(n)=2H_{n-1}-2(n-1)/n\),其中 \(H_{n-1}\) 是第 \(n-1\) 个调和数(Harmonic Number)。若某点明显比普通样本更早被切分隔离,则其平均路径长度更小,异常分数更接近 1。

训练或推断流程
  1. 从训练集中随机抽取多个子样本。
  2. 为每个子样本构建随机隔离树。
  3. 对待测点计算其在所有树中的平均路径长度。
  4. 将平均路径长度映射为异常分数。
应用实例

在交易风控中,若某条交易在金额、时间、地点、设备等多个维度上都明显偏离正常模式,它往往能在随机切分下被较早隔离出来,因此会获得更高异常分数。

优缺点与适用场景
  • 优点:无需显式估计密度,也不依赖两两距离矩阵;因此在大规模数据上通常比基于邻域或密度的方法更高效。
  • 优点:对高维表格数据较友好,对随机噪声通常也有较强鲁棒性,因为最终判断来自多棵随机树上的平均隔离行为,而不是某一次局部切分。
  • 局限:对特征编码和特征尺度的业务含义仍然敏感;若异常与正常高度混叠、或者异常本身并不更容易被切开,隔离优势会下降。
  • 适用场景:风控、日志异常、设备故障、指标监控等无监督异常检测,尤其适合作为高维表格场景中的强基线。
局部异常因子(LOF)
背景和问题定义

局部异常因子(Local Outlier Factor, LOF)主要解决“全局上不远,但在局部邻域中显著稀疏”的异常检测问题。当数据不同区域密度差异很大时,只看全局距离通常不够稳定。

核心思想

LOF 比较的是“这个点相对于其邻居是否更稀疏”。若一个点周围的局部密度显著低于邻居自己的局部密度,则它更像局部异常。它识别的不是“全局上最远的点”,而是相对于自己所在局部环境显得不协调的点。因此,当不同区域本来就有不同密度时,LOF 往往比只看全局距离的方法更稳。

lof

图示解读

图中的实心圆点表示样本点,围绕样本点的空心圆圈大小表示该点的 LOF 分数大小。圆圈越小,说明该点的局部密度与其邻居相近,更像正常簇中的内部样本;圆圈越大,说明该点所在位置相对于邻居显得更稀疏,因此更可能是局部异常点。

这张图直观展示了 LOF 的核心判断方式:它并不先问“这个点离全局中心有多远”,而是先问“这个点和自己周围那一圈邻居相比,是不是显得过于稀疏”。因此,大圆圈对应的未必是全局最远的点,而更可能是那些周围邻居仍然较密、但它自己明显脱离了局部密度水平的点。

若把这张示意图看作两个高密度簇与少量随机噪声点的组合,则邻居数 \(k\) 决定了算法观察“局部环境”的尺度。 \(k\) 较小时,模型更敏感于非常局部的扰动; \(k\) 较大时,密度比较更平滑,但也可能削弱对细粒度异常的敏感性。

算法公式和详细解释

给定邻居数 \(k\),设 \(N_k(\boldsymbol{p})\) 表示点 \(\boldsymbol{p}\) 的 \(k\) 个最近邻集合。LOF 的计算可以拆成三层:先算可达距离(Reachability Distance),再算局部可达密度(Local Reachability Density, LRD),最后比较邻居密度与自身密度,得到局部异常因子(Local Outlier Factor, LOF)。

先定义可达距离(Reachability Distance):

\[\mathrm{rd}_k(\boldsymbol{p},\boldsymbol{o})=\max\big(\text{k-distance}(\boldsymbol{o}),d(\boldsymbol{p},\boldsymbol{o})\big)\]

可达距离会把两个量取最大值:邻居点 \(\boldsymbol{o}\) 自己的第 \(k\) 邻距离,以及点对之间的真实距离。这样做可以防止极近的点对把局部密度估得过于夸张,使密度估计更稳。

再定义局部可达密度(Local Reachability Density, LRD):

\[\mathrm{lrd}_k(\boldsymbol{p})=\left(\frac{1}{|N_k(\boldsymbol{p})|}\sum_{\boldsymbol{o}\in N_k(\boldsymbol{p})} \mathrm{rd}_k(\boldsymbol{p},\boldsymbol{o})\right)^{-1}\]

局部可达密度 \(\mathrm{lrd}_k(\boldsymbol{p})\) 本质上是“平均可达距离”的倒数:平均距离越小,周围越拥挤,密度越大;平均距离越大,周围越稀疏,密度越小。

最终的 LOF 分数为:

\[\mathrm{LOF}_k(\boldsymbol{p})=\frac{1}{|N_k(\boldsymbol{p})|}\sum_{\boldsymbol{o}\in N_k(\boldsymbol{p})} \frac{\mathrm{lrd}_k(\boldsymbol{o})}{\mathrm{lrd}_k(\boldsymbol{p})}\]

LOF 分数比较的是“邻居的局部密度”和“自己本身的局部密度”。若 \(\mathrm{lrd}_k(\boldsymbol{p})\) 明显小于邻居的密度,分数就会大于 1,说明该点相对周围环境显得更孤立。更具体地说,分子是邻居局部密度的平均水平,分母是点 \(\boldsymbol{p}\) 自己的局部密度,因此这个比值本质上是在问:你周围的人都很挤,而你自己是不是站得太空。

结果通常可以这样解读:

  • \(\mathrm{LOF}_k(\boldsymbol{p})\approx 1\):该点的局部密度与邻居相近,通常属于正常样本。
  • \(\mathrm{LOF}_k(\boldsymbol{p})<1\):该点甚至比邻居更密集,往往处于簇的核心区域。
  • \(\mathrm{LOF}_k(\boldsymbol{p})>1\):该点局部密度低于邻居,越大越像异常点。

因此,LOF 不是在回答“这个点离全局中心远不远”,而是在回答“这个点在自己的局部邻域里是不是显得过于稀疏”。这也是它能识别局部异常、却对距离度量与邻居数 \(k\) 较敏感的根本原因。

训练或推断流程
  1. 为每个样本找到 \(k\) 个近邻。
  2. 计算可达距离与局部可达密度。
  3. 比较样本与邻居的局部密度,得到 LOF 分数。
  4. 按分数排序或设置阈值输出异常点。
应用实例

在消费行为数据中,某一线城市用户的高消费在全国范围内未必异常,但在“同年龄、同区域、同收入”的邻域里可能明显偏离。LOF 正是通过这种局部密度比较识别这类异常。

优缺点与适用场景
  • 优点:适合不同密度区域共存的数据,能识别“全局上不极端、但局部上明显失配”的异常。
  • 优点:解释性较强,因为 LOF 分数直接来自“邻居密度 / 自身密度”的局部比较,便于回答异常是相对于谁显得异常。
  • 局限:对距离度量、标准化和邻居数 \(k\) 很敏感; \(k\) 太小会放大噪声,太大又可能抹平真正的局部异常。
  • 局限:大规模近邻搜索成本较高,因此在超大数据上常需要索引加速或近似近邻方法配合。
  • 适用场景:局部离群检测、消费异常、群体内部行为异常、同类用户或设备群体中的行为失配识别。
单类支持向量机(One-Class SVM)
背景和问题定义

单类支持向量机(One-Class Support Vector Machine, One-Class SVM)用于“只有正常样本、缺少可靠异常样本”的异常检测任务。它的目标是学习一个描述正常样本区域的边界。

核心思想

One-Class SVM 通过核映射把样本送到高维特征空间,再寻找一个把大多数正常样本与原点分开的超平面。等价地看,它学习的是一个“包住正常样本”的高维边界,边界外的点更可能是异常。

算法公式和详细解释

一种标准形式为:

\[\min_{\boldsymbol{w},\rho,\boldsymbol{\xi}} \frac{1}{2}\|\boldsymbol{w}\|_2^2+\frac{1}{\nu N}\sum_{i=1}^{N} \xi_i-\rho\]

One-Class SVM 的目标由三部分组成: \(\frac{1}{2}\|\boldsymbol{w}\|_2^2\) 控制边界不要太复杂, \(\frac{1}{\nu N}\sum_i \xi_i\) 惩罚落在边界外或靠得太近的样本, \(-\rho\) 则鼓励把正常区域尽量向外推开。 \(\nu\) 越大,对违约样本的容忍度越高。

\[\text{s.t.} \quad \boldsymbol{w}^\top \phi(\boldsymbol{x}_i) \ge \rho-\xi_i,\qquad \xi_i \ge 0\]

这些约束表示:样本映射到特征空间后,其投影值至少要达到阈值 \(\rho\);若做不到,就用非负松弛变量 \(\xi_i\) 记录违约程度。于是模型允许少量样本越界,但必须为此付出代价。

其中 \(\boldsymbol{w}\) 是超平面法向量, \(\rho\) 是阈值, \(\xi_i\) 是松弛变量, \(\nu\in(0,1]\) 控制允许落在边界外的比例与支持向量比例。判别函数为:

\[f(\boldsymbol{x})=\text{sign}\left(\boldsymbol{w}^\top \phi(\boldsymbol{x})-\rho\right)\]

判别函数先计算样本在特征空间里相对边界的位置:若 \(\boldsymbol{w}^\top \phi(\boldsymbol{x})-\rho\) 为正,说明样本位于学习到的正常区域一侧;若为负,则更可能落在边界之外,被视为异常。

若使用核函数 \(K(\boldsymbol{x},\boldsymbol{x}')\),则该边界可以是非线性的,因此能表达复杂的正常区域。

训练或推断流程
  1. 只用正常样本训练模型,选择核函数与超参数 \(\nu\)。
  2. 在特征空间中学习分离超平面。
  3. 对新样本计算判别函数值。
  4. 若分数低于边界阈值,则判为异常。
应用实例

在设备健康监控中,异常故障类型往往变化很大,难以完整收集,但正常运行数据很多。One-Class SVM 可以只基于正常样本学习边界,一旦新样本落出该区域,就触发异常告警。

优缺点与适用场景
  • 优点:只依赖正常样本;核方法可表达复杂边界。
  • 局限:对特征缩放和核参数敏感;大规模训练较重。
  • 适用场景:设备监控、入侵检测、质量控制等“正常样本丰富、异常样本稀缺”的任务。
神经网络
前馈神经网络
感知机

感知机(Perceptron)是最早的神经元模型之一,也是现代神经网络最基本的计算原型。无论是 MLP、CNN、RNN,还是 Transformer,本质上都由大量“线性变换 + 非线性变换”的单元堆叠而成;从这个意义上说,理解感知机,就是理解大型模型最小的功能部件。

最原始的感知机先做线性组合,再经过一个阈值函数给出二分类输出:

\[\hat y=\mathrm{sign}(\mathbf{w}^\top \mathbf{x}+b)\]

这里 \(\mathbf{x}\) 是输入特征, \(\mathbf{w}\) 是权重, \(b\) 是偏置。 \(\mathbf{w}^\top \mathbf{x}+b\) 的含义是“沿着权重指定的方向对输入做加权打分”,而 \(\mathrm{sign}(\cdot)\) 则把连续分数变成离散决策:高于阈值判为正类,低于阈值判为负类。

需要特别区分的是:最早的感知机确实直接做分类,但现代神经网络里的大多数“感知机式单元”并不直接输出最终类别。隐藏层单元更常见的形式是 \(h=\phi(\mathbf{w}^\top \mathbf{x}+b)\),它们输出的是中间表示(Intermediate Representation),职责是检测局部模式、重组特征并为后续层提供更有用的表示;只有最后的任务头(Task Head)才把这些中间表示转成分类、回归或生成输出。

这里的中间表示(Intermediate Representation)本质上就是一组可被后续层继续计算的数值特征。它既可以是向量(Vector),也可以是矩阵(Matrix),更一般地说,它通常是张量(Tensor)。向量和矩阵都只是张量的特殊情形:若只看单个样本的 MLP 隐层输出,最常见的是向量 \(\boldsymbol{h}\in\mathbb{R}^{d}\);若看 Transformer 对整段序列的隐藏状态,常写成矩阵 \(H\in\mathbb{R}^{L\times d}\);若再把 batch 维也带上,则会变成三维张量 \(\mathcal{H}\in\mathbb{R}^{B\times L\times d}\)。在卷积网络(Convolutional Neural Network, CNN)里,中间表示则常是特征图张量(Feature Map Tensor) \(\mathcal{H}\in\mathbb{R}^{C\times H\times W}\),或带 batch 的 \(\mathbb{R}^{B\times C\times H\times W}\)。

因此,“中间表示”不是某种神秘对象,它就是网络在某一层对输入所形成的内部编码。它不像最终标签那样直接面向人类语义,而是把输入重写成更适合下一层处理的坐标系。例如,文本模型中的某一层隐藏状态可能同时编码词义、上下文关系、句法位置和任务相关线索;图像模型中的某一层特征图则可能突出边缘、纹理、局部部件或更高层形状。后续层与任务头读到的,正是这些内部编码。

感知机的重要性不止在于历史地位,更在于今天大型模型中的知识,本质上仍然是通过这类权重结构逐层编码进去的。训练过程并不会把知识像数据库那样逐条写成显式记录,而是不断调整参数,使某些输入模式被放大、某些输入模式被抑制。于是,模型在数据中反复见到的统计规律——词与词的共现、图像局部纹理、特征之间的组合关系——都会被压缩进参数矩阵的数值结构中。

更准确地说,大模型中的知识通常不是“某一个感知机单独存储一条事实”,而是以分布式表示(Distributed Representation)的形式分散在大量参数里。单个单元更像一个局部特征探测器(Feature Detector):它只对某种模式敏感;许多单元级联后,网络才能把低层简单模式组合成高层抽象概念。模型规模越大、层数越深、参数越多,可被编码的模式组合也越丰富,这正是大模型具备强表达能力与“知识容量”的原因之一。

感知机能学会线性可分任务,但无法处理 XOR 这类线性不可分问题,这正是多层网络出现的动机:当一个超平面不够时,就需要通过多层组合把输入空间逐步重写成更容易分开的表示。

多层感知机(MLP)

多层感知机(Multi-Layer Perceptron, MLP)处理的核心问题是:当输入与输出之间的关系不是一个超平面就能表达时,如何通过多层可学习变换,把原始特征逐步改写成更容易完成任务的表示。它由多层线性变换与逐元素非线性激活交替组成,是最基本也最通用的前馈网络结构。

mlp

单层可写成:

\[\mathbf{h}=\phi(W\mathbf{x}+\mathbf{b})\]

多层堆叠后,可写为:

\[\mathbf{h}^{(1)}=\phi(W^{(1)}\mathbf{x}+\mathbf{b}^{(1)}),\quad \mathbf{h}^{(2)}=\phi(W^{(2)}\mathbf{h}^{(1)}+\mathbf{b}^{(2)}),\quad \hat{\mathbf{y}}=W^{(3)}\mathbf{h}^{(2)}+\mathbf{b}^{(3)}\]

这里 \(W^{(l)}\) 和 \(\mathbf{b}^{(l)}\) 是第 \(l\) 层参数, \(\mathbf{h}^{(l)}\) 是第 \(l\) 层隐藏表示。所谓“逐层重写表示”,就是每一层都在回答一个更具体的问题:哪些原始模式值得保留、哪些组合值得放大、哪些方向更利于后续任务。于是,早期层往往捕捉较局部、较简单的模式,后期层则把这些模式组合成更抽象的语义结构。

MLP 比单层感知机强,关键不在“层数更多”本身,而在于层与层之间插入了非线性激活函数 \(\phi\)。如果没有非线性,多层线性变换满足

\[W^{(2)}(W^{(1)}\mathbf{x}+\mathbf{b}^{(1)})+\mathbf{b}^{(2)}=\tilde W\mathbf{x}+\tilde{\mathbf{b}}\]

最终仍然等价于一层线性变换,表达能力不会因为堆叠而提升。只有加入非线性后,网络才能把输入空间切分、折叠、拉伸并重新组合,形成复杂的分段线性或平滑非线性决策边界。

从几何角度看,单层模型像“用一个超平面切一次”;而多层 MLP 则是在表示空间中反复做坐标变换和非线性折叠,把原本难分的数据逐步变成线性头也能分开的形状。文中的激活函数对比图展示的正是这个过程:不同激活函数会把同一个三层网络变成完全不同的几何变换器。

在现代大模型中,MLP 的作用远不只是“附属模块”。在 Transformer 里,注意力层负责在 token 之间路由信息,而 MLP / Feed-Forward Network(FFN)则负责在每个位置上做通道维度的非线性特征变换,把路由来的信息重新编码进更强的表示。因此,很多语义模式、组合规则与任务相关知识,最终都会沉淀到这些大规模参数化的 MLP 权重中。

更进一步说,在 Transformer 的常见解释框架里,MLP / FFN 往往被看作事实性知识的重要载体之一。一个常见直觉是把 FFN 看成参数化的“键值存储器(Key-Value Memory)”:第一层线性变换更像在检测当前输入是否匹配某种模式或概念,第二层线性变换则把与该模式相关的语义方向重新写回残差流(Residual Stream)。这里的残差流,可以理解为 Transformer 里那条贯穿各层的主表示通道:每一层注意力与 MLP 的输出,都会通过残差相加的方式写回这条主通道,再交给后续层继续处理。因此,诸如“实体—属性”“术语—定义”“模式—响应”这类较稳定的关联,常常更容易在 MLP 权重里留下痕迹。

但这并不意味着“一个神经元就存一条事实”。更准确的描述是:知识通常以分布式方式存在于许多层、许多通道和许多参数方向里。单个神经元有时会对某种关系或概念特别敏感,因而出现所谓“知识神经元(Knowledge Neurons)”现象;但更稳定的事实表示,通常仍然依赖一组共同激活的单元和跨层传递的表示。可以把两类子层的分工概括为:注意力更擅长“去哪里找、和谁建立联系”,MLP 更擅长“把匹配到的模式变成可供后续层使用的语义内容”。因此,说 MLP 是知识的主要载体之一是合理的;说知识只存在于 MLP、完全不在注意力里,则过于简单。

激活函数

激活函数(Activation Function)的作用是给线性层引入非线性。如果没有激活函数,多层线性层叠起来仍然等价于一层线性变换,深度就失去了意义。

先给出一个实用的选型总表。它不代替后文的机制分析,但可以先回答工程上最常见的问题:某个激活函数通常应该放在输出层、隐藏层,还是特定结构里。

激活函数 输出范围 典型适用场景 主要原因
Sigmoid \((0,1)\) 二分类输出层;LSTM / GRU 门控 天然给出概率或开关强度,但隐藏层易饱和
Tanh \((-1,1)\) 较浅网络;需要零中心有界激活的结构 比 sigmoid 更利于优化,但深层仍会饱和
ReLU \([0,+\infty)\) 深层前馈网络、CNN 的默认隐藏层 不饱和、计算便宜、分段线性、优化稳定
Leaky ReLU \((-\infty,+\infty)\) 担心 Dying ReLU 的深层隐藏层 保留 ReLU 优点,同时避免负半轴完全断梯度
ELU \((-\alpha,+\infty)\) 希望激活更平滑、且均值更接近 0 的隐藏层 负区间平滑并可取负值,但计算开销高于 ReLU
GELU \((-\infty,+\infty)\) Transformer、BERT 类模型的隐藏层 选择性强且过渡平滑,兼顾表达能力与优化平滑性
Swish / SiLU \((-\infty,+\infty)\) 现代卷积网络;部分大模型隐藏层 软门控、平滑、比硬截断更柔和
Softmax 各分量在 \((0,1)\) 且总和为 1 多分类输出层;语言模型词表分布输出 把 logits 归一化为概率分布,不用于普通隐藏层

mlp-activation-summary

activation-functions-grid

Sigmoid

Sigmoid 把实数压到 \((0,1)\):

\[\sigma(x)=\frac{1}{1+e^{-x}}\]

Sigmoid 的优势在于输出天然落在 \((0,1)\),因此非常适合表示概率,尤其常用于二分类输出层或门控结构中。但它在隐藏层里的主要问题是饱和(saturation):当输入绝对值较大时,函数会迅速贴近 0 或 1,此时导数接近 0,梯度在反向传播时会被不断压缩,深层网络因此容易出现梯度消失(Vanishing Gradient)。从优化角度看,这意味着前面层参数即使有误,也很难收到足够强的更新信号。

此外,sigmoid 的输出始终为正,不以 0 为中心,这会使后续层接收到带偏移的激活分布,通常不利于优化动态的稳定性。因此,sigmoid 今天更多保留在“需要概率解释”的输出层,或在 LSTM / GRU 等门控结构中充当开关函数,而不再是深层前馈隐藏层的默认选择。

Tanh

Tanh 的输出范围是 \((-1,1)\):

\[\tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}\]

Tanh 可以看作“零中心版 sigmoid”:它同样会在大幅度输入时饱和,但输出分布位于 \((-1,1)\) 且以 0 为中心,这通常比 sigmoid 更利于优化,因为后续层接收到的激活不再整体偏向正侧。对于需要表达“正负方向”差异的隐藏表示,tanh 往往也比 sigmoid 更自然。

不过,tanh 并没有解决饱和带来的根本问题:当 \(|x|\) 很大时,导数仍接近 0,深层网络中的梯度传播依然会变弱。因此,在较深的前馈网络里,tanh 通常不如 ReLU 家族稳定;它更多出现在较浅网络、早期神经网络设计,或某些希望激活有界且零中心的结构中。

ReLU

ReLU(Rectified Linear Unit)定义为

\[\mathrm{ReLU}(x)=\max(0,x)\]

ReLU 看起来几乎“过于简单”,但它之所以长期有效,关键不在公式花哨,而在于它同时满足了深层优化最需要的几条性质。第一,ReLU 在正半轴不饱和(non-saturating):当 \(x>0\) 时导数恒为 1,梯度穿过这一单元时不会像 sigmoid / tanh 那样被持续压小,因此更有利于深层网络中的梯度传播。第二,ReLU 保留了非线性,但正半轴仍是线性的,这使整个网络变成分段线性(piecewise linear)系统:表达能力足够强,同时局部优化形状又比高度弯曲的饱和函数更“规整”。第三,负半轴直接截断会带来自然的稀疏激活(sparse activation):不是所有单元都会在每个样本上同时活跃,这通常有助于提升表示分解能力,并降低无效共适应(co-adaptation)。这里的共适应,指多个神经元在训练中形成了过强的相互依赖:某个单元之所以有效,不是因为它单独学到了稳定、可迁移的模式,而是因为它总是和另外几个特定单元“成套工作”。一旦输入分布变化,或其中某些单元没有按训练时那样响应,这种脆弱的协同关系就容易失效,从而削弱泛化能力。

从工程角度看,ReLU 的优势还包括计算代价极低,只需一次比较运算;这在大规模训练中会被成千上万层和数十亿次前向/反向传播放大。更深层的原因是:深度网络真正需要的不是“平滑得很漂亮”的激活函数,而是一个既能打破线性、又不会在大范围内把梯度压扁、还能让优化器容易工作的非线性。ReLU 恰好在这三点之间取得了非常实用的平衡,这就是为什么一个形式上极其朴素的函数,反而成为现代深度学习最成功的默认选择之一。它的代价也很明确:负区间梯度为 0,单元可能长期失活,这就是后面 Leaky ReLU、ELU、GELU 等变体继续改进的出发点。

Leaky ReLU

Leaky ReLU 给负半轴保留一个很小的斜率:

\[\mathrm{LeakyReLU}(x)=\max(\alpha x,x),\quad \alpha\ll 1\]

这样做是为了缓解“死亡 ReLU(Dying ReLU)”问题:若某神经元长期落在负区间,普通 ReLU 的梯度可能一直为 0,而 Leaky ReLU 仍保留一点更新信号。

从机制上看,Leaky ReLU 的核心改动很小,但很有针对性:它保留了 ReLU 在正半轴的不饱和与分段线性优点,同时避免把负半轴完全切断。这样即使某个单元暂时落入负区间,参数仍有机会通过非零梯度被重新拉回活跃状态。因此,Leaky ReLU 可以看作对 ReLU 的保守修正:表达风格几乎不变,但训练风险更低。

ELU

ELU(Exponential Linear Unit)在负半轴使用指数平滑:

\[\mathrm{ELU}(x)=\begin{cases}x,&x>0\\ \alpha(e^x-1),&x\le 0\end{cases}\]

它的目标是兼顾 ReLU 的优化优势和负区间的平滑性,使激活均值更接近 0。

与 Leaky ReLU 相比,ELU 在负半轴不再是简单直线,而是用指数曲线平滑衰减到负饱和值。这带来两个效果:一是避免了 ReLU 在 0 点附近过于生硬的折线结构;二是允许激活出现稳定的负值,从而减轻隐藏表示整体偏正的问题。代价是计算比 ReLU 更重,且负区间在极小值处同样会逐渐饱和,因此它通常被视为“更平滑、更零中心”的 ReLU 变体,而不是彻底不同的一类激活。

GELU

GELU(Gaussian Error Linear Unit)可理解为“按输入大小平滑地决定保留多少信号”。它不像 ReLU 那样硬截断,而是对小正值和小负值做连续、概率化的保留,因此在 0 附近更平滑。

这种设计的价值在于:它仍然保留了 ReLU 家族的选择性——不是所有信号都被同等对待——但又避免了硬截断带来的尖锐折点和完全失活区。于是,GELU 往往能在“表达选择性”和“优化平滑性”之间取得更好的折中,这也是它在 Transformer、BERT 及其后续大量变体中被广泛采用的重要原因。

Swish / SiLU

Swish / SiLU 定义为

\[\mathrm{SiLU}(x)=x\,\sigma(x)\]

它是平滑、非单调的激活函数,在某些深层网络里表现优于 ReLU。其结构可以直接读成“输入值 \(x\) 乘上一个 sigmoid 门控 \(\sigma(x)\)”:当 \(x\) 很大时, \(\sigma(x)\approx 1\),信号几乎原样通过;当 \(x\) 很小时, \(\sigma(x)\approx 0\),信号被显著压低;在 0 附近则是连续、平滑的软过渡。

这种形式的价值在于:它既不像 ReLU 那样做硬截断,也不像 sigmoid 那样把输出彻底压进固定区间,而是让网络学到一种“按输入强度自适应通过多少”的软门控机制。结果是,SiLU / Swish 往往能在保持优化平滑性的同时,保留较强的表达灵活性,因此在一些现代卷积网络与大模型变体中表现良好。它可以看作介于 ReLU 家族与门控激活之间的一种折中设计。

Softmax

Softmax 把一组实数分数(scores)映射为概率分布(Probability Distribution)。在分类与语言模型里,这组分数通常称为 logit(Logits):它们是 softmax 之前的未归一化输出。

\[\mathrm{softmax}(z)_i=\frac{e^{z_i}}{\sum_{j=1}^{V} e^{z_j}}\]

logits 的两个关键性质:

  • logits 不需要是概率,可以是任意实数;softmax 才把它变成 \([0,1]\) 且和为 1 的分布。
  • softmax 对整体平移不敏感:对任意常数 \(c\),有 \(\mathrm{softmax}(z)=\mathrm{softmax}(z+c\mathbf{1})\)。因此实现里常用 \(z\leftarrow z-\max_i z_i\) 做数值稳定(Numerical Stability)。

这说明 softmax 真正关心的不是某个 logit 的绝对数值,而是各个 logit 之间的相对差值。若把所有分数同时加 10,模型对“哪一类更占优”的判断不会改变,因为指数项会在分子和分母里同时乘上 \(e^{10}\),最终完全约掉。改变 softmax 输出的,不是整体抬高或压低所有分数,而是某个类别相对其他类别高了多少。

也正因为如此,logit 更适合理解为“未归一化偏好分数(unnormalized preference scores)”,而不是“概率雏形”。例如两类 logits 从 \((1,2)\) 变成 \((101,102)\),softmax 输出完全相同;但若从 \((1,2)\) 变成 \((1,5)\),第二类相对第一类的优势被显著拉大,概率才会明显变化。

在语言模型(Language Model)中,给定最后一层隐藏状态 \(h\in\mathbb{R}^{d_{\text{model}}}\),线性输出头产生词表大小 \(V\) 的 logits: \(z=hW_{\text{vocab}}+b\),再经 softmax 得到下一个 token 的分布。若采用权重共享(Weight Tying),则输入嵌入表 \(E\in\mathbb{R}^{V\;\times d_{\text{model}}}\) 与输出头满足 \(W_{\text{vocab}}=E^\top\),于是可直接写成 \(z=hE^\top+b\)。

Softmax和分类任务

在多分类任务里,这几个概念实际上是一条连续的计算链:任务头先输出 logits \(z\in\mathbb{R}^{C}\),softmax 把它们变成条件概率 \(p(y=i|x)\),再取真实类别 \(c\) 的负对数概率作为单样本损失,也就是负对数似然(Negative Log-Likelihood, NLL)。

\[p(y=i|x)=\mathrm{softmax}(z)_i=\frac{e^{z_i}}{\sum_{j=1}^{C}e^{z_j}},\qquad \ell_{\mathrm{NLL}}(z,c)=-\log p(y=c|x)\]

把两步合起来,NLL 可以直接写成 logits 的函数:

\[\ell_{\mathrm{NLL}}(z,c)=-\log\frac{e^{z_c}}{\sum_{j=1}^{C}e^{z_j}}=-z_c+\log\sum_{j=1}^{C}e^{z_j}\]

这个式子把训练目标拆成了两部分:第一项 \(-z_c\) 要求真实类别的 logit 足够大;第二项 \(\log\sum_j e^{z_j}\) 是归一化项(log-sum-exp),它把所有类别的竞争都算进去。因此训练并不是单独把正确类别分数抬高,而是要让它相对其他类别更占优势。

softmax 的平移不变性(Translation Invariance)在这里也能直接看见。对任意常数 \(a\),若把所有 logits 同时改为 \(z+a\mathbf{1}\),则 softmax 概率不变,NLL 也不变:

\[\mathrm{softmax}(z+a\mathbf{1})_i=\mathrm{softmax}(z)_i,\qquad \ell_{\mathrm{NLL}}(z+a\mathbf{1},c)=\ell_{\mathrm{NLL}}(z,c)\]

因此 logits 的绝对零点没有意义,真正有意义的是类别之间的相对差值。工程实现里常把 \(z\) 先整体减去 \(\max_i z_i\),再计算 softmax 或 log-sum-exp。这样不会改变概率与损失,但能显著降低指数溢出的风险。

损失函数

术语区分:假设函数(Hypothesis Function)/模型 \(f_\theta\) 定义“模型在做什么映射”;样本损失(Loss Function)定义在单样本上;代价函数/成本函数(Cost Function)是把样本损失在全数据集上做平均或求和后的经验风险;目标函数(Objective Function)是优化器真正要优化的函数,最常见写法是 \(J(\theta)=L(\theta)+\lambda\Omega(\theta)\)。

回归损失
MSE

均方误差(Mean Squared Error, MSE)定义为

\[\ell_{\mathrm{MSE}}(y,\hat y)=(\hat y-y)^2\]

平方的作用是让大误差被放大处罚。若一个样本错 10,另一个样本错 1,那么前者在 MSE 里不是“重 10 倍”,而是“重 100 倍”。因此 MSE 很适合你明确希望重罚大错的场景,也对应前面讲过的高斯噪声假设。

MAE

平均绝对误差(Mean Absolute Error, MAE)对应单样本形式

\[\ell_{\mathrm{MAE}}(y,\hat y)=|\hat y-y|\]

它直接度量偏差大小,对离群点更鲁棒,因为不会像平方那样把大误差急剧放大。若做房价预测,数据中存在一批价格远高于主体分布的豪宅样本时,MAE 往往比 MSE 更稳;这里的“主体分布”指的是样本中占大多数的普通住宅价格区间,而豪宅样本相对它明显偏高。这样一来,哪怕豪宅样本数量不多,它们也会在 MSE 下因为误差被平方而获得过大的影响力。

Huber Loss

Huber Loss 结合了 MSE 与 MAE:误差小时像平方误差,误差大时像绝对误差。设阈值 \(\delta\),则

\[\ell_\delta(r)=\begin{cases}\frac{1}{2}r^2,&|r|\le \delta\\ \delta(|r|-\frac{1}{2}\delta),&|r|>\delta\end{cases},\quad r=\hat y-y\]

这条式子的直觉是:小误差区间内保持平滑、便于优化;大误差区间内降低对离群点的过度敏感。它像“正常误差严肃处理,极端异常别让它一票否决整个模型”。

分类损失
交叉熵损失(Binary)

二分类交叉熵(Binary Cross-Entropy, BCE)用来训练输出概率 \(p\in(0,1)\) 的二分类器。这里 \(p\) 通常表示模型预测“正类”的概率, \(y\in\{0,1\}\) 是真实标签: \(y=1\) 表示正类, \(y=0\) 表示负类。

\[\ell_{\mathrm{BCE}}(y,p)=-\Big(y\log p+(1-y)\log(1-p)\Big)\]

左边的 \(\ell_{\mathrm{BCE}}(y,p)\) 表示“单个样本在真实标签为 \(y\)、模型预测正类概率为 \(p\) 时的 BCE 损失值”。也就是说,这不是新的概率,而是一个标量惩罚:预测越符合真实标签,它越小;预测越违背真实标签,它越大。

这条公式会根据 \(y\) 的取值自动选择应当惩罚哪一项。当 \(y=1\) 时,式中的 \((1-y)=0\),因此第二项消失,损失化简为 \(-\log p\);当 \(y=0\) 时,第一项中的 \(y=0\),因此第一项消失,损失化简为 \(-\log(1-p)\)。于是它惩罚的本质就是:让真实类别对应的概率尽可能高。

数值例子(自然对数):若 \(y=1\) 且 \(p=0.9\),则 \(\ell\approx 0.105\);若 \(p=0.1\),则 \(\ell\approx 2.303\)。正确但不自信会被罚,错误且自信会被重罚。

交叉熵损失(Categorical)

多分类交叉熵(Categorical Cross-Entropy, CE)与 softmax 通常配套使用。这里 \(y_i\) 是真实分布(Ground-Truth Distribution)在第 \(i\) 类上的概率质量, \(p_i\) 是模型预测分布(Predicted Distribution)在第 \(i\) 类上的概率。若类别总数为 \(C\),则单样本损失写成:

\[\ell_{\mathrm{CE}}(y,p)=-\sum_{i=1}^{C} y_i\log p_i\]

左边的 \(\ell_{\mathrm{CE}}(y,p)\) 表示“当真实标签分布为 \(y\)、模型预测分布为 \(p\) 时,这个样本对应的交叉熵损失值”。其本质是:用真实标签分布 \(y\) 作为权重,对预测分布的负对数概率 \(-\log p_i\) 做加权平均。

当 \(y\) 是 one-hot 分布时,只有真实类别 \(c\) 那一维的权重为 1,其余维度权重都为 0,因此求和会自动塌缩成单项:

\[\ell=-\log p_c\]

这正是分类任务里最常见的形式。它与最大似然估计(Maximum Likelihood Estimation, MLE)完全一致:最小化交叉熵等价于最大化真实类别的对数似然。

若 \(y\) 不再是 one-hot,而是一个在多个类别上分配了非零概率质量的分布,那么交叉熵就不再只读取单个类别 \(p_c\),而是会对整条标签分布做加权。常见来源有三类。

第一类是软标签(Soft Label)。它指真实监督信号本身就是一个概率分布,而不是“只有一个绝对正确类别”的硬标签(Hard Label)。例如一张图像可能被标注为“70% 像猫、30% 像狐狸”,或一个样本本身就带有多标注者投票汇总后的类别分布。在这种情况下, \(y_i\) 直接表示第 \(i\) 类的目标概率,交叉熵自然要对所有类别一起计算。

第二类是标签平滑(Label Smoothing)。它是一种正则化技术:原本 one-hot 标签会把真实类别的目标概率设为 1,其余类别全设为 0;标签平滑则故意把这件事放松一些,例如对 \(C\) 分类问题,取一个很小的 \(\varepsilon\in(0,1)\),把目标分布改写为:

\[y_i^{\mathrm{LS}}=(1-\varepsilon)\mathbf{1}[i=c]+\frac{\varepsilon}{C}\]

这里 \(c\) 是真实类别, \(\mathbf{1}[i=c]\) 是指示函数:当 \(i=c\) 时取 1,否则取 0。这样做的效果是:真实类别仍占最大权重,但其他类别也获得一小部分概率质量。它可以抑制模型过度自信,使输出分布更平滑,并在一定程度上改善泛化与校准。

第三类是教师分布蒸馏(Knowledge Distillation from Teacher Distribution)。知识蒸馏(Knowledge Distillation)的做法是:不用人工标签单独监督学生模型(Student Model),而是让学生去拟合教师模型(Teacher Model)给出的类别分布。若教师在某个样本上输出 \(q\),学生输出 \(p\),则训练目标常包含 \(-\sum_i q_i\log p_i\) 这样的交叉熵或等价的 KL 散度项。它传递的不只是“哪一类是对的”,还传递“其余类别分别有多像”,因此常被称为暗知识(Dark Knowledge)。

这三种情况的共同点是:标签本身已经不是单点答案,而是一条分布。于是交叉熵的计算对象就不再只是“真实类别那一项”,而是整个目标分布与预测分布之间的匹配程度。

从信息论角度看,交叉熵的标准定义是两个分布 \(P\) 与 \(Q\) 之间的

\[H(P,Q)=-\sum_x P(x)\log Q(x)\]

分类里的 \(\ell_{\mathrm{CE}}(y,p)\) 与这个定义并不矛盾,它只是把信息论中的 \(P\) 和 \(Q\) 分别具体化成了“单个样本对应的真实标签分布 \(y\)”与“模型在这个样本上的预测分布 \(p\)”。若标签是 one-hot,那么 \(P\) 退化成一个只在真实类别处取值为 1 的离散分布,于是信息论里的交叉熵自然退化成 \(-\log p_c\)。

进一步地,交叉熵与 KL 散度(Kullback–Leibler Divergence)的关系可以直接写成:

\[H(P,Q)=H(P)+D_{\mathrm{KL}}(P\|Q)\]

这里 \(H(P)=-\sum_x P(x)\log P(x)\) 是真实分布 \(P\) 自身的熵(Entropy),只由数据分布决定; \(D_{\mathrm{KL}}(P\|Q)=\sum_x P(x)\log\frac{P(x)}{Q(x)}\) 是 KL 散度,用来衡量预测分布 \(Q\) 相对真实分布 \(P\) 的偏离程度。于是,在训练数据固定时, \(H(P)\) 是常数,最小化交叉熵 \(H(P,Q)\) 就等价于最小化 \(D_{\mathrm{KL}}(P\|Q)\)。

因此,“最小化交叉熵就是最小化 KL 散度”这句话在监督学习里通常成立,但更准确的表述是:在真实分布固定不变时,最小化交叉熵与最小化预测分布对真实分布的 KL 偏离是等价的。KL 散度确实可以理解为“与真实分布的差异或偏离”,但它不是对称距离(Symmetric Distance):一般有 \(D_{\mathrm{KL}}(P\|Q)
eq D_{\mathrm{KL}}(Q\|P)\)
,也不满足严格距离函数的三角不等式,因此更准确的名称是分布失配(distribution mismatch)或相对熵(relative entropy)。

若进一步把 \(p\) 写成 softmax 作用在 logits \(z\) 上,则多分类交叉熵可直接写成:

\[\ell_{\mathrm{CE}}(z,c)=-\log\mathrm{softmax}(z)_c=-z_c+\log\sum_{j=1}^{C}e^{z_j}\]

这条式子把任务头和损失函数直接接起来:线性头先输出 logits,softmax 把它们归一化为概率,交叉熵再读取真实类别的负对数概率。由于 softmax 具有平移不变性,给所有 logits 同时加上同一个常数不会改变这个损失,因此实现中通常直接从 logits 计算交叉熵(log-sum-exp 形式),并先减去 \(\max_j z_j\) 做数值稳定,而不是显式先算 softmax 再取 log。

Focal Loss

Focal Loss 常用于类别极不平衡的分类任务,尤其是目标检测(Object Detection)这类“负样本远多于正样本”的场景。它不是简单换掉交叉熵,而是在交叉熵前再乘一个与样本难度相关的调制因子,使已经分得很对的容易样本贡献变小,把梯度预算更多留给困难样本:

\[\ell_{\mathrm{focal}}(p_t)=-(1-p_t)^\gamma\log p_t\]

这里 \(p_t\) 表示“真实类别对应的预测概率”:若真实标签 \(y=1\),则 \(p_t=p\);若 \(y=0\),则 \(p_t=1-p\)。因此 \(-\log p_t\) 就是普通交叉熵,而前面的 \((1-p_t)^\gamma\) 是额外加上的难度调制项。参数 \(\gamma\ge 0\) 控制聚焦强度: \(\gamma=0\) 时,Focal Loss 退化回普通交叉熵; \(\gamma\) 越大,对容易样本的压低越明显。

这个机制的关键在于样本难度如何反映到权重上。若某个样本已经分得很对,例如真实类别概率 \(p_t=0.99\),则调制因子 \((1-p_t)^\gamma\) 会非常小;以 \(\gamma=2\) 为例,权重大约只有 \((0.01)^2=10^{-4}\),这意味着它对总损失和梯度的影响被大幅削弱。相反,若某个样本很难,例如 \(p_t=0.2\),则权重约为 \((0.8)^2=0.64\),其损失会被较大程度保留。于是训练过程不再被海量“早就分对的简单样本”主导,而会持续关注误分样本、边界样本和少数类样本。

目标检测是最典型的应用例子。以单阶段检测器(One-stage Detector)为例,一张图像上往往有成千上万个候选框(Anchors),但真正包含目标的正样本只占极少数;绝大多数候选框都是背景。若直接使用普通交叉熵,训练会被这些“背景且容易判断”的负样本淹没:它们单个损失虽小,但数量太多,累积后仍然主导梯度。Focal Loss 的作用正是把这批容易背景样本的权重压下去,让模型把更多注意力放在少数正样本、遮挡目标、边界模糊目标,以及那些看起来像目标但其实是背景的困难负样本上。这样做通常会显著改善长尾检测与前景-背景极不平衡时的训练效果。

Hinge Loss

Hinge Loss 是 SVM 常用的分类损失:

\[\ell_{\mathrm{hinge}}(y,f)=\max(0,1-yf),\quad y\in\{-1,+1\}\]

其中 \(f\) 是模型分数而不是概率。当 \(yf\ge 1\) 时,说明不仅分类正确,而且留出了足够间隔,损失为 0;当 \(yf<1\) 时,就要受罚。它强调的不只是“分对”,而是“分对且留有安全距离”。

度量学习损失

度量学习(Metric Learning)不直接预测类别,而是学习一个表示空间,让“应该相似的样本靠近,不该相似的样本拉远”。这类损失在检索、人脸识别、推荐召回和 embedding 学习中非常常见。

Contrastive Loss

Contrastive Loss 处理样本对(pair)。若一对样本应相似,则拉近它们;若应不同,则至少推开到某个间隔 \(m\) 之外:

\[\ell=y\,d^2+(1-y)\max(0,m-d)^2\]

这里 \(d\) 是两者在嵌入空间中的距离, \(y=1\) 表示正对, \(y=0\) 表示负对。它像“朋友要坐得近,陌生人至少别挤在一起”。

Triplet Loss

Triplet Loss 使用三元组:锚点(Anchor)、正样本(Positive)、负样本(Negative)。目标是让锚点离正样本比离负样本更近至少一个 margin:

\[\ell=\max\big(0,\ d(a,p)-d(a,n)+m\big)\]

这条式子表达的是一种相对排序约束,而不是绝对相似度分数。它非常适合“谁比谁更像”的任务,例如人脸验证:同一个人的两张照片应比不同人的照片更近。

InfoNCE

InfoNCE 是现代对比学习最常见的损失之一。对一个锚点来说,它把正样本放进一堆候选里,要求模型把正样本打分最高:

\[-\log \frac{\exp(\mathrm{sim}(z_i,z_i^+)/\tau)}{\sum_j \exp(\mathrm{sim}(z_i,z_j)/\tau)}\]

分子是正确配对,分母是所有候选。这个结构和 softmax 分类非常像,只不过类别不再是固定标签,而是“在一堆候选里,谁才是真正匹配的那个”。在大语言模型 embedding、图像表征学习和多模态对齐里,它几乎是标准配置。

任务头(Task Head)

任务头(Task Head)是把主干网络(Backbone)产出的隐藏表示(Hidden Representation)映射到具体任务输出空间的模块。主干负责抽取通用特征,任务头负责把特征“读出来”并对齐到目标形式(类别、数值、序列标签、跨度、关系等)。在工程上,绝大多数“用 Transformer 做下游任务”都可以写成:Transformer backbone + task head + task loss。

中间表示、logits 与任务头的关系

主干网络输出的隐藏表示(Hidden Representation)是任务头的输入,任务头则是把这种内部表示读成具体任务输出的最后一层或最后几层变换。若把主干输出记为 \(h\)、\(H\) 或更一般的张量 \(\mathcal{H}\),则任务头通常先做一次线性读出(Linear Readout)得到分数,再视任务类型决定是否接 sigmoid、softmax、CRF 解码或直接保留实数输出。

logits 就是在这个读出阶段最常见的中间产物。它们是任务头输出、但尚未归一化或尚未解码的原始分数。例如,多分类头常先产生 \(z\in\mathbb{R}^{C}\),这里 \(C\) 是类别数, \(z_c\) 表示模型对第 \(c\) 类的偏好分数;softmax 之后这些分数才变成概率。对 token 分类任务,task head 产生的不是单个向量,而是一整张 logits 矩阵 \(Z\in\mathbb{R}^{L\times C}\);对语言模型,输出则是词表 logits \(Z\in\mathbb{R}^{L\times V}\),其中 \(V\) 是词表大小。

因此,关系可以概括为:输入先被 backbone 编码成中间表示,中间表示再被 task head 读成 logits 或其他任务分数,最后再由概率映射、解码器或损失函数把这些分数变成最终预测。logits 不是所有中间表示的统称,而是“距离最终任务输出只差一步”的那类任务分数;它们通常由任务头生成,而不是由主干网络中间每一层都显式生成。

任务头输出对照表

不同任务头的差异,最核心地体现在“直接输出什么张量、这些张量后面还要经过什么处理”这两个问题上。下面这张表把常见任务头的输入形状、直接输出和后续处理并列起来,便于从工程实现角度快速对照。

任务类型 任务头常见输入 任务头直接输出 后续处理
二分类 单样本表示 \(h\in\mathbb{R}^{d}\) 标量 logit \(z\in\mathbb{R}\),或二维 logits \(\mathbf{z}\in\mathbb{R}^{2}\) sigmoid 或 softmax,得到类别概率
多分类 单样本表示 \(h\in\mathbb{R}^{d}\) 类别 logits 向量 \(\mathbf{z}\in\mathbb{R}^{C}\) softmax 后得到 \(C\) 类概率
多标签分类 单样本表示 \(h\in\mathbb{R}^{d}\) 每个标签一个 logit,组成 \(\mathbf{z}\in\mathbb{R}^{C}\) 对每一维独立做 sigmoid,而不是在类别间做 softmax
回归 单样本表示 \(h\in\mathbb{R}^{d}\) 实数或向量 \(\hat{\mathbf{y}}\in\mathbb{R}^{m}\) 通常不做概率归一化,直接配合回归损失
Token 分类 / NER 序列表示 \(H\in\mathbb{R}^{L\times d}\) token-level logits 矩阵 \(Z\in\mathbb{R}^{L\times C}\) 逐 token softmax,或接 CRF 做全局解码
语言模型 / 文本生成 序列表示 \(H\in\mathbb{R}^{L\times d}\) 词表 logits \(Z\in\mathbb{R}^{L\times V}\) 对每个位置在词表维做 softmax,得到 next-token 分布
跨度抽取(Span Extraction) 序列表示 \(H\in\mathbb{R}^{L\times d}\) 起点 logits \(\mathbf{a}\in\mathbb{R}^{L}\) 与终点 logits \(\mathbf{b}\in\mathbb{R}^{L}\),或 span 分数矩阵 在起止位置上做 softmax 或联合评分,输出片段边界
依存句法 / 关系抽取 成对表示 \(h_i,h_j\) 或序列表示 \(H\) 边分数矩阵 \(S\in\mathbb{R}^{L\times L}\),或关系分数张量 \(\mathcal{S}\in\mathbb{R}^{L\times L\times C}\) argmax、biaffine 解码或图结构约束解码
度量学习 / 检索 单样本表示 \(h\in\mathbb{R}^{d}\) embedding 向量 \(e\in\mathbb{R}^{d'}\) 不直接输出 logits;后续用相似度函数或对比损失比较

这张表的关键在于区分“任务头直接输出什么”和“用户最终看到什么”。很多任务头直接输出的并不是概率,也不是标签,而是 logits、边分数、起止位置分数或 embedding。概率、标签、生成 token、依存边、异常分数等最终结果,通常还需要经过归一化、解码、阈值化或搜索过程才能得到。

分类头

分类头(Classification Head)的核心职责,是把主干网络输出的表示 \(h\in\mathbb{R}^{d}\) 变成类别分数(Class Scores)或 logits。最常见的做法是一层线性映射:

\[\mathbf{z}=W\mathbf{h}+\mathbf{b}\]

这里 \(\mathbf{h}\in\mathbb{R}^{d}\) 是单个样本的隐藏表示, \(W\) 是任务头权重矩阵, \(\mathbf{b}\) 是偏置向量, \(\mathbf{z}\) 是未归一化类别分数。分类任务的关键区别不在于“有没有线性层”,而在于:输出空间是否互斥、每个样本允许几个标签成立、以及这些分数之后接什么归一化与损失。

直觉上,这个线性头就是一个“可学习的读出(Readout)”:在高维表示空间里用超平面(Hyperplane)切分区域,或用线性映射把表示投影到目标坐标系。这里的“读出”指的是:主干网络先把输入编码成内部表示,而任务头再把这种内部表示转换成模型真正需要输出的量,例如类别 logits、词表 logits、回归值、span 分数或关系分数。换言之,读出不是“再提特征”,而是把已经形成的表示翻译成任务空间中的可判定分数。

二分类

二分类(Binary Classification)要求每个样本只在两个互斥类别中选一个,例如“垃圾 / 非垃圾”“欺诈 / 正常”“阳性 / 阴性”。最常见的写法是输出一个标量 logit:

\[z=\mathbf{w}^\top \mathbf{h}+b\]

然后通过 sigmoid 得到正类概率:

\[p=P(y=1\mid x)=\sigma(z)=\frac{1}{1+e^{-z}}\]

这里 \(z\) 是模型对正类的原始偏好分数, \(p\) 是正类概率,负类概率则是 \(1-p\)。训练时通常配合二分类交叉熵(Binary Cross-Entropy, BCE)。工程上也可以输出二维 logits \(\mathbf{z}\in\mathbb{R}^{2}\),再接 softmax;但若任务确实只有两个互斥类别,单 logit + sigmoid 更常见,也更经济。

多分类

多分类(Multi-class Classification)要求每个样本在 \(C\) 个互斥类别中恰好选一个类别,例如“猫 / 狗 / 鸟”“体育 / 财经 / 科技 / 娱乐”。此时任务头不会只输出一个标量,而是输出长度为 \(C\) 的 logits 向量:

\[\mathbf{z}=W\mathbf{h}+\mathbf{b},\qquad W\in\mathbb{R}^{C\times d},\ \mathbf{z}\in\mathbb{R}^{C}\]

其中第 \(c\) 维 \(z_c\) 表示模型对第 \(c\) 个类别的原始偏好分数。由于这些类别互斥,后续通常接 softmax,把整组分数归一化成概率分布:

\[p(y=c\mid x)=\frac{e^{z_c}}{\sum_{j=1}^{C}e^{z_j}}\]

这条式子的含义很直接:分子 \(e^{z_c}\) 是第 \(c\) 类的相对强度,分母 \(\sum_{j=1}^{C}e^{z_j}\) 把所有类别一起归一化,因此最终得到的 \(p(y=c\mid x)\) 落在 \((0,1)\) 之间,且所有类别概率和为 1。也正因为总和必须为 1,多分类头天然表达的是“类间竞争”:某一类概率上升,其他类的总概率就必须下降。

训练时通常直接把 logits \(\mathbf{z}\) 输入多分类交叉熵(Cross-Entropy)损失,而不是手动先算 softmax 再取对数。这样做的原因是数值稳定:损失函数内部会把 softmax 与对数合并成 log-sum-exp 形式,避免指数溢出。推理时若只关心类别标签,直接取 \(\arg\max_c z_c\) 或 \(\arg\max_c p(y=c\mid x)\) 即可;若需要概率、阈值或校准,再显式使用 softmax。

多标签分类

多标签分类(Multi-label Classification)与多分类名字相近,但任务结构完全不同。它不是“从多个类里选一个”,而是同一个样本可以同时拥有多个标签。例如一篇文章可以同时属于“AI、NLP、Transformer”,一张图片可以同时打上“室内、人物、宠物”三个标签。

这种任务里,标签之间不再互斥,因此不能使用 softmax。若仍用 softmax,所有标签概率会被强制归一化为和 1,相当于错误地假设“只能有一个标签成立”。多标签头通常输出 \(C\) 个 logits:

\[\mathbf{z}=W\mathbf{h}+\mathbf{b},\qquad \mathbf{z}\in\mathbb{R}^{C}\]

但后续不是做一次整体 softmax,而是对每一维独立做 sigmoid:

\[p_i=\sigma(z_i),\qquad i=1,\dots,C\]

这里 \(p_i\) 表示“第 \(i\) 个标签是否成立”的独立概率。训练时通常使用逐维二分类交叉熵,即把每个标签都当作一个独立的二分类问题,再在标签维上求和或取平均:

\[\ell_{\mathrm{multi\mbox{-}label}}=-\sum_{i=1}^{C}\Big(y_i\log p_i+(1-y_i)\log(1-p_i)\Big)\]

因此,多标签头的关键不是“输出维度也叫 \(C\)”,而是这 \(C\) 维之间不竞争,每一维都在独立回答一个 yes/no 问题。推理时也不是取单个 argmax,而是对每一维做阈值判断,例如输出所有满足 \(p_i>0.5\) 的标签,或按业务分别设定不同标签阈值。

回归头

回归头(Regression Head)不负责在离散类别之间做判别,而是直接输出连续数值(Continuous Value)或连续向量。最常见的形式仍然是一层线性映射:

\[\hat{\mathbf{y}}=W\mathbf{h}+\mathbf{b},\qquad \hat{\mathbf{y}}\in\mathbb{R}^{m}\]

这里 \(m\) 是回归目标维度。若 \(m=1\),就是标量回归,例如房价预测、评分预测、温度预测;若 \(m>1\),则是多维回归,例如边界框坐标回归、姿态参数回归或多目标数值预测。

回归头通常不接 softmax,也不强制输出落在 \((0,1)\)。原因很简单:回归任务关心的是数值大小本身,而不是类别概率竞争。训练时常配合均方误差(MSE)、平均绝对误差(MAE)或 Huber Loss。只有当目标值本身有明确范围约束时,才会额外接 sigmoid、tanh 或其他变换,把输出压到指定区间。

语言模型头(LM Head)

语言模型头(Language Modeling Head, LM Head)是把隐藏表示映射回词表空间的输出头。只要任务目标是“在若干位置上对词表中的 token 做预测”,就会出现这一类头;因此它不只存在于 Decoder-only 大模型,也存在于 Encoder-only 的掩码语言模型(Masked Language Model, MLM)以及 Encoder-Decoder 的生成端。它读取主干网络在每个位置输出的隐藏状态 \(H\in\mathbb{R}^{L\;\times d_{\text{model}}}\),并把每个位置的表示投影到整张词表空间,得到词表 logits:

\[Z = HW_{\text{vocab}} + \mathbf{1}b^\top,\quad W_{\text{vocab}}\in\mathbb{R}^{d_{\text{model}}\;\times {V}},\ Z\in\mathbb{R}^{L\;\times {V}}\]

这条式子先描述整体矩阵,再自然落到单个位置。这里 \(L\) 是序列长度,表示当前一共有多少个位置; \(d_{\text{model}}\) 是隐藏维度; \(V\) 是词表大小(Vocabulary Size)。因此,隐藏状态矩阵 \(H\in\mathbb{R}^{L\;\times d_{\text{model}}}\) 的每一行对应一个位置的表示,输出权重矩阵 \(W_{\text{vocab}}\in\mathbb{R}^{d_{\text{model}}\;\times {V}}\) 的每一列对应“词表中某个 token 作为候选答案时的读出方向”,最终得到的 \(Z\in\mathbb{R}^{L\;\times {V}}\) 就是一个“位置 \(\times\) 词表”的打分表:行表示位置,列表示候选 token。

把这张打分表聚焦到第 \(t\) 行,就得到 \(Z_{t,:}\in\mathbb{R}^{V}\),也就是“第 \(t\) 个位置对整张词表所有 token 的一整行 logits”。这里 \(H_t\in\mathbb{R}^{d_{\text{model}}}\) 表示第 \(t\) 个位置的隐藏状态,冒号 \(:\) 表示该行的全部列;若写成 \(Z_{:,i}\),则表示第 \(i\) 列,也就是“所有位置对第 \(i\) 个 token 的分数”。继续缩小到单个元素 \(Z_{t,i}\),它表示“在第 \(t\) 个位置,把词表中第 \(i\) 个 token 作为下一个输出时的原始分数”。

把矩阵形式按单个位置、单个候选 token 展开后,打分可写成:

\[Z_{t,i}=H_t\cdot W_{\text{vocab},:,i}+b_i\]

这里 \(W_{\text{vocab},:,i}\) 表示输出权重矩阵的第 \(i\) 列,也就是与词表第 \(i\) 个 token 对应的参数向量; \(b_i\) 是该 token 的偏置项。这个公式的读法是:拿第 \(t\) 个位置的隐藏表示 \(H_t\),与“token \(i\) 的读出向量”做一次点积,再加偏置,就得到该 token 在该位置的 logit。

LM Head 与分类头的根本区别在于输出空间。普通分类头通常只需输出 \(C\) 个类别分数;LM Head 则要在每个位置输出 \(V\) 个分数,而 \(V\) 往往达到几万甚至几十万。因此,LM Head 本质上是“逐位置的大规模多分类器”:每一步都在问“下一个 token 应该是词表中的哪一个”。

同一个 LM Head 公式,在不同 Transformer 架构里的使用方式并不相同。对 Encoder-only 模型,LM Head 通常服务于掩码语言建模:模型先用双向注意力得到各位置隐藏状态,再只在被遮蔽的位置上读取 \(Z_{t,:}\) 来预测原 token;这一过程通常是一次性编码,不涉及自回归生成,也没有 KV Cache 逐步增长的问题。对 Decoder-only 模型,LM Head 用于 next-token 预测:第 \(t\) 个位置的隐藏状态对应预测 \(x_{t+1}\),推理时会逐步生成,因此会配合因果注意力(Causal Self-Attention)和 KV Cache。对 Encoder-Decoder 模型,LM Head 位于解码器一侧:编码器先产出源序列表示,解码器再在因果自注意力与交叉注意力(Cross-Attention)的共同作用下生成目标侧隐藏状态,最后由 LM Head 映射到词表。

训练时,自回归语言模型(Autoregressive Language Model)通常采用 next-token 目标:第 \(t\) 个位置的隐藏状态 \(H_t\) 用来预测真实的下一个 token \(x_{t+1}\)。对应损失可写成:

\[\mathcal{L}_{\mathrm{LM}}=-\sum_{t=1}^{L-1}\log \frac{\exp(Z_{t,x_{t+1}})}{\sum_{i=1}^{V}\exp(Z_{t,i})}\]

这个损失公式也可以逐项拆开理解。左边的 \(\mathcal{L}_{\mathrm{LM}}\) 是整段序列的语言模型损失;求和下标 \(t=1,\dots,L-1\) 表示:前 \(L-1\) 个位置都要各自预测一次下一个 token。分子里的 \(\exp(Z_{t,x_{t+1}})\) 表示“真实下一个 token 在第 \(t\) 个位置对应的指数化分数”;这里 \(x_{t+1}\) 是真实的下一个 token id,所以 \(Z_{t,x_{t+1}}\) 表示在位置 \(t\) 对这个真实 token 的 logit。分母 \(\sum_{i=1}^{V}\exp(Z_{t,i})\) 则把整张词表所有候选 token 的分数全部加起来做归一化。因此整个分式就是“在位置 \(t\) 预测真实下一个 token 的概率”,外面的负对数再把它变成训练损失。

推理时则不是直接输出标签,而是先对 \(Z_{t,:}\) 做 softmax 得到下一个 token 的条件分布。这里的 \(Z_{t,:}\) 不是一个标量,而是长度为 \(V\) 的向量,包含位置 \(t\) 对整张词表每个 token 的分数。对这整行做 softmax 后,得到的是:

\[p(x_{t+1}=i\mid x_{\le t})=\frac{e^{Z_{t,i}}}{\sum_{j=1}^{V}e^{Z_{t,j}}},\qquad i=1,\dots,V\]

这条式子表示:在已经看到前缀 \(x_{\le t}\) 的条件下,下一个 token 取词表中第 \(i\) 个词的概率是多少。随后再配合贪心搜索(Greedy Decoding)、束搜索(Beam Search)、温度采样(Temperature Sampling)、top-k / top-p 等策略,从这组概率中选出真正生成的 token。也就是说,LM Head 负责把隐藏表示变成“词表级候选分数”,真正的文本生成还要再经过一层解码(Decoding)策略。

很多 LLM 还会使用权重共享(Weight Tying):把输入嵌入表 \(E\in\mathbb{R}^{V\;\times d_{\text{model}}}\) 与输出头绑定,使 \(W_{\text{vocab}}=E^\top\)。这样一来,输入端“一个 token 的向量表示”与输出端“一个 token 作为候选答案时的原型向量”共用同一套参数空间。它通常既能减少参数量,也让输入和输出语义空间保持更强一致性。

从工程角度看,LM Head 往往比分类头更贵,因为它直接与词表大小 \(V\) 成正比:词表越大,最后一层的矩阵乘法、softmax 和采样都越重。因此,大模型的推理优化常会专门围绕 LM Head 展开,例如 fused softmax、采样优化、logits processor、词表裁剪或 speculative decoding 等。本质上,这些优化都在解决同一个问题:如何更高效地从词表 logits 走到最终生成 token。

序列标注头(Token Classification)

序列标注(Sequence Labeling)/Token 分类(Token Classification)要求对每个 token 预测一个标签(例如 NER)。设主干输出 \(H\in\mathbb{R}^{L\times d}\)(长度 \(L\),隐藏维 \(d\)),则逐 token 线性头为:

\[Z=HW^\top+\mathbf{1}b^\top,\quad W\in\mathbb{R}^{C\times d},\ Z\in\mathbb{R}^{L\times C}\]

对第 \(t\) 个 token,用 softmax 得到 \(p(y_t|x)\) 并用逐 token 交叉熵训练。该做法把每个位置的标签看作条件独立,能工作,但会忽略标签之间的结构约束(例如 BIO 体系中不允许 I-ORG 紧跟 O)。

例:对 “Apple Inc. is in California” 的 NER(Named Entity Recognition),合理标签序列可能是 B-ORG I-ORG O O B-LOC。若逐 token softmax 独立预测,模型可能输出不合法的组合;这类“结构错误”通常需要结构化任务头(Structured Head)来显式建模。

条件随机场(CRF)

线性链条件随机场(Linear-chain Conditional Random Field, CRF)在 token 分类头上增加一个转移矩阵(Transition Matrix)\(A\in\mathbb{R}^{C\times C}\),对整段标签序列做归一化建模。令发射分数(Emission Score)为 \(s_t(y)=Z_{t,y}\),则序列 \(y_{1:L}\) 的总分为:

\[\mathrm{score}(x,y)=\sum_{t=1}^{L}\Big(A_{y_{t-1},y_t}+s_t(y_t)\Big)\]

并定义条件概率:

\[p(y|x)=\frac{\exp(\mathrm{score}(x,y))}{\sum_{y'}\exp(\mathrm{score}(x,y'))}\]

训练最小化负对数似然(Negative Log-Likelihood);解码用 Viterbi 算法(动态规划)求 \(\arg\max_y \mathrm{score}(x,y)\)。CRF 的收益是把“标签合法性/连贯性”学进转移项,从而显著减少结构错误。

双仿射头(Biaffine)

双仿射(Biaffine)任务头常用于“成对打分”(Pairwise Scoring),例如依存句法(Dependency Parsing)里的“当前词应依附到哪个词”,或关系抽取(Relation Extraction)里的“两个实体之间是否存在某种关系”。它的名字可以按层级直接理解:对一个变量, \(Wx\) 是线性, \(Wx+b\) 是仿射;对两个变量, \(h_i^\top U h_j\) 是双线性(Bilinear);在这个双线性项之外再加上线性项和偏置项,就得到双仿射(Biaffine)。因此,双仿射的本质是:既建模两个表示之间的交互,又保留各自单独的角色偏好。

\[s(i,j)=h_i^\top U h_j + w^\top [h_i;h_j] + b\]

这条式子可以逐项拆开读。 \(h_i,h_j\in\mathbb{R}^{d}\) 是两个待配对对象的表示向量;在依存句法里,它们可分别表示“当前词”和“候选 head”;在关系抽取里,它们可分别表示“实体 1”和“实体 2”。 \(U\in\mathbb{R}^{d\times d}\) 是双线性参数矩阵,因此 \(h_i^\top U h_j\) 建模的是二者之间的交互强度:不是只看 \(h_i\) 自己,也不是只看 \(h_j\) 自己,而是看“这两个向量放在一起是否匹配”。把它展开后就是 \(\sum_{p=1}^{d}\sum_{q=1}^{d}(h_i)_p\,U_{pq}\,(h_j)_q\),因此 \(U_{pq}\) 可以理解为“第 \(p\) 个 dependent 特征与第 \(q\) 个 head 特征同时出现时,该给多少分”。

若任务需要一次输出多类关系分数,工程实现通常会为每个类别各放一张矩阵 \(U^{(k)}\),或直接使用三阶参数张量。这样不同关系类型就能拥有不同的交互模式,而不必共用同一套 \(U\)。

\([h_i;h_j]\in\mathbb{R}^{2d}\) 表示把两个向量直接拼接; \(w^\top [h_i;h_j]\) 是普通仿射项,可以进一步拆成“只依赖 \(h_i\) 的线性项 + 只依赖 \(h_j\) 的线性项”。它的作用是补充单边信息:即使暂时不看两者之间的乘性交互,某些 token 或实体本身也可能更像 head、更像 dependent,或更像某类关系的一端。最后的 \(b\) 是全局偏置,给整类配对提供一个基线分数。

具象地看, \(h_i^\top U h_j\) 像在问“这两个人之间是否搭得上”, \(w^\top [h_i;h_j]\) 像在问“这两个人各自单独看,是否本来就带某种角色倾向”。把两部分合起来,模型既能利用配对关系,也不会丢掉单个对象自身的类型线索。这正是双仿射通常比纯双线性更稳、更有表达力的原因。

把 \(s(i,j)\) 对所有 \((i,j)\) 组合都算出来,就能形成一个 \(L\times L\) 的分数矩阵;对每个位置 \(i\),再在所有候选 \(j\) 上做 \(\arg\max\) 或 softmax 分类,就能得到“它最可能依附到谁”或“它与谁最可能存在某种关系”。这种头的关键点在于:任务监督信号作用在“对”的层面,而不是单点分类。

解析式 NLP(Analytical NLP)任务选型

解析式 NLP(Analytical NLP)指一类“结构化输出”的语言任务:输出不是一段自由文本,而是标签序列、树或图。这类任务的工程难点通常不在 backbone,而在输出结构约束、标注成本、以及错误后果(例如信息抽取用于合规/风控)。

任务 输出结构 常见任务头 数据/标注成本 蒸馏难度
NER BIO 标签序列 Token 分类;CRF(可选) 中(需要一致的标注规范) 低~中(教师模型能稳定给出 token-level 或 span-level 标签)
DEP(Dependency Parsing) 树(每 token 一个 head) Biaffine / 图解析器(Parser) 高(标注复杂;语言差异大) 中~高(结构约束更强;蒸馏需覆盖长尾句式)
SDP(Semantic Dependency Parsing) 有向图(多 head / 多边) 图结构头(Graph Head) 很高(语义标注成本高) 高(输出空间更大;错误更难用局部规则修正)
多任务与多头

同一个 backbone 可以挂多个任务头(Multi-head / Multi-task):共享表示学习带来数据效率,但不同任务的梯度可能冲突,需要权衡损失权重(Loss Weighting)与采样策略。工程上也常见“同任务多头”:例如同时输出 token 标签与 span 边界,或同时输出检索 embedding 与分类 logits,用不同头对齐不同指标。

反向传播
链式法则与雅可比连乘

反向传播(Backpropagation)本质是链式法则(Chain Rule)在计算图(Computational Graph)上的系统化应用:把最终损失对中间变量的导数沿依赖关系向后传。

固定一个训练样本 \((x,y)\) 后,损失 \(L\) 最终当然可以看成参数 \(\theta\) 的函数;训练时真正要更新的也确实是权重(Weight)。但在计算图里, \(L(\theta)\) 并不是一步直接从 \(\theta\) 跳到损失,而是先经过各层线性变换、激活值(Activation)和输出再到损失。因此,反向传播会先求 \(\frac{\partial L}{\partial h_l}\) 这类“损失对中间激活值的敏感度”,再由这些中间梯度继续求出 \(\frac{\partial L}{\partial \theta_l}\)。

Jacobian 一节已经给出局部线性化:若 \(h_{l+1}=f_l(h_l)\),则在当前点附近有 \(dh_{l+1}\approx J_l\,dh_l\),其中 \(J_l=\frac{\partial h_{l+1}}{\partial h_l}\)。这条式子描述的是输入扰动如何向前传到输出扰动;反向传播关心的是相反方向的问题:输出端的损失敏感度如何传回输入端。

先看一层。由于损失 \(L\) 是标量,若采用与前文 Jacobian 一致的分子布局(Numerator Layout),把 \(\frac{\partial L}{\partial h_l}\) 记成 \(1\times d_l\) 的行向量,则向量链式法则写成:

\[\frac{\partial L}{\partial h_l}=\frac{\partial L}{\partial h_{l+1}}\frac{\partial h_{l+1}}{\partial h_l}=\frac{\partial L}{\partial h_{l+1}}J_l\]

这条式子的维度是完全对齐的: \(\frac{\partial L}{\partial h_{l+1}}\in\mathbb{R}^{1\times d_{l+1}}\), \(J_l\in\mathbb{R}^{d_{l+1}\times d_l}\),所以结果落回 \(\mathbb{R}^{1\times d_l}\)。含义也很直接:先知道损失对当前层输出各分量有多敏感,再乘上该层的局部线性映射,就得到损失对该层输入各分量的敏感度。

把这条一层公式沿网络递推展开,对深度网络 \(h_{l+1}=f_l(h_l)\) 可得:

\[\frac{\partial L}{\partial h_0}=\frac{\partial L}{\partial h_L}J_{L-1}J_{L-2}\cdots J_0,\qquad J_l=\frac{\partial h_{l+1}}{\partial h_l}\]

这条公式的读法非常具体:前向传播按 \(h_0\to h_1\to\cdots\to h_L\) 计算;反向传播则从最终梯度 \(\frac{\partial L}{\partial h_L}\) 出发,依次乘上最后一层到第一层的 Jacobian,把敏感度一层层传回去。矩阵乘法满足结合律(Associativity),因此可以逐层累积;但不满足交换律,乘法顺序不能改,因为每个 Jacobian 都对应不同层的局部坐标变换。

一个最小可算例可以把这件事完全写开。设输入 \(x\) 是标量,第一层有两个参数 \(w_{11},w_{12}\),输出二维隐藏表示:

\[h_1=\begin{bmatrix}h_{1,1}\\h_{1,2}\end{bmatrix}=\begin{bmatrix}w_{11}x\\w_{12}x\end{bmatrix}\]

第二层有两个参数 \(w_{21},w_{22}\),把二维隐藏表示读成一个标量预测:

\[\hat y=w_{21}h_{1,1}+w_{22}h_{1,2}\]

损失取最简单的平方损失(Squared Loss):

\[L=\frac12(\hat y-y)^2\]

这里总参数一共四个,但反向传播不会直接去“猜” \(\frac{\partial L}{\partial w_{11}}\)、 \(\frac{\partial L}{\partial w_{12}}\) 等结果,而是先沿着计算图写出中间量:

\[x\ \longrightarrow\ h_1\ \longrightarrow\ \hat y\ \longrightarrow\ L\]

先看第二层的局部 Jacobian。因为 \(\hat y\) 是标量、 \(h_1\in\mathbb{R}^2\),所以

\[J_1=\frac{\partial \hat y}{\partial h_1}=\begin{bmatrix}w_{21}&w_{22}\end{bmatrix}\]

再看第一层的局部 Jacobian。因为 \(h_1\in\mathbb{R}^2\)、 \(x\) 是标量,所以

\[J_0=\frac{\partial h_1}{\partial x}=\begin{bmatrix}w_{11}\\w_{12}\end{bmatrix}\]

损失对最终输出的导数最容易先算:

\[\frac{\partial L}{\partial \hat y}=\hat y-y\]

于是,损失对隐藏表示的梯度由链式法则得到:

\[\frac{\partial L}{\partial h_1}=\frac{\partial L}{\partial \hat y}\frac{\partial \hat y}{\partial h_1}=(\hat y-y)\begin{bmatrix}w_{21}&w_{22}\end{bmatrix}\]

这一步已经把“损失对输出的敏感度”传回到了中间激活值 \(h_1\)。继续往回乘第一层 Jacobian,就得到损失对输入的梯度:

\[\frac{\partial L}{\partial x}=\frac{\partial L}{\partial \hat y}J_1J_0\] \[=(\hat y-y)\begin{bmatrix}w_{21}&w_{22}\end{bmatrix}\begin{bmatrix}w_{11}\\w_{12}\end{bmatrix}\] \[=(\hat y-y)(w_{21}w_{11}+w_{22}w_{12})\]

对参数的梯度也是同样的思路。第二层参数直接作用在 \(\hat y\) 上,因此

\[\frac{\partial L}{\partial w_{21}}=\frac{\partial L}{\partial \hat y}\frac{\partial \hat y}{\partial w_{21}}=(\hat y-y)h_{1,1}\] \[\frac{\partial L}{\partial w_{22}}=\frac{\partial L}{\partial \hat y}\frac{\partial \hat y}{\partial w_{22}}=(\hat y-y)h_{1,2}\]

第一层参数不直接连到损失,而是先影响 \(h_1\),再影响 \(\hat y\) 和 \(L\),所以必须经过中间激活值这一站:

\[\frac{\partial L}{\partial w_{11}}=\frac{\partial L}{\partial h_{1,1}}\frac{\partial h_{1,1}}{\partial w_{11}}=[(\hat y-y)w_{21}]\,x\] \[\frac{\partial L}{\partial w_{12}}=\frac{\partial L}{\partial h_{1,2}}\frac{\partial h_{1,2}}{\partial w_{12}}=[(\hat y-y)w_{22}]\,x\]

若取一组具体数值 \(x=2\)、 \(y=1\)、 \(w_{11}=1\)、 \(w_{12}=-1\)、 \(w_{21}=0.5\)、 \(w_{22}=2\),则前向传播先得到

\[h_1=\begin{bmatrix}2\\-2\end{bmatrix},\qquad \hat y=0.5\cdot 2+2\cdot(-2)=-3,\qquad \frac{\partial L}{\partial \hat y}=\hat y-y=-4\]

于是反向传播依次得到

\[\frac{\partial L}{\partial h_1}=-4\begin{bmatrix}0.5&2\end{bmatrix}=\begin{bmatrix}-2&-8\end{bmatrix}\] \[\frac{\partial L}{\partial x}=\begin{bmatrix}-2&-8\end{bmatrix}\begin{bmatrix}1\\-1\end{bmatrix}=6\] \[\frac{\partial L}{\partial w_{21}}=-4\cdot 2=-8,\qquad \frac{\partial L}{\partial w_{22}}=-4\cdot(-2)=8\] \[\frac{\partial L}{\partial w_{11}}=(-2)\cdot 2=-4,\qquad \frac{\partial L}{\partial w_{12}}=(-8)\cdot 2=-16\]

这个最小例子把反向传播的结构完整展示了出来:损失函数最终是参数的函数,但梯度并不是“绕开中间层直接对权重求”。它必须先通过 \(\frac{\partial L}{\partial \hat y}\)、 \(\frac{\partial L}{\partial h_1}\) 这样的中间敏感度逐步回传。激活值因此不是“额外引入的变量”,而是计算图中必经的节点。

若改用深度学习里更常见的列向量梯度记号 \(\nabla_{h_l}L\in\mathbb{R}^{d_l}\),同一件事会写成

\[\nabla_{h_l}L=J_l^\top \nabla_{h_{l+1}}L\]

这与上面的公式没有本质区别,只是把“左乘 Jacobian 的行向量记号”改写成了“右侧乘 Jacobian 转置的列向量记号”。工程实现里常见的 Vector-Jacobian Product,本质上就是这一步。

对参数的梯度也是同一个模式。若第 \(l\) 层含参数 \(\theta_l\),则

\[\frac{\partial L}{\partial \theta_l}=\frac{\partial L}{\partial h_{l+1}}\frac{\partial h_{l+1}}{\partial \theta_l}\]

因此 backward 的核心不是“把前向再算一遍”,而是复用每一层的局部 Jacobian,把同一个上游梯度分别传给输入变量和参数。

梯度消失与爆炸

梯度消失(Vanishing Gradients)与梯度爆炸(Exploding Gradients)通常来自连乘的数值尺度:若这些雅可比的有效增益(Effective Gain)的奇异值(Singular Values)长期小于 1,则梯度指数级衰减;长期大于 1 则指数级放大。

在 RNN 的 BPTT 中,这种现象尤其明显:同一递归矩阵在时间轴上重复相乘。粗略地看,若 \(W_{hh}\) 的谱半径(Spectral Radius)\(\rho(W_{hh})\) 明显大于 1,梯度更易爆炸;明显小于 1 更易消失。但这不是“只要 \(\lambda>1\) 就一定爆炸”的二选一结论,因为实际还受到激活函数导数、归一化、残差/门控结构、以及数据分布的共同影响。

“梯度随训练慢慢变小是否正常?”在接近最优点时,梯度范数下降是预期现象;需要警惕的是训练早期就出现系统性消失(例如大量饱和激活导致导数接近 0)或出现不稳定爆炸(loss/梯度频繁变成 NaN/Inf)。

常见应对:

  • 梯度裁剪(Gradient Clipping):抑制爆炸。
  • 合理初始化(Xavier/He)、归一化(BatchNorm/LayerNorm)、残差连接(Residual)。
  • 门控结构(Gated Units):LSTM/GRU 通过门控缓解长程梯度问题。
权重初始化

权重初始化(Weight Initialization)的目标不是“随机给一个小数”,而是控制信号在层间传播的数值尺度。设第 \(l\) 层的线性部分为 \(z^{(l)}=W^{(l)}h^{(l-1)}+b^{(l)}\)。若 \(z^{(l)}\) 的二阶原点矩(Second Raw Moment)在层间持续放大,前向激活与反向梯度都会倾向爆炸;若持续衰减,则会出现梯度消失。

对单个神经元,写成 \(z=\sum_{i=1}^{n}w_i x_i+b\)。初始化分析里通常进一步假设 \(w_i\) 与 \(x_i\) 相互独立,且权重满足 \(\mathbb{E}[w_i]=0\)。这里的 \(\mathbb{E}[w_i]=0\) 不是在声称“训练后的权重天然应当均值为 0”,而是在分析初始化时,把权重看作从一个以 0 为中心的随机分布中抽样得到;这样做的目的,是避免网络在一开始就对某一方向产生系统性偏置,并让前向输出的均值计算更干净。基于这一初始化假设,在线性部分有

\[\mathbb{E}[z]=0,\quad \mathbb{E}[z^2]=n\,\mathrm{Var}(w)\,\mathbb{E}[x^2]\]

当输入也近似零均值时, \(\mathbb{E}[x^2]\approx \mathrm{Var}(x)\),于是常写成 \(\mathrm{Var}(z)\approx n\,\mathrm{Var}(w)\,\mathrm{Var}(x)\)。这里 \(n\) 就是 fan_in。因此初始化的核心约束可以概括为:让 \(n\,\mathrm{Var}(w)\) 保持在 1 附近。

更严格地说,深度初始化分析常跟踪的是 \(\mathbb{E}[h^2]\),而不是所有层都精确使用方差;因为经过 ReLU 之后,激活不再零均值,此时二阶原点矩与方差不再完全相同。但在线性层与零均值近似下,两者是一致的,因此“保持方差稳定”仍是准确的工程表述。

两种朴素做法都会失败:若所有权重都初始化为 0,则各神经元保持完全对称,反向传播得到相同更新,网络退化为“许多拷贝的同一个单元”;若直接令 \(\mathrm{Var}(w)=1\),则线性输出的尺度会随层数按 fan_in 连乘,深层网络极易数值失稳。偏置(Bias)通常初始化为 0 或很小的常数;真正决定尺度的是权重矩阵的方差结构。

这里的 fan_in 与 fan_out 可以直接按“这层连接了多少路信号”来理解。对某个线性层中的一个输出神经元,fan_in 是流入它的输入通道数;输入通道越多,很多随机小贡献叠加后,输出就越容易变大。对某个输入神经元,fan_out 是它连接到下一层多少个输出通道;fan_out 越大,这个输入方向上的梯度在反向传播时就会被分发到更多支路。因此,fan_in 主要约束前向激活的放大量级,fan_out 主要约束反向梯度的放大量级。

具象地看,一个神经元像一个汇流节点:fan_in 决定有多少根水管把信号同时灌进来,fan_out 决定这股信号会被分流到多少个下游节点。初始化如果不考虑这两个连接数,网络就会在“汇流过猛”与“分流过弱”之间失衡。Xavier 正是在前向与反向之间做折中,He 则进一步把激活函数本身带来的能量损失也纳入补偿。

Xavier 初始化

Xavier 初始化(Xavier Initialization)也称 Glorot 初始化(Glorot Initialization),针对近似线性的激活工作区间设计,例如 tanh 与 sigmoid 在原点附近的局部线性区域。它的目标是同时控制前向激活与反向梯度的尺度,使它们在穿过每一层时不发生系统性放大或衰减。

若暂时忽略激活函数对二阶原点矩的额外缩放,则前向保持尺度不变要求 \(\mathrm{Var}(w)\approx 1/\mathrm{fan\_in}\);反向对应地要求 \(\mathrm{Var}(w)\approx 1/\mathrm{fan\_out}\)。Glorot 给出的折中形式因此写成:

\[\mathrm{Var}(w)=\frac{2}{\mathrm{fan\_in}+\mathrm{fan\_out}}\]

常见实现包括正态版 \(w\sim\mathcal{N}\!\left(0,\frac{2}{\mathrm{fan\_in}+\mathrm{fan\_out}}\right)\),以及均匀版 \(w\sim U\!\left[-\sqrt{\frac{6}{\mathrm{fan\_in}+\mathrm{fan\_out}}},\sqrt{\frac{6}{\mathrm{fan\_in}+\mathrm{fan\_out}}}\right]\)。

从直觉上看,Xavier 初始化像是在给每一层设置一个“不过度放大、也不过度压缩”的中性增益(neutral gain)。可以把一层线性变换想成一组并联的混音器:输入信号从上一层流入,经过许多权重通道混合后送到下一层。Xavier 的目标就是让这组混音器在初始状态下近似保持“总音量”不变,使信号既不会层层变得越来越吵,也不会层层变得越来越弱。

Xavier 的局限在于:它默认激活函数不会系统性丢失太多能量。对 ReLU 这类半波整流(Half-wave Rectification)激活,这个假设不再成立;即使线性层前后的尺度匹配,经过激活后信号的二阶原点矩仍会明显下降。

He 初始化

He 初始化(He Initialization)也称 Kaiming 初始化(Kaiming Initialization),专门处理 ReLU 家族的整流效应。若线性输出 \(z\) 近似关于 0 对称,经过 \(\mathrm{ReLU}(z)=\max(0,z)\) 后,大约一半的质量被截断为 0,并且

\[\mathbb{E}[\mathrm{ReLU}(z)^2]=\frac{1}{2}\mathbb{E}[z^2]\]

因此,若仍使用 Xavier 量级,信号的二阶原点矩会随层数持续衰减。He 初始化通过把权重方差提高到

\[\mathrm{Var}(w)=\frac{2}{\mathrm{fan\_in}}\]

来补偿这一半波损失。对应实现可写为正态版 \(w\sim\mathcal{N}\!\left(0,\frac{2}{\mathrm{fan\_in}}\right)\),或均匀版 \(w\sim U\!\left[-\sqrt{\frac{6}{\mathrm{fan\_in}}},\sqrt{\frac{6}{\mathrm{fan\_in}}}\right]\)。

具象地看,ReLU 像一道只允许正值通过的闸门:一批近似对称分布的信号经过后,负半边会被直接截成 0,等于天然损失了一部分能量。He 初始化做的事情就是在闸门前把信号预先放大一些,使它通过这道“半波闸门”之后,整体尺度仍能维持在稳定区间。Xavier 假定通道基本不漏能量,He 则明确把 ReLU 的漏损补偿计入初始化方差。

对 Leaky ReLU/PReLU,补偿因子可推广为 \(\frac{2}{(1+a^2)\,\mathrm{fan\_in}}\),其中 \(a\) 是负半轴斜率。实践上,ReLU 及其变体默认优先使用 He 初始化;tanh/sigmoid 更适合 Xavier。归一化层与残差连接可以进一步放宽初始化的容错区间,但不能替代合理的初始尺度控制。

大语言模型里的初始化

Transformer / 大语言模型(Large Language Model, LLM)里的初始化通常不按“整模统一套 Xavier”或“整模统一套 He”来理解,而更像一套围绕残差流(Residual Stream)稳定性、归一化层和深度扩展设计的小方差初始化配方。原因在于:LLM 的主干不是简单的“线性层 + 单一激活函数”堆叠,而是由自注意力、残差连接、LayerNorm / RMSNorm、MLP / SwiGLU 等子结构共同组成;纯粹以某个激活函数为中心推导的 Xavier / He,只能覆盖其中一部分局部直觉。

工程上最常见的做法是:嵌入层与线性层权重用零均值的小方差正态分布初始化,偏置置零或省略;随后依靠 LayerNorm / RMSNorm 与残差结构维持训练初期的数值稳定。BERT、GPT-2 一类经典 Transformer 常见做法是使用标准差约为 \(0.02\) 的正态或截断正态初始化;很多更现代的 Decoder-only LLM 仍延续“小方差高斯初始化”这一主线,只是在具体投影层上再叠加按隐藏维度、层数或残差分支做缩放的配方。

从直觉上看,LLM 初始化更像是在给一条很深的多车道主干道设置初始车流密度。若注意力里的 \(Q/K/V/O\) 投影、FFN 的升维/降维投影以及其他会把结果写回残差流的线性层初始尺度过大,残差分支会把信号越叠越猛,训练初期容易震荡;若尺度过小,几十层上百层残差块叠起来后,真正进入有效学习区的信号又会太弱。因此,现代 LLM 初始化的重点往往不是“严格选 Xavier 还是 He”,而是让残差支路在深层网络中既能传递信息,又不会在训练一开始就把数值尺度推离稳定区。

具体到模块分工,也可以这样理解:MLP 内部若使用 ReLU 家族激活,He 的补偿思想仍然成立;若使用 GELU、SiLU、SwiGLU 这类更平滑或带门控的激活,则实现里往往直接采用统一的小方差正态初始化,再由归一化、残差和训练配方共同保证稳定性。换言之,LLM 并没有抛弃 Xavier / He 背后的“方差守恒”原则,而是把这套原则嵌入到了更完整的 Transformer 初始化策略里。

方法 核心方差 适用激活 主要问题 / 逻辑
零初始化 \(\mathrm{Var}(w)=0\) 无 破坏对称性;所有神经元学到相同特征
标准正态随机 \(\mathrm{Var}(w)=1\) 无 尺度随深度快速放大;易导致爆炸
Xavier / Glorot \(\frac{2}{\mathrm{fan\_in}+\mathrm{fan\_out}}\) Tanh、Sigmoid 兼顾前向与反向尺度;假设激活近似线性
He / Kaiming \(\frac{2}{\mathrm{fan\_in}}\) ReLU、Leaky ReLU 补偿 ReLU 的半波截断;保持二阶原点矩稳定
LLM 常用小方差高斯初始化 常取固定小标准差,或再叠加按宽度 / 深度缩放 Transformer 模块整体 服务残差流、归一化层与深层稳定训练;不是单纯按某一种激活推导
正则化

正则化(Regularization)在经验风险(Empirical Risk)上增加复杂度惩罚,缓解过拟合(Overfitting)。假设函数/模型 \(f_\theta\) 决定预测;样本损失 \(\ell\) 度量单样本误差;代价函数/成本函数 \(L(\theta)\) 汇总训练集误差;目标函数 \(J(\theta)\) 则是 \(L(\theta)\) 加上正则化项: \(J(\theta)=L(\theta)+\lambda\Omega(\theta)\)。

\[J(\theta)=\frac{1}{m}\sum_{i=1}^{m}\ell\!\left(f_{\theta}(x^{(i)}),y^{(i)}\right)+\lambda\Omega(\theta)\]
L1 正则化(Lasso)

L1 正则化(L1 Regularization)使用 \(\Omega(\theta)=\|\theta\|_1\)。它倾向产生稀疏解(Sparsity),即一部分权重被直接压到 0,因此可同时做参数学习和特征选择(Feature Selection)。

从优化角度看,L1 的梯度是次梯度(Subgradient):对单个参数 \(\theta_k\),当 \(\theta_k\ne 0\) 时有 \(\frac{\partial}{\partial \theta_k}\|\theta\|_1=\mathrm{sign}(\theta_k)\);在 0 点是一段区间 \([-1,1]\)。这使得优化过程更容易把小权重“推过 0”,形成精确稀疏。

在很多实现中,会用近端算子(Proximal Operator)给出更清晰的“压到 0”机制:对标量 \(w\),软阈值化(Soft-Thresholding)是

\[\mathrm{soft}(w,\alpha)=\mathrm{sign}(w)\max(|w|-\alpha,0)\]

当 \(|w|\le \alpha\) 时直接变为 0。

L2 正则化(Ridge / Weight Decay)

L2 正则化(L2 Regularization)使用 \(\Omega(\theta)=\|\theta\|_2^2\)。它倾向均匀缩小参数,但通常不会把参数精确压到 0。直观上,L1 在 0 点不可导,更容易触发“阈值化”解;L2 是光滑二次惩罚,更新更连续。

梯度层面,L2 会在原梯度上叠加一个“拉回原点”的项:若目标为 \(\ell(\theta)+\lambda\|\theta\|_2^2\),则 \(\nabla_\theta=\nabla \ell(\theta)+2\lambda\theta\)。工程上常把这个效果称为权重衰减(Weight Decay):每一步都把权重按比例缩小。

需要区分一个常见细节:在自适应优化器(如 Adam)里,“把 \(\lambda\|\theta\|_2^2\) 加到损失里”与“直接做 weight decay”在数值上并不完全等价;因此实践中常用解耦权重衰减(Decoupled Weight Decay,典型实现是 AdamW)来获得更可控的正则化行为。

regularization-l1-l2-geometry

把带惩罚的目标改写成约束形式后,几何差异会非常直观: \(\min_\theta L(\theta)\ \mathrm{s.t.}\ \|\theta\|_1\le t\) 的可行域在二维里是菱形, \(\min_\theta L(\theta)\ \mathrm{s.t.}\ \|\theta\|_2\le t\) 的可行域则是圆盘。损失等高线从外向内收缩时,第一次接触 \(L_1\) 边界,往往更容易落在角点;角点恰好对应某些坐标精确等于 0。 \(L_2\) 边界处处光滑,接触点通常只是把所有坐标一起缩小,而不是把其中一部分直接压成 0。

从一维更新机制看,这个差异也对应两种不同的收缩方式。 \(L_2\) 更像连续比例收缩:权重越大,拉回原点的力越强,但通常不会在有限步内变成精确 0。 \(L_1\) 则对应软阈值化(Soft-Thresholding):一旦 \(|w|\) 小于阈值,就会被直接压成 0。因此, \(L_1\) 不只是“把权重变小”,而是会主动把一部分坐标从模型中删掉,这就是稀疏性(Sparsity)的来源。

Dropout

Dropout 通过随机屏蔽部分神经元输出,减少共适应(Co-adaptation),等价于在训练时对网络做一种随机子网络集成(Ensemble)。这里的共适应,是指若干神经元彼此形成了固定搭配:模型过度依赖它们同时出现、按特定组合共同完成判断,而不是让每个单元都学到相对独立、稳健的特征。Dropout 随机拿掉其中一部分单元后,网络不能再把能力押注在某一组固定配合上,只能把有用模式分散到更稳健的表示里。令隐藏向量为 \(h\),mask \(m_i\sim \mathrm{Bernoulli}(p)\),常见的 inverted dropout 写法为:

\[\tilde h = \frac{m\odot h}{p}\]

其中 \(p\) 是保留概率(Keep Probability)。这样推理时可直接使用原网络(不再采样 mask),避免额外缩放。

Batch Normalization

Batch Normalization(BatchNorm)在训练时用 mini-batch 的均值/方差做归一化,并学习缩放/平移参数。对特征维上的某个分量 \(x\),典型形式是:

\[\mathrm{BN}(x)=\gamma\cdot \frac{x-\mu_{\text{batch}}}{\sqrt{\sigma_{\text{batch}}^2+\epsilon}}+\beta\]

推理阶段通常使用训练过程累积的运行均值(Running Mean)与运行方差(Running Variance),因此训练/推理行为不同。BatchNorm 在 CNN 中极常见,因为卷积特征图在同一通道上的空间位置具有较强同质性,跨样本统计量较容易稳定;但在 Transformer 中,主流做法并不是沿 batch 维做归一化,而是使用与 batch 统计无关的 LayerNorm 或 RMSNorm。

原因在于 Transformer 的基本计算单元是 token 表示。序列长度常常可变,batch size 在训练与推理中也经常变化,尤其大模型训练会受到显存限制而使用较小、波动甚至分布式切分后的 micro-batch。若使用 BatchNorm,某个 token 的归一化结果会显式依赖同一 batch 中其他样本与其他位置的统计量,这会引入跨样本耦合,使训练和推理的数值语义不一致,也不利于自回归解码阶段逐 token 稳定生成。

Layer Normalization

Layer Normalization(LayerNorm)对每个样本(或每个 token)的特征维做归一化,不依赖 batch 统计量,因此更适合变长序列与自回归推理。对向量 \(x\in\mathbb{R}^{d}\):

\[\mathrm{LN}(x)=\gamma\odot \frac{x-\mu}{\sqrt{\sigma^2+\epsilon}}+\beta,\quad \mu=\frac{1}{d}\sum_{i=1}^{d}x_i,\ \sigma^2=\frac{1}{d}\sum_{i=1}^{d}(x_i-\mu)^2\]

这里的均值 \(\mu\) 与方差 \(\sigma^2\) 都只在当前样本、当前 token 的特征维内部计算,因此每个 token 都能独立完成归一化。这个性质与 Transformer 的残差流(Residual Stream)非常匹配:无论 batch 如何变化、序列如何裁剪、推理时是否一次只输入一个 token,归一化规则都保持一致。

当前主流的 Transformer 归一化实践可以概括为两类。Encoder-only 与很多 Vision Transformer(ViT)架构通常沿用 LayerNorm;Decoder-only 大语言模型(Large Language Model, LLM)则大量采用 Pre-Norm 残差块,并进一步把 LayerNorm 简化为 RMSNorm。前者保留去均值与方差缩放,后者只保留尺度归一化,计算更轻,也更适合超大规模训练。

Early Stopping

Early Stopping 用验证集指标监控训练过程,在泛化性能不再提升时提前停止,从而避免在训练集上继续拟合噪声。工程上常用“耐心(Patience)”:若验证集指标连续 \(K\) 次评估都未改善,则停止训练并回滚到最佳 checkpoint。它属于训练流程级的隐式正则化(Implicit Regularization)。

卷积神经网络(CNN)
卷积层与池化层

卷积(Convolution)在连续形式下定义为函数重叠积分:

\[(f*g)(t)=\int_{-\infty}^{+\infty} f(\tau)\,g(t-\tau)\,d\tau\]

在离散二维图像中常写为:

\[(I*K)(i,j)=\sum_m\sum_n I(i-m,j-n)\,K(m,n)\]

深度学习框架里多数“卷积层”实现的是互相关(Cross-Correlation)而非严格翻转核的数学卷积,但工程上沿用“卷积”命名。卷积核(Kernel)共享权重(Weight Sharing),天然利用局部性(Locality)与平移等变(Translation Equivariance)。

直观上,卷积层做的事情是:对每个位置取一个局部窗口,把窗口里的像素与卷积核做加权求和,得到该位置的响应。不同卷积核学习不同的局部模式(边缘、纹理、角点等)。

一维互相关示例:输入 \(x=[0,0,1,1,1,0,0]\),核 \(w=[1,0,-1]\),则在从左到右滑动时,核会对“上升沿/下降沿”给出大幅响应(本质上是比较左右两侧的差异)。这就是经典的边缘检测直觉在离散信号上的对应。

卷积的“系统视角”能统一理解 CNN 与信号处理:把卷积核看作响应函数(Response Kernel),输出就是对历史输入的加权累积。参见“微积分 -> 卷积(Convolution)”中的因果卷积与“打点滴累积药效”直觉例子。

经典架构
LeNet

LeNet 可以看作现代卷积神经网络(Convolutional Neural Network, CNN)的原型。它面对的是手写数字识别这类“局部笔画决定整体类别”的任务,因此核心思想很直接:先用卷积层提取局部边缘、角点和笔画,再用池化(Pooling)降低分辨率与局部扰动敏感性,最后把高层特征送入全连接层做分类。

经典 LeNet-5 的结构可以概括为“卷积 - 池化 - 卷积 - 池化 - 全连接”。前面的卷积层负责把原始像素变成越来越抽象的特征图(Feature Map),后面的全连接层负责把这些局部特征整合成类别判断。它的重要性不只是“识别数字有效”,更在于证明了三件事可以协同工作:局部感受野(Local Receptive Field)、权重共享(Weight Sharing)和层级特征提取(Hierarchical Feature Learning)。

卷积层里的一个典型计算是:

\[y_{i,j}^{(k)}=\sum_{u}\sum_{v}\sum_{c} W_{u,v,c}^{(k)}\,x_{i+u,j+v,c}+b^{(k)}\]

这里 \(x\) 是输入图像或上一层特征图, \(W^{(k)}\) 是第 \(k\) 个卷积核, \(c\) 是输入通道索引, \((i,j)\) 是空间位置, \(y_{i,j}^{(k)}\) 是输出特征图在该位置上的响应。这个公式表达的就是:用同一个卷积核在整张图上滑动,寻找“哪里出现了我关心的局部模式”。

训练上,LeNet 已经体现出现代深度学习的基本闭环:前向传播得到类别 logits,损失函数衡量预测与真实标签的差距,反向传播把梯度传回卷积核和全连接层参数,再用梯度下降更新权重。它最典型的应用是 MNIST 手写数字识别,也常被用作理解 CNN 的第一块教学样板,因为结构短、计算图清晰、局部模式学习的直觉非常强。

AlexNet

AlexNet 标志着深度卷积网络在大规模视觉识别上的突破。它面对的不是手写数字这种相对简单的灰度图,而是 ImageNet 级别的彩色自然图像,因此核心思想从“能提特征”进一步推进到“更深、更宽、更可训练”:增加网络容量,用 ReLU(Rectified Linear Unit)加快优化,用 Dropout 缓解过拟合,用数据增强提升泛化,再借助 GPU 让大模型真正训得动。

其典型结构是多层卷积堆叠后接全连接层,早期卷积核较大、步幅较大,用于迅速降采样并提取低层纹理;中后期卷积核变小,重点转向更细粒度的组合特征。AlexNet 还使用了局部响应归一化(Local Response Normalization, LRN)这一今天较少使用、但在当时有历史意义的设计。整体上,它把 CNN 从“可用于小型任务的模型”推向了“可以在大规模视觉基准上碾压传统方法的通用架构”。

它最有代表性的非线性是 ReLU:

\[\mathrm{ReLU}(z)=\max(0,z)\]

其中 \(z\) 是线性层或卷积层的输出。与 sigmoid / tanh 相比,ReLU 在正半轴不饱和,梯度传播更直接,因此深层网络更容易优化。AlexNet 的历史意义之一,就是把“激活函数的选择会显著影响深网络可训练性”这件事变成了工程共识。

训练上,AlexNet 典型地结合随机裁剪、翻转、颜色扰动等数据增强,并在全连接层使用 Dropout。它的直接应用是大规模图像分类;更深远的影响则是推动了整个视觉领域转向“预训练 CNN + 迁移学习”的工作流。很多后续检测、分割与检索系统,都曾把 AlexNet 当作特征提取骨干网络(Backbone)。

VGG

VGG 的核心思想是:用结构极其规整的小卷积核反复堆叠,把网络做深。它放弃了早期“大卷积核 + 大步幅”的粗放设计,转而几乎全程使用 \(3\times 3\) 卷积,通过增加层数来扩大感受野、提高非线性表达能力,并让整套架构在工程上更统一、更易复用。

VGG 的典型结构非常整齐:若干个 \(3\times 3\) 卷积层组成一个 stage,stage 之间通过池化层下采样,最后再接全连接分类头。它的重要工程思想是“深度本身就是能力来源之一”。相较于更杂糅的早期网络,VGG 的层次感非常强:浅层提边缘和纹理,中层提局部部件,高层提更完整的语义结构。

为什么反复使用 \(3\times 3\) 卷积有效,可以从感受野和参数量两方面理解。两个连续的 \(3\times 3\) 卷积,其有效感受野接近一个 \(5\times 5\) 卷积,但中间多了一次非线性变换,参数量通常还更少。若忽略通道数变化,单层 \(5\times 5\) 卷积大约有 25 个核参数,而两层 \(3\times 3\) 卷积一共是 18 个核参数。

训练上,VGG 比 AlexNet 更依赖较好的初始化、较强的正则化和更大的算力预算,因为它的参数量尤其在全连接部分非常大。它的直接应用是图像分类,但工程上更著名的是作为“通用视觉特征提取器”:在风格迁移、感知损失(Perceptual Loss)、检测与分割早期系统中,VGG 特征长期是强基线。它的代价也很明显:参数多、推理重、显存占用高,这直接推动了后续更高效架构的出现。

ResNet

ResNet(Residual Network)的关键突破不是再把卷积堆得更深,而是重新设计“深层网络应该学什么”。它提出残差学习(Residual Learning):一层或一组层不必直接学习完整映射 \(H(x)\),而是学习相对于输入的增量 \(F(x)=H(x)-x\)。这样网络输出就写成:

\[y=F(x)+x\]

这里 \(x\) 是块输入, \(F(x)\) 是若干卷积层、归一化和激活组成的残差分支输出, \(y\) 是该残差块的最终输出。若最优映射本身就接近恒等映射(Identity Mapping),那么让网络学习“只改一点点”通常比“从零重建整个映射”更容易优化。

具象地看,普通深网络像要求每一层都重新写一遍完整答案;ResNet 则允许每一层在原答案旁边写批注:需要修改的地方补上增量,不需要改的地方直接走捷径。这个“捷径连接(Skip Connection)”让梯度能沿更短路径传播,因此网络深到几十层、上百层时仍可训练。ResNet 解决的核心不是表达能力不足,而是深层优化退化(Degradation)问题:层数增加后,训练误差反而上升。

训练上,ResNet 通常结合 BatchNorm、较深的 stage 结构和全局平均池化(Global Average Pooling)来替代庞大的全连接头。它在图像分类上大获成功后,很快成为检测、分割、关键点、视频理解等视觉任务的主流骨干网络。更深远的影响是:残差连接后来成为 Transformer、扩散模型和许多现代深网络的标准部件,因为它本质上是在为深层优化建立稳定的信息主通路。

循环神经网络(RNN)
RNN

循环神经网络(Recurrent Neural Network, RNN)按时间步(Time Step)处理序列。第 \(t\) 个时刻输入是 \(x_t\),隐藏状态(Hidden State)递推为:

\[h_t=\phi(W_{xh}x_t+W_{hh}h_{t-1}+b_h),\quad y_t=W_{hy}h_t+b_y\]

\(W_{xh}\)(输入到隐层)与 \(W_{hh}\)(隐层到隐层)在所有时刻共享,这是 RNN 能在变长序列上泛化的关键。

把它展开(Unroll)到时间轴上会更直观:同一套参数在每个时间步重复使用,形成一个深度为 \(T\) 的计算图。这也是 RNN 训练常说的“通过时间的反向传播(Backpropagation Through Time, BPTT)”。

RNN 的经典难点是梯度消失/爆炸(Vanishing/Exploding Gradients):反向传播时会反复乘以 \(W_{hh}\) 的雅可比,从而导致梯度范数指数级衰减或增长。LSTM/GRU 通过门控(Gating)与更“线性”的记忆通道缓解这一问题。

Seq2Seq(Sequence-to-Sequence)是任务范式,不限定具体单元。早期 Seq2Seq 常由 RNN/LSTM/GRU 的编码器-解码器(Encoder-Decoder)实现;后续被 Transformer 大规模替代。

“乘法 + 加法 + 非线性”为何有效:线性变换负责特征重表达,非线性激活(Nonlinearity)提供函数逼近能力,时间递推提供记忆路径,三者叠加形成高表达力。

LSTM

LSTM(Long Short-Term Memory)是为了解决普通 RNN 难以稳定保留长程信息的问题而设计的门控循环结构。它的核心思想不是简单把隐藏状态不断往前传,而是显式维护一个记忆单元(Cell State) \(c_t\),并用门控决定“忘掉什么、写入什么、读出什么”。这使得序列中的关键信息可以沿着一条更接近线性的通道向后传播,而不必在每个时间步都被强非线性反复改写。

LSTM 的典型更新写成:

\[f_t=\sigma(W_f x_t+U_f h_{t-1}+b_f),\quad i_t=\sigma(W_i x_t+U_i h_{t-1}+b_i)\] \[\tilde c_t=\tanh(W_c x_t+U_c h_{t-1}+b_c),\quad c_t=f_t\odot c_{t-1}+i_t\odot \tilde c_t\] \[o_t=\sigma(W_o x_t+U_o h_{t-1}+b_o),\quad h_t=o_t\odot \tanh(c_t)\]

其中 \(x_t\) 是当前输入, \(h_{t-1}\) 是前一时刻隐藏状态, \(c_{t-1}\) 是前一时刻记忆单元; \(f_t\) 是遗忘门(Forget Gate),控制旧记忆保留多少; \(i_t\) 是输入门(Input Gate),控制当前候选记忆 \(\tilde c_t\) 写入多少; \(o_t\) 是输出门(Output Gate),控制当前记忆暴露给隐藏状态多少; \(\sigma\) 是 sigmoid,把门值压到 \((0,1)\) 区间; \(\odot\) 是逐元素乘法。

具象地看,LSTM 像一条带阀门的记忆水管。普通 RNN 每走一步都把旧信息和新输入一锅重拌,长距离信息容易被冲淡;LSTM 则允许旧记忆沿主管道直接往后流,同时用三个阀门分别控制“放掉旧水”“注入新水”“输出多少”。这正是它能比普通 RNN 更稳定地记住长距离依赖的原因。

训练上,LSTM 仍然通过时间反向传播(BPTT)学习参数,但门控结构显著改善了梯度流。它曾长期是机器翻译、语音识别、语言建模、时间序列预测和序列标注的主力模型。在 Transformer 出现之前,大量 Seq2Seq 系统都建立在双向 LSTM 或多层 LSTM 之上;在某些中小规模时序任务里,LSTM 今天仍然是强而稳的基线。

GRU

GRU(Gated Recurrent Unit)可以看作 LSTM 的简化版本。它保留了“用门控控制信息保留与更新”的核心思想,但把记忆单元与隐藏状态合并,不再单独维护 \(c_t\),从而用更少参数换取更紧凑的结构与更快的训练速度。

GRU 的一组典型公式是:

\[z_t=\sigma(W_z x_t+U_z h_{t-1}+b_z),\quad r_t=\sigma(W_r x_t+U_r h_{t-1}+b_r)\] \[\tilde h_t=\tanh(W_h x_t+U_h(r_t\odot h_{t-1})+b_h)\] \[h_t=(1-z_t)\odot h_{t-1}+z_t\odot \tilde h_t\]

这里 \(z_t\) 是更新门(Update Gate),决定旧状态保留多少、新候选状态写入多少; \(r_t\) 是重置门(Reset Gate),决定在构造候选状态 \(\tilde h_t\) 时,历史信息应当被参考到什么程度。若 \(z_t\) 很小,模型更倾向保留旧记忆;若很大,模型更倾向用新信息刷新状态。

从直觉上看,GRU 把 LSTM 的三道阀门压缩成两道更紧凑的控制逻辑:一方面决定“要不要更新”,另一方面决定“生成候选更新时要不要忘掉旧状态的一部分”。这让它在很多任务上能以更少参数达到与 LSTM 相近的效果,尤其适合数据量不极大、模型容量受限或推理效率敏感的场景。

训练上,GRU 与 LSTM 一样使用 BPTT。应用上,它常见于语音、时序预测、较轻量的编码器-解码器模型,以及很多工业界的表格时间序列任务。若需要更强的显式记忆控制,LSTM 往往更稳;若更看重结构简洁和训练效率,GRU 常是更自然的选择。

生成模型

生成模型(Generative Model)关注的核心问题不是“这个样本属于哪一类”,而是“数据本身是如何产生出来的”。更形式化地说,它试图学习数据分布 \(p(x)\),或条件分布 \(p(x|c)\),从而能够采样、重建、补全、去噪或按条件生成新样本。不同生成模型的主要差别在于它们选择了不同的概率建模路径:有的学隐变量,有的学博弈过程,有的学逐步去噪,有的更偏重表示压缩。

自编码器(AE)

自编码器(Autoencoder, AE)的核心思想是“先压缩,再重建”。它把输入 \(x\) 通过编码器(Encoder)映射到低维或受约束的隐表示(Latent Representation) \(z\),再通过解码器(Decoder)把 \(z\) 重建回 \(\hat x\)。如果模型在受限瓶颈下仍能较好重建输入,就说明 \(z\) 抓住了数据中的关键结构。

其基本形式可以写成:

\[z=f_{\theta}(x),\qquad \hat x=g_{\phi}(z)\] \[\mathcal{L}_{\mathrm{AE}}=\|x-\hat x\|_2^2\quad \text{或}\quad -\sum_i x_i\log \hat x_i\]

这里 \(f_{\theta}\) 是编码器, \(g_{\phi}\) 是解码器, \(z\) 是瓶颈表示, \(\hat x\) 是重建结果。若输入是连续值,常用均方误差;若输入近似二值或归一化到概率意义,常用逐维交叉熵。这个目标迫使模型学习“怎样用更紧凑的表示保存足够重建原样本的信息”。

自编码器本身并不天然是强生成模型,因为它主要学会的是“给定输入怎么重建自己”,而不是如何从一个规则、可采样的潜空间中稳定地产生新样本。它更适合理解为表示学习或降维模型。通过在结构或训练目标上增加限制,例如稀疏自编码器(Sparse AE)、去噪自编码器(Denoising AE)或收缩自编码器(Contractive AE),它可以学到更稳健的隐表示。

应用上,AE 常用于降维、异常检测、去噪、预训练和表征学习。例如在工业异常检测里,模型只用正常样本训练,推理时若某个输入无法被良好重建,重建误差就可能提示该样本偏离了正常分布。

变分自编码器(VAE)

变分自编码器(Variational Autoencoder, VAE)是在 AE 基础上把“隐空间可采样”这件事做成概率建模的方案。它不再把编码器输出一个确定的潜向量,而是输出一个潜变量分布 \(q_{\phi}(z|x)\);同时假设存在生成分布 \(p_{\theta}(x|z)\)。这样,模型既能重建输入,又能从一个规则的潜空间里采样新样本。

VAE 的核心训练目标是证据下界(Evidence Lower Bound, ELBO):

\[\mathcal{L}_{\mathrm{VAE}}=\mathbb{E}_{q_{\phi}(z|x)}[\log p_{\theta}(x|z)]-D_{\mathrm{KL}}\big(q_{\phi}(z|x)\,\|\,p(z)\big)\]

其中第一项是重建项,鼓励给定 \(z\) 时能把 \(x\) 生成回来;第二项是 KL 散度(Kullback-Leibler Divergence),把编码器输出的后验近似分布 \(q_{\phi}(z|x)\) 拉向先验分布 \(p(z)\),通常取标准高斯 \(\mathcal{N}(0,I)\)。这一步的作用是把隐空间整理成“规则、连续、可插值、可采样”的形状。

训练上的关键技巧是重参数化(Reparameterization Trick):若直接从 \(q_{\phi}(z|x)\) 采样,梯度难以回传;VAE 通常把采样写成 \(z=\mu+\sigma\odot \epsilon\),其中 \(\epsilon\sim\mathcal{N}(0,I)\),而 \(\mu,\sigma\) 由编码器输出。这样随机性被转移到与参数无关的 \(\epsilon\) 上,梯度就能顺利穿过 \(\mu,\sigma\) 回传。

应用上,VAE 特别适合做潜空间操作,例如插值生成、属性控制、缺失补全和概率建模。与 GAN 相比,VAE 生成结果往往更平滑、更稳定,但图像清晰度常较弱;与扩散模型相比,VAE 在采样效率上更高,但生成质量上通常不是最强路线。

生成对抗网络(GAN)

生成对抗网络(Generative Adversarial Network, GAN)的核心思想是对抗式学习:让生成器(Generator)负责“伪造样本”,让判别器(Discriminator)负责“分辨真假”,两者在博弈中共同提高。生成器学会把随机噪声变成越来越像真实数据的样本,判别器则学会识别这些样本是否来自真实分布。

经典 GAN 的目标写成:

\[\min_G\max_D\ V(D,G)=\mathbb{E}_{x\sim p_{\mathrm{data}}}[\log D(x)]+\mathbb{E}_{z\sim p(z)}[\log(1-D(G(z)))] \]

这里 \(z\) 是从先验分布中采样的随机噪声, \(G(z)\) 是生成器产生的假样本, \(D(x)\) 输出输入样本为真样本的概率。判别器希望让真实样本分数高、伪样本分数低;生成器则希望骗过判别器,让 \(G(z)\) 看起来足够真实。

具象地看,GAN 像“伪造者”和“鉴定师”的对抗升级。鉴定师越强,伪造者就被迫学会更精细的伪造技巧;伪造者越强,鉴定师也必须学会更细致的辨别规则。理论上,这种动态会把生成分布推向真实数据分布;工程上,它带来的最大问题是训练不稳定,常见现象包括模式崩塌(Mode Collapse)、震荡和判别器过强导致生成器梯度过弱。

GAN 在图像生成、图像翻译、超分辨率和风格迁移里曾经极其成功,因为它特别善于生成锐利、感知上真实的图像纹理。但它对训练技巧依赖很强,后来在大规模高保真图像生成上逐渐被扩散模型压过;即便如此,GAN 在需要低步数快速生成或特定视觉变换任务中仍然很有生命力。

扩散模型(Diffusion)

扩散模型(Diffusion Model)的核心思想是:把“直接学会生成复杂数据”拆成“先逐步加噪,再逐步去噪”这条更稳定的路径。前向过程把真实样本一步步污染成近似高斯噪声,反向过程则训练一个神经网络学会在每一步去掉一小部分噪声。最终从纯噪声出发,经过多步反向去噪,就能逐步生成结构清晰的样本。

记号上,前向扩散链从真实样本 \(x_0\) 出发,依次得到 \(x_1,x_2,\dots,x_T\)。因此 \(x_0\) 表示原始数据样本, \(x_t\) 表示第 \(t\) 步加噪后的样本。

一个常见的前向加噪过程写成:

\[q(x_t|x_{t-1})=\mathcal{N}\!\left(x_t;\sqrt{1-\beta_t}\,x_{t-1},\beta_t I\right)\]

这里 \(\beta_t\) 是第 \(t\) 步的噪声强度:它控制从 \(x_{t-1}\) 走到 \(x_t\) 时,原信号衰减多少、随机噪声注入多少。训练时常把从 \(x_0\) 到 \(x_t\) 的若干步合并写成

\[x_t=\sqrt{\bar\alpha_t}\,x_0+\sqrt{1-\bar\alpha_t}\,\epsilon,\qquad \epsilon\sim\mathcal{N}(0,I)\]

这里 \(\bar\alpha_t\) 是由噪声日程(Noise Schedule)累乘得到的系数,控制到第 \(t\) 步时,原始信号保留了多少、噪声混入了多少。实际训练中,网络通常不直接预测 \(x_0\),而是预测噪声 \(\epsilon\),典型损失是:

\[\mathcal{L}_{\mathrm{diff}}=\mathbb{E}\big[\|\epsilon-\epsilon_{\theta}(x_t,t)\|_2^2\big]\]

这条路径之所以有效,在于“预测一步噪声”比“直接一次生成整张复杂图片”更容易优化。训练上,扩散模型相对稳定,较少出现 GAN 那种对抗不平衡;代价是采样通常需要多步迭代,推理速度较慢。应用上,扩散模型已经成为图像生成、文生图、图像编辑、超分辨率、视频生成和分子设计的重要主线。Stable Diffusion 一类系统,本质上就是把扩散过程放到了潜空间(Latent Space)里执行,以降低像素空间扩散的计算成本。

图神经网络(GNN)

图神经网络(Graph Neural Network, GNN)处理的对象不是规则网格上的序列或图像,而是由节点(Node)和边(Edge)组成的图(Graph)。它的核心问题是:当样本之间存在不规则连接关系时,如何让一个节点的表示同时反映“自己的特征”和“邻居结构中的上下文”。因此,GNN 的基本直觉不是滑动卷积核,也不是按时间递推,而是让节点在图上传递消息、聚合邻居信息,再更新自身表示。

图卷积网络(GCN)

图卷积网络(Graph Convolutional Network, GCN)把卷积思想推广到图结构上。它的核心思想是:一个节点的新表示,不应只由自己决定,还应由其邻居节点的表示共同决定;但这种聚合不能简单相加,而需要根据图结构做适当归一化,否则高度节点会在信息聚合中占据过大权重。

GCN 的经典一层更新公式写成:

\[H^{(l+1)}=\sigma\!\left(\tilde D^{-1/2}\tilde A\tilde D^{-1/2}H^{(l)}W^{(l)}\right)\]

其中 \(H^{(l)}\) 是第 \(l\) 层所有节点的表示矩阵; \(W^{(l)}\) 是该层可学习权重; \(\tilde A=A+I\) 表示在原邻接矩阵 \(A\) 上加自环(Self-loop),让节点保留自己的信息; \(\tilde D\) 是 \(\tilde A\) 的度矩阵(Degree Matrix); \(\sigma\) 是非线性激活。中间那项对邻居求和并按度做归一化,本质上是在做“平滑的邻居平均”。

具象地看,GCN 像在社交网络里更新一个人的画像:不仅看这个人自己填写的特征,还参考他一跳邻居的大致特征,再做归一化,避免“朋友特别多的人”把自己的表示稀释得过于严重。多层堆叠后,一个节点就能间接接触到两跳、三跳甚至更远范围的信息。

训练上,GCN 常用于节点分类、图分类和链路预测。它的经典应用包括引文网络分类、分子图预测和推荐系统图表示学习。局限也很典型:层数太深时,节点表示会越来越相似,出现过平滑(Oversmoothing);大图上直接用全图邻接矩阵训练也会带来显存与计算压力。

图注意力网络(GAT)

图注意力网络(Graph Attention Network, GAT)在 GCN 的“统一归一化邻居平均”之上进一步提出:不同邻居的重要性不应被预先固定,而应由模型动态学习。它的核心思想是把注意力机制引入图结构,使每个节点在聚合邻居时,能够自适应决定“更该听谁的话”。

一层 GAT 的典型计算是:

\[e_{ij}=a(Wh_i,Wh_j),\qquad \alpha_{ij}=\frac{\exp(e_{ij})}{\sum_{k\in \mathcal{N}(i)}\exp(e_{ik})}\] \[h_i'=\sigma\!\left(\sum_{j\in \mathcal{N}(i)} \alpha_{ij}\,Wh_j\right)\]

这里 \(h_i\) 是节点 \(i\) 的输入表示, \(W\) 是线性变换矩阵, \(a(\cdot,\cdot)\) 是注意力打分函数, \(e_{ij}\) 是节点 \(j\) 对节点 \(i\) 的未归一化重要性分数, \(\alpha_{ij}\) 是在邻居集合 \(\mathcal{N}(i)\) 内 softmax 归一化后的注意力权重。

与 GCN 相比,GAT 的关键收益是更灵活:若某个邻居特别重要,模型可以给它更高权重;若某个邻居噪声较大,则可自动抑制。训练上,GAT 仍通过监督或自监督目标学习节点表示,常用多头注意力(Multi-head Attention)稳定训练。应用上,它常见于异质关系更复杂、邻居重要性差异显著的图任务,例如社交网络分析、知识图谱局部推断和分子性质预测。

GraphSAGE

GraphSAGE(Graph Sample and Aggregate)的核心思想是把 GNN 从“转导式(Transductive)图编码”推进到“归纳式(Inductive)图表示学习”。传统 GCN 常依赖整张训练图;GraphSAGE 则强调:即使测试时出现训练中未见过的新节点,只要能拿到它的邻居特征,也应能在线生成它的表示。

其典型更新形式是先采样邻居,再做聚合:

\[h_{\mathcal{N}(v)}^{(k)}=\mathrm{AGG}^{(k)}\big(\{h_u^{(k-1)}:u\in \mathcal{N}(v)\}\big)\] \[h_v^{(k)}=\sigma\!\left(W^{(k)}[h_v^{(k-1)}\|h_{\mathcal{N}(v)}^{(k)}]\right)\]

这里 \(h_v^{(k)}\) 是节点 \(v\) 在第 \(k\) 层的表示, \(\mathcal{N}(v)\) 是其邻居集合, \(\mathrm{AGG}\) 可以是均值、池化或 LSTM 聚合器, \([\cdot\|\cdot]\) 表示向量拼接。GraphSAGE 的关键工程点是“采样”,因为超大图中不可能每次把全部邻居完整展开。

具象地看,GraphSAGE 像为每个节点建立一套“从邻居摘要中构造自我画像”的规则。它不要求记住整张训练图中每个节点的专属嵌入,而是学会一套可迁移的邻域聚合函数。这正是它能处理新节点、动态图和大规模图数据的原因。

应用上,GraphSAGE 在推荐系统、社交网络、风控图谱和工业知识图谱中非常常见,因为这些场景经常不断出现新节点、新边,归纳式能力比单纯在固定图上做转导预测更重要。

消息传递机制(Message Passing)

消息传递(Message Passing)不是某一个具体模型,而是理解 GNN 的统一抽象框架。无论是 GCN、GAT 还是 GraphSAGE,本质上都可以拆成两步:第一步,节点从邻居那里接收消息;第二步,把这些消息与自己的旧表示结合,更新成新的节点表示。

这一抽象常写成:

\[m_v^{(l+1)}=\mathrm{AGG}\Big(\{M^{(l)}(h_v^{(l)},h_u^{(l)},e_{uv})\,:\,u\in\mathcal{N}(v)\}\Big)\] \[h_v^{(l+1)}=U^{(l)}\big(h_v^{(l)},m_v^{(l+1)}\big)\]

其中 \(h_v^{(l)}\) 是节点 \(v\) 在第 \(l\) 层的表示, \(e_{uv}\) 是边特征, \(M^{(l)}\) 是消息函数,决定一条边上传递什么信息; \(\mathrm{AGG}\) 是聚合函数,如求和、均值、最大值或注意力加权和; \(U^{(l)}\) 是更新函数,把旧表示与聚合后的消息合成为新表示。

这个框架的重要性在于,它把看似不同的图模型放进了一套统一语言里:GCN 相当于使用归一化线性消息与均值式聚合,GAT 相当于把注意力权重写进聚合,GraphSAGE 相当于强调采样与归纳式聚合。理解了消息传递,就能把很多图模型看成“消息函数、聚合函数、更新函数”三处设计选择的不同组合。

训练上,消息传递式 GNN 常用于三类任务:节点级任务(例如节点分类)、边级任务(例如链路预测)、图级任务(例如分子性质预测)。它们的共同难点包括:过平滑、邻居爆炸(Neighborhood Explosion)、异质图关系复杂,以及深层堆叠后长程依赖难以稳定传播。很多现代 GNN 改进,本质上都在围绕这几个瓶颈重新设计消息传递规则。

Transformers
概述

Transformer 是现代大模型最核心的统一架构。它最初被提出用于序列到序列(Sequence-to-Sequence)任务,但很快演化成大语言模型(Large Language Model, LLM)、视觉 Transformer、多模态模型以及各类基础模型(Foundation Model)的共同骨架。它之所以重要,不只是因为“效果好”,更因为它提供了一种高度模块化、可并行扩展、易于堆叠放大的建模方式:输入被表示成一串 token,对这些 token 的关系建模主要依赖注意力(Attention),而每一层又通过前馈网络(Feed-Forward Network, FFN / MLP)继续做非线性变换与特征重组。

从工程角度看,Transformer 的成功来自三件事的结合:第一,注意力机制让模型能直接建模长距离依赖,而不必像循环网络那样逐步传递状态;第二,层与层之间结构统一,非常适合在 GPU / TPU 上做大规模并行训练;第三,模型规模可以沿着层数、隐藏维度、注意力头数、词表大小与训练数据量持续扩展,于是它天然适合作为“可放大”的通用架构。

因此,理解 Transformer 不应只停留在“注意力公式怎么写”,还要把它看成一条完整的信息处理流水线:token 如何变成向量,向量如何在注意力里彼此通信,MLP 如何重组和放大模式,残差流(Residual Stream)如何把各层计算串接起来,最后这些中间表示又如何被任务头(Task Head)读出,变成分类结果、生成 token 或其他下游输出。

transformers

整体架构

Transformer 的“基本计算单元”是一个 Transformer block:把注意力子层(Attention Sublayer)与前馈子层(FFN Sublayer)串联起来,并在每个子层外包一层残差连接(Residual Connection)与归一化(Normalization)。注意力子层的输出不是最终预测,而是作为中间表示继续送入 FFN 与下一层 Transformer block,逐层构建更抽象的特征。

典型层结构(概念上)可以写成:

\[H'=\mathrm{Add\&Norm}(H,\ \mathrm{Attention}(H)),\quad H^{\text{next}}=\mathrm{Add\&Norm}(H',\ \mathrm{FFN}(H'))\]

这条式子描述的是一个 Transformer block 内部最核心的两步。这里 \(H\) 表示进入当前层的隐藏状态矩阵(Hidden States),形状通常是 \(L\;\times d_{\text{model}}\): \(L\) 是序列长度, \(d_{\text{model}}\) 是每个 token 的隐藏维度。 \(\mathrm{Attention}(H)\) 表示注意力子层对整段序列做一次“彼此通信”后的结果:每个 token 会结合其他位置的信息,得到新的上下文化表示。

第一步 \(H'=\mathrm{Add\&Norm}(H,\ \mathrm{Attention}(H))\) 中,Add 表示残差相加:把原输入 \(H\) 与注意力输出相加;Norm 表示再做归一化(通常是 LayerNorm)。残差的作用是保留原始信息并让梯度更容易穿过深层网络,归一化的作用是让数值尺度更稳定。经过这一步后,得到的 \(H'\) 可以理解为“已经完成一次上下文交互”的中间表示。

第二步 \(H^{\text{next}}=\mathrm{Add\&Norm}(H',\ \mathrm{FFN}(H'))\) 则把 \(H'\) 送入前馈网络(Feed-Forward Network, FFN)。FFN 不负责 token 之间的信息交换,而是对每个位置的向量分别做非线性变换与特征重组。它更像是在每个 token 内部重新编码:放大有用模式、抑制无关模式,并把低层线索组合成更抽象的表示。再经过一次“残差相加 + 归一化”后,输出 \(H^{\text{next}}\),作为下一层 Transformer block 的输入。

因此,这个公式的阅读顺序可以概括为:先让 token 之间通过注意力交换信息,再让每个 token 自己通过 FFN 重组特征。多层堆叠之后,模型就会沿着这条路径逐层把原始输入变成越来越适合任务头读取的高层表示。

这里还需要区分 Pre-LN(Pre-LayerNorm)与 Post-LN(Post-LayerNorm)。它们的区别在于 LayerNorm 放在子层计算之前,还是放在残差相加之后。

若是 Post-LN,概念上更接近前面那条写法:先做子层计算,再与输入做残差相加,最后归一化。例如注意力子层可写成 \(H'=\mathrm{LN}(H+\mathrm{Attention}(H))\)。若是 Pre-LN,则顺序改成“先归一化,再做子层计算,再走残差”:注意力子层更接近 \(H'=H+\mathrm{Attention}(\mathrm{LN}(H))\),FFN 子层同理。

两者表达的功能主线相同:信息都要经过注意力与 FFN,再靠残差流向后传递。差异主要体现在训练动力学(Training Dynamics)上。Post-LN 更贴近原始 Transformer 论文的写法,直观上像“每次子层更新完,再把结果规范一下”;Pre-LN 则让梯度更容易沿残差路径稳定传播,因此在很深的大模型里更常见。工程实现会在 Pre-LN / Post-LN 之间选择,这会影响训练稳定性、学习率可用范围以及深层可训练性,但不会改变我们对 block 主流程的理解:注意力负责跨 token 交互,FFN 负责单 token 特征重组,残差负责让信息与梯度顺畅穿层流动。

Transformer 这个名字源自 “Attention Is All You Need” 论文:模型不再依赖循环结构来处理序列,而是通过注意力把序列表示不断变换(Transform)为更适合预测的表征。

Transformer 的参数(Parameters)不是单一矩阵,而是一组可学习张量的集合,主要包括嵌入(Embedding)、注意力投影(Attention Projections)、前馈网络(FFN)以及归一化的缩放/平移参数等。

参数组 符号 典型形状(Typical Shape) 备注
Token Embedding \(E\) \(\mathbb{R}^{V\;\times d_{\text{model}}}\) 词表大小 \(V\);常与输出头权重共享(Weight Tying)。
位置嵌入(Learned) \(P\) \(\mathbb{R}^{L_{\max}\;\times d_{\text{model}}}\) 仅当使用可学习绝对位置嵌入时存在;正弦位置编码无此参数。
注意力投影 \(W_Q,W_K,W_V\) \(\mathbb{R}^{d_{\text{model}}\;\times d_{\text{model}}}\) 实现上常把多头合并成一次线性投影,等价于 \(\mathbb{R}^{d_{\text{model}}\;\times (H d_k)}\)。
注意力输出投影 \(W_O\) \(\mathbb{R}^{d_{\text{model}}\;\times d_{\text{model}}}\) 对拼接后的多头输出做线性混合;并非 \(H\;\times d_v\;\times d_{\text{model}}\) 的三维张量。
FFN \(W_1,W_2\) \(W_1\in\mathbb{R}^{d_{\text{model}}\;\times d_{\text{ff}}},\ W_2\in\mathbb{R}^{d_{\text{ff}}\;\times d_{\text{model}}}\) 通常 \(d_{\text{ff}}\gg d_{\text{model}}\)。
LayerNorm \(\gamma,\beta\) \(\mathbb{R}^{d_{\text{model}}}\) 每个 LayerNorm 有一组缩放与平移参数。
输出头(LM Head) \(W_{\text{vocab}},b\) \(W_{\text{vocab}}\in\mathbb{R}^{d_{\text{model}}\;\times V}\) 把隐藏状态映射为词表 logits;常与 \(E\) 共享权重。

transformers-dimsTransformer 的不可解释性(Lack of Interpretability)不是由某一个参数“导致”,而是由整体机制共同产生:表示是分布式(Distributed)且高维的,多层叠加的非线性变换把因果链条变长;注意力权重可视化能提供线索,但它不是完整解释。

知识如何存储

大模型中的知识通常不是“某一个感知机单独存储一条事实”,而是以分布式表示(Distributed Representation)的形式分散在大量参数里。单个单元更像一个局部特征探测器(Feature Detector):它只对某种模式敏感;许多单元级联后,网络才能把低层简单模式组合成高层抽象概念。模型规模越大、层数越深、参数越多,可被编码的模式组合也越丰富,这正是大模型具备强表达能力与“知识容量”的原因之一。

对于 Transformer 这样的模型,知识并不是以“一层一个概念、一神经元一事实”的方式整齐排布,而更像是沿着残差流(Residual Stream)在多层之间不断被提取、重组、放大和读出。注意力层更擅长在上下文中定位相关信息、建立 token 之间的依赖;MLP 层则更像参数化的模式变换器或记忆单元,会把某些已经被触发的模式映射成更强的语义方向,再写回主表示中。

从经验上看,这种知识分布有一些常见规律。较低层往往更接近词形、局部模式与浅层统计相关性;中间层更容易出现实体属性、关系模式和事实联想的组合;较高层则更接近任务相关读出,也就是更接近“最后怎样把内部表示变成具体输出”的阶段,例如下一 token 预测、答案选择或标签判别。但这更像统计趋势,而不是严格分工:同一类知识往往会跨多个层段冗余存在,并通过许多参数共同表达。

因此,更准确的理解不是“第几层存了什么知识”,而是“不同层在知识处理流水线里承担了什么功能”。有的层更偏检索线索,有的层更偏关系组合,有的层更偏把结果变成可供输出头使用的表示。单个 MLP 模块有时可以表现出类似键值记忆(Key-Value Memory)的行为,但真正稳定的知识通常仍然是跨层、跨参数、跨方向分布的。也正因为这种分布式编码,大模型既能表现出较强的知识容量,也会显得难以直接解释和精确定位。

transformers-knowledge

编码器-解码器

编码器-解码器(Encoder–Decoder)结构对应经典 Seq2Seq:编码器先对输入序列做双向自注意力(Bidirectional Self-Attention)编码,即编码器里的每个 token 都可以直接看到源序列中的其他 token,不使用因果掩码(Causal Mask),因此更擅长形成充分的上下文化输入表示;随后解码器在自回归生成(Autoregressive Generation)时,一边做因果自注意力(Causal Self-Attention),只看已经生成的前缀,一边通过交叉注意力(Cross-Attention)读取编码器输出。于是,编码器负责把“输入内容本身”编码清楚,解码器负责在“已生成前缀 + 编码器语义表示”条件下逐步生成输出。典型用于机器翻译、摘要、问答等“输入到输出”的条件生成任务(Conditional Generation),代表模型如 T5、BART。

仅编码器

仅编码器(Encoder-only)结构使用双向自注意力(Bidirectional Self-Attention):位置 \(i\) 可以看见所有位置(不做因果屏蔽)。它更擅长做“理解与表示”(Representation Learning),常见预训练目标是掩码语言建模(Masked Language Modeling, MLM):把输入里部分 token 替换为 \([\mathrm{MASK}]\),训练模型根据上下文预测被遮住的 token。代表模型如 BERT、RoBERTa;ELECTRA 则用“替换检测(Replaced Token Detection)”作为预训练任务,但架构仍是 Encoder-only。

注意“掩码(Mask)”在这里指的是 MLM 的 token masking,不是自回归解码里的因果 attention mask。

仅解码器

仅解码器(Decoder-only)结构使用因果自注意力(Causal Self-Attention):位置 \(i\) 只能看见 \(j\le i\) 的历史 token,通过三角形掩码避免“偷看未来”。它天然对应自回归语言建模(Causal Language Modeling, CLM):最大化 \(\prod_t p(x_t|x_{<t})\)。代表模型如 GPT 系列、LLaMA、Qwen。

这里的“掩码(Mask)”指的是 attention 里的因果屏蔽,与 MLM 的 \([\mathrm{MASK}]\) token 概念不同。

主流 Decoder-only 细节差异(选型表)

Decoder-only 成为主流之后,架构创新集中在“稳定性、KV Cache 成本与训练效率”三个轴:归一化/激活影响深层训练稳定性;注意力侧的 KV 结构决定长上下文推理成本;FFN 稠密/稀疏(MoE)与训练目标改造影响单位算力的有效学习信号。

技术点 常见选项 动机 影响
归一化(Normalization) LayerNorm / RMSNorm 提升深层训练稳定性 RMSNorm 省掉去均值,算子更简单;实际表现依赖整体配方
激活/FFN(Activation/FFN) GELU / SwiGLU / GLU 变体 门控提升表达力与稳定性 通常带来更好效果,但实现与吞吐会受内核支持影响
KV Cache 压力 MHA / GQA / MQA 减少 KV heads,降低显存与带宽 长上下文收益显著;可能牺牲部分表示自由度
KV 压缩(Latent KV) 低秩/潜变量压缩(如把 KV 投影到低维潜空间) 进一步压缩 KV Cache 上下文长度与并发能力提升,但架构更复杂、实现更依赖细节
FFN 稠密 vs 稀疏 Dense / MoE 用稀疏激活扩大参数容量 训练更复杂(路由/负载均衡);推理吞吐依赖专家并行与缓存
预训练目标 Next-token / Multi-token Prediction(MTP) 提升单位 token 的监督信号密度 MTP 可能提高训练效率,但会改变解码对齐与训练配方
输入处理

Transformer 并不直接处理原始字符串。文本进入模型之前,必须先经过一条输入处理流水线:文本规范化、切分为 token、映射为 token id,再查表转成向量表示。只有完成这一步,后续的注意力、FFN 和位置编码才有可计算的离散输入。输入处理决定了模型“看见世界的最小单位”是什么,因此它不仅影响参数规模与推理效率,也会影响稀有词覆盖、跨语言能力、长度利用率以及生成结果的边界质量。

Tokenization

Tokenization 的核心任务是把连续文本切分成模型可处理的离散符号序列。这个离散化过程看似只是“切词”,实际上定义了词表(Vocabulary)、序列长度、未知词处理方式以及字符到语义表示的映射粒度。若切得过粗,词表会过大、稀有词泛化差;若切得过细,序列会变长、计算成本升高。因此,现代语言模型通常采用子词分词(Subword Tokenization):用有限词表在“整词”和“字符”之间取得平衡。

分词并不只是训练前的一道预处理工序,它深度参与了模型能力边界的形成。相同一句文本,换一种 tokenizer,模型看到的 token 序列长度、常见片段分布、数字和符号的切分方式都会变化,进而影响上下文利用率、训练效率、长文本成本、代码与多语言表现,甚至影响困惑度(Perplexity)等指标的可比性。也正因为如此,跨模型比较时,若 tokenizer 不同,很多“每 token 指标”都不能直接横向解读。

此外,现代 tokenizer 通常不只负责“切分”,还负责一组配套约定:例如保留哪些特殊 token(Special Tokens),如何处理大小写、空格、换行、标点、表情与 Unicode 字符,以及遇到词表里没有的片段时如何回退。像 [UNK] 这样的未知词标记(Unknown Token)就是早期整词分词里常见的退路:当输入片段不在词表中时,直接映射成一个统一的“未知”符号。它的问题是信息损失很大,不同未知词都会塌缩成同一个 token。子词分词与字节分词之所以重要,一个核心原因就是它们大幅减少了对 [UNK] 的依赖。

从风格上看,分词大致可以分为四类。第一类是整词分词(Word-level Tokenization):把单词当作基本单位,优点是语义直观,缺点是词表会迅速膨胀,且对未登录词(Out-of-Vocabulary, OOV)非常敏感。第二类是字符分词(Character-level Tokenization):把每个字符都当作 token,几乎没有 OOV 问题,但序列会显著变长,模型需要自己学习更多组合关系。第三类是子词分词(Subword Tokenization):用常见片段构成词表,让高频词保持完整、低频词拆成片段,这是现代 NLP 最主流的折中路线。第四类是字节分词(Byte-level Tokenization):直接在字节层处理输入,覆盖能力最强,跨语言和特殊符号最稳,但序列通常更长,对模型容量和训练配方要求更高。

因此,不同分词风格的本质取舍是:词表越大,单个 token 的语义通常越完整,但 OOV 与稀疏性越严重;词表越小,覆盖越稳,但序列越长、建模负担越重。现代大模型之所以大量采用 BPE、WordPiece、SentencePiece 或 byte-level BPE,本质上都是在这条权衡曲线上寻找更合适的工程平衡点。

分词风格 基本单位 主要优点 主要代价 常见场景
整词分词 单词 语义直观;序列较短 词表膨胀;OOV 严重 早期 NLP;规则较强的封闭词表任务
字符分词 字符 覆盖稳定;几乎无 OOV 序列长;组合学习负担大 鲁棒输入建模;字符级任务
子词分词 高频片段 / 子词 词表与序列长度折中较好 切分方式影响语义边界 BERT、T5、LLaMA 等主流文本模型
字节分词 字节 覆盖最强;特殊符号与多语言稳健 序列更长;训练成本更高 byte-level BPE、多语言与噪声文本
BPE

BPE(Byte Pair Encoding)从字符(或字节)开始,通过统计合并高频相邻符号对(Pair Merge)逐步构建子词(Subword)词表。它的核心收益是用有限词表覆盖开放词汇:常见词被合并成整体,罕见词被拆成更小片段,减少 \([\mathrm{UNK}]\)。

BPE 的直觉可以概括为“把最常一起出现的片段逐步固化成一个 token”。例如,若训练语料里 t 和 h 经常相邻,就可能先合并成 th;若 th 与 e 又高频共现,就可能继续合并成 the。经过大量合并之后,词表里会同时存在完整高频词、常见词根、后缀、数字片段和标点组合。这样一来,模型既能用短序列表达常见模式,又不必为每个罕见词都预留独立词条。

从工程谱系上看,GPT 家族总体属于 BPE 路线的延伸:早期 GPT / GPT-2 风格 tokenizer 采用 byte-level BPE,把文本先映射到字节层,再做 BPE 合并;这种设计能更稳地覆盖任意 Unicode 文本、空格和特殊符号。对 OpenAI 当前模型生态而言,官方开发工具链中程序化分词通常使用 tiktoken;它对应的是面向具体模型的 encoding 体系,但核心思想仍然是 BPE 家族的子词压缩与高覆盖率路线。对开发者来说,更重要的实践结论是:GPT 并不是“按词”切分,而是按 BPE 家族 tokenizer 切成子词或字节片段;同一个自然语言单词,可能被切成一个 token,也可能被切成多个 token,取决于它在词表中的合并状态。

WordPiece

WordPiece 与 BPE 同属子词分词(Subword Tokenization),但合并准则更偏向最大化语言模型似然(Likelihood)。BERT 系列常用 WordPiece,因此会看到以 ## 标记的子词前缀(如 play + ##ing)。

SentencePiece

SentencePiece 是一种分词器(Tokenizer)训练与推理框架(常见算法包括 BPE 与 Unigram LM)。它可以直接在原始文本上训练(不依赖空格分词),因此在多语言与无空格语言(如中文、日文)上更常用;LLaMA 等模型的 tokenizer 通常基于 SentencePiece。

Token Embedding

Token Embedding 的核心是一个可训练的嵌入表(Embedding Table,也常被称为嵌入矩阵(Embedding Matrix)):

\[E\in\mathbb{R}^{V\;\times d_{\text{model}}}\]

其中 \(V\) 是词表大小(Vocabulary Size),每一行对应一个 token 的向量表示。给定输入 token id 序列 \((t_1,\dots,t_L)\),查表得到输入嵌入序列(Embedding Output):

\[X=\begin{bmatrix}E_{t_1}\\ \vdots\\ E_{t_L}\end{bmatrix}\in\mathbb{R}^{L\;\times d_{\text{model}}}\]

一些材料会把 \(E\)(参数表)和 \(X\)(某次输入的嵌入结果)都叫“嵌入矩阵”,容易混淆。区分的一个简单方式是:E 是全词表参数,X 是当前输入的嵌入输出。

在语言模型里,这张输入嵌入表常与输出处理中的语言模型头(LM Head)共享参数,即权重共享(Weight Tying)。这里先记住这一点即可;它的具体计算方式与工程含义放在后面的“输出处理”中展开。

位置编码

位置编码(Positional Encoding)解决一个根本问题:注意力机制本身对输入顺序是置换不变(Permutation-Invariant)的,如果不显式注入位置信息,模型无法区分“AB”和“BA”。因此需要把“位置”以某种方式编码进每个 token 的表示。

绝对位置编码

绝对位置编码(Absolute Positional Encoding)最常见的做法之一是学习一个位置嵌入表(Position Embedding Table):

\[P\in\mathbb{R}^{L_{\max}\;\times d_{\text{model}}}\]

\(L_{\max}\) 是模型支持的最大位置索引数量(Maximum Position Index)。对长度为 \(L\) 的输入序列,取 \(P_{0:L}\)(或 \(P_{1:L}\),取决于实现)得到当前序列的位置嵌入矩阵 \(P_{\text{seq}}\in\mathbb{R}^{L\;\times d_{\text{model}}}\)。

Transformer 通常用逐元素相加把 token 嵌入与位置嵌入融合:

\[H^{(0)} = X + P_{\text{seq}}\]

这里 \(H^{(0)}\) 仍然是 \(d_{\text{model}}\) 维向量序列,不是“位置标量”。位置是否用一个标量并不重要;重要的是这种表示能让后续的线性层与注意力计算利用位置关系。高维位置向量提供了更丰富的可学习空间。

“相加会不会把信息混在一起、无法区分?”这个直觉常见,但对表示学习而言关键不是可逆性,而是可用性:模型不需要从 \(H^{(0)}\) 精确还原 \(X\) 与 \(P_{\text{seq}}\),只需要用它们的组合完成预测。并且在高维空间里,模型可以把“语义”和“位置”分配到近似正交(Approximately Orthogonal)的方向,使得线性变换能有效解耦。

一个二维玩具例子:令 token 向量 \(x=(1,0)\),位置向量 \(p=(0,0.1)\),则 \(h=x+p=(1,0.1)\)。如果模型的某个线性读出只看第二维(例如乘以 \((0,10)\)),就能强烈感知位置而几乎不受语义影响。真实模型在上千维空间里有更大的自由度(Degree of Freedom, DOF)。

把位置“拼接”(Concatenation)到额外维度也能工作,但它会改变隐藏维度,影响后续层形状与参数规模;而加法保持 \(d_{\text{model}}\) 不变,是一种参数与工程都更稳定的设计选择。

正弦位置编码(Sinusoidal Positional Encoding)

另一类绝对位置编码是正弦位置编码(Sinusoidal Positional Encoding),它不引入可学习参数,而是用不同频率的正弦/余弦把位置 \(\text{pos}\) 映射为向量(原始 Transformer 的设计):

\[\mathrm{PE}(\text{pos},2i)=\sin\!\left(\frac{\text{pos}}{10000^{2i/d_{\text{model}}}}\right),\quad \mathrm{PE}(\text{pos},2i+1)=\cos\!\left(\frac{\text{pos}}{10000^{2i/d_{\text{model}}}}\right)\]

为什么要成对使用 \(\sin\) 与 \(\cos\)(而不是全用 \(\sin\))?因为对同一频率而言,\((\sin\phi,\cos\phi)\) 组成一个二维正交基(Orthogonal Basis),位置平移 \(\phi\mapsto \phi+\Delta\) 等价于二维平面上的旋转(Rotation):

\[\begin{bmatrix}\sin(\phi+\Delta)\\ \cos(\phi+\Delta)\end{bmatrix}=\begin{bmatrix}\cos\Delta & \sin\Delta\\ -\sin\Delta & \cos\Delta\end{bmatrix}\begin{bmatrix}\sin\phi\\ \cos\phi\end{bmatrix}\]

这让“相对位移”变成一个固定的线性变换,从而更容易被后续线性层和点积注意力利用;如果只用 \(\sin\),相位信息会丢失,平移不再能用线性变换稳定表达。

若只取一个最小的 4 维例子,即 \(d_{\text{model}}=4\),那么位置编码就会具体化成:

\[\mathrm{PE}(\text{pos})=\big[\sin(\text{pos}),\ \cos(\text{pos}),\ \sin(\text{pos}/100),\ \cos(\text{pos}/100)\big]\]

这时每个位置都不再是“一个编号”,而是一个 4 维向量。前两维变化很快,负责较短尺度的位置区分;后两维变化很慢,负责较长尺度的位置区分。例如 \(\text{pos}=0\) 时编码是 \([0,1,0,1]\);\(\text{pos}=1\) 时约为 \([0.84,0.54,0.01,1.00]\);\(\text{pos}=2\) 时约为 \([0.91,-0.42,0.02,1.00]\)。因此,不同位置会同时在多种频率刻度上留下痕迹,而不是只靠一个单调递增的数字区分。

sinusoidal-positional-encoding-4d

上图把这个 4 维例子拆成三种读法。左侧热力图直接列出位置 \(0\sim 7\) 在四个维度上的编码值;右上角把前两维 \((\sin(\text{pos}),\cos(\text{pos}))\) 直接当成二维平面坐标,因此可以把它理解成:位置每增加一点,平面上的点就沿圆周往前走一步;右下角则把快频对与慢频对分开画出。图里第 3、4 维之所以先前看起来几乎是平的,不是因为它们不变,而是因为在标准公式里它们对应更低频率:在 \(\text{pos}=0\sim 12\) 这样很短的区间上, \(\sin(\text{pos}/100)\) 只从 0 变化到约 0.12, \(\cos(\text{pos}/100)\) 只从 1 下降到约 0.99,必须单独放大才容易看见变化。

模型利用这套编码的方式,可以直接理解成“拿多把不同刻度的尺子同时量位置关系”。同一对 token 的距离,在高频维度上会表现成较快的相位差,在低频维度上会表现成较慢的相位差;于是模型看到的就不是一个孤立的位置编号,而是一组跨多个尺度同时变化的模式。对于很近的 token,高频维度会给出很敏感的区分;对于距离更远的 token,低频维度仍然能保留稳定变化,不会太快绕回去。注意力层随后并不是逐维人工判读这些数值,而是在训练中学会:某些相位差组合通常意味着“相邻修饰”“短程依赖”,另一些更慢变化的组合更像“跨句呼应”或“长程对应”。这里并不存在一个必须被显式恢复出来的“角度标量”或“距离标量”。只要位置变化能够稳定地改变表示与点积结果,后续线性层和注意力头就可以把这种差异当作可利用特征。正弦位置编码的作用正是在于把位置关系改写成一组可被模型利用的周期信号,让模型自己在不同频率上学会读出距离与相对顺序。

相对位置编码

相对位置编码(Relative Positional Encoding)不直接编码“绝对索引”,而是让注意力更显式地依赖 token 之间的相对距离 \(i-j\)。典型做法是在注意力打分里加入相对位置偏置(Relative Position Bias):

\[\alpha_{ij}\propto \exp\!\left(\frac{q_i k_j^\top}{\sqrt{d_k}} + b_{i-j}\right)\]

这条式子描述的是:位置 \(i\) 的 query 去看位置 \(j\) 的 key 时,未归一化注意力权重会受到两部分共同决定。第一部分 \(\frac{q_i k_j^\top}{\sqrt{d_k}}\) 是标准内容相关性打分:其中 \(q_i\) 是第 \(i\) 个位置的查询向量(Query Vector),\(k_j\) 是第 \(j\) 个位置的键向量(Key Vector),二者点积 \(q_i k_j^\top\) 衡量“位置 \(i\) 当前想找的信息,与位置 \(j\) 持有的信息是否匹配”;\(d_k\) 是 key/query 的维度,除以 \(\sqrt{d_k}\) 是为了控制数值尺度,避免维度增大后 softmax 过早饱和。

第二部分 \(b_{i-j}\) 是只由相对距离决定的偏置项(Bias Term)。若 \(i-j=1\),表示当前 token 正在看它左边紧邻的位置;若 \(i-j=10\),表示它正在看更远的上文。这个偏置可以通过查表得到:给每一种相对距离,或给若干距离分桶(bucket)后的区间,各分配一个可学习标量;也可以由一个小网络根据 \(i-j\) 生成。它的作用是把“距离本身是否重要”直接加进打分,而不必完全依赖内容向量自己去隐式学出这种规律。

式子左边的 \(\alpha_{ij}\) 表示位置 \(i\) 对位置 \(j\) 的注意力权重;这里写成 \(\propto\) 而不是等号,是因为右边还只是指数化前的未归一化权重。真正的注意力概率还要在固定 \(i\) 后,对所有 \(j\) 一起做 softmax 归一化:

\[\alpha_{ij}=\frac{\exp\!\left(\frac{q_i k_j^\top}{\sqrt{d_k}} + b_{i-j}\right)}{\sum_{j'}\exp\!\left(\frac{q_i k_{j'}^\top}{\sqrt{d_k}} + b_{i-j'}\right)}\]

因此,相对位置编码的含义可以概括为:注意力不只比较“内容是否匹配”,还显式比较“这个位置离我有多远”。很多语言现象更依赖相对距离而不是绝对序号,例如局部搭配、邻近修饰、长程指代和句法依赖,因此把 \(i-j\) 直接写进打分,往往比单纯依赖绝对位置索引更贴近任务结构。

RoPE

RoPE(Rotary Position Embedding)把位置信息以“旋转”的方式注入到 \(Q\)/\(K\) 中。若按实数矩阵来写,就是把向量的每两维视为一个二维平面,再用角度与位置成正比的旋转矩阵作用在这两维上。对第 \(i\) 个二维分量,令 \(\theta_{m,i}\) 表示位置 \(m\) 在该(每两维一个)频段上的旋转角,则

\[\begin{bmatrix}x'_{2i}\\ x'_{2i+1}\end{bmatrix}=\begin{bmatrix}\cos\theta_{m,i} & -\sin\theta_{m,i}\\ \sin\theta_{m,i} & \cos\theta_{m,i}\end{bmatrix}\begin{bmatrix}x_{2i}\\ x_{2i+1}\end{bmatrix}\]

实现上,RoPE 不是“只把当前 query 旋转一下”,而是对每个位置的 \(Q\) 和 \(K\) 都各自按该位置做旋转;随后不同位置之间再做点积匹配。这样一来,位置 \(m\) 的 \(Q_m\) 和位置 \(n\) 的 \(K_n\) 在相遇时,二者各自携带的位置相位就会共同决定匹配结果。通常只有 \(Q\)/\(K\) 参与这种旋转, \(V\) 不旋转,因为位置信息的关键作用点在“如何计算注意力权重”,而不是在“被加权汇总的内容值”本身。

上述矩阵式在实现上是正确的,但从理解角度看仍然偏“机械”。更直接的方式是用复数视角(Complex Perspective):把每两维 \((x_{2i},x_{2i+1})\) 看成一个复数

\[z_i = x_{2i} + \mathrm{i}x_{2i+1}\]

于是 RoPE 的位置注入就可以写成一个极其紧凑的式子:

\[z_i' = z_i \, e^{\mathrm{i} m \theta_i}\]

这里 \(m\) 是位置索引, \(\theta_i\) 是第 \(i\) 个频段的基础角速度, \(e^{\mathrm{i} m \theta_i}\) 表示“在复平面上旋转 \(m\theta_i\) 角”。这时 RoPE 的直觉就变得很清楚:同一个向量本身不变,变化的是它在不同位置上附带的相位(phase)。位置越靠后,相位就继续往前转。

这种写法的关键价值在于:相对位置会自然地从乘法里浮现出来。若位置 \(m\) 的 query 与位置 \(n\) 的 key 都经过旋转,则它们的匹配项可写成

\[q_m^{(i)} e^{\mathrm{i} m \theta_i}\cdot \overline{k_n^{(i)} e^{\mathrm{i} n \theta_i}} = q_m^{(i)} \overline{k_n^{(i)}} e^{\mathrm{i}(m-n)\theta_i}\]

这里上划线表示复共轭(Complex Conjugate)。前文“二维向量的复数表示”已经给出同一条基本关系:二维点积可以写成复共轭乘积的实部,因此把二维块写成复数后,位置相位会直接进入匹配项。最重要的结果是指数项里只剩下 \((m-n)\theta_i\):绝对位置 \(m\) 与 \(n\) 被自动折叠成了相对位移 \(m-n\)。因此,RoPE 并不是先写出绝对位置、再额外补一个相对位置项,而是通过“给每个位置乘一个相位因子”的方式,让相对位移直接出现在注意力匹配里。

若用一句更通俗的话概括,RoPE 做的事情是:给每个位置的 \(Q\)/\(K\) 都拧上一点角度;两个位置一做点积,位置差就会体现在匹配分数里。矩阵形式更像工程实现的展开式,复数形式更接近它的数学本质。模型并不需要在内部先还原出一个单独的“角度值”再决定如何注意;它只需要利用这种旋转所造成的分数差异与模式差异。只要某类相位关系稳定对应某类局部依赖、顺序关系或长程对应,训练过程就会把这些模式吸收到注意力头和后续层的参数里。也正因为这种“相对位移直接进入匹配”的结构,RoPE 在 Decoder-only 大模型中成为主流选择(例如 LLaMA 系列)。

RoPE 长度外推(Length Extrapolation)

RoPE 的旋转角随位置线性增长。若训练阶段最大长度为 \(L_{\text{train}}\),推理时直接扩展到 \(L_{\text{test}}\gg L_{\text{train}}\),部分频段会出现“过快旋转”:模型开始在比训练时更长得多的位置区间上继续累积相位,而这些大角度相位组合在训练中几乎没有见过。结果是远距离 token 之间的相对相位关系超出训练分布,注意力更容易退化为近邻偏好,长上下文检索与推理准确率下降。

典型评测是大海捞针(Needle in a Haystack):在很长的上下文中埋入一条关键信息(needle),要求模型在指定问题下准确复述该信息。常见现象是针落在开头/结尾时表现更好,但针落在中间位置时准确率显著下降;这通常与位置编码外推、注意力实现细节与 KV Cache 行为共同相关。

工程上常见的 RoPE 外推改造包括:

  • 位置插值(Position Interpolation, PI):把推理位置按比例压缩回训练范围,相当于把 RoPE 角速度整体放慢。
  • NTK-aware 缩放(NTK-aware Scaling):按“有效核宽度”视角调整频率谱,缓和远距离相对位移失真。
  • YaRN:对不同频段做分段/渐变缩放,尽量同时保住短程精度与长程外推。

以 PI 为例,一个常用写法等价于把 RoPE 的位置 \(\text{pos}\) 映射为 \(\text{pos}'=\text{pos}/s\)(\(s=L_{\text{test}}/L_{\text{train}}\)),从而把角度压回训练范围:

\[\theta'_{\text{pos},i}=\frac{\text{pos}/s}{\text{base}^{2i/d}},\quad s=\frac{L_{\text{test}}}{L_{\text{train}}}\]
方法 是否需要再训练 核心超参 优势 风险/备注
PI 建议配合长上下文继续预训练/微调 缩放因子 \(s\) 实现简单;可在保持短程行为的同时扩展长度 若只做推理时改造,可能出现分布错配;需用 needle 测试验证“中间段”能力
NTK-aware scaling 可仅推理侧启用;配合微调更稳 频谱/基数缩放规则 对远距离更平滑;常用于把“可用上下文”拉长 不同实现差异大;需关注与 KV Cache、GQA/MQA 等工程优化的耦合
YaRN 通常建议配合继续预训练 分段/渐变缩放参数 兼顾短程精度与长程外推;对 needle 中段退化更友好 超参更多;需要系统评测(含不同位置、不同检索难度)
ALiBi

ALiBi(Attention with Linear Biases)直接在注意力 logits 上加一个与距离线性相关的偏置,而不改变表示维度,也不引入位置向量:

\[\alpha_{ij}\propto \exp\!\left(\frac{q_i k_j^\top}{\sqrt{d_k}} - m\cdot (i-j)\right),\quad j\le i\]

其中斜率 \(m\) 可按 head 设置。直觉上它鼓励模型更关注近邻 token,同时具备较好的长度外推(Length Extrapolation)行为。

注意力机制

注意力机制(Attention Mechanism)是序列模型中的动态信息选择机制。对于一个由多个 token 构成的输入序列,模型不会把所有上下文位置等量混合,而是会针对当前正在计算的位置,动态判断哪些位置更相关、相关程度有多大,以及这些位置的信息应当如何组合成新的表示。这个过程本质上是一个与输入内容相关的加权汇聚:当前位置先形成查询信号,再在上下文中寻找与之匹配的位置,最后把这些位置承载的信息按权重聚合回来。

这种设计改变了传统序列建模的信息传递路径。循环结构主要依赖状态沿时间步逐步传递,卷积结构主要依赖固定大小的局部感受野,而注意力机制允许任意两个位置直接建立联系,并且联系强度由内容决定而不是由距离预先写死。长距离依赖(Long-Range Dependency)因此可以被更直接地建模:一个 token 可以立刻读取很远处但与当前语义高度相关的信息,而不必等待信息穿过很长的递归链条或许多层局部卷积。

Transformer 将注意力机制置于核心位置。自注意力(Self-Attention)让同一序列内部的各个 token 相互读取;交叉注意力(Cross-Attention)让一个序列读取另一个序列的表示;因果注意力(Causal Attention)则通过掩码限制当前位置只能访问过去的信息,从而支撑自回归生成(Autoregressive Generation)。这些形式都遵循同一条主线:先计算相关性分数,再把分数归一化为权重,最后对承载内容的向量做加权求和。其最经典、最常见的数学形式就是缩放点积注意力(Scaled Dot-Product Attention)。

self-attention-mechanism

Scaled Dot-Product Attention

自注意力(Self-Attention)中,输入表示 \(X\) 通过三组参数投影为:

\[Q=XW_Q,\quad K=XW_K,\quad V=XW_V\]

注意力输出为:

\[\mathrm{Attention}(Q,K,V)=\mathrm{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}}\right)V\]

其中 \(W_Q,W_K,W_V\)(以及多头里的 \(W_O\))都是模型参数(Parameters),训练的目标不是“生成这些矩阵”,而是在损失函数(Loss)下通过梯度下降(Gradient Descent)把它们优化到能完成任务的取值。

把公式按 token 展开更清楚。设当前只看一个注意力头,序列长度为 \(L\)。对第 \(i\) 个 token,模型先取出它的查询向量 \(q_i\in\mathbb{R}^{d_k}\),再与序列中每个位置 \(j=1,\dots,L\) 的键向量 \(k_j\in\mathbb{R}^{d_k}\) 做点积,得到一个标量打分:

\[s_{ij}=q_i k_j^\top\]

这里 \(d_k\) 表示每个头里 Key / Query 向量的维度,也就是 \(q_i\) 与 \(k_j\) 的长度。它之所以记作 \(d_k\),是因为这个维度首先由 Key 空间定义;而 Query 必须与 Key 处在同样维度里,才能做点积匹配。因此 \(q_i\) 和 \(k_j\) 的长度通常相同。Value 向量的维度记作 \(d_v\);实践中常见设置是 \(d_v=d_k\),但这不是数学上的硬要求。

接着,对第 \(i\) 个 query 的整行打分做缩放和 softmax,得到一组对所有位置的注意力权重:

\[\alpha_{ij}=\mathrm{softmax}_j\!\left(\frac{s_{ij}}{\sqrt{d_k}}\right)=\frac{\exp\!\left(s_{ij}/\sqrt{d_k}\right)}{\sum_{t=1}^{L}\exp\!\left(s_{it}/\sqrt{d_k}\right)}\]

因此,对固定的 \(i\) 来说, \(\alpha_{i1},\dots,\alpha_{iL}\) 构成一个标量概率分布:它们都非负,且总和为 1。这个分布回答的是“第 \(i\) 个 token 应该从整段序列的哪些位置读取多少信息”。

输出 \(o_i\) 则是一个向量(Vector),由所有 Value 向量 \(v_j\in\mathbb{R}^{d_v}\) 按权重加权求和得到:

\[o_i=\sum_{j=1}^{L}\alpha_{ij} v_j\]

查询向量(Query)与键向量(Key)负责“匹配打分”;值向量(Value)承载被聚合的信息内容。把注意力看作“内容寻址(Content-based Addressing)”:先用 \(QK^\top\) 计算“应该看谁”,再用权重对 \(V\) 做加权求和得到“看到了什么”。

缩放因子 \(\sqrt{d_k}\) 的作用是控制数值尺度。由于 \(q_i\) 与 \(k_j\) 的点积是 \(d_k\) 个乘积项的求和,若各维分量方差相近,则点积分数的方差通常会随着 \(d_k\) 增长。维度一大, \(s_{ij}\) 的绝对值就更容易变大,softmax 会更快进入饱和区:某几个位置的权重接近 1,其余位置接近 0,梯度也会变小。除以 \(\sqrt{d_k}\) 后,分数尺度被拉回更稳定的范围,不同 head 维度设置下的 softmax 行为会更可控。

attention-softmax-saturation

理论上可以让寻址与内容共用投影(例如令 \(V=K\) 或直接取 \(V=X\)),但实践中通常把 Q/K 与 V 分开,是为了让“打分空间”和“内容表示空间”解耦,提升表示能力与训练稳定性。

一个极简数值例子:若某个 Query 与 3 个 Key 的相似度(未缩放)为 \([2,1,0]\),softmax 权重大约是 \([0.665,0.245,0.090]\),输出就是把三个 Value 按这个比例加权求和。

Multi-Head Attention

多头注意力(Multi-Head Attention)把注意力拆成 \(H\) 个头(Heads),每个头在不同的子空间里独立做一次注意力,然后在特征维度上拼接(Concatenation)并用输出矩阵混合:

\[\text{head}_h=\mathrm{Attention}(XW_Q^{(h)},XW_K^{(h)},XW_V^{(h)})\] \[\mathrm{MultiHead}(X)=\mathrm{Concat}(\text{head}_1,\dots,\text{head}_H)W_O\]

若 \(d_{\text{model}}\) 固定,常见做法是每个头的维度 \(d_k=d_v=d_{\text{model}}/H\),拼接后回到 \(d_{\text{model}}\)。多头的收益来自“并行关注不同关系”:有的头偏向局部邻域,有的头偏向长程依赖,有的头学到语法/实体指代等不同模式。

Masked Attention

Masked Attention(因果注意力 / Causal Attention)在自回归(Autoregressive)生成中使用:通过掩码(Mask)禁止位置 \(i\) 看到未来位置 \(j>i\)。实现上通常是在 softmax 前把被禁止位置的打分加上一个极小值(如 \(-\infty\))。

注意力机制在训练阶段和推理阶段都会执行。区别在于:训练时通常一次性输入整段序列(Teacher Forcing)并使用因果掩码;推理时逐 token 解码,并结合 KV Cache 避免重复计算历史。

Cross-Attention

交叉注意力(Cross-Attention)让一个序列“去读另一个序列”。在 Encoder–Decoder Transformer 里:解码器当前状态提供 Query,编码器输出提供 Key/Value。若编码器输出为 \(H_{\text{src}}\in\mathbb{R}^{L_{\text{src}}\times d}\),解码器输入为 \(H_{\text{tgt}}\in\mathbb{R}^{L_{\text{tgt}}\times d}\),则

\[Q=H_{\text{tgt}}W_Q,\quad K=H_{\text{src}}W_K,\quad V=H_{\text{src}}W_V\] \[\mathrm{CrossAttn}(H_{\text{tgt}},H_{\text{src}})=\mathrm{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}}\right)V\]

它与自注意力(Self-Attention)的区别仅在于 \(K,V\) 来自“别的序列”,因此能把“源序列信息”按需注入到“目标序列生成”中。

在交叉编码器(Cross-Encoder)语境里,很多实现并不显式写 cross-attention:它们把两段文本拼接成一个序列,用全连接自注意力直接建模跨序列交互;从效果上看等价于“允许任意 token 互相注意”。

Decoder-only 架构本身没有 cross-attention 子层;只有在做 Seq2Seq(有 encoder 输出)或显式引入外部记忆(Memory)时,才会在解码器里加入 cross-attention。

KV Cache

KV Cache(Key-Value Cache)是自回归(Autoregressive)解码的关键工程优化:生成到第 \(t\) 步时,历史 token 的 Key/Value 已经在前序计算中得到;缓存它们可以避免每一步都重算整段历史的 K/V。

形式上,单层注意力在序列长度为 \(L\) 时需要缓存:

\[K,V\in\mathbb{R}^{L\times n_{\text{kv}}\times d_k}\]

其中 \(n_{\text{kv}}\) 是 KV 头数量(对标准多头注意力通常等于头数;对 GQA/MQA 通常更小),\(d_k\) 是每个 head 的维度。忽略实现细节(对齐、分块、paged layout)时,KV Cache 的显存规模近似线性增长:

\[\mathrm{Mem}_{\mathrm{KV}}\approx 2\cdot N_{\text{layers}}\cdot B\cdot L\cdot n_{\text{kv}}\cdot d_k\cdot \text{bytes}\]

这里前面的 2 来自同时缓存 K 与 V;\(B\) 是并发请求(batch)数;\(\text{bytes}\) 是每元素字节数(FP16/BF16 为 2)。因此 KV Cache 常成为长上下文与高并发推理的显存瓶颈。

典型优化方向包括:减少 \(n_{\text{kv}}\)(GQA/MQA)、压缩 KV(KV 量化/低秩/选择性缓存)、以及改进分配与复用(Paged Attention、前缀缓存(Prompt Caching))。

FlashAttention
为什么需要 FlashAttention

FlashAttention 首先要解决的不是“注意力公式错了”,而是标准注意力(Standard Attention)在长序列上的 中间张量 IO 成本 过高。标准缩放点积注意力(Scaled Dot-Product Attention)可写为:

\[S=\frac{QK^\top}{\sqrt{d_k}},\quad P=\mathrm{softmax}(S),\quad O=PV\]

其中:

  • \(Q\in\mathbb{R}^{N\times d_k}\):查询矩阵(Query Matrix),\(N\) 是序列长度, \(d_k\) 是每个 head 的查询/键维度。
  • \(K\in\mathbb{R}^{N\times d_k}\):键矩阵(Key Matrix),与 \(Q\) 做点积打分。
  • \(V\in\mathbb{R}^{N\times d_v}\):值矩阵(Value Matrix),\(d_v\) 是每个 head 的值维度。
  • \(S\in\mathbb{R}^{N\times N}\):注意力分数矩阵(Score Matrix),其中 \(S_{ij}\) 表示第 \(i\) 个 query 对第 \(j\) 个 key 的未归一化打分。
  • \(P\in\mathbb{R}^{N\times N}\):softmax 归一化后的注意力权重矩阵(Attention Probability Matrix)。
  • \(O\in\mathbb{R}^{N\times d_v}\):最终输出矩阵(Output Matrix)。

问题集中在 \(S\) 和很多实现中的 \(P\):它们都是 \(N\times N\) 规模。序列一长,中间矩阵就会迅速膨胀。计算复杂度依然是 \(\mathcal{O}(N^2)\) 级别,但在 GPU 上更先撞上的往往不是算力上限,而是高带宽显存(High Bandwidth Memory, HBM)与片上共享内存 / SRAM(Static Random Access Memory, SRAM)之间的数据搬运成本。

传统实现通常经历三步:先算出整个 \(S=QK^\top\) 并写回显存;再把它读出来做 softmax,得到 \(P\) 并再次写回;最后再把 \(P\) 读出来与 \(V\) 相乘得到 \(O\)。这意味着真正拖慢速度的往往不是矩阵乘法本身,而是对 \(N^2\) 中间结果的反复显式物化(Materialization)与反复搬运。

一个直接类比是流水线工厂。普通注意力像“先把全部半成品都堆进仓库,再统一拿出来做下一道工序”;仓库本身就成了瓶颈。FlashAttention 则像“边加工边流转”的流水线:中间块只在车间里短暂停留,不建立巨大的中间仓库。

核心思想

FlashAttention 的核心可以压缩成一句话:分块(Tiling)+ 在线 softmax(Online Softmax)+ 融合输出(Fused Output Accumulation)。

它并不改变注意力的数学目标,仍然精确计算同一个 \(\mathrm{softmax}(QK^\top/\sqrt{d_k})V\);它改变的是计算顺序与中间结果的存储方式。具体来说,FlashAttention 不再把整个 \(N\times N\) 的注意力矩阵一次性算完并落到 HBM 中,而是把 \(Q,K,V\) 切成若干小块(tiles),每次只在 SRAM 中处理一小块分数、归一化和输出累加。

设查询块(query tile)为 \(Q_i\in\mathbb{R}^{B_q\times d_k}\),键块和值块分别为 \(K_j\in\mathbb{R}^{B_k\times d_k}\) 与 \(V_j\in\mathbb{R}^{B_k\times d_v}\)。这里 \(B_q\) 和 \(B_k\) 是 tile 大小,远小于完整序列长度 \(N\)。FlashAttention 每次只把这样的局部块搬进 SRAM,在块内完成当前 query tile 对当前 key/value tile 的全部贡献计算。

数学本质:块级注意力与在线 softmax

对第 \(i\) 个 query 块和第 \(j\) 个 key/value 块,先计算块级分数矩阵:

\[S_{ij}=\frac{Q_iK_j^\top}{\sqrt{d_k}},\qquad S_{ij}\in\mathbb{R}^{B_q\times B_k}\]

其中:

  • \(S_{ij}\):当前块内的注意力打分矩阵。
  • \(S_{ij}[r,c]\):query 块中第 \(r\) 行与 key 块中第 \(c\) 行的打分。
  • \(\sqrt{d_k}\):缩放因子,用于抑制点积随维度增长而导致的 softmax 饱和。

难点在于 softmax 的分母依赖整行所有 key:对一个 query 而言,必须把它对所有位置的打分都考虑进去,才能完成归一化。FlashAttention 的关键突破是:不必先看到整行全部元素,再做 softmax;可以用在线算法维护“到目前为止的最大值、分母和分子累加量”,随着块不断读入而精确更新。

对当前 query 块 \(Q_i\),FlashAttention 维护三个按行统计的状态:

\[\mathbf{m}_i\in\mathbb{R}^{B_q},\qquad \boldsymbol{\ell}_i\in\mathbb{R}^{B_q},\qquad R_i\in\mathbb{R}^{B_q\times d_v}\]
  • \(\mathbf{m}_i\):每个 query 行到目前为止见过的最大分数(row-wise running max)。
  • \(\boldsymbol{\ell}_i\):每个 query 行当前的 softmax 分母累加量。
  • \(R_i\):每个 query 行对输出向量的未归一化加权和(unnormalized weighted sum)。

初始时可设:

\[\mathbf{m}_i=-\infty,\qquad \boldsymbol{\ell}_i=\mathbf{0},\qquad R_i=0\]

当读入第 \(j\) 个块时,先求该块每一行的局部最大值:

\[\tilde{\mathbf{m}}_{ij}=\mathrm{rowmax}(S_{ij})\]

这里 \(\mathrm{rowmax}(\cdot)\) 表示对矩阵每一行取最大值,因此输出是长度为 \(B_q\) 的向量。再把旧最大值和当前块最大值合并成新的全局参考点:

\[\mathbf{m}_i^{\mathrm{new}}=\max\!\left(\mathbf{m}_i,\tilde{\mathbf{m}}_{ij}\right)\]

这里的 \(\max\) 是逐元素最大值(element-wise max),因为每个 query 行都维护自己的 softmax 参考值。

接着把当前块的指数项按新参考点重写:

\[P_{ij}=\exp\!\left(S_{ij}-\mathbf{m}_i^{\mathrm{new}}\mathbf{1}^\top\right)\]

其中:

  • \(P_{ij}\in\mathbb{R}^{B_q\times B_k}\):当前块中按新最大值平移后的指数权重。
  • \(\mathbf{1}\in\mathbb{R}^{B_k}\):全 1 向量,用于把 \(\mathbf{m}_i^{\mathrm{new}}\) 广播到块内每一列。
  • \(\exp(\cdot)\):逐元素指数函数。

然后更新分母累加量:

\[\boldsymbol{\ell}_i^{\mathrm{new}}=\exp\!\left(\mathbf{m}_i-\mathbf{m}_i^{\mathrm{new}}\right)\odot \boldsymbol{\ell}_i+\mathrm{rowsum}(P_{ij})\]

这里 \(\odot\) 表示逐元素乘法, \(\mathrm{rowsum}(P_{ij})\) 表示对 \(P_{ij}\) 每一行求和。这个式子的含义是:旧块已经累积的分母,先因为参考最大值改变而按 \(\exp(\mathbf{m}_i-\mathbf{m}_i^{\mathrm{new}})\) 重新缩放,再加上当前块的新贡献。

再更新输出分子的累加量:

\[R_i^{\mathrm{new}}=\mathrm{Diag}\!\left(\exp\!\left(\mathbf{m}_i-\mathbf{m}_i^{\mathrm{new}}\right)\right)R_i+P_{ij}V_j\]

其中:

  • \(\mathrm{Diag}(\cdot)\):把向量放到对角线上形成对角矩阵,用于按行缩放 \(R_i\)。
  • \(P_{ij}V_j\in\mathbb{R}^{B_q\times d_v}\):当前块对输出的新增贡献。

所有 \(K_j,V_j\) 块处理完之后,当前 query 块的最终输出为:

\[O_i=\mathrm{Diag}\!\left((\boldsymbol{\ell}_i)^{-1}\right)R_i\]

这里 \((\boldsymbol{\ell}_i)^{-1}\) 表示对向量每个元素取倒数,作用是把“未归一化加权和”除以 softmax 分母,从而得到真正的注意力输出。

为什么这仍然是精确 softmax

FlashAttention 的关键并不是“近似 softmax”,而是“换一种保持数值等价的累计方式”。设某一行已经处理过的旧分数集合为 \(\mathcal{A}\),其旧最大值为 \(m_{\mathrm{old}}\),旧分母为:

\[\ell_{\mathrm{old}}=\sum_{x\in\mathcal{A}} e^{x-m_{\mathrm{old}}}\]

新读入一块分数集合 \(\mathcal{B}\) 后,若新的全局最大值变成 \(m_{\mathrm{new}}\),则旧部分相对于新参考点的分母贡献恰好变成:

\[\sum_{x\in\mathcal{A}} e^{x-m_{\mathrm{new}}}=e^{m_{\mathrm{old}}-m_{\mathrm{new}}}\sum_{x\in\mathcal{A}} e^{x-m_{\mathrm{old}}}=e^{m_{\mathrm{old}}-m_{\mathrm{new}}}\ell_{\mathrm{old}}\]

这正是在线更新公式里那一项缩放因子的来源。分子累加量 \(R_i\) 也是同样的道理:旧部分先按新参考点缩放,再加上新块贡献。因此块级处理结束后得到的 \(O_i\) 与一次性对整行做 softmax 再乘 \(V\) 的结果完全一致。

与普通 Attention 的区别
维度 普通 Attention FlashAttention
数学目标 计算 \(\mathrm{softmax}(QK^\top/\sqrt{d_k})V\) 计算同一个精确结果,不改目标函数
中间矩阵 常显式存 \(S\),很多实现还显式存 \(P\) 不显式存完整 \(N\times N\) 矩阵,只保留 tile 级临时块与行级累加状态
计算顺序 先全部算完分数,再整体 softmax,再乘 \(V\) 边读块边更新 softmax,边把当前块对输出的贡献累加进去
显存特征 中间激活常呈 \(\mathcal{O}(N^2)\) 增长 额外中间存储近似降到 \(\mathcal{O}(N)\) 级别
性能瓶颈 更容易受 HBM 读写限制,属于强 memory-bound 场景 显著减少 HBM 往返,更接近 compute-bound
为什么它会快

FlashAttention 更快的根源并不是把 \(\mathcal{O}(N^2)\) 计算复杂度改成了更低阶,而是把 IO 模式改对了。它的核心收益主要来自四点:

  • 减少 HBM 访问:不再反复把 \(S\) 与 \(P\) 这类 \(N^2\) 中间张量写回、读回。
  • 提升 SRAM 复用:一个 tile 被搬进片上后,会在同一块内连续完成分数计算、归一化和输出累加。
  • 算子融合(Kernel Fusion):原本分散的 \(QK^\top\)、softmax、\(PV\) 被压成一条更短的数据通路。
  • 数值稳定:在线 softmax 仍然使用减最大值(max trick),避免指数溢出,也避免了“先大矩阵 softmax 再回写”带来的额外数值压力。

因此,FlashAttention 的本质不是“更少的数学”,而是“更少的无效搬运”。从硬件视角看,它把一个明显受内存带宽制约的算子,改造成更能吃满矩阵乘法单元和 Tensor Core 的实现。

复杂度与工程直觉

复杂度上需要严格区分“算了多少”和“存了多少”。FlashAttention 与普通注意力在算术复杂度上仍然同阶,因为每个 query 与每个 key 的交互并没有消失:

\[\text{FLOPs: }\mathcal{O}(N^2d_k)\quad\text{vs.}\quad \mathcal{O}(N^2d_k)\]

但中间激活的显存复杂度发生了根本变化。若只看注意力算子额外需要保留的中间结果,则:

\[\text{普通 Attention: }\mathcal{O}(N^2),\qquad \text{FlashAttention: }\mathcal{O}(N)\]

这里的 \(\mathcal{O}(N)\) 指的是按行维护的 softmax 统计量与输出累加量;tile 临时块的大小由 \(B_q,B_k\) 控制,不随完整序列平方增长。工程直觉可以概括为:算力阶数没变,但仓库规模从平方级中间仓库变成了线性级流水线缓存。

一个极简伪代码
1
2
3
4
5
6
7
8
9
10
11
12
for each query tile Q_i:
    m_i = -inf
    l_i = 0
    R_i = 0
    for each key/value tile (K_j, V_j):
        S_ij = Q_i K_j^T / sqrt(d_k)
        m_new = max(m_i, rowmax(S_ij))
        P_ij = exp(S_ij - m_new)
        l_i = exp(m_i - m_new) * l_i + rowsum(P_ij)
        R_i = diag(exp(m_i - m_new)) * R_i + P_ij * V_j
        m_i = m_new
    O_i = diag(1 / l_i) * R_i

这段伪代码对应的正是“边看块、边归一化、边输出”的流水线结构。与普通实现相比,最大的变化不是公式,而是调度顺序。

反向传播(Backward):为什么也能不存 \(N^2\)

FlashAttention 的关键价值不仅在前向传播(Forward Pass),也在反向传播(Backward Pass)。训练时真正吃显存的不只是前向输出,还包括为了求梯度而保留的中间激活。如果 backward 仍然要求把完整的 \(S\) 或 \(P\) 存下来,那么前向省出来的显存会被反向阶段重新吃掉。因此,FlashAttention backward 的核心原则与前向一致:不保存 \(N\times N\) 注意力矩阵,而是在 backward 中按块重算(recompute)它们。

设前向定义为:

\[S=\frac{QK^\top}{\sqrt{d_k}},\qquad P=\mathrm{softmax}(S),\qquad O=PV\]

设损失函数为 \(\mathcal{L}\),并记上游传回的输出梯度为:

\[G=\frac{\partial \mathcal{L}}{\partial O},\qquad G\in\mathbb{R}^{N\times d_v}\]

这里:

  • \(\mathcal{L}\):整个模型的标量损失(scalar loss)。
  • \(G\):损失对注意力输出 \(O\) 的梯度,也就是 backward 进入注意力层时收到的上游信号。

普通 attention 的 backward 可以按链式法则拆成四步。先对 \(V\) 求梯度:

\[\frac{\partial \mathcal{L}}{\partial V}=P^\top G\]

这个式子表示:某个 value 向量 \(v_j\) 对多少个 query 产生了贡献,就会按相应注意力权重 \(P_{ij}\) 把这些上游梯度累加回来。

再对概率矩阵 \(P\) 求梯度:

\[\frac{\partial \mathcal{L}}{\partial P}=GV^\top\]

这里 \(\frac{\partial \mathcal{L}}{\partial P}\in\mathbb{R}^{N\times N}\) 的第 \((i,j)\) 项表示:若第 \(i\) 行第 \(j\) 列的注意力权重略有变化,会怎样影响损失。

关键一步是 softmax 的梯度。对第 \(i\) 行,记 \(p_i\) 为第 \(i\) 行概率向量, \(g_i^P\) 为 \(\frac{\partial \mathcal{L}}{\partial P}\) 的第 \(i\) 行,则:

\[\frac{\partial \mathcal{L}}{\partial s_i}=p_i\odot \left(g_i^P-\delta_i\mathbf{1}\right),\qquad \delta_i=\sum_{j=1}^{N} g_{ij}^P p_{ij}\]

其中:

  • \(s_i\):分数矩阵 \(S\) 的第 \(i\) 行。
  • \(\odot\):逐元素乘法。
  • \(\delta_i\):第 \(i\) 行 softmax Jacobian 压缩后的标量项,用来扣掉“整行归一化”带来的耦合影响。
  • \(\mathbf{1}\in\mathbb{R}^{N}\):全 1 向量。

把所有行拼起来,可写成矩阵形式:

\[D=\mathrm{rowsum}\!\left(\frac{\partial \mathcal{L}}{\partial P}\odot P\right),\qquad \frac{\partial \mathcal{L}}{\partial S}=P\odot \left(\frac{\partial \mathcal{L}}{\partial P}-D\mathbf{1}^\top\right)\]

这里 \(D\in\mathbb{R}^{N}\) 是逐行标量向量,第 \(i\) 个分量就是 \(\delta_i\)。最后再通过 \(S=QK^\top/\sqrt{d_k}\) 回传到 \(Q\) 与 \(K\):

\[\frac{\partial \mathcal{L}}{\partial Q}=\frac{\partial \mathcal{L}}{\partial S}\frac{K}{\sqrt{d_k}},\qquad \frac{\partial \mathcal{L}}{\partial K}=\left(\frac{\partial \mathcal{L}}{\partial S}\right)^\top\frac{Q}{\sqrt{d_k}}\]

若直接照这些公式实现,最大问题是:看起来必须先拿到完整的 \(P\) 和 \(\frac{\partial \mathcal{L}}{\partial P}\),而它们又都是 \(N\times N\)。FlashAttention backward 的突破在于,真正必须永久保存的量远比这少。

第一,前向阶段只需保存每一行的 log-sum-exp 统计量(Log-Sum-Exp Statistics),而不必保存整张 \(P\)。若前向某一行的最大值为 \(m_i\),归一化因子为 \(\ell_i\),则可存:

\[L_i=m_i+\log \ell_i=\log\sum_{j=1}^{N} e^{S_{ij}}\]

这里 \(L_i\) 是第 \(i\) 行 softmax 分母的对数。只要 backward 时重新算出某个块的分数 \(S_{ij}\),就可以把该块的概率精确重建为:

\[P_{ij}=\exp\!\left(S_{ij}-L_i\mathbf{1}^\top\right)\]

这说明 backward 不需要读取前向保存下来的整张 \(P\);它只需要 \(Q\)、\(K\)、行级统计量 \(L_i\),就能按块把局部概率重新算出来。

第二,softmax backward 中的行级标量 \(\delta_i\) 也可以不通过整张 \(\frac{\partial \mathcal{L}}{\partial P}\) 显式求和,而是用一个更紧凑的等价式:

\[\delta_i=\sum_{j=1}^{N} g_{ij}^P p_{ij}=g_i^\top o_i\]

其中 \(g_i\) 是上游梯度矩阵 \(G\) 的第 \(i\) 行, \(o_i\) 是前向输出 \(O\) 的第 \(i\) 行。这个恒等式来自:

\[g_i^P=g_iV^\top,\qquad o_i=p_iV\]

于是:

\[\sum_{j=1}^{N} g_{ij}^P p_{ij}=\sum_{j=1}^{N}(g_i v_j^\top)p_{ij}=g_i\left(\sum_{j=1}^{N}p_{ij}v_j\right)^\top=g_i o_i^\top\]

这一步非常关键,因为它说明 softmax backward 所需的行级校正项 \(\delta_i\),可以直接由前向输出 \(O\) 和上游梯度 \(G\) 得到,而不需要显式展开整个 \(N\times N\) 概率矩阵。

因此,FlashAttention backward 的块级流程可以概括为:

  1. 读取一个 query tile \(Q_i\)、对应输出 tile \(O_i\)、上游梯度 tile \(G_i\),以及该 tile 的行级统计量 \(L_i\)。
  2. 逐块读取 \(K_j,V_j\),重算当前块分数 \(S_{ij}=Q_iK_j^\top/\sqrt{d_k}\)。
  3. 由 \(L_i\) 重建当前块概率 \(P_{ij}=\exp(S_{ij}-L_i\mathbf{1}^\top)\)。
  4. 用 \(G_iV_j^\top\) 得到当前块的 \(\frac{\partial \mathcal{L}}{\partial P_{ij}}\),再结合 \(\delta_i=g_i^\top o_i\) 计算当前块的 \(\frac{\partial \mathcal{L}}{\partial S_{ij}}\)。
  5. 把该块对 \(dQ_i\)、\(dK_j\)、\(dV_j\) 的贡献直接累加到输出梯度中。

写成块级公式,就是:

\[dV_j \mathrel{+}= P_{ij}^\top G_i\] \[dP_{ij}=G_iV_j^\top\] \[dS_{ij}=P_{ij}\odot \left(dP_{ij}-\delta_i\mathbf{1}^\top\right)\] \[dQ_i \mathrel{+}= dS_{ij}\frac{K_j}{\sqrt{d_k}},\qquad dK_j \mathrel{+}= dS_{ij}^\top\frac{Q_i}{\sqrt{d_k}}\]

这里 \(dQ_i,dK_j,dV_j\) 分别表示当前块对 \(\frac{\partial \mathcal{L}}{\partial Q}\)、\(\frac{\partial \mathcal{L}}{\partial K}\)、\(\frac{\partial \mathcal{L}}{\partial V}\) 的局部累加贡献;符号 \(\mathrel{+}=\) 表示“把当前块的贡献继续累加到已有梯度里”,而不是一次性覆盖赋值。

这个设计的代价是:backward 需要重算部分前向中的块级分数和概率,因此算术量会比“全存中间矩阵”的朴素实现略多;但现代 GPU 上,额外矩阵乘法通常比反复读写 \(N^2\) HBM 张量便宜得多。于是 FlashAttention backward 的工程哲学可以概括为:用少量重算换大幅节省显存与 IO。

一个直观类比是:普通 backward 像把前向每一道工序的全部半成品都堆满仓库,等回头算梯度时再逐件取出来;FlashAttention backward 则更像保留每条流水线的关键账本和最终产物,真正需要某段中间细节时,再按原流程快速重演一小段。仓库变小了,流水线也更连贯。

FlashAttention v1:算法层优化

FlashAttention v1 的核心贡献在于算法层:它首先把“注意力必须显式存下 \(N\times N\) 矩阵”这一默认前提打破,给出了一种精确、稳定、块级流式的注意力实现。v1 的关键词是 memory optimization:让注意力从“被中间矩阵拖慢”转向“更像一个流式矩阵核”。

在这个阶段,最重要的不是把 GPU 跑满,而是先证明:不物化注意力矩阵,仍然可以精确完成前向与反向计算,并把显存墙显著后移。它解决的是“能不能这样算”的问题。

FlashAttention v2:并行层优化

FlashAttention v2 保留了 v1 的数学等价性与在线 softmax 思路,但把优化重点从“省内存”推进到“把 GPU 吃满”。它关注的是并行工作划分(Work Partitioning):如何把 query 块、head 维度、batch 维度和线程块(Thread Block)组织得更均匀,让更多流式多处理器(Streaming Multiprocessor, SM)同时处于忙碌状态。

v1 的一个现实限制是:虽然显存访问已经大幅减少,但某些场景下并行粒度仍然偏粗,导致 GPU 占用率(Occupancy)不够高。v2 因此重写了 kernel 调度策略,让同一个大任务能够拆给更多线程块并行处理,同时尽量减少线程同步(Synchronization)带来的停顿。

从本质上看,v2 做的不是“新的注意力公式”,而是“同一公式在 GPU 上的更优任务分发”。如果说 v1 的问题是“别把中间矩阵落盘”,那么 v2 的问题就是“别让 GPU 的很多 SM 闲着”。

这也是 v2 在反向传播(Backward Pass)上价值很高的原因。前向只解决一半问题;训练吞吐还取决于 backward kernel 能否在不恢复 \(N^2\) 显存占用的前提下保持高并行度。v2 在这一点上比 v1 更成熟,因此更适合作为训练时的高性能默认实现。

FlashAttention v3:硬件协同优化

FlashAttention v3 的重点进一步从并行层推进到硬件协同设计(Hardware Co-design),尤其针对 NVIDIA Hopper / H100 这类新一代 GPU。它不再只关心“块怎么切、线程怎么分”,而是进一步追问:数据加载、矩阵计算、结果写回能否形成异步流水线。

v3 的几个代表性关键词包括:

  • 异步流水线(Asynchronous Pipeline):加载下一块数据时,当前块已经在计算,从而重叠 load 与 compute。
  • Warp 专职分工(Warp Specialization):不同 warp 分别负责搬运、计算、写回,减少彼此等待。
  • Tensor Core 深度利用:tile 尺寸与数据流更贴近 Tensor Core 最擅长的矩阵乘法路径。
  • 更适合低精度数据类型:如 FP16、BF16,以及面向新硬件的 FP8 路径。

如果把 v1 看成“算法上不建大仓库”,把 v2 看成“让更多工人同时开工”,那么 v3 更像“把整座工厂变成不停顿的装配线”:搬运、计算、写回三条流水同时进行,尽量让每一级硬件资源都不空转。

版本演进总结
版本 主要优化层次 核心目标 本质关键词
v1 算法层 避免 \(N^2\) 中间矩阵物化 分块、在线 softmax、融合计算
v2 并行层 提高 Occupancy,减少同步,提升训练吞吐 更细粒度 work partitioning
v3 硬件层 让 load / compute / store 深度重叠 异步流水线、warp specialization、Tensor Core 对齐

因此,FlashAttention 的演进可以概括为三层推进:v1 解决“能否不存矩阵”、v2 解决“如何把 GPU 跑满”、v3 解决“如何贴着新硬件的数据通路跑”。三代版本的数学目标完全一致,差异主要体现在实现层面对 IO、并行性与硬件流水的挖掘深度。

线性注意力(Linear Attention)

线性注意力(Linear Attention)不是“更快的实现”,而是对注意力公式做近似/改写,把复杂度从 \(\mathcal{O}(L^2)\) 降到近似 \(\mathcal{O}(L)\)。一类常见思路是用核函数特征映射(Kernel Feature Map)近似 softmax kernel:把 \(\exp(q^\top k)\) 写成 \(\phi(q)^\top \phi(k)\),从而把“先算 \(QK^\top\) 再乘 \(V\)”改写为“先聚合 \(\phi(K)\) 与 \(V\) 再与 \(\phi(Q)\) 交互”。

一个典型形式(省略实现细节)是:

\[\mathrm{Attn}(Q,K,V)\approx \frac{\phi(Q)\big(\phi(K)^\top V\big)}{\phi(Q)\big(\phi(K)^\top \mathbf{1}\big)}\]

线性注意力更适合“极长序列下的吞吐/显存”目标,但它往往需要在表示、数值稳定性与效果之间做取舍;在通用 LLM 上,主流路径仍然是“精确注意力 + 更好的内核 + 更强的位置/缓存工程”,线性注意力更多作为特定场景或混合架构的选项。

状态空间模型(State Space Model, SSM / Mamba)

状态空间模型(State Space Model, SSM)用“隐状态递推(State Recurrence)”建模序列:每步用一个小状态 \(s_t\) 累积历史信息,避免显式构造 \(L\times L\) 注意力矩阵。经典线性 SSM 的抽象形式是:

\[s_{t+1}=As_t+Bx_t,\quad y_t=Cs_t+Dx_t\]

近年的 Mamba 等结构可理解为在此基础上引入输入依赖的选择性/门控机制(Selective / Input-dependent Dynamics),使得模型在保持线性复杂度的同时具备更强的表征能力。工程上,SSM 的优势通常体现在长序列吞吐与显存;代价是“按内容随机访问历史”的能力不如注意力直观,因此在需要强检索/对齐的任务上常见的是混合架构或与注意力模块组合使用。

路线 序列复杂度 显存瓶颈 强项 典型代价
精确注意力(FlashAttention 等) \(\mathcal{O}(L^2)\) 注意力中间张量 + KV Cache 强检索/对齐;通用能力稳健 长上下文成本陡增;需要大量工程优化(GQA/分页/缓存)
线性注意力 近似 \(\mathcal{O}(L)\) 缓存布局与数值稳定性 极长序列吞吐/显存友好 近似误差;需要专门核函数/特征映射设计
SSM / Mamba \(\mathcal{O}(L)\) 状态与算子实现 长序列吞吐;流式友好 随机访问历史不如注意力直观;常需混合架构补齐能力
GQA(Grouped Query Attention)

GQA(Grouped Query Attention)用“更少的 KV 头”服务“更多的 Query 头”:多个 Query heads 共享同一组 Key/Value heads,从而显著降低 KV Cache 的显存与带宽压力。极端情形 \(n_{\text{kv}}=1\) 称为 MQA(Multi-Query Attention)。

对比标准多头注意力(MHA):MHA 通常 \(n_{\text{kv}}=n_q\);而 GQA 让 \(n_{\text{kv}}\ll n_q\),注意力仍然按 head 计算,但 KV 表示被“组共享”。在长上下文推理中,它带来的收益往往比对算力的节省更关键:KV Cache 与内存带宽近似按 \(n_{\text{kv}}/n_q\) 比例下降。

代价是表示自由度下降:不同 Query heads 看到的 Key/Value 空间更相似,可能带来一定质量损失;工程上通常通过更大的模型维度、更多 Query heads、或更强的 FFN 来补偿。

KV 压缩注意力(Latent KV / MLA)

GQA/MQA 通过减少 KV 头数降低缓存;更激进的路线是对 KV 表示做压缩(Compression):把每个 token 的 Key/Value 先映射到一个更低维的潜空间(Latent Space)并缓存潜变量,再在需要时把潜变量“解码”成用于注意力计算的表示。这类方法常被概括为 Latent KV 或 MLA(Multi-head Latent Attention)一类思路。

它解决的是同一个瓶颈:长上下文推理时,KV Cache 的存储与带宽是主导成本。Latent KV 的收益通常体现在“同等显存下更长上下文/更高并发”;代价是算子更复杂、实现更依赖内核与数值细节,并且压缩会引入表示损失,需要训练配方与模型容量补偿。

前馈网络(FFN)
MLP

Transformer 层里的前馈网络(Feed-Forward Network, FFN)本质上就是一个位置前馈(Position-wise)MLP:它对每个 token 的向量独立作用,不在序列维度做混合(序列维度的混合由注意力完成)。典型形式是两层线性变换加非线性:

\[\mathrm{FFN}(x)=W_2\,\sigma(W_1 x+b_1)+b_2\]

其中 \(\sigma\) 常用 GELU/ReLU,且通常设置 \(d_{\text{ff}}\gg d_{\text{model}}\)(先升维再降维)以提升表达能力。很多教材把它叫 “MLP 模块”,强调的是它在每层里与注意力并列构成 Transformer block 的两大子层。

很多现代大模型会用门控线性单元(Gated Linear Unit, GLU)的变体替代“Linear → 激活 → Linear”的经典 FFN,例如 SwiGLU(Swish-Gated Linear Unit):把中间层拆成两路投影并逐元素相乘作为门控:

\[\mathrm{SwiGLU}(x)=W_2\Big(\mathrm{SiLU}(xW_1)\odot (xW_3)\Big)\]

门控(Gating)让 FFN 具备“按特征选择通过/抑制”的能力,在相近参数规模下常带来更好的效果与训练稳定性。

“升维(Up-Projection)如何填充新增维度”在实现上就是矩阵乘法:每个新增特征维度都是输入向量的一个线性组合,而不是“补零”。若 \(x\in\mathbb{R}^{d_{\text{model}}}\)、\(W_1\in\mathbb{R}^{d_{\text{model}}\;\times d_{\text{ff}}}\),则 \(h=W_1^\top x+b_1\in\mathbb{R}^{d_{\text{ff}}}\),第 \(j\) 维是 \(h_j=\sum_i x_i (W_1)_{ij}+b_{1j}\)。

“降维(Down-Projection)如何合并多余维度”同理:线性层把高维特征再做一次线性组合回 \(d_{\text{model}}\)。这不是简单丢弃维度,而是学习一个把有用特征聚合回低维表示的映射。

从能力角度看,增大 \(d_{\text{ff}}\) 会增加中间表征的自由度(Degree of Freedom, DOF)与参数量,使模型能构造更丰富的非线性特征;但“维度更高”不等于“信息一定更多”,它提供的是可学习的表示空间与容量(Capacity),是否有效取决于数据与训练目标。

Mixture of Experts(MoE)

MoE(Mixture of Experts)把 FFN 子层替换成“多个专家网络(Experts)+ 路由器(Router/Gate)”:对每个 token,路由器只激活少数几个专家(Top-k),因此计算量近似不随专家总数线性增长,但参数容量可以大幅增加。

一种常见形式(概念表达)是:

\[\mathrm{MoE}(x)=\sum_{e\in\mathrm{TopK}(x)} p_e(x)\,\mathrm{Expert}_e(x),\quad p(x)=\mathrm{softmax}(W_g x)\]

其中 \(p_e(x)\) 是路由概率,专家通常就是不同参数的 FFN。工程实现会加入负载均衡(Load Balancing)损失,避免所有 token 都挤到少数专家导致容量瓶颈。

MoE 会“导致随机性”吗?结构本身不必然随机:若路由使用确定性的 top-k,且推理使用确定性算子,则同一输入在同一权重下输出应是确定的。训练阶段常见的随机性来自 dropout、路由噪声(noisy gating)、以及硬件/并行计算的非确定性;这些会影响训练轨迹,但不等价于“模型本质随机”。

归一化
Layer Normalization

层归一化(Layer Normalization, LayerNorm)在每个 token 的特征维度上做归一化(Normalization),与 BatchNorm 不同,它不依赖 batch 统计量,因此更适合变长序列与自回归推理。对向量 \(x\in\mathbb{R}^{d_{\text{model}}}\):

\[\mathrm{LN}(x)=\gamma\odot \frac{x-\mu}{\sqrt{\sigma^2+\epsilon}}+\beta,\quad \mu=\frac{1}{d}\sum_{i=1}^{d}x_i,\ \sigma^2=\frac{1}{d}\sum_{i=1}^{d}(x_i-\mu)^2\]

其中 \(\gamma,\beta\) 是可学习的缩放与平移参数(Learnable Scale/Shift)。当前主流的 Transformer 几乎都采用“token 内部归一化”,而不是跨 batch 的 BatchNorm:经典 Transformer、BERT、ViT 这一路架构以 LayerNorm 为主;许多更新的 Decoder-only 大模型则把每个残差块写成 Pre-Norm 结构,并进一步用 RMSNorm 取代标准 LayerNorm。

Pre-LN(Pre-LayerNorm)指先做归一化,再进入 Attention 或 MLP 子层,最后与残差分支相加;其典型形式可写为:

\[y=x+\mathrm{Sublayer}(\mathrm{LN}(x))\]

这种写法把归一化放进残差支路内部,有利于维持深层网络中的梯度流稳定。与之对应,Post-LN 会写成 \(y=\mathrm{LN}(x+\mathrm{Sublayer}(x))\);它在早期 Transformer 中出现较多,但随着层数、上下文窗口和参数规模持续增大,Pre-LN 在大模型训练中更常见。

BatchNorm 很少出现在 Transformer 主干中的原因,是它要求当前表示依赖同一 batch 里其他样本的统计量。对于序列模型,这会带来三个直接问题:第一,变长序列和 padding 会污染 batch 统计;第二,训练与推理使用的统计规则不同,自回归逐 token 生成时尤其不自然;第三,大模型训练常依赖小 batch、梯度累积和跨设备切分,batch 统计噪声更大。LayerNorm / RMSNorm 则完全避免了这些问题,因为每个 token 的归一化只依赖其自身特征。

RMS Normalization

RMSNorm(Root Mean Square Normalization)与 LayerNorm 的相同点是:都在每个 token 的特征维度上做归一化;不同点是 RMSNorm 不做去均值,只按均方根(RMS)缩放:

\[\mathrm{RMSNorm}(x)=\gamma\odot \frac{x}{\sqrt{\frac{1}{d}\sum_{i=1}^{d}x_i^2+\epsilon}}\]

其中 \(\gamma\in\mathbb{R}^{d}\) 是可学习缩放参数(通常不需要 \(\beta\))。RMSNorm 省掉了均值计算,算子更简单、数值更稳定,因此在许多 Decoder-only 大模型中被广泛采用(例如 LLaMA 系列)。

残差连接

残差连接(Residual Connection)把子层输出与输入做逐元素相加:

\[y=x+\mathrm{Sublayer}(x)\]

它不增加维度(Dimension)——前提是 \(x\) 与 \(\mathrm{Sublayer}(x)\) 形状相同。直觉上,子层只需要学习“在恒等映射(Identity)基础上加什么修正”,这让优化更容易,并为梯度提供一条稳定的捷径路径(Shortcut Path)。

关于“相加后混合、无法区分”的担忧:残差并不要求模型在表示上可逆分离,而是给模型提供了同时保留原信息与叠加新变换的能力。后续线性层与注意力可以在更高层特征空间里重新组织信息,使“跳跃信息”和“变换信息”以可用的方式共存。

输出处理

Transformer 主干(Backbone)本身的直接产物通常不是“类别”或“文字”,而是一组上下文化隐藏状态(Contextual Hidden States)。若输入序列长度为 \(T\),模型宽度为 \(d_{\text{model}}\),经过最后一层后常得到:

\[H^{(L)}\in\mathbb{R}^{T\;\times d_{\text{model}}}\]

其中 \(L\) 是 Transformer 层数, \(T\) 是当前序列的 token 数,矩阵第 \(t\) 行 \(h_t^{(L)}\) 表示第 \(t\) 个 token 在吸收了上下文信息后的最终表示。输出处理(Output Processing)的任务,就是把这组隐藏状态映射到具体任务所需的输出空间:可以是词表概率、类别分数、序列标签、起止位置分数,或回归数值。

从隐藏状态到输出空间

最常见的输出处理是在线性读出(Linear Readout)层中,把 \(d_{\text{model}}\) 维隐藏状态投影到目标维度 \(d_{\text{out}}\)。若按 token 逐位置读出,可写成:

\[Z=HW_{\text{out}}+\mathbf{1}b^\top\]

这里 \(H\in\mathbb{R}^{T\;\times d_{\text{model}}}\) 是最后一层隐藏状态; \(W_{\text{out}}\in\mathbb{R}^{d_{\text{model}}\;\times d_{\text{out}}}\) 是输出投影矩阵; \(b\in\mathbb{R}^{d_{\text{out}}}\) 是偏置; \(\mathbf{1}\in\mathbb{R}^{T}\) 是全 1 列向量,用来把同一个偏置加到每个位置; \(Z\in\mathbb{R}^{T\;\times d_{\text{out}}}\) 则是每个位置对应的输出分数。若任务是词表预测,则 \(d_{\text{out}}=V\), \(V\) 是词表大小;若任务是 token 分类,则 \(d_{\text{out}}=C\), \(C\) 是标签类别数。

并非所有任务都对每个 token 独立读出。序列分类常从整段序列中先取一个聚合表示,再做线性映射。例如 BERT 类模型常使用 \([\mathrm{CLS}]\) 位置的隐藏状态 \(h_{\mathrm{CLS}}\),再输出:

\[z=h_{\mathrm{CLS}}W_c+b_c\]

其中 \(z\in\mathbb{R}^{C}\) 是整句的类别 logits。跨度抽取(Span Extraction)任务则常对每个位置分别给出“作为起点”和“作为终点”的分数;序列到序列任务中,解码器则对每个时间步读出一个词表分布。

语言模型中的输出处理

在 Decoder-only 或 Encoder-Decoder 的生成端,输出处理通常还包含最后一次归一化层(如 LayerNorm 或 RMSNorm)以及语言模型头(Language Modeling Head, LM Head)。概念上可写成:

\[\tilde H=\mathrm{Norm}(H^{(L)}),\qquad Z=\tilde H W_{\mathrm{vocab}}+\mathbf{1}b^\top\]

这里 \(\tilde H\in\mathbb{R}^{T\;\times d_{\text{model}}}\) 是最终归一化后的隐藏状态; \(W_{\mathrm{vocab}}\in\mathbb{R}^{d_{\text{model}}\;\times V}\) 是词表投影矩阵; \(Z\in\mathbb{R}^{T\;\times V}\) 是每个位置对整个词表的 logits。矩阵第 \(t\) 行 \(z_t\in\mathbb{R}^{V}\) 描述的是:当模型已经看到当前位置之前允许访问的上下文后,当前位置对每个候选 token 的偏好分数。

权重共享(Weight Tying)

语言模型里常把输入嵌入表 \(E\in\mathbb{R}^{V\;\times d_{\text{model}}}\) 与输出头权重绑定为同一组参数。若不共享,输出头通常写成 \(W_{\mathrm{vocab}}\in\mathbb{R}^{d_{\text{model}}\;\times V}\);若共享,则直接令

\[W_{\mathrm{vocab}}=E^\top\]

这不是把“两份数据塞进一个矩阵”,而是让同一个参数矩阵在前向计算的两个位置重复使用:输入阶段按 token id 取出 \(E\) 的某一行作为该 token 的嵌入;输出阶段则把隐藏状态 \(h\) 与所有 token 向量做点积,得到整张词表的 logits:

\[z=hE^\top+b\]

这里 \(z\in\mathbb{R}^{V}\),第 \(i\) 个分量 \(z_i=h\cdot E_i+b_i\) 表示当前隐藏状态 \(h\) 与第 \(i\) 个 token 向量 \(E_i\) 的匹配分数。输入嵌入回答“这个 token 进来时长什么样”,输出头回答“当前语境最像词表里的哪个 token”;Weight Tying 让这两种词向量语义共用同一个坐标系。

这里共享的是参数,不是样本。训练时,这张矩阵同时接收两类梯度:一类来自输入查表路径,更新当前 batch 真正出现过的 token 行;另一类来自输出 softmax 路径,推动隐藏状态与目标 token 更接近、与竞争 token 拉开。自动求导会把这两部分梯度加到同一份参数上,形成联合更新。因此它通常能减少参数量、增强输入与输出语义空间的一致性,并起到一定正则化(Regularization)作用。

只有在输入嵌入维度与输出读出维度一致时,这种共享才最直接。若模型在读出前额外引入了投影层,使输出维度不再等于 \(d_{\text{model}}\),则需要先做维度变换,或不共享。Weight Tying 因而是常见做法,但不是所有架构都必须采用的硬规则。

lm-output-head

从分数到最终结果

输出处理的最后一步,是把 logits 变成任务可用的结果。训练时,很多损失函数会直接接收 logits,例如交叉熵损失(Cross-Entropy Loss)内部会把 softmax 与负对数似然(Negative Log-Likelihood)合并计算,以提高数值稳定性。推理时,则通常再做显式后处理:分类任务对 logits 做 softmax 或 sigmoid 得到概率;序列标注任务可在 logits 之上接 CRF 解码;生成任务则对词表 logits 做 softmax 后,再通过贪心搜索(Greedy Decoding)、束搜索(Beam Search)、Top-k 采样或 Top-p 采样等策略选择下一个 token。

以生成任务为例,若当前位置的词表 logits 为 \(z_t\in\mathbb{R}^{V}\),则先得到条件分布:

\[p(x_{t+1}=i\mid x_{\le t})=\frac{e^{z_{t,i}}}{\sum_{j=1}^{V}e^{z_{t,j}}}\]

这里 \(V\) 是词表大小, \(z_{t,i}\) 是第 \(t\) 个位置对第 \(i\) 个候选 token 的 logit, \(p(x_{t+1}=i\mid x_{\le t})\) 则是在当前前缀 \(x_{\le t}\) 下,下一个 token 取第 \(i\) 个词的概率。解码策略的区别,不在于 logits 或 softmax 公式不同,而在于:拿到这组概率之后,究竟用什么规则选出真正输出的 token。

贪心搜索

贪心搜索(Greedy Decoding)是最直接的策略:每一步都选当前概率最大的那个 token。写成公式,就是

\[x_{t+1}=\arg\max_{i} \ p(x_{t+1}=i\mid x_{\le t})\]

它的优点是速度快、实现简单、结果确定;缺点是过于短视。因为它每一步都只看“眼前概率最高”,而不考虑“当前稍差一点、但后续整体更优”的路径。于是贪心搜索很容易陷入局部最优:第一步看起来最稳的选择,不一定能导向整句概率最好的结果。

直觉上,它像每到路口都选眼前最宽的一条路,而不回头评估整条路线是否更通畅。因此贪心适合需要稳定、低延迟输出的场景,但在开放生成任务里往往较保守,也更容易重复。

束搜索

束搜索(Beam Search)是在每一步同时保留多个高分候选前缀,而不是像贪心那样只保留 1 条路径。设束宽(Beam Width)为 \(B\),则在第 \(t\) 步,算法会维护 \(B\) 条当前最优候选序列;每条序列再向外扩展多个 token,最后从所有扩展结果中重新筛出新的 \(B\) 条最高分路径继续前进。

若一条候选序列为 \(x_{1:T}\),其常见打分方式是对数概率和:

\[\mathrm{score}(x_{1:T})=\sum_{t=1}^{T}\log p(x_t\mid x_{<t})\]

因为概率连乘会非常小,所以实现里通常比较对数概率之和,而不是直接比较概率乘积。有时还会加长度惩罚(Length Penalty),避免模型系统性偏爱过短序列。

束搜索的优点是全局性比贪心更强,常用于机器翻译、摘要等更强调整体序列质量的任务;缺点是计算量更高,而且它本质上仍是“找高分路径”的搜索,不会主动引入随机性,因此输出可能仍然偏保守、偏模板化。

Top-k 采样

Top-k 采样(Top-k Sampling)先把概率最高的 \(k\) 个 token 保留下来,其余 token 概率全部截断为 0,然后在这 \(k\) 个候选里重新归一化并随机采样。设保留下来的候选集合为 \(\mathcal{K}_k\),则采样分布可写成:

\[p_k(i)=
\begin{cases}
\frac{p_i}{\sum_{j\in \mathcal{K}_k}p_j}, & i\in \mathcal{K}_k\\
0, & i\notin \mathcal{K}_k
\end{cases}\]

这里 \(p_i\) 是 softmax 后原始概率, \(\mathcal{K}_k\) 是当前概率最高的 \(k\) 个 token 集合。这样做的效果是:极小概率的长尾 token 不再参与抽样,从而降低胡言乱语或离谱跳转的风险;同时又保留了随机性,不会像贪心那样永远输出同一条路径。

Top-k 的关键超参数是 \(k\)。 \(k\) 太小,分布会重新变得接近贪心; \(k\) 太大,又会把很多低质量候选放回来。它本质上是在“稳定性”和“多样性”之间做硬截断式折中。

Top-p 采样

Top-p 采样(Top-p Sampling, Nucleus Sampling)不固定保留多少个 token,而是先按概率从高到低排序,再取最小的前缀集合 \(\mathcal{N}_p\),使其累计概率至少达到阈值 \(p\):

\[\sum_{i\in \mathcal{N}_p} p_i \ge p\]

然后只在这个“概率核心区”里重新归一化并随机采样。与 Top-k 相比,Top-p 的保留集合大小是动态变化的:如果当前分布非常尖锐,可能只需要少数几个 token 就能覆盖 90% 或 95% 的概率质量;如果当前分布较平,保留下来的 token 数量就会自动增多。

这种自适应机制更贴合语言生成的实际状态:有些位置模型非常确定,例如固定短语或语法闭合,此时候选空间本来就应很小;有些位置模型不那么确定,例如开放内容展开,此时候选空间应更大。Top-p 因而通常比固定的 Top-k 更灵活,也是现代大模型推理中非常常见的采样策略。

温度与策略取舍

温度(Temperature)常与上述采样策略配合使用。若把 logits \(z_{t,i}\) 除以温度 \(\tau\) 后再做 softmax,则有:

\[p_\tau(i)=\frac{e^{z_{t,i}/\tau}}{\sum_{j=1}^{V}e^{z_{t,j}/\tau}}\]

当 \(\tau<1\) 时,分布会变尖,模型更保守;当 \(\tau>1\) 时,分布会变平,采样更发散。于是,解码策略的工程取舍可以概括为:

  • 贪心搜索:最快、最稳定,但最短视。
  • 束搜索:更重视整句高分路径,但计算更贵、表达更保守。
  • Top-k 采样:固定候选数,简单直接,易于控制长尾噪声。
  • Top-p 采样:候选数自适应,通常更自然、更适合开放生成。
重复惩罚与频率控制

仅靠解码策略本身,往往还不足以避免模型进入重复、啰嗦或机械回环的状态。例如开放生成时,模型可能连续输出相同短语,或不断在几个近义表达之间打转。工程上因此常在 logits 层再加入一类后处理规则:对已经出现过的 token 施加惩罚,从而改变下一步的候选分布。

最常见的一类是重复惩罚(Repetition Penalty)。它的思想很直接:若某个 token 已经在当前上下文中出现过,就下调它再次被选中的倾向。实现细节在不同框架里略有差异,一种常见写法是对已出现 token 的 logit \(z_i\) 施加按符号分段的缩放:

\[z_i'=
\begin{cases}
z_i / r, & z_i>0\\
z_i \cdot r, & z_i\le 0
\end{cases},\qquad r>1\]

这里 \(r\) 是重复惩罚系数。这样处理的目的,是在不破坏 logit 正负号语义的前提下,整体压低“已经出现过的 token 再次被选中”的优势。 \(r\) 越大,惩罚越强;过大则可能把正常重复也压掉,使输出变得生硬。

另一类常见控制项是 presence penalty(出现惩罚)与 frequency penalty(频次惩罚)。它们的共同目标是抑制重复,但力度来源不同:前者只关心“出现过没有”,后者关心“已经出现了多少次”。若原始 logit 为 \(z_i\),token \(i\) 在当前已生成文本中的出现次数为 \(c_i\),则一个常见抽象写法是:

\[z_i' = z_i - \lambda_{\mathrm{pres}}\mathbf{1}[c_i>0] - \lambda_{\mathrm{freq}}c_i\]

这里 \(\lambda_{\mathrm{pres}}\) 是 presence penalty 系数, \(\mathbf{1}[c_i>0]\) 是指示函数:只要 token \(i\) 出现过至少一次,就减去一个固定惩罚; \(\lambda_{\mathrm{freq}}\) 是 frequency penalty 系数, \(c_i\) 越大,惩罚越强。因此:

  • presence penalty 更像“出现过就提醒一次”,主要鼓励模型换新词、开新话题。
  • frequency penalty 更像“出现越多罚越重”,主要抑制机械重复和啰嗦堆叠。

三者的作用位置都在 softmax 之前:先修改 logits,再重新归一化成概率。它们不是在训练阶段改变模型参数,而是在推理阶段临时改写候选分布。因此,它们更像输出控制器(Output Controller),而不是模型能力本身的一部分。

工程上,这些惩罚项通常与温度、Top-k、Top-p 一起调节。若目标是严谨、稳定、少跑偏的回答,常采用较低温度并只施加较轻的重复控制;若目标是创意写作或开放发散,则可能提高温度,同时保留较温和的 presence penalty,鼓励内容展开但避免原句循环。它们解决的不是“模型知不知道答案”,而是模型在已知概率分布下,最终说话风格如何被约束。

因此,Transformer 的“输出”需要分成两个层次理解。主干网络输出的是高维隐藏表示;真正面向任务的可解释结果,来自这些隐藏表示经过归一化、线性读出、概率映射与解码后的最终读出。输出处理连接了通用表示学习与具体任务目标,是 Transformer 从“会表示”走向“会预测、会生成、会决策”的最后一跳。

语言模型

语言模型(Language Model)并不是单一物种,而是一组可以从多个维度同时刻画的模型家族。对同一个模型,既可以按预训练目标来描述,也可以按输出形式、主要用途、架构信息流以及是否经过任务特化来描述。分类时若把这些维度混在一起,就容易出现“同一个模型到底属于哪一类”的表述冲突;更准确的方式,是把它看成一个多维坐标系中的点。

语言模型分类

理解语言模型时,至少需要区分四个互相独立但彼此关联的维度:第一,模型在预训练时学的是什么;第二,模型最终主要输出什么;第三,模型内部的信息流结构如何组织;第四,模型在工程上是通用基座、指令对齐模型,还是任务特定模型。它们回答的是四个不同问题,因此一个模型完全可以同时拥有多重身份。例如,BERT 可以同时被描述为“掩码语言模型(Masked Language Model, MLM)+ 表示模型(Representation Model)+ Encoder-only 模型”;GPT / Qwen / LLaMA 则通常是“自回归语言模型(Autoregressive Language Model)+ 生成模型(Generative Model)+ Decoder-only 模型”。

分类维度 它回答的问题 典型类别
按预训练目标 模型在预训练阶段究竟被要求预测什么 掩码语言模型、自回归语言模型、替换检测、去噪重建
按输出与用途 模型最终主要产出向量、表示还是可直接生成的文本 嵌入模型、表示模型、生成模型
按架构信息流 模型内部如何读取上下文、如何组织编码与生成 Encoder-only、Decoder-only、Encoder–Decoder
按工程形态 模型在实际系统里扮演什么角色 通用预训练基座、指令对齐模型、任务特定模型
按预训练目标分类

按预训练目标分类,关注的是模型在大规模无标注文本上被要求完成什么自监督任务。这一维决定了模型最初学会的信息组织方式,但不直接等价于它最终能做什么任务。最经典的两类是掩码语言模型与自回归语言模型。

类别 核心训练目标 上下文可见性 典型模型 更常见优势
掩码语言模型(MLM) 遮住部分 token,再根据其余上下文恢复被遮住内容 通常可双向看左右文 BERT、RoBERTa、DeBERTa 表示学习强;适合理解、分类、匹配、序列标注
自回归语言模型(CLM / ARLM) 根据前文预测下一个 token 因果约束,只看历史上下文 GPT、LLaMA、Qwen、Mistral 生成自然;统一接口强;适合对话、续写、代码生成

两者的差异首先体现在条件概率分解方式上。自回归语言模型直接建模整段文本的联合概率:

\[p(x_1,\dots,x_T)=\prod_{t=1}^{T}p(x_t\mid x_{<t})\]

这里 \(x_t\) 是第 \(t\) 个 token, \(x_{<t}\) 表示它之前所有 token;模型在第 \(t\) 步输出的是“下一个 token 的词表分布”。掩码语言模型则不是按固定顺序展开整句,而是在输入中随机挑出若干位置 \(M\) 做遮蔽,训练目标可写成:

\[\max \sum_{i\in M}\log p(x_i\mid x_{\setminus M})\]

其中 \(M\) 是被遮住的位置集合, \(x_{\setminus M}\) 表示其余未遮住 token。它学到的是“给定上下文,如何恢复缺失信息”,而不是“如何一步步把整段文本续写出来”。因此,MLM 天然更偏表示学习;ARLM 天然更偏生成建模。

这一维并不只有两类。ELECTRA 的替换检测(Replaced Token Detection, RTD)不直接恢复 mask,而是判断 token 是否被替换;T5、BART 的去噪重建(Denoising Reconstruction)则通过破坏输入再让模型恢复原文。因此,“掩码 vs 自回归”是最核心的一条主线,但不是全部可能性。

按输出与用途分类

按输出与用途分类,关注的是模型最终主要产出什么,以及这些产出在工程系统里被如何使用。这里最容易混淆的是“嵌入模型”和“表示模型”。两者都能产出向量,但优化目标和默认使用方式并不相同。

类别 主要输出 优化重点 典型用途 典型代表
嵌入模型(Embedding Model) 固定维度向量 让语义相近样本在向量空间里更近 检索、聚类、召回、语义匹配 Word2Vec、SBERT、BGE、E5、text-embedding 系列
表示模型(Representation Model) 上下文化隐藏表示 学到可迁移的中间表示,再交给任务头读出 分类、序列标注、匹配、判别式 NLU BERT、RoBERTa、DeBERTa、ModernBERT
生成模型(Generative Model) 逐步生成的 token 分布与文本序列 最大化生成质量、上下文延续性与指令跟随能力 对话、写作、摘要、翻译、代码生成、结构化输出 GPT、Qwen、LLaMA、T5、BART

嵌入模型的关键特征是:它的向量空间本身就是最终产品。用户真正拿来用的是向量之间的距离、余弦相似度或最近邻结构。表示模型则更像通用特征提取器:它输出的隐藏状态通常还要再接一个任务头(Task Head)或额外池化层,才能变成分类分数、序列标签或其他任务结果。生成模型的最终输出则是一个条件词表分布,经过解码后形成文本或结构化序列。

同一底座模型有时可以被改造成不同用途。例如,BERT 原本是表示模型,但经过对比学习和专门池化后可以变成句向量嵌入模型;Decoder-only 大模型原本是生成模型,但也可以通过取隐藏状态做 embedding。不过从默认训练目标与最强项看,这三类仍然应当区分。

按架构与信息流分类

按架构分类,关注的是模型内部如何读取上下文,以及输入和输出是如何在网络中流动的。这一维对应的是结构设计,而不是预训练目标本身。

架构类别 信息流特征 注意力方式 典型任务 典型代表
Encoder-only 把输入编码成上下文化表示,不直接负责逐步生成 通常是双向自注意力 分类、检索、匹配、序列标注 BERT、RoBERTa、DeBERTa、ELECTRA
Decoder-only 按时间步自回归地产生输出 因果自注意力 对话、续写、代码生成、开放式问答 GPT、LLaMA、Qwen、Mistral、DeepSeek
Encoder–Decoder 先编码输入,再由解码器条件生成输出 编码器双向自注意力 + 解码器因果自注意力 + 交叉注意力 翻译、摘要、改写、条件生成 T5、BART

这一维与前两维经常联动,但不是一一对应。Encoder-only 模型常与 MLM 或 RTD 结合,Decoder-only 模型常与自回归目标结合,Encoder–Decoder 模型则常与去噪或条件生成目标结合;但它们分别回答的是“结构长什么样”和“训练时学什么”的两个不同问题。

按工程形态分类

在工程落地中,还需要区分模型处于哪种产品化形态。通用预训练基座(Base Model)强调语言知识与可迁移能力;指令对齐模型(Instruction-tuned Model)强调遵循人类指令、对话风格与格式约束;任务特定模型(Task-specific Model)则围绕某个明确监督目标继续微调,并常配合专门任务头工作。

工程形态 核心特点 适合场景 典型例子
通用预训练基座 保留通用语言知识,强调可迁移性与再训练空间 继续预训练、SFT、LoRA、蒸馏 BERT base、LLaMA base、Qwen base
指令对齐模型 通过指令微调与偏好优化提升对话和任务遵循能力 问答助手、Agent、工具调用、结构化生成 ChatGPT 类、Qwen-Instruct、LLaMA-Instruct
任务特定模型 围绕明确任务输出继续微调,并常接专门任务头 NER、分类、匹配、排序、信息抽取 DeBERTa-CRF、BERT 分类器、LLM + PEFT

把四个维度合在一起看,模型的定位会变得清晰得多。BERT 大致对应“MLM + 表示模型 + Encoder-only + 常作为任务特定模型底座”;SBERT 或 BGE 更接近“表示/对比学习 + 嵌入模型 + 常为双编码检索结构”;GPT / Qwen / LLaMA 更接近“自回归 + 生成模型 + Decoder-only + 常见指令对齐形态”;T5 / BART 则更接近“去噪或 text-to-text 目标 + 生成模型 + Encoder–Decoder”。

主流表示型语言模型
BERT

BERT(Bidirectional Encoder Representations from Transformers)是典型的 Encoder-only 模型:用双向注意力做表示学习,预训练目标以掩码语言建模(MLM)为主(原始 BERT 还包含 NSP 任务)。它更擅长理解类任务:分类、匹配、序列标注等。

BERT 的“是否支持中文”关键在词表与分词器(Tokenizer)。英文 BERT-base 的 WordPiece 词表主要覆盖英文子词;对中文文本可能会大量落到 \([\mathrm{UNK}]\) 或被切成极碎片段,效果通常不理想。要做中文任务更常用中文 BERT、mBERT(multilingual BERT)或以 SentencePiece 为主的多语模型。

RoBERTa

RoBERTa(Robustly Optimized BERT Approach)延续 BERT 的 Encoder-only 架构,但通过更大规模数据与训练配方改进(例如更长训练、更大 batch、动态 masking、移除或弱化 NSP 等)显著提升表示质量。它的工程意义在于:在不改变基本架构的前提下,训练细节足以带来可观收益。

RoBERTa 证明了一个重要事实:Encoder-only 模型的性能上限,不完全取决于“是否换了新架构”,训练数据规模、batch 策略、masking 方式和目标设计本身就足以显著改变表示质量。

ELECTRA

ELECTRA(Efficiently Learning an Encoder that Classifies Token Replacements Accurately)仍属于 Encoder-only 模型,但它不再让主模型只做“把被遮住的词猜出来”的掩码语言建模(Masked Language Modeling, MLM)。它先用一个较小的生成器替换部分 token,再让主模型判断每个位置上的 token 是原词还是替换词,这就是替换检测(Replaced Token Detection, RTD)。这种训练方式让模型几乎在每个 token 上都获得监督信号,因此在相近预训练预算下通常比纯 MLM 更高效。

DeBERTa

DeBERTa(Decoding-enhanced BERT with Disentangled Attention)可以看作对 BERT / RoBERTa 的一次结构级强化。它仍然是典型的判别式 Encoder-only 语言模型,因此特别适合文本分类、自然语言推断(Natural Language Inference, NLI)、命名实体识别(Named Entity Recognition, NER)和情感分析等理解类任务;但它不满足于只靠“更大数据、更长训练”来变强,而是直接对注意力机制本身做了精细改造。

它最核心的突破是解耦注意力(Disentangled Attention)。在传统 BERT 中,词的内容信息与位置信息通常会较早融合;DeBERTa 则把“这个 token 是什么”和“这个 token 在哪里”分开处理。对位置 \(i\) 与 \(j\) 的注意力打分,可直观写成三部分:

\[A_{i,j}=\underbrace{C_iC_j^\top}_{\text{内容-内容}}+\underbrace{C_iP_{j|i}^\top}_{\text{内容-相对位置}}+\underbrace{P_{i|j}C_j^\top}_{\text{相对位置-内容}}\]

其中 \(C_i\) 表示第 \(i\) 个位置的内容表示(Content Representation),\(P_{j|i}\) 和 \(P_{i|j}\) 表示相对位置表示(Relative Position Representation)。这个拆分的意义在于:模型不必把“词义”和“位置”混成一个整体再去匹配,而可以更精细地学习“哪个内容会关注什么位置关系”。对于短语修饰、依存关系和实体边界判定这类任务,这种改造往往更有利。

DeBERTa 的第二个关键设计是增强型掩码解码器(Enhanced Mask Decoder, EMD)。它的动机是:相对位置固然重要,但在掩码预测时,绝对位置有时也能提供额外信息。因此 DeBERTa 在接近输出端的位置再次显式注入绝对位置信息,让模型在做 MLM 预测时同时利用相对与绝对位置信号。这相当于在保持主体编码过程解耦的前提下,在最后的“读答案”阶段补上一层位置提醒。

从工程结果看,DeBERTa 长期是判别式 NLU 的强基线之一。它的重要性不只在于“分数更高”,还在于它说明了一个事实:Encoder-only 模型的上限不只是由数据和算力决定,内容表示、位置表示和解码方式本身的结构设计也会显著影响表示质量。后续的 DeBERTa-V3 又把替换检测(RTD)这类更高效的预训练目标引入进来,进一步改善了训练效率与效果,使其在很多精细理解任务里依然保持很强竞争力。

模型 架构 预训练目标 特点 常见用途
BERT Encoder-only MLM(+ NSP 变体) 通用基线;生态成熟 分类、匹配、序列标注
RoBERTa Encoder-only MLM 更强训练配方;更稳的表示质量 理解类任务强基线
ELECTRA Encoder-only 替换检测(Replaced Token Detection) 训练效率高;对小算力友好 理解类任务、低成本预训练
DeBERTa Encoder-only MLM / RTD(V3) 解耦注意力 + 增强型掩码解码器;对结构敏感任务更强 高精度 NLU、NER、文本分类
主流生成式语言模型
GPT 系列

GPT 系列是典型 Decoder-only:以 CLM(自回归 next-token)为主目标,把各种任务统一为“续写”。工程上其优势来自统一接口与强 in-context learning;代价是推理成本高(尤其长上下文与高并发场景)。

LLaMA

LLaMA 系列是开源 Decoder-only 基座的重要代表,强调稳定的训练配方与生态可用性(tokenizer、推理支持、微调社区)。它常作为“可控、可复现”的研究/工程基线,用于 SFT、LoRA、RAG 与本地部署。

Qwen

Qwen 系列同属开源 Decoder-only 生态,中文与多语言能力通常更受关注;在工具调用、代码与多模态等方向也有较多衍生版本。工程上,它常被用作中文业务与多语言场景的基座候选。

Mistral

Mistral 系列强调“更高性价比的推理与训练”:通过架构与工程优化在相近成本下获得更强的生成质量与吞吐表现,常见于高并发推理与轻量级部署场景。

DeepSeek

DeepSeek 系列更强调训练与推理效率的极致:在注意力 KV 压缩、稀疏结构(MoE)与训练目标(如 Multi-Token Prediction)等方向探索更激进的工程取舍,目标是在同等算力预算下提升有效容量与上下文能力。

家族 定位 常见优势 常见代价
LLaMA 稳健开源基座 生态成熟;微调与推理支持广 配置与版本较多,需选对上下文/推理配方
Qwen 多语言/中文友好基座 中文场景覆盖好;衍生模型多 需关注 tokenizer/指令对齐数据分布
Mistral 高性价比推理 吞吐与质量兼顾;工程落地友好 不同版本/配方差异会影响最佳实践
DeepSeek 效率优先(MoE/压缩) 在算力/显存约束下追求更强能力 架构复杂度更高;推理与部署依赖实现细节
主流嵌入模型
Word2Vec(CBOW / Skip-gram)

Word2Vec 用一个简单的自监督目标(Self-supervised Objective)学习词向量(Word Embeddings):监督信号来自文本的共现上下文(Context),而不是人工标签。

它可以理解为学习两个嵌入表:输入词向量 \(V\in\mathbb{R}^{|{\cal V}|\times d}\) 与输出词向量 \(U\in\mathbb{R}^{|{\cal V}|\times d}\)(\(|{\cal V}|\) 为词表大小)。训练结束后,常用 \(V\)(或 \((V+U)/2\))作为词向量。

Skip-gram 的核心是:给定中心词(center word)\(w_c\),预测窗口内的上下文词(context word)\(w_o\)。若用 full softmax:

\[p(w_o|w_c)=\frac{\exp\left(u_{w_o}^\top v_{w_c}\right)}{\sum_{w\in{\cal V}}\exp\left(u_{w}^\top v_{w_c}\right)}\]

由于分母对全词表求和代价高,实践常用负采样(Negative Sampling):对每个正样本对 \((w_c,w_o)\) 采样 \(K\) 个噪声词 \(w_k\),最大化

\[\log\sigma(u_{w_o}^\top v_{w_c})+\sum_{k=1}^{K}\log\sigma(-u_{w_k}^\top v_{w_c})\]

这里的“模型参数”主要就是这些词向量;模型输入通常是 token id(或 one-hot)经查表得到的 \(v_{w_c}\)。

GloVe

GloVe(Global Vectors for Word Representation)用全局共现统计学习词向量:目标是让词向量的内积拟合共现概率(或其对数)。与 Word2Vec 相比,它更强调全局统计的一致性;但二者都属于“静态词向量”(Static Embedding),无法像 Transformer 那样根据上下文动态改变词义表示。

Sentence-BERT

Sentence-BERT(SBERT)是句向量(Sentence Embedding)常用范式之一:用双编码器(Dual Encoder)把两个输入句子分别编码成向量,再用相似度(Similarity)或一个小头(Head)做匹配/检索。

它与 Cross-Encoder 的关键差异在于计算结构:

  • 双编码器:两个输入分别编码,可离线预计算候选向量,适合大规模检索(ANN)。
  • 交叉编码器(Cross-Encoder):把两个输入拼接后一起编码,匹配更精细但无法离线索引,适合重排序(Reranking)。

训练上常用对比学习(Contrastive Learning)/多负样本(In-batch Negatives)等目标,让语义相近的句子向量更近,语义无关的更远。

需要注意一个常见坑:直接把 BERT 的 [CLS] 或平均池化向量当“句向量”效果通常不佳,原因之一是表示各向异性(Anisotropy):向量分布在高维空间中高度聚集,导致余弦相似度区分度差。SBERT 通过对比目标显式优化“句向量空间”,从而更适合检索、聚类与语义匹配。

text-embedding 系列

通用嵌入模型(General-purpose Embedding Model)的目标通常是“语义相似近、语义无关远”,因此天然适配检索与聚类。也可以把嵌入模型微调成“任务特化嵌入”(Task-specialized Embedding):用监督标签构造正/负样本对(同类为正、异类为负),用对比学习目标把同类拉近、异类推远,然后用最近邻/类原型(Prototype)实现分类。

与“表示模型 + 分类头(Representation Model + Classifier Head)”相比,二者取舍通常是:

  • 特化嵌入:推理时只算一次向量 + 相似度,便于大规模检索/多标签扩展;但输出是距离分数,概率校准与细粒度判别能力通常不如专门的分类头。
  • 分类头微调:直接最小化分类损失,闭集分类效果与可解释的概率输出更强;但对大规模候选检索不友好,且不同任务往往需要不同 head。
类别 代表模型/服务 特点 适用场景 备注
开源通用嵌入(General-purpose) BGE / E5 / GTE 部署可控;可做领域微调 私有化 RAG;向量检索;聚类 选型关注多语言、长度与 license
商用 API 嵌入 text-embedding-3 / Cohere Embed 效果稳定;无需运维 快速上线;跨团队复用 成本与数据合规是主约束
领域特化嵌入(Task-specialized) 对比学习微调后的 embedding 对业务分布拟合更强 垂直领域检索;闭集分类 需要高质量正/负样本构造
多向量/late interaction ColBERT 类 token-level 匹配更细 高精度检索;精排候选压缩 索引与存储成本更高
主流 Encoder–Decoder 模型
T5

T5(Text-to-Text Transfer Transformer)是典型 Encoder–Decoder:把所有任务统一为“文本到文本”的生成问题(text-to-text)。它既可用于摘要/翻译等生成任务,也可用于分类(把类别名当作输出 token)。

BART

BART(Bidirectional and Auto-Regressive Transformers)同属 Encoder–Decoder,但预训练更强调去噪自编码(Denoising Autoencoding):对输入做扰动(mask、shuffle、delete 等),让模型恢复原文。它在摘要、生成式改写与条件生成任务上常用作强基线。

模型 架构 预训练直觉 强项
T5 Encoder–Decoder 统一 text-to-text 任务统一;文本生成与分类都自然
BART Encoder–Decoder 去噪重建 摘要与生成式改写强基线
任务特定语言模型
概述

任务特定语言模型(Task-specific Language Model)指在通用预训练模型基础上,围绕某个明确监督任务附加任务头(Task Head)并继续微调的模型。常见任务包括句子级分类、token 级序列标注、文本匹配、排序与信息抽取。工程上它并不是一类全新架构,而是“预训练主干 + 任务头 + 对应损失函数”的组合:同样是 BERT、DeBERTa、T5 或大语言模型(Large Language Model, LLM),接什么头、优化什么目标,决定了它最终服务什么任务。

对 BERT 类 Encoder-only 模型,多分类通常采用“句向量 + 线性分类头(Linear Classification Head)”的形式。设句子表示为 \(h\in\mathbb{R}^{d}\),类别数为 \(K\),则分类头输出 logits:

\[z=Wh+b,\quad W\in\mathbb{R}^{K\times d},\quad b\in\mathbb{R}^{K}\]

其中 \(h\) 是主干模型抽取出的整句语义表示,常取自 [CLS] 对应隐藏状态或池化结果;\(W\) 把 \(d\) 维表示映射到 \(K\) 个类别;\(b\) 是偏置项;\(z_k\) 是第 \(k\) 类的原始分数(logit)。若需要概率,可再经过 softmax:

\[p(y=k|x)=\frac{e^{z_k}}{\sum_{j=1}^{K}e^{z_j}}\]

训练时通常直接把 logits \(z\) 输入交叉熵(Cross-Entropy)损失,softmax 与对数运算一般由损失函数内部完成,以获得更好的数值稳定性;推理时若需要概率分布、阈值决策或置信度排序,再显式做 softmax。实践中还常在分类头前加入 Dropout,以降低小样本场景下的过拟合风险。

命名实体识别(Named Entity Recognition, NER)等 token 级任务的输出结构不同。设序列长度为 \(T\),第 \(t\) 个 token 的隐藏状态为 \(h_t\),则每个位置的标签打分可写成:

\[z_t=Wh_t+b,\quad t=1,\dots,T\]

此时分类头不再输出“整句一个类别”,而是为每个 token 输出一组 BIO / BIOES 标签 logits。若任务更强调标签转移的一致性,还可在 token 分类头后叠加条件随机场(Conditional Random Field, CRF),显式约束标签序列的合法转移。

因此,任务头的输出形式始终取决于任务本身:句子分类输出 \(\mathbb{R}^{K}\) 上的一组 logits,token 分类为每个位置输出一组 logits,匹配/排序任务常输出单个相关性分数,生成任务则在词表维度输出下一 token 的 logits。主干负责提供中间表示(Intermediate Representation),任务头负责把这种表示投影成可直接优化的任务空间。

到 2026 年,任务特定语言模型的工程选型已经稳定分化。对高并发、闭集标签、边界清晰且标注数据相对充足的文本分类与 NER,DeBERTa、ModernBERT 一类 Encoder-only 模型仍然具有极高性价比:延迟低、吞吐高、概率校准更稳、部署成本更可控。对样本极少、语义规则复杂、输出结构开放,或需要“理解 + 生成”一体化的任务,LLM 配合参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)通常更有优势。

在这类 LLM 任务里,LoRA 仍然是默认起点:它最适合指令跟随、风格迁移、格式约束、轻量领域适配等大多数常规需求。若显存是第一约束,QLoRA 往往是最自然的落点;若任务要求更接近全参数微调的表达力,例如深领域知识吸收、复杂推理、困难边界判别或更强的稳定性,则可优先考虑 DoRA 或 Q-DoRA。全参数微调仍然保留在少数高门槛场景:领域迁移极深、训练数据极大,或需要改动词表、上下文长度、位置编码等底层结构时,它仍然提供最高上限。

任务形态 更常见方案 主要原因 典型模型
闭集文本分类 Encoder-only + 分类头 判别边界清晰;推理便宜;概率输出稳定 BERT / RoBERTa / DeBERTa / ModernBERT
标准 NER / 序列标注 Encoder-only + token head(可叠加 CRF) 天然适配 token 级标签;边界学习直接 BERT-CRF / DeBERTa-CRF
低资源复杂分类 LLM + LoRA / QLoRA 预训练知识丰富;少样本泛化强;显存门槛低 Qwen / Llama / Gemma + LoRA
复杂结构抽取 / JSON 输出 LLM + PEFT 或指令微调 可同时完成理解、抽取、归纳与结构化生成 Qwen / Llama / Mistral 系列
高难推理 / 深领域适配 LLM + DoRA / Q-DoRA 比普通 LoRA 更接近全参数微调;适合高质量知识注入 Qwen / Llama + DoRA
极致吞吐线上服务 LLM 标注或蒸馏,Encoder-only 上线 兼顾数据质量、速度与运维成本 LLM 教师 + DeBERTa 学生
超大规模深度迁移 / 底层结构改造 全参数微调 需要改动表示空间本身,低秩适配容量不足 领域基座继续训练或全量 SFT

工业系统中也常采用混合路线:先用强 LLM 做数据清洗、弱标注、难例发现或标签体系归并,再把任务蒸馏到更轻的 Encoder-only 模型上线。这种做法利用了 LLM 的语义泛化能力,也保留了小模型在延迟、吞吐与稳定性上的优势。

多模态模型
视觉-语言模型
CLIP

CLIP(Contrastive Language–Image Pre-training)用对比学习(Contrastive Learning)把图像与文本对齐到同一嵌入空间:图像编码器与文本编码器分别输出向量,通过 InfoNCE 类目标让匹配对相似度更高、非匹配对更低。它既可用于图文检索,也可把类别名/提示词当作文本侧输入实现零样本分类(Zero-shot Classification)。

LLaVA

LLaVA(Large Language and Vision Assistant)属于“视觉编码器 + LLM”的多模态对话范式:用视觉编码器(如 ViT)提取图像特征,通过投影层把视觉特征对齐到语言模型输入空间,再做视觉指令微调(Visual Instruction Tuning),让模型学会围绕图像进行问答、描述与推理。

GPT-4V / Gemini

GPT-4V / Gemini 这类通用多模态大模型(General-purpose Multimodal LLM)通常把视觉理解、OCR、推理与工具使用统一到一个端到端系统中,并以 API 形态提供能力。工程上它们常作为“强但贵”的最终裁决器:当规则与小模型不稳时,用多模态 LLM 做兜底或少量精排。

范式 典型代表 训练目标 强项 局限
对比学习对齐(Dual Encoder) CLIP 图文对比(InfoNCE) 检索与零样本分类强;向量可索引 生成能力弱;细粒度推理受限
视觉编码器 + LLM LLaVA 类 视觉指令微调 对话与推理能力强;可扩展工具调用 推理成本高;视觉细节依赖对齐质量
通用多模态 LLM GPT-4V / Gemini 多任务端到端 能力上限高;工程集成成熟 成本与可控性;数据合规
图像生成模型
DALL-E

DALL-E 属于“文本到图像”(Text-to-Image, T2I)生成模型路线之一:输入提示词生成图片。工程上更关注提示词控制、风格一致性与安全过滤,而不是单纯的像素指标。

Stable Diffusion

Stable Diffusion 属于扩散模型(Diffusion Model)的潜空间版本(Latent Diffusion):在潜变量空间做扩散与去噪,再解码为图像。它的工程优势在于开源生态、可控微调(LoRA/ControlNet 等)与本地部署可能性。

Imagen

Imagen 是文本到图像扩散路线的代表之一,强调高质量生成与文本-图像对齐。与其他 T2I 模型一样,最终效果高度依赖数据与训练配方。

类别 代表 优势 常见玩法
商业 T2I DALL-E / Imagen 效果稳定;产品化完善 提示词工程;风格控制;安全策略
开源扩散 Stable Diffusion 可本地部署;可深度定制 LoRA/ControlNet;自定义 checkpoint;工作流编排
语音模型
Whisper

Whisper 是自动语音识别(Automatic Speech Recognition, ASR)模型代表之一:输入音频输出转写文本。工程落地的关键在于流式推理(Streaming)、噪声鲁棒性、领域词表与端到端延迟控制。

语音合成(TTS)

语音合成(Text-to-Speech, TTS)把文本转为音频波形。工程关注点包括音色一致性(Voice Consistency)、韵律(Prosody)、多说话人控制、以及与 ASR/对话系统的整体延迟。

多模态对齐
对比学习对齐(CLIP 范式)

对比学习对齐(Contrastive Alignment)用“匹配对相似、非匹配对不相似”的目标把不同模态映射到同一空间。它的最大价值是:对齐后可以做检索(Retrieval)、聚类与零样本迁移(Zero-shot Transfer),并为后续的多模态 LLM 提供可用的视觉表示初始化。

视觉指令微调

视觉指令微调(Visual Instruction Tuning)把多模态输入组织为对话/指令格式,用监督数据训练模型按指令理解图像并输出文本。与纯对比对齐相比,它更强调“可用性”:模型能解释、能推理、能按格式回答。

预训练与微调
预训练(Pre-training)
自回归语言建模(CLM)

自回归语言建模(Causal Language Modeling, CLM)把文本建模为从左到右的条件概率连乘:给定前缀 \(x_{<t}\) 预测下一个 token \(x_t\)。训练目标是最小化 next-token 交叉熵:

\[\mathcal{L}_{\mathrm{CLM}}(\theta)=-\sum_{t=1}^{L}\log p_\theta(x_t\mid x_{<t})\]

CLM 与 Decoder-only 架构天然匹配:因果 attention mask 保证模型只能看见历史 token,避免训练-推理不一致。绝大多数通用生成式大模型都以 CLM 为主目标。

Multi-Token Prediction(MTP)

多 token 预测(Multi-Token Prediction, MTP)是在 CLM 基础上的“监督信号加密”:除了预测 \(x_{t+1}\),还额外让模型在同一隐藏状态上预测更远的未来 token(例如 \(x_{t+2}\)、\(x_{t+3}\)),从而在相同序列长度下产生更多训练信号。一个抽象写法是:

\[\mathcal{L}_{\mathrm{MTP}}(\theta)=-\sum_{t=1}^{L}\sum_{j=1}^{K}\log p_\theta(x_{t+j}\mid x_{<t})\]

MTP 通常作为辅助损失(Auxiliary Loss)提升训练效率或长程规划能力;但推理阶段是否能“真正一次生成多个 token”取决于解码与验证策略,不能简单由训练目标推出。

掩码语言建模(MLM)

掩码语言建模(Masked Language Modeling, MLM)随机遮住输入中的一部分 token(替换为 \([\mathrm{MASK}]\) 或其他扰动),训练模型用双向上下文预测被遮住位置的 token。它是 Encoder-only 表示模型(如 BERT 系列)的典型预训练目标:

\[\mathcal{L}_{\mathrm{MLM}}(\theta)=-\sum_{t\in \mathcal{M}}\log p_\theta(x_t\mid x_{\setminus \mathcal{M}})\]

其中 \(\mathcal{M}\) 是被 mask 的位置集合。MLM 的优势是能学到更强的双向表示,但它与生成式解码不天然一致,因此“理解类任务”更常用 MLM 预训练模型,“生成类任务”更常用 CLM。

对比学习预训练

对比学习预训练(Contrastive Pre-training)把“相似样本拉近、非相似样本推远”作为核心目标。它广泛用于句向量/图像-文本对齐等场景:例如 CLIP 用图像编码器与文本编码器产生表示,对匹配对最大化相似度;Sentence-BERT 等句向量模型也常用对比目标训练。

典型形式是 InfoNCE:对 batch 内正对(Positive Pair)与负对(Negative Pair)做 softmax,对每个 query 只奖励其匹配的 key:

\[\mathcal{L}=-\sum_{i}\log \frac{\exp(\mathrm{sim}(q_i,k_i)/\tau)}{\sum_{j}\exp(\mathrm{sim}(q_i,k_j)/\tau)}\]

其中 \(\tau\) 是温度(Temperature),\(\mathrm{sim}\) 常用余弦相似度或内积。

目标 代表架构 擅长 典型下游
CLM Decoder-only 生成(Generation) 对话、写作、代码生成
MLM Encoder-only 表示学习(Representation) 分类、匹配、序列标注、reranking
对比学习 Dual Encoder / 多塔 对齐与检索(Alignment/Retrieval) Embedding、图文检索、聚类
继续预训练(Continual Pre-training)
领域适配
灾难性遗忘问题
监督微调(SFT)

监督微调(Supervised Fine-Tuning, SFT)用“输入 -> 期望输出”的监督数据继续训练预训练模型,使其在特定分布上更符合目标行为。对自回归语言模型(Autoregressive LM)而言,SFT 仍然是 next-token 交叉熵:给定提示词 \(x\) 与目标回复 \(y\),最小化

\[\mathcal{L}_{\mathrm{SFT}}(\theta)=-\sum_{t}\log \pi_\theta\!\left(y_t\mid x,y_{<t}\right)\]

训练通常使用 teacher forcing:把 \(x\) 与 \(y\) 拼接作为输入,但只在目标回复 token 上计算损失(对提示词部分做 label masking),避免模型被迫“复述提示词”。

全量微调

全量微调(Full Fine-tuning)更新模型的全部参数,表达能力最强,但训练成本高、对数据规模与分布漂移更敏感,也更容易出现灾难性遗忘(Catastrophic Forgetting)。

指令微调(Instruction Tuning)

指令微调(Instruction Tuning)是 SFT 的一种数据组织方式:把任务描述(Instruction)显式写进输入,使模型学习“读懂指令并按指令输出”。典型样本是三元组:指令(instruction)、输入(input,可为空)、输出(output)。

instruction-tuning-sample.jsonl
1
{"instruction":"回答以下问题","input":"世界上最高的山是什么?","output":"珠穆朗玛峰。"}

对话/FAQ 场景更常用多轮消息格式(Chat Format),把 role(system/user/assistant)显式编码进序列;训练时同样只在 assistant 角色对应的目标 token 上计算损失。

chat-finetune-sample.jsonl
1
2
3
4
5
{"messages":[
  {"role":"system","content":"你是一个严谨的技术助手。"},
  {"role":"user","content":"解释什么是交叉熵损失。"},
  {"role":"assistant","content":"交叉熵损失用于衡量预测分布与真实分布的差异……"}
]}

数据规模没有统一答案,但工程上最关键的是质量(Quality)与覆盖(Coverage)。常见实践:

  • 领域 SFT:从 \(10^3\sim10^5\) 级别的高质量样本起步,先跑通指标与错误分析,再扩充数据与任务覆盖。
  • 通用指令微调:更常见的是 \(10^5\sim10^6+\) 的多任务指令样本,用多样性换泛化。
  • 偏好对齐数据:比较对(Preference Pairs)常在 \(10^4\sim10^6\) 级别,且对标注一致性要求更高。
聊天微调(Chat Fine-tuning)

聊天微调(Chat Fine-tuning)强调多轮对话一致性:除单轮问答外,还需要覆盖上下文承接、拒答策略、工具调用格式、长对话记忆等。它通常仍是 SFT,只是数据分布更贴近真实对话。

参数高效微调(PEFT)

参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)把“微调”从“更新全部参数”变成“冻结基座(Base Model),只训练一小部分新增参数”。它仍然是当前大模型落地的主流选择之一:成本更低、训练更快、便于为不同任务保存多份轻量适配(例如每个业务一套 LoRA)。

Adapter

Adapter 在每个 Transformer block 里插入一个小瓶颈模块(Bottleneck MLP):先降维再升维。微调时只更新 Adapter 参数,主干权重保持冻结。它的直觉是:用一个低参数量的残差支路学习任务特定偏移。

LoRA

LoRA(Low-Rank Adaptation)不改动原权重 \(W\),而是学习一个低秩增量 \(\Delta W\):

\[W' = W + \Delta W,\quad \Delta W = BA,\quad B\in\mathbb{R}^{d_{\text{out}}\times r},\ A\in\mathbb{R}^{r\times d_{\text{in}}},\ r\ll \min(d_{\text{in}},d_{\text{out}})\]

由于 \(r\) 很小,可训练参数与优化器状态显著减少。实践里常把 LoRA 加在注意力投影(如 \(W_Q,W_K,W_V,W_O\))和/或 FFN 上。

截至 2026 年,LoRA 仍然是大语言模型参数高效微调里最常见的默认方案。原因并不神秘:它与主流 Transformer 线性层天然兼容,适配器权重体积小,便于为不同任务单独保存、热切换与合并;同时它对训练框架、推理框架和量化框架的兼容性也最成熟。因此,工程上常把 LoRA 看成 PEFT 的基线接口:后续很多方法,本质上都是在 LoRA 的参数化、量化方式或更新几何上继续细化。

LoRA 挂在哪些线性层上,并不是纯工程细节,而与希望改变模型的哪一部分能力直接相关。若目标更偏风格迁移、格式控制、对话行为调整或路由方式改变,注意力投影层上的 LoRA 往往已经能带来明显效果;但若目标是注入新的领域术语、事实关联、实体属性映射或专业概念之间的稳定关系,FFN / MLP 往往更关键。原因在于:Transformer 里的 MLP 常被视为知识写入与模式重编码的重要位置,因此很多“新知识”最终要落到这些大规模前馈权重所张成的表示子空间里。

这也是为什么在不少实践中,LoRA 不只挂在 \(W_Q,W_K,W_V,W_O\) 上,还会同时挂在 FFN 的线性层上,甚至在资源允许时为 FFN 分配更高的秩(Rank)。低秩更新的本质是在原有权重空间附近增加一个受限的可训练子空间;如果希望修改的是知识关联本身,而不仅是信息流动方式,那么只改注意力层常常不够,需要让 MLP / FFN 也获得足够的适配容量。沿着这条思路发展的变体,如 DoRA(Weight-Decomposed Low-Rank Adaptation),本质上也是在不做全参数微调的前提下,给参数更新更强的表达能力。

这里的低秩假设作用于微调增量 \(\Delta W\),而不是作用于预训练知识本身的存储方式。预训练模型中的知识通常以分布式表示(Distributed Representation)的方式编码在大量参数 \(W\) 里;LoRA 近似的是“为了适配当前任务,需要沿哪些方向改动这些参数”。前者讨论的是 \(W\) 如何承载知识,后者讨论的是 \(\Delta W\) 如何改变模型行为与输出边界。

很多微调任务并不要求模型写入大规模新知识,而是要求它重新组织已有表示:调整回答风格、强化指令跟随、遵守输出格式、放大某些线索、抑制另一些线索。这类任务的有效更新方向往往集中在少数子空间中,小秩 \(r\) 就足以带来明显收益。若任务要求模型稳定吸纳新的领域本体(Ontology)、术语体系、事实关系或复杂规则,适配增量的有效维度通常会上升,低秩近似就更容易成为容量瓶颈。

分布式存储也不意味着所有参数同等重要。即便在全参数微调(Full Fine-tuning)中,显著变化的往往也是少数关键方向;LoRA 的核心假设是,这些方向可以被一个较低维的子空间有效覆盖。当任务迁移幅度较小,这个假设通常成立;当关键更新分散在许多彼此独立的方向上,就需要更高的秩、更广的挂载范围,尤其是让 FFN / MLP 参与适配,必要时再转向 DoRA 或全参数微调。工程上,这体现为一条清晰的权衡:LoRA 优先优化效率,全参数微调提供更高上限;二者对应的是不同任务内在维度(Intrinsic Dimension)下的不同最优解。

LoRA 合并(Merging)

LoRA 的一个工程优势是“可合并(Mergeable)”:推理前可把增量权重并入基座权重,从而不引入额外前向分支。对单个 LoRA,合并后得到的有效权重就是 \(W_{\text{merged}}=W+\Delta W\)(实践中常包含缩放系数)。

当存在多份 LoRA(多任务/多领域适配)时,最简单的合并是对增量做加权和:

\[W' = W + \sum_{j=1}^{M}\lambda_j\,\Delta W^{(j)}\]

这种“线性缝合”实现简单,但容易出现任务干扰(Interference):不同 LoRA 在同一参数子空间里叠加,可能让模型对多个任务都变差。若你需要同时服务多个领域,更稳健的方案往往是“运行时选择哪一份 LoRA”或引入路由(Routing)机制,而不是把它们永久混成一份权重。

DoRA

DoRA(Weight-Decomposed Low-Rank Adaptation)并不是把 LoRA 的两个低秩矩阵 \(A\) 与 \(B\) 再拆一遍,而是把原始权重 \(W\) 的“大小”和“方向”拆开建模,再让 LoRA 只负责更新方向部分。对第 \(j\) 个输出通道,可写成:

\[W'_{:,j}=m_j\frac{V_{:,j}+\Delta V_{:,j}}{\left\|V_{:,j}+\Delta V_{:,j}\right\|_2},\quad \Delta V=BA\]

其中 \(V_{:,j}\) 是方向向量(Direction),决定该通道“朝哪个方向投影”;\(m_j\) 是幅值(Magnitude),决定该通道“放大到多大”;\(\Delta V\) 仍由 LoRA 的低秩增量给出。这样做的效果是把“方向调整”和“尺度调整”解耦,使更新轨迹更接近全参数微调。若任务要求模型更深地吸纳新领域知识、重塑复杂判别边界,DoRA 往往比原始 LoRA 更有表达力;代价是额外的参数、归一化计算与实现复杂度。

QLoRA

QLoRA 在 LoRA 基础上进一步把基座权重量化(Quantize)到低比特(常见 4-bit),以极小显存加载大模型;训练时仍只更新 LoRA 参数。它把“能不能放得下”从硬约束变成可控工程问题,是许多个人/小团队微调 7B/13B 的关键技术路径之一。

其核心思路是:冻结量化后的基座权重,只在前向/反向计算时对它们做解量化(Dequantize),而真正需要学习的仍是低秩增量。一个简化写法是:

\[Y=X\,\operatorname{Dequant}(W_q)+\frac{\alpha}{r}XBA,\quad W_q=\operatorname{Quant}(W)\]

其中 \(X\) 是输入激活, \(W_q\) 是量化后冻结的基座权重, \(\operatorname{Dequant}(W_q)\) 表示把低比特权重恢复到计算精度后的近似值, \(\frac{\alpha}{r}BA\) 是 LoRA 分支, \(\alpha\) 是缩放系数(Scaling Factor),用来控制低秩增量对原模型的影响强度。

QLoRA 的关键不只是“4-bit”,而是分块量化(Block-wise Quantization):权重不会用一套全局刻度统一压缩,而是被划分成许多小块,每块各自保存缩放因子。若第 \(g\) 个块的量化码为 \(\hat{w}^{(g)}\),对应缩放因子为 \(s_g\),则可抽象写成:

\[w^{(g)}\approx s_g\,\hat{w}^{(g)}\]

这里的 \(s_g\) 可以理解为该块的“比例尺”。不同块的权重统计范围并不相同:有些块存在更大的离群值(Outlier)或更强的激活通道,有些块整体数值更平缓。分块量化允许每个局部区域使用更合适的刻度,因此比全局共用一个缩放因子保留更多有效信息。QLoRA 常配合 NF4、双重量化(Double Quantization)与分页优化器(Paged Optimizer)使用,目标都是在尽量不损失质量的前提下降低显存压力。

Q-DoRA

Q-DoRA 可以看作 QLoRA 与 DoRA 的组合:基座仍采用低比特量化以节省显存,但更新形式不再是普通 LoRA,而是“量化基座 + 方向/尺度解耦”的 DoRA 结构。一个简化表达是:

\[W'_{:,j}=m_j\frac{\operatorname{Dequant}(W_{q,:,j})+\Delta V_{:,j}}{\left\|\operatorname{Dequant}(W_{q,:,j})+\Delta V_{:,j}\right\|_2},\quad \Delta V=BA\]

它的工程含义很直接:用 QLoRA 解决“显存放不下”的问题,用 DoRA 缓解“低秩更新表达力不够”的问题。若资源非常紧、任务主要是格式控制与轻量指令对齐,普通 QLoRA 往往已经足够;若任务更偏逻辑推理增强、专业知识注入、复杂边界判别或高质量垂直领域适配,Q-DoRA 往往是更稳妥的折中。对应代价是训练更慢、实现更复杂,且并非所有推理栈都像原始 LoRA 那样原生支持。

LoRA-MoE

LoRA-MoE 可以理解为“适配器级的 MoE”:不把 FFN 变成稀疏专家,而是保留基座不变,准备多份 LoRA 作为“领域专家”,再用一个路由器(Router)按请求/句子/甚至 token 选择或加权组合这些 LoRA。直觉上,它用极小的可训练参数,为同一个基座提供多域能力,同时避免把所有任务硬合并到一份权重里。

一种抽象表达是把输出写成“基座 + 适配器混合”:

\[h' = f_{\text{base}}(h) + \sum_{e\in \mathcal{E}} g_e(x)\,f_{\text{lora},e}(h),\quad \sum_e g_e(x)=1\]

其中 \(g_e(x)\) 是路由权重,可以来自显式分类器(域识别)、检索到的任务标签,或一个可训练的 gating 网络。工程上,LoRA-MoE 的关键不在公式,而在路由与评测:你需要定义“什么输入该走哪套 LoRA”,并防止路由错误导致质量抖动。

方案 参数/存储 推理开销 多域能力 主要风险
多 LoRA 合并 单份权重 最低(一次 forward) 不稳定(易相互干扰) 合并策略难;回滚困难
LoRA-MoE(路由) 多份 LoRA + 路由器 低~中(取决于是否多专家叠加) 强(可按域选择) 路由错误;线上一致性与可观测性要求更高
全量 MoE(FFN 专家) 多专家权重 中(Top-k 专家计算) 强(容量大) 训练与部署复杂;负载均衡与稳定性
Prefix Tuning

Prefix Tuning 学习一段连续前缀(Continuous Prefix),并把它作为每层注意力的额外 Key/Value 注入,相当于“在每层都加一段可训练的记忆”。它通常比只在输入层加软提示更强,但实现更复杂。

Prompt Tuning

Prompt Tuning(软提示/软 Prompt)学习一小段可训练的“虚拟 token embedding”,只加在输入层。它在某些分类/检索类任务上仍然有价值(尤其当希望极小的参数与存储开销时),但在大模型指令/对话能力微调上,LoRA 往往更稳定、效果更可预期。

强化学习对齐

强化学习对齐(RL-based Alignment)更准确的说法是“偏好对齐(Preference Alignment)”:用偏好信号把模型输出推向“更符合人类/评审标准”的区域。主流路线分为两类:

  • 显式奖励:先训练奖励模型(Reward Model),再用 PPO 等策略优化算法做 RLHF。
  • 直接偏好:不显式训练奖励模型,直接用偏好对优化策略(例如 DPO)。
奖励模型(Reward Model)

奖励模型(Reward Model, RM)把(提示词 \(x\),回复 \(y\))映射为一个标量分数 \(r_\theta(x,y)\in\mathbb{R}\)。训练数据通常来自偏好比较:给定同一提示词下的两条候选回复,标注哪条更好。

对一对“胜/负”样本 \((x,y_w,y_l)\),常用 Bradley–Terry / Logistic 形式把分数差转为偏好概率:

\[\Pr(y_w \succ y_l\mid x)=\sigma\!\left(r_\theta(x,y_w)-r_\theta(x,y_l)\right)\]

并用对数损失训练:

\[\mathcal{L}_{\mathrm{RM}}(\theta)=-\log \sigma\!\left(r_\theta(x,y_w)-r_\theta(x,y_l)\right)\]

关键点:sigmoid 用在“分数差”上,而不是对每个 \(r_\theta(x,y)\) 再套一层 sigmoid。分数本身不需要限制在 \([0,1]\);概率来自差值的 logistic 映射。

参数 \(\theta\) 表示奖励模型的参数集合(Parameter Set),包含全部权重矩阵与偏置项,并非单一标量。

单调性视角:因为 \(\sigma\) 单调递增且 \(-\log(\cdot)\) 在 \((0,1)\) 上单调递减,所以 \(\mathcal{L}_{\mathrm{RM}}\) 对分数差 \(\Delta r=r_\theta(x,y_w)-r_\theta(x,y_l)\) 单调递减。训练会推动 \(\Delta r\) 变大,从而把胜者分数推高、败者分数压低。

RLHF

RLHF(Reinforcement Learning from Human Feedback)用奖励模型把“语言生成”转为 RL:token 是动作(Action),策略是语言模型 \(\pi_\phi(y|x)\),奖励来自 \(r_\theta(x,y)\)。常见做法是用 PPO(Proximal Policy Optimization)优化下式的 KL 正则目标:

\[\max_{\phi}\ \mathbb{E}_{y\sim \pi_\phi(\cdot|x)}\big[r_\theta(x,y)\big]-\beta\,D_{\mathrm{KL}}\!\left(\pi_\phi(\cdot|x)\,\|\,\pi_{\mathrm{ref}}(\cdot|x)\right)\]

KL 项把策略锚定在参考模型(Reference Model)附近,抑制奖励黑客(Reward Hacking)与分布漂移造成的不稳定。

DPO

DPO(Direct Preference Optimization)直接用偏好对 \((x,y_w,y_l)\) 优化策略,不显式训练奖励模型,也不需要 PPO rollout。典型目标把“更偏好”转成一个二分类问题:让策略相对参考模型更偏向 \(y_w\) 而远离 \(y_l\)。

\[\mathcal{L}_{\mathrm{DPO}}(\phi)=-\log \sigma\!\Big(\beta\big[\log\pi_\phi(y_w|x)-\log\pi_\phi(y_l|x)-\log\pi_{\mathrm{ref}}(y_w|x)+\log\pi_{\mathrm{ref}}(y_l|x)\big]\Big)\]

直觉上,DPO 直接增大“胜者相对败者”的对数概率优势(log-odds margin),同时用参考模型作为锚点。

GRPO

GRPO(Group Relative Policy Optimization)是一类“组内相对比较”的偏好优化方法:对同一个提示词 \(x\) 采样一组候选回复 \(\{y_k\}_{k=1}^{K}\),用奖励/偏好信号在组内排序或打分,再把“相对好坏”转成策略梯度更新。它的核心动机是:用 组内比较 构造优势(Advantage)或基线(Baseline),从而减少对显式价值网络(Critic / Value Function)的依赖。

一种常见的做法是把组内奖励做标准化得到相对优势:

\[A_k=\frac{r_k-\mu_r}{\sigma_r+\epsilon},\quad \mu_r=\frac{1}{K}\sum_{k=1}^{K}r_k,\ \sigma_r^2=\frac{1}{K}\sum_{k=1}^{K}(r_k-\mu_r)^2\]

并用 PPO 风格的 clipped objective 更新策略(仍然可带 KL 正则到参考模型):

\[\max_{\phi}\ \mathbb{E}\Big[\min\big(\rho_k A_k,\ \mathrm{clip}(\rho_k,1-\epsilon,1+\epsilon)\,A_k\big)\Big]-\beta D_{\mathrm{KL}}\!\left(\pi_\phi\,\|\,\pi_{\mathrm{ref}}\right),\quad \rho_k=\frac{\pi_\phi(y_k|x)}{\pi_{\phi_{\mathrm{old}}}(y_k|x)}\]

GRPO 仍然需要某种奖励/偏好信号(显式奖励模型、规则打分、对比标注等);它改变的是“如何用这些信号构造稳定的更新”,而不是免除奖励来源本身。

推理阶段优化

推理优化(Inference Optimization)目标是在质量约束下同时降低延迟(Latency)、显存(Memory)和成本(Cost)。主线方法包括量化(Quantization)、KV Cache 优化、推测解码(Speculative Decoding)和连续批处理(Continuous Batching)。

关于“温度(Temperature)设为 0 仍可能不完全一致”的现象:温度为 0 通常等价于贪心解码(Greedy Decoding),理论上对固定权重与固定数值计算应是确定的;但线上推理系统可能包含非确定性来源(Non-determinism),例如并行算子中的浮点归约顺序差异、不同硬件/内核实现、以及服务端的动态调度与缓存策略。若业务需要强确定性,除了设置 \(\text{temperature}=0\),还需要禁用采样相关选项并启用确定性计算(Deterministic Kernels)/固定随机种子(Seed)(若推理框架支持)。

量化

量化(Quantization)通过降低数值精度减少带宽与显存占用。常见路径:FP16/BF16 到 INT8/INT4/FP8。大模型推理最常见的是权重量化(Weight-only Quantization),因为它实现简单、收益稳定;进一步的激活量化(Activation Quantization)能带来更大的加速空间,但对硬件与校准(Calibration)更敏感。

常见概念:

  • PTQ(Post-Training Quantization):训练后量化,依赖少量校准数据估计尺度(Scale)与零点(Zero-point)。
  • QAT(Quantization-Aware Training):训练时模拟量化误差,通常精度更好但成本更高。
  • 按粒度:per-tensor / per-channel / group-wise,粒度越细通常越准但开销更高。
INT8 / INT4 / FP8
GGUF / GGML
KV Cache 优化

KV 缓存(Key-Value Cache, KV Cache)用于避免重复计算历史 token 的 Key/Value。在解码器(Decoder-only)模型中,生成第 \(t\) 个 token 时需要与前 \(t-1\) 个位置做注意力;若不缓存,每一步都会重复算一遍历史的 K/V,代价极高。

代价分解常用“预填充(Prefill)+ 解码(Decode)”来理解:Prefill 处理提示词(Prompt)并写入 KV;Decode 每生成一个 token 只需计算新 token 的 Q/K/V,并与缓存做一次注意力。这把每步成本从“重算整段历史”降为“读取缓存并做一次加权求和”。

KV Cache 的主要代价是显存:缓存规模与层数、头数、上下文长度线性增长,因此优化会围绕缓存布局(如 Paged Attention)、压缩(如 KV 量化)与复用策略展开。

粗略的量级估算:若每层缓存张量形状近似为 \(K,V\in\mathbb{R}^{L\times n_{\text{kv}}\times d_k}\),则单 batch 的显存规模约为

\[\mathrm{Mem}_{\mathrm{KV}}\approx 2\cdot N_{\text{layers}}\cdot B\cdot L\cdot n_{\text{kv}}\cdot d_k\cdot \text{bytes}\]

其中 \(n_{\text{kv}}\) 在 GQA/MQA 中显著小于 Query 头数,因此 GQA/MQA 往往是降低 KV Cache 的一阶有效手段;进一步的手段包括 KV 量化、Paged KV(按块管理与回收)、以及对重复前缀做复用/持久化(Prompt Caching)。

Prompt Caching(前缀缓存)

Prompt Caching(前缀缓存)缓存的是“提示词前缀的 KV Cache”,目标是避免在多轮对话或重复前缀场景下反复做 Prefill:当新请求的开头 token 序列与某个已缓存前缀完全一致时,推理引擎可以直接复用这段前缀的 KV blocks,只对新增 token 做增量计算。

它直接优化两个指标:

  • 首 token 延迟(Time To First Token, TTFT):减少或跳过重复前缀的 Prefill。
  • 成本:若推理服务对缓存命中(Cache Hit)的前缀按更低费率计费,则输入 token 成本显著下降。

Prompt Caching 的工程前提是“字节级一致(Exact Prefix Match)”:通常要求 tokenizer 后的 token 序列完全一致,任何空格/标点/系统提示词差异都会导致 cache miss。因此它更适合“系统提示词固定 + 文档前缀固定 + 多次追问”的产品形态,而不是随意变化的自由对话。

多租户隔离(Multi-tenancy Isolation)

在共享推理后端中,Prompt Caching 必须严格做多租户隔离(Multi-tenancy Isolation):缓存命中不能只依赖“前缀文本哈希”,还需要把租户/用户身份与模型版本纳入缓存键(Cache Key),避免跨用户“串台”与侧信道泄露。典型复合键(Composite Key)包括:

  • 租户 ID(Org/User ID)
  • 模型版本(Model/Weights Version)
  • 前缀 token 哈希(Prefix Hash)与长度等元数据

缓存生命周期通常很短:KV Cache 占用显存,后端会用 LRU(Least Recently Used)等策略在压力下淘汰缓存;因此“隔天再聊成本回到原价”是常见现象。若业务需要跨小时/跨天复用长前缀,工程上一般转向两类手段:长效上下文缓存(Context Caching,若服务支持)或 RAG/摘要把长前缀变成可检索的外部状态。

场景 策略 成本 延迟 风险/约束
连续多轮对话(分钟级) Prompt Caching 低(命中时前缀“打折”) 低(TTFT 改善明显) 要求前缀严格一致;缓存易被淘汰
跨小时/跨天复用长文档前缀 Context Caching / 预热 中(通常含存储费) 中-低 依赖服务能力;需要明确缓存生命周期与权限
大规模文档问答 RAG(检索增强生成) 低且稳定 稳定 需要索引构建、召回/重排与证据注入治理
长对话状态维护 滚动摘要(Rolling Summary) 低 稳定 摘要漂移与可验证性问题;需结构化约束
Speculative Decoding

推测解码(Speculative Decoding)用一个更小更快的草稿模型(Draft Model)一次提出多个候选 token,再由大模型(Target Model)并行验证并接受其中尽可能长的前缀。若接受率高,就能显著减少大模型需要执行的解码步数;若接受率低,则会退化并产生额外验证开销。实际收益取决于草稿模型速度、分布匹配程度与实现细节。

连续批处理(Continuous Batching)

连续批处理(Continuous Batching)面向在线服务:请求不断到达、序列长度各不相同。与“固定 batch + padding”相比,连续批处理按 token 粒度调度,把不同请求的下一步解码拼到同一个批次里,从而提升吞吐并减少 padding 浪费。实现上的关键在于:高效的 KV Cache 管理、动态调度策略,以及在吞吐与 P99 延迟之间做权衡。

推理框架

推理框架(Inference Serving Stack)把“模型权重 + 推理图 + 调度策略”封装成可部署的服务。选型时优先看三件事:是否支持你的模型与精度(Compatibility)、是否能把 KV Cache 与批处理调度做对(Scheduler + KV Management)、以及在你的硬件上能否稳定达到目标吞吐/延迟(Performance Envelope)。

框架 定位 强项 代价/约束 适用场景
vLLM 高吞吐在线推理 Paged KV + 连续批处理;并发友好 需要围绕显存/并发做参数调优 多租户在线服务;RAG/Agent 高并发
TensorRT-LLM NVIDIA 推理加速栈 内核与图级优化;低延迟上限高 构建/调参成本高;硬件绑定强 对延迟敏感的核心服务;固定模型部署
TGI(Text Generation Inference) 通用推理服务 生态成熟;易集成;支持常见部署形态 极致吞吐/显存利用率取决于具体模型与配置 快速上线;标准化 HuggingFace 模型服务
SGLang 面向 LLM 应用的推理与编排 更贴近应用侧的执行模型;对复杂推理/工具调用友好 需要接受其编排抽象;生态仍在快速演进 复杂 Agent/RAG pipeline;结构化推理任务
llama.cpp(GGUF) 本地/边缘推理 CPU/小 GPU 友好;量化生态完善;分发简单 吞吐与模型规模受硬件限制;在线并发能力有限 个人/离线实验;边缘设备;小规模服务
Ollama 本地运行与分发工具 易用;模型拉取与管理简单 更偏开发者体验而非极致服务性能 本地原型;团队内共享本机模型
vLLM

vLLM 是面向大模型推理的高吞吐推理引擎(Inference Engine),核心目标是在显存受限的情况下提升并发与吞吐。它的代表性设计是 PagedAttention:把 KV Cache 按固定大小切成块(Blocks),用块表(Block Table)把“逻辑连续的序列”映射到“物理上不必连续的显存块”。

这样做的收益是:按需分配 KV、降低内存碎片(Fragmentation),并支持前缀共享(Prefix Sharing):当多个请求共享同一段前缀(例如相同系统提示词/相同文档前缀)时,可以复用同一份缓存块,从而节省显存并降低 Prefill 成本。

TensorRT-LLM

TensorRT-LLM 是面向 NVIDIA GPU 的大模型推理加速栈,重点在于高效算子(Kernel)与图级优化(Graph-level Optimization):通过更强的算子融合、更贴近硬件的精度与布局选择(例如 FP16/BF16/FP8、weight-only quantization),把通用 Transformer 计算编译成更高吞吐、更低延迟的推理执行计划。

它更偏“部署与性能工程”路径:需要围绕目标 GPU、精度与 batch/seq 长度做构建与调优;换来的是更稳定的延迟与更高的吞吐上限。

Ollama

Ollama 是面向本地开发的模型运行与分发工具:提供统一的模型拉取、量化版本管理与本地推理接口,降低“把模型跑起来”的工程摩擦。它更适合个人/小团队在本机进行原型验证与离线实验;若追求高并发在线服务,通常会使用更专业的推理引擎与服务编排。

TGI(Text Generation Inference)

TGI(Text Generation Inference)是面向 HuggingFace 模型生态的通用推理服务:提供标准化的 HTTP/gRPC 接口与常见的批处理/流式输出能力,适合把“能跑的模型”快速变成“可用的服务”。它的价值在于工程整合与稳定性,而不是把每个场景都推到极致性能。

SGLang

SGLang 强调“把推理当作可编排的程序执行”:当应用需要多步生成、结构化输出、工具调用或复杂控制流时,推理框架不仅要快,还要能把控制逻辑表达清楚并与 KV Cache 调度协同。它更像是服务端的“推理 DSL + runtime”。

llama.cpp(GGUF)

llama.cpp 是一套本地/边缘推理 runtime:围绕 GGUF/量化权重与 CPU/GPU 混合执行做了大量工程优化。它在“把模型放到普通机器上跑起来”这一目标上极具性价比,但并不追求云端多租户场景下的极限吞吐。

上下文工程(Context Engineering)
提示策略
零样本(Zero-shot)
少样本(Few-shot)
思维链(Chain-of-Thought)
Self-Consistency
ReAct
Tree of Thoughts(ToT)
上下文构建
系统提示(System Prompt)
对话历史与记忆

多数大模型 API 是无状态(Stateless)的:模型在一次调用中只“看到”你发送的输入(Prompt),不会自动记住上一次调用的对话内容。因此对话应用通常需要把对话历史(Conversation History)连同当前用户输入一起发给模型。

这会带来两个直接后果:

  • token 占用会随着历史增长而上升(直到触达上下文窗口上限)。
  • 并非“发得越多越好”:冗余历史会稀释注意力、提高成本,并可能引入过时/冲突信息。

工程上常见的记忆(Memory)分层是:

  • 短期记忆(Short-term Memory):保留最近 N 轮原文对话,确保局部连贯。
  • 工作记忆(Working Memory):把对话状态压缩成结构化摘要(例如用户偏好、已确认事实、当前任务约束)。
  • 长期记忆(Long-term Memory):把历史片段写入外部存储(向量库/数据库),需要时检索回填。
工具调用上下文
上下文窗口管理
Token 预算

Token 预算(Token Budget)是把上下文窗口(Context Window)当作一种“稀缺资源”来管理:一次请求的输入 token + 输出 token 都要计入模型的最大长度限制,并直接影响延迟与成本。

经验做法是把 prompt 切成可控的几块:系统提示(System Prompt)尽量短且稳定;对话历史只保留近期原文;把长期信息通过检索(Retrieval)按需注入。

压缩与摘要

压缩与摘要(Compression & Summarization)的核心不是把文本“变短”,而是把信息从“逐字转录(Transcript)”变成“可被模型继续使用的状态(State)”。常见策略:

  • 滚动摘要(Rolling Summary):每轮对话后更新一段固定长度的“当前状态”。
  • 层级摘要(Hierarchical Summarization):长文先分块总结,再总结摘要。
  • 结构化记忆(Structured Memory):用 JSON/表格保存关键字段(偏好、约束、已决策项),避免自然语言摘要漂移。

摘要要可验证:优先保留可操作事实(约束、数值、名称、决策),少写主观评价。

长文本处理策略

当“最新一次对话依赖很久以前的信息”时,最可靠的方法不是无限追加历史,而是检索增强:把历史切成片段并建立索引(向量索引/关键词索引/主题标签),在每次请求前先检索与当前问题最相关的片段,再把这些片段注入上下文。

在当前智能体(AI Agent)开发里,最主流的组合通常是:滑动窗口 + 滚动摘要 + 向量检索(RAG)。早期的外部记忆网络(Memory Networks / Neural Turing Machine)更多是研究范式,工程落地上更常见的是向量数据库与检索管线。

结构化输出
JSON Schema 约束
函数调用(Function Calling)
检索增强生成(RAG)

检索增强生成(Retrieval-Augmented Generation, RAG)把“外部知识”通过检索在推理时注入到上下文里:先检索,再生成。它解决的不是模型能力问题,而是信息可得性与可控性问题:把知识放在可更新的外部存储里,而不是指望模型参数记住一切。

真正落地到生产后,RAG 很快会从“模型 + 向量库”的玩具结构,变成一套完整的知识处理系统。一个更接近现实的抽象是:知识源接入、文档获取、分块、增强、索引、召回、融合、重排、上下文回拼、生成。其中任何一步做得粗糙,最终回答质量都会明显退化。

从工程视角看,RAG 的核心不只是“把文本切块后丢进向量数据库”,而是把知识库建成一个可持续演化的外部记忆系统。这里通常至少会区分三层对象:知识库(Base)负责来源配置、召回策略与索引策略;文档(Document)负责内容文件、语言、状态与分块配置;块(Chunk)负责可检索的最小语义单元及其摘要、问题、向量、命中统计等元数据。再往上,很多系统还会加一个目录(Catalog)层,把知识按业务树、产品线、权限域或租户边界组织起来。这种分层的意义在于:RAG 检索的不是“一个文本文件夹”,而是一个带治理、带生命周期、带配置继承的知识对象系统。

生产 RAG 的系统视角

一个成熟的知识库系统通常会显式区分知识源(Source)与检索目标(Target)。知识源回答“内容从哪里来”,例如上传文件、网页抓取、代码仓库、目录扫描;检索目标回答“内容最终由谁提供召回能力”,可以是系统自建索引,也可以是外部知识平台。这样设计的好处是把“接入来源”与“服务出口”解耦:同一套文档采集和治理流程,可以接到不同的检索后端,而不用把采集逻辑和向量库实现绑死。

另一个关键决策是把知识处理做成异步流水线,而不是同步上传即就绪。现实中的知识库往往需要经历扫描、下载、解析、分块、摘要生成、问题生成、向量化、索引构建等多个阶段。把这些阶段拆开,一方面是因为它们耗时、依赖不同资源且失败模式不同;另一方面是为了支持恢复、重试、并发控制与增量更新。于是,生产 RAG 往往天然带有一个状态机:知识库有自己的状态,文档有自己的状态,块也有自己的状态。这个状态机的作用是把长链路处理过程显式化,使每个阶段都能被观察、重跑和局部修复。

教程中的“上传文档 -> embedding -> 检索 -> 回答”只覆盖了最小闭环。真实系统里的知识库会持续新增、修改、下线、重建索引,并不断调整切分方式和召回参数。因此,RAG 更接近“搜索系统 + 知识处理中台 + 生成模型”的组合,而不是一次性的离线脚本。

分块策略(Chunking)

分块(Chunking)决定了“检索的最小单位”。块太大:召回相关信息但携带大量噪声;块太小:召回片段零散,缺上下文导致生成不稳。分块应与文档结构、问题类型、上下文窗口预算一起设计。

固定大小分块

固定大小分块(Fixed-size Chunking)按 token/字符数切片,简单稳定,适合结构较弱的纯文本与大规模离线构建。常配合重叠窗口(Overlap)避免跨边界信息断裂。

语义分块

语义分块(Semantic Chunking)用段落/标题/语义边界切分,目标是让一个 chunk 自洽(Self-contained)。它通常更适合技术文档与带层级结构的内容,但需要更复杂的解析与规则。

递归分块

递归分块(Recursive Chunking)先按大结构切(章节/标题),再对子块继续切(段落/句子/固定大小),兼顾结构与长度约束,是很多工程实现的折中方案。

生产系统里的分块通常远比这三类更细。除了固定大小、递归和语义切分,还会按 Markdown、HTML、PDF、代码、表格、JSON、LaTeX、句子、段落、滑动窗口等内容类型选择不同 chunker。这背后的设计判断非常重要:分块不是一个通用算法参数,而是内容理解策略的一部分。代码和 API 文档更适合按语法结构或标题层级切;表格和 PDF 更需要保留版面边界;Markdown/HTML 则需要保留层次结构,甚至形成父子 chunk 树。

这类设计会直接改变召回质量。若把所有内容都按固定长度切块,标题、层级、页面边界、代码块和表格结构都会被抹平;若系统保存 chunk 的父子关系、边界分隔符、正文起止位置、重叠前后文与结构元数据,那么检索命中的就不再只是孤立片段,而是文档结构中的一个明确位置。此时的 RAG 更接近结构化文档检索。

Agentic Chunking 进一步把 LLM 引入切分阶段,由模型判断哪些内容应属于同一语义单元。它在复杂文档上可能带来更强的语义完整性,但代价同样明显:构建成本高、可重复性差、调试难度大,提示词质量会直接影响索引结果。因此它更适合作为高价值内容的增强型切分,而不适合作为默认的全量基础设施。

向量数据库

向量数据库(Vector Database)存储每个 chunk 的向量表示(Embedding Vector)及其元数据(Metadata),支持近似最近邻(Approximate Nearest Neighbor, ANN)检索。向量并不“包含全文”,它是语义相似度的索引键;检索结果仍然需要回源拿到原文片段。

工程上需要区分“向量索引(Vector Index)”与“向量数据库(Vector Database)”:前者强调 ANN 检索算法与数据结构;后者强调持久化、增量更新、元数据过滤(Metadata Filtering)、分片/副本与多租户(Multi-tenancy)等系统能力。

生产知识库通常会同时维护多个索引平面:chunk 正文索引、chunk 摘要索引、chunk 问题索引,必要时还有文档摘要索引。它们对应的是不同的检索语义:正文索引擅长直接召回原文;摘要索引更适合长文压缩后的主题级匹配;问题索引则把 chunk 改写成更贴近用户查询的可检索意图。因此,生产 RAG 的索引设计本质上是“同一内容的多种检索视图”。

双后端架构也是常见现实。高质量知识库常把 Milvus/Qdrant 一类向量系统与 Elasticsearch/OpenSearch 一类全文检索系统并行使用:前者负责稠密向量、稀疏向量与 ANN 检索,后者负责 BM25、字段过滤和业务搜索。这种组合对应的是信号分工:向量擅长语义匹配,词项系统擅长精确关键词与过滤。真正的难点随之转移到一致性和融合上:索引命名要对齐,更新要同步,删除要清理,跨系统分数不能直接比较。

实现形态与选型

向量检索组件通常有三种部署形态:向量索引库(如 FAISS/ScaNN)偏“库”;向量数据库(如 Milvus/Qdrant/Weaviate)偏“服务”;全文检索引擎(如 Elasticsearch/OpenSearch)则以 BM25 为核心并逐步补齐向量检索能力。许多生产系统采用“双引擎”组合:向量库负责高性能 ANN,全文检索负责复杂过滤与关键词召回,最终在融合/重排阶段统一排序。

形态 代表实现 优势 局限 适用场景
向量索引库(In-process Vector Index) FAISS / ScaNN 单机性能极强;集成简单;易做离线批构建 分布式/多租户/权限/运维能力弱;元数据过滤能力有限 原型验证;单机检索;离线候选生成
向量数据库(Vector Database Service) Milvus / Qdrant / Weaviate 持久化 + CRUD;支持元数据过滤;更易做水平扩展 需要运维;延迟/吞吐取决于索引与集群配置 生产 RAG;增量更新频繁;需要过滤/权限
全文检索 + 向量检索(Hybrid Search Engine) Elasticsearch / OpenSearch BM25 + 过滤能力强;生态成熟;适合业务检索 向量能力与性能细节高度依赖具体版本/配置;向量索引形态可选项较少 强关键词依赖;复杂过滤/字段检索;混合检索一体化
组合架构(Vector DB + Search Engine) Milvus/Qdrant + ES 各取所长;向量与词项召回分别优化;融合/重排可控 系统更复杂;需要去重、打分对齐与一致性策略 对检索质量要求高,且有复杂过滤/排序逻辑
托管服务(Managed Service) Pinecone / 各云厂商向量服务 运维成本低;弹性扩缩容;通常带权限与监控 成本较高;可控性与部署形态受限 快速上线;团队缺乏检索基础设施经验
ANN 索引与过滤

ANN 索引(ANN Index)在“速度、召回率(Recall)与内存”之间权衡。检索侧常见痛点是“向量相似度可算,但业务过滤很难做快”:元数据过滤会破坏 ANN 的近邻结构,使得系统需要在“先过滤再向量检索”和“先向量检索再过滤”之间做策略选择。

在生产知识库里,过滤通常不是可选项,而是第一等公民。目录树(Catalog Tree)、启用状态、文档类型、租户边界、语言、内容类型、业务域前缀,都可能成为过滤条件。也正因为如此,许多系统会把 catalog 前缀过滤、enabled 标志、source_type/source_id 等字段同时写入 Milvus 和 ES,两边都能先做过滤再做召回。否则,召回质量再高,也可能把“本不该返回的内容”混进上下文。

索引/策略 核心思路 优点 代价
Flat(Exact) 全量计算相似度 精确;实现最简单 规模上去后延迟/成本不可接受
HNSW 分层小世界图近邻搜索 高召回、低延迟;对在线增量友好 内存占用较高;过滤条件复杂时性能波动
IVF / IVF-PQ 先粗聚类(倒排),再在桶内搜索;PQ 进一步压缩 更省内存;适合大规模离线构建 更新成本高;召回/延迟依赖参数调优
DiskANN / Hybrid Memory 把索引/向量放到 SSD,内存放导航结构 降低内存压力;可支持更大规模 I/O 成为瓶颈;工程复杂度更高
检索策略
稠密检索(向量相似度)

稠密检索(Dense Retrieval)用向量相似度(如余弦相似度/内积)做 top-k 召回,擅长语义匹配与同义改写,但可能漏掉精确关键词(如错误码、版本号)。

全文检索(BM25 / ES)

全文检索(Lexical Retrieval)以 BM25 等词项匹配为核心,擅长精确匹配与关键词召回。它对拼写、专有名词、数字更敏感,但对语义改写不够鲁棒。

稀疏检索(Sparse Retrieval / SPLADE)

稀疏检索(Sparse Retrieval)用“稀疏向量”表示文本:向量维度对应词项(或子词),权重表示该词项对匹配的贡献。与 BM25 相比,稀疏检索的权重来自模型学习而非纯统计;与稠密检索相比,它保留了词项级可解释性与对罕见词/数字的敏感性。

典型路线包括 SPLADE(Sparse Lexical and Expansion Model):通过学习得到“词项扩展(Lexical Expansion)”,让语义相关但不共词的文本仍能在词项空间相遇。工程上,稀疏检索常作为混合检索的一路召回信号,而不是单独替代 BM25。

混合检索

混合检索(Hybrid Retrieval)把稠密检索与全文检索结合:先分别召回,再融合排序(如加权、去重、学习排序)。这是目前最稳健的通用策略之一。

在更完整的知识库系统里,混合检索不只是“dense + BM25”两路,而可能是 chunk / summary / question 三类检索目标与 dense / sparse / fulltext 三类检索路径的组合矩阵。换句话说,生产 RAG 召回的是多个“信号通道”,而不是单一相似度函数。它的优势是覆盖面更强:原文命中、主题命中、问句改写命中可以互补;但代价也很直接:路径暴涨、分数更不可比、日志更难读、回归测试更复杂。

这类系统往往还会按知识库能力做“有效方法裁剪”。例如,用户请求 fullhybrid,但某个知识库只建了 dense 和 sparse 索引,那么实际就只能退化成 hybrid;某个库没有开启 question recall,就不该在该路径上浪费资源。这个细节反映出一个成熟的 RAG 判断:检索策略不是全局写死的,而是知识库级配置与请求级策略共同决定的。

分数融合(Score Fusion)

混合检索的难点不在“多路召回”,而在“分数不可比(Incomparable Scores)”:BM25 分数、余弦相似度/内积分数、稀疏向量分数往往不在同一尺度,不能直接相加。常见融合策略:

  • 归一化后加权:对各路分数做 min-max / z-score 等归一化,再做加权求和或加权乘积。
  • 基于排序的融合:不依赖原始分数尺度,例如 RRF(Reciprocal Rank Fusion):\(\mathrm{score}(d)=\sum_{s}\frac{1}{k+\mathrm{rank}_s(d)}\)。
  • 学习排序(Learning to Rank):把各路分数与特征(BM25、embedding sim、字段匹配、长度等)作为特征,训练一个排序模型做融合。

生产系统通常更偏爱基于排序的融合,而不是直接拼原始分数。这是因为 ES 的 \(_score\)、Milvus 稠密距离、Milvus 稀疏 BM25 分数往往来自完全不同的评分体系。RRF 或加权 RRF 的价值就在于鲁棒:它不要求各后端分数可比,只要求各路径给出相对顺序。若再往上追求精度,则会在粗召回后接一个模型重排器,对融合后的候选做统一判断。

重排序(Reranking)

重排序(Reranking)在“召回”(Recall)之后提升“相关性排序”(Precision@k):用更强但更慢的模型对候选片段重新打分。

成熟 RAG 系统里的 rerank 还常分成两层。第一层是每个知识库内部的局部重排:对该库自己的候选做加权、RRF 或模型精排。第二层是多知识库结果合并后的全局重排:当查询同时打到多个知识库时,再在总候选集合上做一次统一排序。这样做的动机很现实:单库内部的分数可比较,并不代表跨库结果也天然可比较;若不做第二层,全局 top-k 往往会被某个打分体系更“激进”的知识库垄断。

Cross-Encoder Reranker

Cross-Encoder Reranker 把 query 与候选 chunk 拼接后输入同一个编码器,用注意力做细粒度匹配,相关性通常更高,但计算更慢,适合对 top-k(例如 50→10)做精排。

典型输入形式是 [CLS] query [SEP] doc [SEP](或对应模型的特殊 token)。在 BERT 类模型中,token type embeddings(也称 segment embeddings)可用于区分两段文本;随后 Transformer 的全连接自注意力允许 query token 与 doc token 在每一层发生深度交互,这正是 cross-encoder “cross” 的本质。

打分通常取 \([\mathrm{CLS}]\) 位置的最终隐向量 \(h_{\mathrm{CLS}}\) 过一个线性层得到相关性分数(或二分类 logits)。与双编码器(Bi-Encoder / Dual Encoder)相比,cross-encoder 更准但无法离线预计算候选向量,因此在线成本更高。

LLM Reranker

LLM Reranker 用大模型直接判断相关性或做对比选择,能融合更复杂的语义与任务约束,但成本更高且需要防止“自信乱判”。工程上常用它做少量候选的最终筛选。

生成式重排序(Generative Reranking)

生成式重排序(Generative Reranking)把“相关性打分”转写为生成任务:把 query 与 doc 拼接输入解码器(Decoder-only)或编码器-解码器(Encoder–Decoder),让模型生成一个标签 token(例如 Yes/No)或一个短评分文本,并用生成概率作为分数。

常见的点式打分形式是二分类 log-odds:令 \(y\in\{0,1\}\) 表示是否相关,则

\[\mathrm{score}(q,d)=\log p_\theta(y=1\mid q,d)-\log p_\theta(y=0\mid q,d)\]

相比传统 BERT 类 cross-encoder,生成式 reranker 往往更擅长处理长文本匹配、复杂约束与隐含推理;工程上常用“轻量级 LLM + 领域数据微调”来获得显著增益。

列表式重排序(Listwise Reranking)

列表式重排序(Listwise Reranking)把多个候选 doc 一次性送入模型,在同一个上下文窗口中共同建模“相对顺序”,而不是对每个(query, doc)独立跑一次 forward。直觉上,它让候选之间在 self-attention 中“同台竞争”,从而提升排序一致性,并降低多次推理带来的总开销。

实现上常见做法是:把候选 doc 按截断长度拼接成一个 list,要求模型输出每个 doc 的分数或名次;也有实现会在末尾使用一个专门的“汇聚 token”对每个 doc 读取表示。Listwise 方法的工程约束更强:候选数、每段 doc 的截断长度与模型上下文窗口会直接决定可吞吐的 top-k。

训练目标与 Hard Negatives

精排训练的难点是“区分相似但不相关”:需要硬负样本(Hard Negatives)来逼迫模型学习细粒度差异。硬负样本通常来自第一阶段召回:对同一 query,取检索 top-k 中不相关的候选作为 negatives(也可混入 BM25 negatives、in-batch negatives、或对抗式 negatives)。

目标 形式 直觉 常见风险
点式(Pointwise) 学习 \(s(q,d)\) 或 \(p(y=1\mid q,d)\) 把相关性当作二分类/回归 分数标定(Calibration)难;对“相对顺序”监督较弱
对式(Pairwise) 学习 \(s(q,d^+)>s(q,d^-)\) 直接优化排序边际(Margin) 负样本质量决定上限;采样偏差可能放大
列表式(Listwise) 对候选列表联合优化(如 softmax over list) 更贴近 NDCG/MRR 等排序指标 计算与实现复杂;受上下文窗口约束
蒸馏(Knowledge Distillation)

蒸馏(Knowledge Distillation)把一个强但慢的教师模型(Teacher)产生的打分/偏好,转移给一个更快的学生模型(Student)。在重排序里,蒸馏最常见的目标不是“压缩参数”,而是把 LLM 级别的相关性判断能力下放到可规模化的 reranker,使线上能承载更大的 top-k、更高的 QPS 或更低的 P99。

Teacher → Student 监督信号 常见损失 收益 主要风险
LLM / 生成式 reranker → Cross-Encoder 软分数(log-odds / graded)或偏好对 回归(MSE)/ 对式(pairwise logistic) 显著降成本;保留较强语义与推理能力 学生上限受教师约束;教师偏差会被复制
Cross-Encoder → Bi-Encoder 相对顺序/分数 对比学习(InfoNCE)/ 蒸馏排序边际 把精排能力“下放”到召回,提高召回质量 需要大量 hard negatives;对领域漂移敏感
LLM → 数据标注(作为训练集构造器) 弱标注标签 + 解释/证据 按目标任务训练(点式/对式/列表式) 快速构造大规模领域数据;迭代快 噪声标注;需抽样人工复核与在线 A/B 验证
返回内容不是只给命中文本

RAG 检索阶段的最终产物并不一定只是“命中的那一小段 chunk”。很多高质量系统会把返回内容模式做成显式策略:只返回命中块正文、返回去掉 overlap 的核心正文、返回命中块加邻近上下文、或按文档中的位置范围把相关块递归拼回更完整的片段。这样做的原因是:模型生成真正需要的是足够完整且边界清晰的证据上下文,而不是孤立句子。

这里的关键判断是:检索命中的是索引单元,但喂给模型的应是生成单元。索引单元倾向短小、便于召回;生成单元则要兼顾上下文完整性、token 预算和可引用性。若两者完全绑定,系统通常会在召回精度与生成可读性之间来回拉扯。

从项目设计能看到的几条经验

第一,RAG 的上限不只由 embedding 模型决定,而是由“分块质量、索引视图、融合策略、回拼策略、状态治理”共同决定。把注意力只放在换一个更强 embedding 上,通常抓不住主矛盾。

第二,知识库不是静态文件集合,而是带状态机的外部知识资产。只有显式区分 base、document、chunk,并让它们有自己的生命周期,系统才可能支持增量更新、失败恢复、重建和审计。

第三,生产 RAG 常常天然走向双后端和多路径召回。这个方向的收益是更稳健的覆盖率,代价是系统复杂度、索引一致性成本和观测难度都会明显上升。因此它适合高价值知识库,不一定适合所有团队的第一版系统。

第四,把摘要和问题也视作可检索对象,是一个非常务实的设计。它等于承认“原文表述”与“用户提问方式”经常不一致,于是用知识增强知识本身的可检索性。但它也会带来额外索引、额外 embedding 成本与额外一致性问题,因此只有在召回质量确实成为瓶颈时,这种多视图索引才值得引入。

第五,外部知识平台同步并不等于“复制一份数据就结束”。一旦系统允许一部分知识由外部平台托管、另一部分知识由内部系统自建索引,那么“谁是事实源、谁负责更新、谁负责删除、谁负责召回”就必须在架构上说清楚。否则最容易出现的不是召回不到,而是召回出重复、过期或跨系统不一致的内容。

主流选型对比
阶段 常见架构 代表实现 核心逻辑 速度 精度
召回 双编码器(Bi-Encoder) BGE-Embedding
text-embedding-3
向量相似度 极快 中
精排(稳健基线) 交叉编码器(Cross-Encoder) BAAI
bge-reranker-v2-m3
\([q;d]\) 深度交互 中 高
精排(顶配) 生成式 / 列表式(LLM-based) BGE-Reranker-v2-Gemma
Jina-Reranker-v3
生成式打分或 listwise 竞争 较慢 极高
生成与融合

生成与融合(Generation & Fusion)的关键在于:把检索到的证据(Evidence)以可控格式注入 prompt,并要求模型“基于证据回答”。常见做法包括:

  • Stuffing:把 top-k 片段直接拼接进上下文(最简单,最易超预算)。
  • Map-Reduce:先对各片段分别提炼要点,再汇总生成最终答案(更稳,成本更高)。
  • Refine:先用少量证据生成初稿,再逐片段增量修订(适合长证据链)。
智能体(Agent)
核心概念
计划-执行

计划-执行(Plan-Execute)是智能体最常见的控制流之一:先把“用户目标”分解为一组可操作步骤(计划),再逐步调用工具/模型完成这些步骤(执行),并把中间结果写回状态(State)。当环境反馈与计划假设不一致时,触发再计划(Replan)。工程上,它的价值是把一次长输出变成可观测(Observable)、可重试(Retryable)、可中断(Interruptible)的多步过程。

感知-推理-行动循环
工具使用(Tool Use)
记忆系统
短期记忆(上下文窗口)
长期记忆(外部存储)
记忆类型:情景 / 语义 / 程序
推理与规划
ReAct
Reflection(自我反思)
Plan-and-Solve
MCTS(蒙特卡洛树搜索)
工具与行动
Function Calling
Code Interpreter
Web 搜索
Computer Use
MCP(模型上下文协议)
多智能体系统
角色分工
Planner
Executor
Critic
协作模式
顺序执行
并行执行
层级委派
主流框架

智能体框架(Agent Framework)解决的是“把一次模型调用变成可控的多步程序执行”:包括状态管理(State)、工具调用(Tool Use)、失败重试(Retry)、并发/队列(Concurrency)、以及可观测性(Observability)。选型应优先匹配你的系统形态:你是要做“单智能体工具链”,还是“多智能体协作”,以及你希望控制流是“图(Graph)”还是“对话(Conversation)”。

框架/形态 控制流模型 强项 代价 适用
LangChain / LangGraph 链式/图式(Graph) 组件化;易组合 RAG、工具与记忆;LangGraph 适合复杂状态机 抽象层较多;需要明确工程边界 生产 RAG/Agent pipeline
AutoGen 多智能体对话(Conversation) 多角色协作自然;适合研究与原型 落地时需补齐状态持久化与治理 多智能体实验;协作式任务
CrewAI 角色 + 任务流水线 任务编排直观;适合“岗位分工”式流程 可控性取决于框架提供的扩展点 面向业务流程的多角色 Agent
OpenAI Assistants API 平台托管(Managed) 线程/工具/文件等能力平台化;减少自建状态机成本 能力与约束随平台演进;更依赖供应商 快速上线;不想自建编排与存储
LangChain / LangGraph

LangChain 偏“组件库”:把 prompt、模型、检索器、工具等抽象成可组合模块;LangGraph 偏“控制流”:用图结构显式表示状态转移与循环,适合需要反复计划-执行-校验的场景。

AutoGen

AutoGen 强调多智能体(Multi-agent)协作:用不同角色的 agent 互相对话、互相评审来完成复杂任务。工程落地时通常需要额外补齐:权限隔离、外部记忆与执行沙箱。

CrewAI

CrewAI 把多智能体协作组织为“角色(Role)+ 任务(Task)+ 工具(Tool)”:更贴近业务流程编排。它的价值是降低多角色 workflow 的表达成本。

OpenAI Assistants API

Assistants API 属于“托管式编排”:把对话线程、工具调用与部分状态管理放到平台侧,应用只需提供指令、工具与外部数据。这类托管方案的优点是工程摩擦小;缺点是当业务需要强定制的控制流与存储策略时,可控性会成为约束。

← Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • Octave知识集锦
  • 吴恩达机器学习笔记
  • LaTex语法速查
  • 线性代数学习笔记
  • 利用LangChain和语言模型交互

Recent Posts

  • 人工智能知识速查
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 利用LangChain和语言模型交互
  • K8S集群跨云迁移
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注国际售后AI落地。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • 人工智能知识速查
    基础数学 代数基础 运算律与代数式 代数式(Algebraic Expression)由常数、变量与运算构 ...
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
  • Istio中的透明代理问题
    为何需要透明代理 Istio的Sidecar作为一个网络代理,它拦截入站、出站的网络流量。拦截入站流量后,会使 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • Bazel学习笔记 38 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
  • Three.js学习笔记 24 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • 杨松涛 on snmp4j学习笔记
  • kaka on Cilium学习笔记
  • JackZhouMine on Cesium学习笔记
  • 陈黎 on 通过自定义资源扩展Kubernetes
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
©2005-2026 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2