AI 工程基础体系 · 第 34/100 篇。内容覆盖机器学习、深度学习与生成式 AI;模型、数据、评测、权限和成本会作为同一生产系统处理。

AI 线性代数:向量、矩阵、张量、特征分解与几何直觉

线性代数是机器学习中表示数据、组合特征、变换空间和分析模型的共同语言。一个训练样本可以表示为向量,一批样本组成矩阵,图像和视频通常表示为高阶张量,神经网络层则主要执行矩阵乘法、张量收缩和逐元素非线性变换。

更重要的是,线性代数不仅描述“数据长什么样”,还解释以下问题:

  • 为什么神经网络层可以写成 Wx+bWx+b
  • 为什么特征缩放会影响距离、优化和模型结果;
  • 为什么 PCA 能找到“最重要的方向”;
  • 为什么 Transformer 中的注意力需要矩阵乘法;
  • 为什么某些模型会出现梯度爆炸、表示坍缩或数值不稳定;
  • 为什么形状、秩、条件数和内存布局会直接影响生产系统的正确性与成本。

一、先建立对象:标量、向量、矩阵和张量

1. 标量

标量是单个数,例如:

3,0.5,π3,\quad -0.5,\quad \pi

在机器学习中,损失值、学习率、温度参数和一个神经元的偏置通常是标量。

标量没有轴,也没有形状;如果用数组库表示,标量可以是零维数组,或者某些框架中的标量张量。


2. 向量

向量是一列有顺序的数:

x=[x1x2xd]Rdx= \begin{bmatrix} x_1\\ x_2\\ \vdots\\ x_d \end{bmatrix} \in \mathbb{R}^d

其中 dd 是维度,xix_i 是第 ii 个分量。

在机器学习中,向量可以表示:

  • 一个样本的 dd 个特征;
  • 一个词或句子的嵌入;
  • 一个分类器的权重;
  • 一个输入样本关于各类别的 logits;
  • 一个时刻的隐藏状态。

“向量”不仅是一个数组,更重要的是它所在的空间和坐标含义。例如,年龄、收入、点击次数组成的向量,其各维的单位和尺度不同;词嵌入的各维通常没有人类可直接解释的物理单位。

行向量与列向量

严格的矩阵记号通常区分:

xRd×1x\in\mathbb{R}^{d\times 1}

表示列向量,而

xR1×dx^\top\in\mathbb{R}^{1\times d}

表示行向量。

工程代码中,一个形状为 (d,) 的 NumPy 数组既不像严格的行向量,也不像严格的列向量。它在不同运算中的行为可能不同,因此在需要明确矩阵乘法时,应主动使用 (d, 1)(1, d)

例如:

import numpy as np

x = np.array([1.0, 2.0, 3.0])       # shape: (3,)
x_col = x[:, None]                   # shape: (3, 1)
x_row = x[None, :]                   # shape: (1, 3)

print(x.shape, x_col.shape, x_row.shape)
# (3,) (3, 1) (1, 3)

x_colx_row 的数值相同,但在矩阵乘法中含义不同:

xxR1×1x^\top x\in\mathbb{R}^{1\times 1}

是内积,而

xxRd×dxx^\top\in\mathbb{R}^{d\times d}

是外积。


3. 矩阵

矩阵是按行和列排列的二维数组:

A=[a11a12a1na21a22a2nam1am2amn]Rm×nA= \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n}\\ a_{21} & a_{22} & \cdots & a_{2n}\\ \vdots & \vdots & \ddots & \vdots\\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{bmatrix} \in\mathbb{R}^{m\times n}

mm 表示行数,nn 表示列数。

在常见的数据表中:

XRN×DX\in\mathbb{R}^{N\times D}

通常表示 NN 个样本、每个样本有 DD 个特征:

  • iiXi,:X_{i,:}:第 ii 个样本;
  • jjX:,jX_{:,j}:第 jj 个特征。

监督学习中的标签也可以是矩阵:

  • 回归标签:YRN×KY\in\mathbb{R}^{N\times K}
  • 多分类 one-hot 标签:Y{0,1}N×KY\in\{0,1\}^{N\times K}

矩阵的形状不是装饰信息,而是运算合法性的条件。若:

ARm×n,BRn×pA\in\mathbb{R}^{m\times n},\quad B\in\mathbb{R}^{n\times p}

则矩阵乘法 ABAB 才有定义,结果为:

ABRm×pAB\in\mathbb{R}^{m\times p}

中间维度 nn 必须相同。


4. 张量

张量是可以有任意多个轴的数组。严格的数学张量还涉及坐标变换下的多线性结构;在深度学习框架中,“张量”通常指带有:

  • 数值;
  • 形状 shape
  • 数据类型 dtype
  • 设备位置,如 CPU 或 GPU;
  • 可选的自动微分状态

的多维数组。

例如:

数据 常见形状 含义
单个标量 () 一个损失值
一个样本 (D,) DD 个特征
一批表格样本 (B, D) batch size 为 BB
灰度图像批次 (B, H, W) 批次、高、宽
RGB 图像批次 (B, C, H, W)(B, H, W, C) 通道布局不同
文本隐藏状态 (B, T, D) 批次、序列长度、隐藏维度
多头注意力表示 (B, H, T, D_h) 批次、头数、序列长度、每头维度

这里的 BBTTDD 不能只看数字,必须同时理解轴的语义。把 (B, T, D) 错当成 (B, D, T),代码可能仍能运行,却会让模型在错误的维度上做运算。


二、向量的几何:长度、方向、角度与投影

1. 范数:向量有多大

向量的范数是衡量其大小的函数。最常用的是 L2L_2 范数:

x2=i=1dxi2\|x\|_2=\sqrt{\sum_{i=1}^{d}x_i^2}

例如:

x=[34]x= \begin{bmatrix} 3\\ 4 \end{bmatrix}

则:

x2=32+42=5\|x\|_2=\sqrt{3^2+4^2}=5

常见范数还包括:

x1=ixi\|x\|_1=\sum_i|x_i|

以及:

x=maxixi\|x\|_\infty=\max_i |x_i|

它们产生不同的几何形状:

  • L2L_2 单位球是圆或球;
  • L1L_1 单位球在二维中是菱形;
  • LL_\infty 单位球在二维中是正方形。

在正则化中,L1L_1 惩罚常产生稀疏解,L2L_2 惩罚更倾向于让参数整体变小,但“产生稀疏”的结论并不是所有优化实现都能无条件保证的。


2. 内积:相似方向与投影

两个同维向量 x,yRdx,y\in\mathbb{R}^d 的内积为:

xy=i=1dxiyix^\top y=\sum_{i=1}^{d}x_i y_i

几何上:

xy=x2y2cosθx^\top y=\|x\|_2\|y\|_2\cos\theta

其中 θ\theta 是两个向量的夹角。

因此:

  • xy>0x^\top y>0:夹角小于 9090^\circ,方向总体相近;
  • xy=0x^\top y=0:正交;
  • xy<0x^\top y<0:方向总体相反。

余弦相似度定义为:

cos(x,y)=xyx2y2\cos(x,y)=\frac{x^\top y}{\|x\|_2\|y\|_2}

它只关注方向,不关注长度。若两个向量方向相同但长度差异很大,余弦相似度仍为 1;内积则会随长度变大。

这一区别在嵌入检索中十分重要:

  • 使用内积时,向量范数本身可能影响排序;
  • 使用余弦相似度时,需要避免零向量,因为分母为零;
  • 将向量先做 L2L_2 归一化后,内积等于余弦相似度。

3. 投影:一个向量在另一个方向上的分量

xx 投影到非零向量 uu 的方向上:

proju(x)=xuuuu\operatorname{proj}_u(x) = \frac{x^\top u}{u^\top u}u

推导来自以下要求:投影结果应为 cucu,且残差 xcux-cuuu 正交:

u(xcu)=0u^\top(x-cu)=0

于是:

uxcuu=0u^\top x-c\,u^\top u=0

得到:

c=uxuuc=\frac{u^\top x}{u^\top u}

例如:

x=[32],u=[10]x= \begin{bmatrix} 3\\ 2 \end{bmatrix}, \quad u= \begin{bmatrix} 1\\ 0 \end{bmatrix}

则:

proju(x)=31[10]=[30]\operatorname{proj}_u(x) = \frac{3}{1} \begin{bmatrix} 1\\ 0 \end{bmatrix} = \begin{bmatrix} 3\\ 0 \end{bmatrix}

残差为 (0,2)(0,2)^\top,与 uu 正交。

线性回归、最小二乘法和 PCA 都可以从“投影”理解:它们试图把数据投影到某个子空间,同时控制投影误差或保留信息。


4. 距离与特征缩放

欧氏距离是:

d(x,y)=xy2d(x,y)=\|x-y\|_2

若一个特征的数值范围远大于其他特征,它会主导距离。例如,年龄差异可能是几十,而收入差异可能是几万。未经缩放时,距离模型、K 近邻、聚类和 RBF 核方法可能主要根据收入作出判断。

常见标准化为:

zj=xjμjσjz_j=\frac{x_j-\mu_j}{\sigma_j}

其中 μj\mu_jσj\sigma_j 必须只使用训练集计算。若把验证集或测试集也用于计算它们,就会把评测数据的分布信息泄漏进训练流程。

标准化并不意味着所有特征变得“同样重要”。它只是改变坐标尺度,使距离和优化过程不被原始单位单方面支配。业务上真实重要性仍应通过模型、实验和评测验证。


三、矩阵:线性变换、组合特征与批量计算

1. 矩阵乘法不是逐元素乘法

若:

ARm×n,BRn×pA\in\mathbb{R}^{m\times n}, \quad B\in\mathbb{R}^{n\times p}

矩阵乘法的第 i,ji,j 个元素为:

(AB)ij=k=1nAikBkj(AB)_{ij} = \sum_{k=1}^{n}A_{ik}B_{kj}

它把 AA 的第 ii 行与 BB 的第 jj 列做内积。

例如:

A=[1234],B=[5678]A= \begin{bmatrix} 1&2\\ 3&4 \end{bmatrix}, \quad B= \begin{bmatrix} 5&6\\ 7&8 \end{bmatrix}

则:

AB=[15+2716+2835+4736+48]=[19224350]AB= \begin{bmatrix} 1\cdot5+2\cdot7 & 1\cdot6+2\cdot8\\ 3\cdot5+4\cdot7 & 3\cdot6+4\cdot8 \end{bmatrix} = \begin{bmatrix} 19&22\\ 43&50 \end{bmatrix}

逐元素乘法则是:

AB=[5122132]A\odot B= \begin{bmatrix} 5&12\\ 21&32 \end{bmatrix}

二者通常不同。工程中 @matmul 或框架的矩阵乘法算子表示前者,而 * 通常表示逐元素乘法;但具体行为仍受语言和库规则影响,必须检查形状。


2. 矩阵作为线性变换

矩阵 ARm×nA\in\mathbb{R}^{m\times n} 定义了一个线性映射:

f(x)=Axf(x)=Ax

它满足:

A(x+y)=Ax+AyA(x+y)=Ax+Ay

A(cx)=cAxA(cx)=cAx

二维中的矩阵可以表示旋转、缩放、剪切和反射。例如:

R=[cosθsinθsinθcosθ]R= \begin{bmatrix} \cos\theta&-\sin\theta\\ \sin\theta&\cos\theta \end{bmatrix}

表示绕原点旋转 θ\theta 角度,并保持长度不变:

Rx2=x2\|Rx\|_2=\|x\|_2

缩放矩阵:

S=[sx00sy]S= \begin{bmatrix} s_x&0\\ 0&s_y \end{bmatrix}

则把 xx 的两个坐标分别缩放为 sxx1s_xx_1syx2s_yx_2

神经网络中的线性层:

z=Wx+bz=Wx+b

严格来说,带偏置的映射不是线性的,而是仿射变换,因为:

f(0)=bf(0)=b

只有 b=0b=0 时才是线性变换。工程文献常把 Linear 层统称为线性层,但在数学上应区分“线性”和“仿射”。


3. 行空间、列空间和秩

矩阵的列空间是所有列向量线性组合形成的空间:

C(A)={Ax:xRn}\mathcal{C}(A)=\{Ax:x\in\mathbb{R}^n\}

它描述矩阵能够产生哪些输出。矩阵的秩是列空间的维度,也等于行空间的维度:

rank(A)=dim(C(A))\operatorname{rank}(A) = \dim(\mathcal{C}(A))

若矩阵的列线性相关,秩小于列数。低秩意味着存在冗余方向,这在压缩、推荐系统、PCA 和参数高效建模中都很重要。

例如:

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

第二列是第一列的 2 倍,因此:

rank(A)=1\operatorname{rank}(A)=1

尽管 AA 有两个列,但它只能把输入映射到一条直线上。它不可逆,因为不同输入可能得到相同输出。


4. 转置、对称矩阵和正交矩阵

转置把行列交换:

(A)ij=Aji(A^\top)_{ij}=A_{ji}

A=AA=A^\top,则称为对称矩阵。

若矩阵满足:

QQ=IQ^\top Q=I

则称为正交矩阵。其逆为:

Q1=QQ^{-1}=Q^\top

正交变换保持内积、长度和角度:

(Qx)(Qy)=xy(Qx)^\top(Qy)=x^\top y

这解释了为什么旋转不会改变距离。数值计算中,正交矩阵通常比任意矩阵更稳定,因为它不会放大或缩小向量的长度。


四、线性方程组与最小二乘:从拟合到投影

1. 方程组

线性方程组可以写作:

Ax=bAx=b

其中:

  • AA 是系数矩阵;
  • xx 是未知向量;
  • bb 是目标向量。

如果 AA 是方阵且可逆,则:

x=A1bx=A^{-1}b

但实际计算中通常不应显式求逆。直接计算 A1A^{-1} 既可能更慢,也可能放大数值误差;应使用线性求解器,例如 np.linalg.solve


2. 过定约束与最小二乘

当样本多于参数时,方程:

Xw=yXw=y

通常没有完全精确的解。最小二乘法寻找:

w^=argminwXwy22\hat w = \arg\min_w \|Xw-y\|_2^2

令目标函数:

J(w)=(Xwy)(Xwy)J(w)=(Xw-y)^\top(Xw-y)

展开并求梯度:

wJ(w)=2X(Xwy)\nabla_w J(w) = 2X^\top(Xw-y)

令梯度为零:

XXw=XyX^\top Xw=X^\top y

这就是正规方程。若 XXX^\top X 可逆:

w^=(XX)1Xy\hat w=(X^\top X)^{-1}X^\top y

几何上,Xw^X\hat wyyXX 的列空间上的正交投影,因此残差满足:

X(yXw^)=0X^\top(y-X\hat w)=0

也就是说,残差与所有特征列都正交。

为什么正规方程不是总是首选

当特征高度相关时,XXX^\top X 的条件可能很差。因为:

κ(XX)κ(X)2\kappa(X^\top X)\approx \kappa(X)^2

条件数平方会放大数值问题。生产代码通常优先使用 QR 分解、SVD 或经过正则化的求解,而不是手动计算逆矩阵。


3. 岭回归与正则化

岭回归在最小二乘目标上加入 L2L_2 惩罚:

w^=argminw(Xwy22+λw22)\hat w = \arg\min_w \left( \|Xw-y\|_2^2+\lambda\|w\|_2^2 \right)

其中 λ0\lambda\ge 0。求导得到:

(XX+λI)w=Xy(X^\top X+\lambda I)w=X^\top y

λ>0\lambda>0 时,即使 XXX^\top X 不可逆,矩阵也可能变得可解,并且能抑制过大的参数。但正则化会引入偏差,不能简单理解为“永远提高准确率”;应通过独立验证集选择 λ\lambda


五、特征值与特征向量:变换中不改变方向的轴

1. 定义

对于方阵 ARn×nA\in\mathbb{R}^{n\times n},如果存在非零向量 vv 和标量 λ\lambda,使得:

Av=λvAv=\lambda v

则称:

  • vvAA 的特征向量;
  • λ\lambda 是对应的特征值。

通常,矩阵会改变一个向量的方向和长度;特征向量是例外:变换后仍在原方向上,只是被缩放 λ\lambda 倍。

λ>1|\lambda|>1 时,该方向被放大;当 0<λ<10<|\lambda|<1 时,该方向被缩小;当 λ<0\lambda<0 时,还会发生方向反转。


2. 特征值方程的推导

由:

Av=λvAv=\lambda v

移项:

(AλI)v=0(A-\lambda I)v=0

要使存在非零解,矩阵 AλIA-\lambda I 必须不可逆:

det(AλI)=0\det(A-\lambda I)=0

这称为特征多项式方程。解出 λ\lambda 后,再求解:

(AλI)v=0(A-\lambda I)v=0

得到相应的特征向量。


3. 完整算例

考虑对称矩阵:

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

特征多项式为:

det(AλI)=2λ112λ\det(A-\lambda I) = \begin{vmatrix} 2-\lambda&1\\ 1&2-\lambda \end{vmatrix}

=(2λ)21=λ24λ+3=(λ3)(λ1)=(2-\lambda)^2-1 =\lambda^2-4\lambda+3 =(\lambda-3)(\lambda-1)

因此特征值为:

λ1=3,λ2=1\lambda_1=3,\qquad \lambda_2=1

对于 λ1=3\lambda_1=3

(A3I)v=0(A-3I)v=0

即:

[1111][v1v2]=0\begin{bmatrix} -1&1\\ 1&-1 \end{bmatrix} \begin{bmatrix} v_1\\v_2 \end{bmatrix} =0

所以 v1=v2v_1=v_2,可取归一化特征向量:

q1=12[11]q_1=\frac{1}{\sqrt 2} \begin{bmatrix} 1\\1 \end{bmatrix}

对于 λ2=1\lambda_2=1

(AI)v=0(A-I)v=0

得到 v1=v2v_1=-v_2,可取:

q2=12[11]q_2=\frac{1}{\sqrt 2} \begin{bmatrix} 1\\-1 \end{bmatrix}

这两个向量正交。令:

Q=[q1q2],Λ=[3001]Q= \begin{bmatrix} |&|\\ q_1&q_2\\ |&| \end{bmatrix}, \quad \Lambda= \begin{bmatrix} 3&0\\ 0&1 \end{bmatrix}

则:

A=QΛQA=Q\Lambda Q^\top

几何含义是:先把坐标旋转到特征向量方向,再分别沿两个正交轴缩放 3 倍和 1 倍,最后旋转回原坐标。

例如:

x=[10]x= \begin{bmatrix} 1\\0 \end{bmatrix}

在这两个特征方向上的坐标为:

Qx=[1/21/2]Q^\top x= \begin{bmatrix} 1/\sqrt2\\ 1/\sqrt2 \end{bmatrix}

缩放后:

ΛQx=[3/21/2]\Lambda Q^\top x= \begin{bmatrix} 3/\sqrt2\\ 1/\sqrt2 \end{bmatrix}

再变换回原坐标:

QΛQx=[21]=AxQ\Lambda Q^\top x = \begin{bmatrix} 2\\1 \end{bmatrix} =Ax


4. 对称矩阵的特殊保证

实对称矩阵满足谱定理:

A=AA=A^\top

则:

  1. 所有特征值都是实数;
  2. 存在一组正交归一的特征向量;
  3. 可以写成:

A=QΛQA=Q\Lambda Q^\top

这对协方差矩阵尤其重要,因为协方差矩阵天然是对称半正定矩阵:

Σ=1N1XcXc\Sigma=\frac{1}{N-1}X_c^\top X_c

其中 XcX_c 是中心化后的数据。半正定意味着:

zΣz0z^\top\Sigma z\ge 0

因此协方差矩阵的特征值不会为负,表示沿特征方向的方差大小。


5. 特征分解的边界

并非所有矩阵都能在实数范围内写成完整的特征分解:

A=VΛV1A=V\Lambda V^{-1}

成立需要 AA 有足够多的线性无关特征向量,也就是矩阵可对角化。

反例:

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

其唯一特征值为 λ=1\lambda=1。求特征向量:

(AI)v=[0100][v1v2]=0(A-I)v= \begin{bmatrix} 0&1\\ 0&0 \end{bmatrix} \begin{bmatrix} v_1\\v_2 \end{bmatrix} =0

得到 v2=0v_2=0,只有一个独立方向。这个矩阵没有两个线性无关的特征向量,因此不能被对角化。

此外,非对称实矩阵可能具有复数特征值。例如旋转矩阵在非零旋转角度下通常没有实特征向量。实际数值分析中,不能无条件假设 eig 的结果都是实数或可以正交化。


六、奇异值分解:比特征分解更通用的工具

任意实矩阵 ARm×nA\in\mathbb{R}^{m\times n} 都可以进行奇异值分解:

A=UΣVA=U\Sigma V^\top

其中:

  • URm×mU\in\mathbb{R}^{m\times m} 的列是左奇异向量;
  • VRn×nV\in\mathbb{R}^{n\times n} 的列是右奇异向量;
  • Σ\Sigma 是非负对角奇异值矩阵。

几何上,SVD 把一个任意线性变换分解为:

  1. 通过 VV^\top 旋转或改变输入坐标;
  2. 通过 Σ\Sigma 沿正交方向分别缩放;
  3. 通过 UU 旋转到输出坐标。

与特征分解相比,SVD:

  • 不要求矩阵是方阵;
  • 不要求矩阵可对角化;
  • 奇异值始终是非负实数;
  • 可用于低秩近似和伪逆。

矩阵的非零奇异值是 AAA^\top A 特征值的平方根:

AAvi=σi2viA^\top A v_i=\sigma_i^2v_i

因此,SVD 连接了特征分解、矩阵秩和最小二乘。


低秩近似

按奇异值从大到小排列:

σ1σ20\sigma_1\ge\sigma_2\ge\cdots\ge0

保留前 kk 个奇异值:

Ak=UkΣkVkA_k=U_k\Sigma_kV_k^\top

这是秩不超过 kk 的近似,并且在 Frobenius 范数和谱范数意义下具有最优性。直觉上,它保留了矩阵中能量最大的 kk 个正交方向。

低秩方法可用于:

  • 图像压缩;
  • 推荐系统中的用户—物品矩阵分解;
  • 文本主题表示;
  • 大模型参数或适配器的低秩更新。

但“奇异值大”只表示在给定数据和度量下方差或能量大,不自动等价于业务信息重要,更不代表因果关系。


七、PCA:用特征分解寻找最大方差方向

主成分分析(PCA)试图找到一组正交方向,使数据投影后保留尽可能多的方差。

设中心化数据矩阵为:

XcRN×DX_c\in\mathbb{R}^{N\times D}

对单位向量 ww,样本投影为:

z=Xcwz=X_cw

投影方差为:

1N1Xcw22=1N1wXcXcw=wΣw\frac{1}{N-1}\|X_cw\|_2^2 = \frac{1}{N-1}w^\top X_c^\top X_cw = w^\top\Sigma w

其中:

Σ=1N1XcXc\Sigma=\frac{1}{N-1}X_c^\top X_c

为了寻找方差最大的方向,求解:

maxw2=1wΣw\max_{\|w\|_2=1} w^\top\Sigma w

使用拉格朗日乘子:

L(w,λ)=wΣwλ(ww1)\mathcal{L}(w,\lambda) = w^\top\Sigma w-\lambda(w^\top w-1)

ww 求导:

2Σw2λw=02\Sigma w-2\lambda w=0

得到:

Σw=λw\Sigma w=\lambda w

因此,第一主成分是协方差矩阵最大特征值对应的特征向量。后续主成分要求与前面的方向正交,并按剩余方差最大原则依次求出。

解释:

  • 特征向量给出主方向;
  • 特征值给出该方向上的方差;
  • 最大特征值对应数据变化最大的方向。

PCA 的重要边界

PCA 是无监督的,它最大化总体方差,而不是分类准确率。一个分类相关方向可能方差很小,从而被 PCA 丢弃。

例如,二维数据的类别差异主要沿 yy 轴,而 xx 轴包含很大的与类别无关噪声。PCA 可能优先保留 xx 轴,降维后反而损害分类。

此外,PCA 对特征尺度敏感:

  • 在原始单位下计算 PCA,方差大的特征会主导结果;
  • 先标准化再 PCA,相当于更关注相关结构;
  • 是否标准化必须由数据含义和验证结果决定,不能机械执行。

用 NumPy 验证特征分解与 PCA

以下代码可直接运行:

import numpy as np

A = np.array([
    [2.0, 1.0],
    [1.0, 2.0],
])

eigenvalues, eigenvectors = np.linalg.eigh(A)

print("eigenvalues:", eigenvalues)
print("eigenvectors:\n", eigenvectors)
print("reconstruction error:",
      np.linalg.norm(A - eigenvectors @ np.diag(eigenvalues) @ eigenvectors.T))

X = np.array([
    [2.0, 0.0],
    [1.0, 0.0],
    [-1.0, 0.0],
    [-2.0, 0.0],
])

X_centered = X - X.mean(axis=0)
cov = X_centered.T @ X_centered / (len(X) - 1)

values, vectors = np.linalg.eigh(cov)
order = np.argsort(values)[::-1]

print("covariance:\n", cov)
print("PCA eigenvalues:", values[order])
print("first principal direction:", vectors[:, order[0]])

预期现象:

  • A 的特征值接近 13
  • 重构误差接近浮点误差范围;
  • PCA 的第一方向接近 xx 轴;
  • 特征向量的正负号可能整体翻转,这不影响其表示的方向。

np.linalg.eigh 专门用于实对称或复 Hermitian 矩阵,通常比对称矩阵使用通用 eig 更合适。对于一般方阵,应使用 np.linalg.eig,但要处理复数结果和不可对角化情况。


八、张量运算:从二维矩阵乘法扩展到深度学习

1. 逐元素运算、广播与收缩

张量运算至少要区分三类:

逐元素运算

对形状相同的张量:

Cijk=Aijk+BijkC_{ijk}=A_{ijk}+B_{ijk}

加法、减法、乘法和除法通常逐元素执行。

广播

广播允许某些轴在运算中被“扩展”。例如:

X = np.array([
    [1.0, 2.0, 3.0],
    [4.0, 5.0, 6.0],
])                  # shape (2, 3)

bias = np.array([10.0, 20.0, 30.0])  # shape (3,)

Y = X + bias
print(Y)
# [[11. 22. 33.]
#  [14. 25. 36.]]

这里 (3,) 被广播到每一行。广播不会真的复制所有数据,但结果计算仍有相应的内存和带宽成本。错误的广播可能产生“形状合法但语义错误”的结果。

收缩

矩阵乘法是对一个索引求和:

Cij=kAikBkjC_{ij}=\sum_k A_{ik}B_{kj}

更一般的张量收缩也会对指定轴求和。einsum 可以显式写出索引:

A = np.random.randn(2, 3, 4)
B = np.random.randn(2, 4, 5)

C = np.einsum("bik,bkj->bij", A, B)
print(C.shape)
# (2, 3, 5)

这里对索引 k 求和,保留 b、i、j。这相当于对每个 batch 分别做矩阵乘法。


2. 图像卷积的形状直觉

以无 padding、步长为 1 的二维卷积为例,输入空间尺寸为 H×WH\times W,卷积核为 Kh×KwK_h\times K_w,则输出空间尺寸为:

Hout=HKh+1H_{\text{out}}=H-K_h+1

Wout=WKw+1W_{\text{out}}=W-K_w+1

如果输入有 CinC_{\text{in}} 个通道,输出有 CoutC_{\text{out}} 个通道,则卷积核参数形状常为:

(Cout,Cin,Kh,Kw)(C_{\text{out}},C_{\text{in}},K_h,K_w)

每个输出位置都会对输入局部区域和卷积核做乘加。卷积不是简单复制相同的矩阵乘法,但它仍然是线性运算的一种局部、参数共享形式;加入偏置后是仿射变换。


3. Transformer 注意力中的矩阵关系

设一层 Transformer 的隐藏状态为:

XRB×T×DX\in\mathbb{R}^{B\times T\times D}

其中:

  • BB:批次大小;
  • TT:序列长度;
  • DD:隐藏维度。

通过线性映射得到:

Q=XWQ,K=XWK,V=XWVQ=XW_Q,\quad K=XW_K,\quad V=XW_V

在单头情形下,若:

WQ,WKRD×dk,WVRD×dvW_Q,W_K\in\mathbb{R}^{D\times d_k}, \quad W_V\in\mathbb{R}^{D\times d_v}

则:

Q,KRB×T×dkQ,K\in\mathbb{R}^{B\times T\times d_k}

VRB×T×dvV\in\mathbb{R}^{B\times T\times d_v}

注意力分数为:

S=QKdkS=\frac{QK^\top}{\sqrt{d_k}}

对每个 batch,QKQK^\top 的形状是:

(T×dk)(dk×T)=T×T(T\times d_k)(d_k\times T)=T\times T

因此每个 token 都会得到对所有 token 的一组分数。对最后一个维度做 softmax:

Pij=exp(Sij)jexp(Sij)P_{ij} = \frac{\exp(S_{ij})}{\sum_{j'}\exp(S_{ij'})}

于是每一行的权重和为 1,输出为:

O=PVO=PV

形状为:

(B×T×T)(B×T×dv)=B×T×dv(B\times T\times T)(B\times T\times d_v) = B\times T\times d_v

除以 dk\sqrt{d_k} 的原因是:若 QQKK 的分量独立、均值为 0、方差约为 1,则点积的方差大致随 dkd_k 增长。分数过大时,softmax 容易饱和,梯度变小;缩放可以减轻这种问题。

自回归生成时还要使用因果掩码,使位置 ii 不能访问未来位置 j>ij>i。掩码通常在 softmax 前把非法位置设为极小值。若掩码轴或广播形状错误,模型仍可能输出文本,但会发生信息泄漏或生成行为异常。


九、线性代数与神经网络训练

1. 梯度是向量,参数是张量

将所有模型参数暂时展平为向量 θ\theta,损失函数记为:

L(θ)L(\theta)

梯度为:

θL=[Lθ1Lθn]\nabla_\theta L = \begin{bmatrix} \frac{\partial L}{\partial \theta_1}\\ \vdots\\ \frac{\partial L}{\partial \theta_n} \end{bmatrix}

梯度指向局部上升最快的方向,因此梯度下降更新为:

θt+1=θtηθL(θt)\theta_{t+1} = \theta_t-\eta\nabla_\theta L(\theta_t)

其中 η\eta 是学习率。

在实际深度学习模型中,参数不是一个向量,而是多个矩阵和张量;框架会按照每个参数的形状保存梯度。梯度的形状必须与参数相同,这是反向传播正确性的基本条件。


2. Jacobian 与 Hessian

对于向量函数:

f:RnRmf:\mathbb{R}^n\to\mathbb{R}^m

Jacobian 矩阵为:

Jij=fixjJ_{ij}=\frac{\partial f_i}{\partial x_j}

它描述输入的微小变化如何影响输出:

f(x+Δx)f(x)+JΔxf(x+\Delta x)\approx f(x)+J\Delta x

对于标量损失函数,Hessian 为:

Hij=2LxixjH_{ij} = \frac{\partial^2 L}{\partial x_i\partial x_j}

Hessian 描述曲率。如果某些方向曲率很大、另一些方向曲率很小,损失地形会狭长,固定学习率优化可能在陡峭方向震荡、在平坦方向前进缓慢。

这也是特征缩放和参数化方式会影响优化速度的原因:它们改变了坐标系统和局部曲率。


3. 梯度爆炸与消失的线性代数解释

深层网络反向传播会连续乘上 Jacobian:

hLh0=JLJL1J1\frac{\partial h_L}{\partial h_0} = J_LJ_{L-1}\cdots J_1

若这些矩阵的谱范数长期大于 1,乘积的范数可能指数增长,导致梯度爆炸;若长期小于 1,梯度可能衰减到接近零。

对循环网络尤其明显,因为同一个变换会被重复乘很多次。初始化、归一化、残差连接和门控结构的作用之一,就是改善这些乘积的数值性质。但它们不能保证所有数据、深度和学习率下都稳定,仍需监控损失、梯度范数和激活分布。


十、数值稳定性:理论正确不代表浮点计算可靠

1. 不要显式计算矩阵逆

理论公式可能写成:

x=A1bx=A^{-1}b

但代码应优先写:

x = np.linalg.solve(A, b)

而不是:

x = np.linalg.inv(A) @ b

solve 直接求解线性系统,通常更高效,也更少产生不必要的舍入误差。


2. softmax 的稳定实现

直接计算:

softmax(zi)=ezijezj\operatorname{softmax}(z_i) = \frac{e^{z_i}}{\sum_j e^{z_j}}

ziz_i 很大时,可能溢出。利用平移不改变 softmax:

softmax(zi)=ezimjezjm\operatorname{softmax}(z_i) = \frac{e^{z_i-m}}{\sum_j e^{z_j-m}}

其中:

m=maxjzjm=\max_j z_j

因为分子分母同时除以 eme^m。NumPy 实现如下:

import numpy as np

def stable_softmax(x, axis=-1):
    x = np.asarray(x, dtype=np.float64)
    shifted = x - np.max(x, axis=axis, keepdims=True)
    exp_x = np.exp(shifted)
    return exp_x / np.sum(exp_x, axis=axis, keepdims=True)

p = stable_softmax(np.array([1000.0, 1001.0, 1002.0]))
print(p)
print(p.sum())
# 概率和接近 1

实际框架的交叉熵损失通常会使用融合实现,避免先显式计算概率再取对数。手动拆分时,容易出现 log(0)、上溢或下溢。


3. 条件数与病态问题

矩阵的条件数可粗略表示输入扰动被输出放大的程度。对可逆矩阵:

κ(A)=AA1\kappa(A)=\|A\|\|A^{-1}\|

条件数很大意味着矩阵病态:输入、标签或计算中的微小误差,可能导致解发生很大变化。

常见来源包括:

  • 特征高度相关;
  • 特征尺度差异过大;
  • 样本数量不足;
  • 训练数据中存在近重复列;
  • 低精度计算。

诊断时可以检查奇异值谱:

s = np.linalg.svd(X, compute_uv=False)
condition_number = s[0] / s[-1]
print("condition number:", condition_number)

若最小奇异值接近零,条件数会很大。此时可考虑移除冗余特征、标准化、正则化或使用更稳定的分解方法,但不能仅凭一个阈值自动判定模型应如何修改。


4. 精度、设备与成本

FP32、FP16、BF16 等数据类型会改变:

  • 可表示的数值范围;
  • 有效精度;
  • 显存占用;
  • 矩阵乘法吞吐;
  • 溢出和下溢风险。

低精度通常能降低显存和计算成本,但需要确认算子、硬件和训练策略是否支持。混合精度训练常把矩阵乘法放在低精度,将部分累加或损失计算保留在更高精度,并可能使用 loss scaling。具体行为取决于框架和硬件版本,不能把一种设备上的性能或稳定性结论直接推广到另一种设备。


十一、机器学习中的完整线性代数数据流

一个典型的监督学习流程可以抽象为:

原始数据X预处理X模型变换y^L(y^,y)L参数更新\text{原始数据} \rightarrow X \rightarrow \text{预处理} \rightarrow X' \rightarrow \text{模型变换} \rightarrow \hat y \rightarrow L(\hat y,y) \rightarrow \nabla L \rightarrow \text{参数更新}

其中:

  1. 原始记录被编码为矩阵或张量;
  2. 训练集统计量用于中心化、标准化或词表构建;
  3. 模型执行矩阵乘法、张量收缩和非线性变换;
  4. 预测与标签计算损失;
  5. 自动微分得到梯度;
  6. 优化器更新参数;
  7. 验证集用于选择配置,测试集用于最终评估。

评测也有线性代数边界:

  • 分类 logits 是向量或矩阵;
  • softmax 将 logits 转为概率;
  • 多标签任务可能对每个类别独立使用 sigmoid;
  • 回归输出可以是多维向量;
  • embedding 检索依赖距离、内积或余弦相似度;
  • 生成模型的 token 概率本质上是高维向量上的归一化分布。

如果训练和推理使用的特征顺序不同,矩阵列的语义就会错位。即使形状完全一致,模型也可能输出数值正常但含义错误的结果。因此生产系统必须同时保存特征 schema、预处理参数、模型参数和版本信息。


十二、生成式 AI 中的线性代数边界

1. Embedding 与向量空间

文本、图像或代码经过编码器后,通常得到向量:

eRDe\in\mathbb{R}^D

语义检索把查询向量 qq 与候选向量 eie_i 比较:

si=qeis_i=q^\top e_i

或:

si=qeiq2ei2s_i=\frac{q^\top e_i}{\|q\|_2\|e_i\|_2}

这类相似度只是模型学习出的几何关系,不等于逻辑蕴含、事实正确性或权限判断。一个文档与查询很相似,不代表调用者有权读取它。

因此,在检索增强生成系统中,访问控制不能被向量相似度替代。权限过滤应使用结构化的租户、用户、文档 ACL 或安全标签,并在检索结果进入提示词前执行。


2. Logits、概率与采样

生成模型在每个位置输出词表大小为 VV 的 logits:

zRVz\in\mathbb{R}^{V}

温度采样使用:

pi=softmax(ziτ)p_i = \operatorname{softmax}\left(\frac{z_i}{\tau}\right)

其中 τ>0\tau>0

  • τ\tau 较小,分布更尖锐;
  • τ\tau 较大,分布更平坦;
  • τ0+\tau\to0^+ 时趋向选择最大 logit,但数值实现不能真的使用零温度。

top-k、top-p 等策略是在概率向量上截断候选集合,再重新归一化。它们改变采样分布,不会修复模型内部表示错误、训练数据污染或事实性问题。


3. KV Cache 的形状与内存

自回归生成时,注意力会反复使用历史 token 的 Key 和 Value。KV cache 常包含形状类似:

(B,H,T,Dh)(B,H,T,D_h)

的张量,其中 TT 会随着生成长度增长。粗略地,缓存内存与:

B×H×T×Dh×层数B\times H\times T\times D_h\times \text{层数}

成正比,并且还与数据类型字节数有关。

因此,上下文长度、并发请求数、批处理方式和精度会共同决定推理成本。延长上下文不仅增加 token 数,也会增加注意力计算和缓存占用。生产系统应把模型、输入数据、评测流量、权限过滤和 GPU/内存成本放在同一条链路上分析,而不是只比较模型参数量。


十三、常见误解与失败表现

误解一:维度越高,向量越有意义

高维向量可以表达更丰富的模式,但维度增加也可能带来:

  • 存储和检索成本增加;
  • 距离集中现象;
  • 噪声方向增多;
  • 训练和评测样本需求增加。

在高维空间中,许多随机向量的距离可能变得相近,单纯依赖欧氏距离未必有效。应结合归一化、度量选择、索引结构和实际召回评测判断。


误解二:特征值越大,业务价值越高

特征值表示矩阵变换或协方差在某方向上的缩放量或方差,不表示因果影响、商业价值或公平性。

PCA 保留最大方差方向,可能保留用户数量最多的群体结构,却丢失少数群体的重要方向。降维前后应分别检查总体指标、分群指标和下游任务表现。


误解三:矩阵形状正确,就说明模型正确

下面的代码可能运行成功:

X = np.random.randn(4, 3)
w = np.array([1.0, 2.0, 3.0])

y = X @ w

但如果 X 的三列实际顺序是 [收入, 年龄, 点击次数],而训练时顺序是 [年龄, 点击次数, 收入],矩阵乘法仍然合法,结果却完全失去原本语义。

形状检查只能发现一部分错误。还需要检查:

  • 轴名称和顺序;
  • 单位;
  • 训练与推理预处理是否一致;
  • dtype 与设备;
  • 是否发生了错误广播;
  • 是否混入了未来信息或测试信息。

误解四:余弦相似度可以完成权限控制

相似度是统计或表示空间中的关系,权限是安全策略。两者的判定依据不同。

失败表现通常是:检索结果语义相关,但包含不应返回给当前用户的文档。恢复方法不是调低或调高相似度阈值,而是在向量检索前后都应用结构化权限过滤,并在评测中加入跨租户、越权查询和敏感文档用例。


误解五:显式求逆或直接扩大精度可以解决所有数值问题

如果矩阵本身病态,换成更高精度只能缓解部分误差,不能消除问题。若输入特征高度共线,模型仍可能对数据扰动敏感。

诊断应同时观察:

  • 奇异值;
  • 条件数;
  • 梯度范数;
  • loss 是否出现 NaNInf
  • 输入和激活的最小、最大值;
  • 不同精度下的结果差异;
  • 训练、验证和线上数据分布。

十四、一个小型端到端示例:标准化、PCA 与投影

下面使用二维数据展示从矩阵到 PCA 的完整过程:

import numpy as np

# 每行是一个样本,每列是一个特征
X = np.array([
    [2.0, 1.0],
    [3.0, 1.5],
    [4.0, 2.0],
    [5.0, 2.5],
])

# 1. 只根据当前数据计算均值;真实训练流程中应只用训练集计算
mean = X.mean(axis=0)
X_centered = X - mean

# 2. 计算协方差矩阵
cov = X_centered.T @ X_centered / (X.shape[0] - 1)

# 3. 协方差矩阵是对称矩阵,使用 eigh
values, vectors = np.linalg.eigh(cov)

# 4. 从大到小排列特征值和特征向量
order = np.argsort(values)[::-1]
values = values[order]
vectors = vectors[:, order]

# 5. 投影到第一主成分
first_direction = vectors[:, :1]       # shape (2, 1)
Z = X_centered @ first_direction       # shape (4, 1)

# 6. 用第一主成分重构
X_reconstructed = Z @ first_direction.T + mean

print("mean:\n", mean)
print("covariance:\n", cov)
print("explained variance:", values)
print("first direction:\n", first_direction)
print("projected data:\n", Z)
print("reconstructed data:\n", X_reconstructed)

每一步成立的原因是:

  1. X_centered 让每个特征均值为 0,避免均值位置影响协方差;
  2. X_centered.T @ X_centered 统计特征之间的共同变化;
  3. eigh 找到协方差的正交特征方向;
  4. 最大特征值对应的方向保留最多方差;
  5. X_centered @ first_direction 是每个样本在该方向上的坐标;
  6. 乘回方向向量是投影空间中的重构。

该示例数据近似位于一条直线上,所以第一主成分可以较好重构数据。若数据呈现多个独立方向,保留一个主成分的重构误差就会增加。


十五、在生产系统中如何诊断线性代数问题

1. 先验证形状和语义

对每个关键张量记录:

  • 形状;
  • dtype;
  • 设备;
  • 数值范围;
  • 是否包含 NaN 或 Inf;
  • 各轴的语义;
  • batch、序列和特征维度的位置。

例如注意力模块至少应确认 QQKKVV 的最后维度满足矩阵乘法要求,并确认 mask 可以正确广播到分数矩阵。


2. 再验证代数关系

可以对小规模输入做不变量测试:

  • 正交矩阵是否满足 QQIQ^\top Q\approx I
  • 对称矩阵是否满足 AAA\approx A^\top
  • 特征分解是否满足 AvλvAv\approx\lambda v
  • PCA 重构误差是否随主成分数增加而不增;
  • 归一化向量的范数是否接近 1;
  • softmax 每行概率和是否接近 1;
  • mask 后的非法位置是否不会影响输出。

这些测试比只检查“代码是否执行成功”更能发现语义错误。


3. 结合数据、模型、评测、权限和成本

线性代数错误经常跨越组件边界:

  • 数据列顺序错误会让模型权重作用到错误特征;
  • 训练集统计量泄漏会让评测结果虚高;
  • embedding 维度或归一化方式变化会破坏索引兼容性;
  • attention mask 错误可能造成信息泄漏;
  • batch 或上下文长度增加会扩大张量内存和推理成本;
  • 权限过滤缺失会使正确的相似度计算产生错误的安全结果。

因此,生产诊断不应只问“模型是否收敛”,还要问:

  1. 输入张量是否来自允许的数据范围;
  2. 预处理是否与训练版本一致;
  3. 评测集是否独立且未泄漏;
  4. 输出是否经过正确的权限过滤;
  5. 并发和上下文长度是否超出内存预算;
  6. 降精度后数值和指标是否仍在接受范围内。

线性代数的核心不是记住若干 API,而是能够把一个运算还原为三个问题:对象的形状是什么,运算改变了哪个空间,结果保留或丢失了哪些方向。向量提供方向和距离,矩阵表示线性或仿射变换,张量组织多轴数据,特征分解揭示特殊方向,SVD 提供通用的正交变换与缩放分解。掌握这些关系后,机器学习中的特征工程、最小二乘、PCA、神经网络、注意力、嵌入检索和生成采样就不再是互不相关的技巧,而是同一套空间变换语言在不同系统中的具体形式。


系列导航与关联阅读

官方资料

本文依据研究论文、标准组织与主流框架官方文档重新梳理;正文、示例与工程清单由 WR BLOG 编写。