「ml-llm-math.zip」
链接:https://pan.quark.cn/s/35fc37047e5e

一句话版:矩阵世界的数值误差来自两头------问题本身的"体质"(条件数) 和 算法/实现的"手法"(舍入与稳定性) 。工程上要做的,是挑好问题表述 (比如用 QR/SVD 代替 A ⊤ A A^\top A A⊤A)、用稳定算法 (正交变换、配对求和、迭代精炼)、搭配合适精度(混合精度中保留关键归约为 FP32)。
1. 误差模型:从标量到矩阵
1.1 浮点舍入模型
记机器精度(单位舍入)为 u u u(float32 约 10 − 7 10^{-7} 10−7)。一条浮点运算可近似为
fl ( a ∘ b ) = ( a ∘ b ) ( 1 + δ ) , ∣ δ ∣ ≤ u , ∘ ∈ { + , − , × , ÷ } . \operatorname{fl}(a \circ b) = (a \circ b)(1+\delta),\quad |\delta|\le u,\quad \circ\in\{+,-,\times,\div\}. fl(a∘b)=(a∘b)(1+δ),∣δ∣≤u,∘∈{+,−,×,÷}.
将很多次运算"串起来",误差会像 γ n \gamma_n γn 一样积累:
γ n : = n u 1 − n u ≈ n u ( 当 n u ≪ 1 ) . \gamma_n := \frac{nu}{1-nu}\approx nu \quad(\text{当 } nu\ll 1). γn:=1−nunu≈nu(当 nu≪1).
1.2 前向/后向误差与条件数
- 后向误差 :算法等价于在输入上加了一个小扰动再做精确计算。
- 前向误差 :得到的解和真解有多远。
- 条件数 刻画问题对输入扰动的敏感度:
对线性方程 A x = b Ax=b Ax=b,二范数条件数 κ 2 ( A ) = ∥ A ∥ 2 ∥ A − 1 ∥ 2 = σ max / σ min \kappa_2(A)=\|A\|2\|A^{-1}\|2=\sigma{\max}/\sigma{\min} κ2(A)=∥A∥2∥A−1∥2=σmax/σmin。
重要不等式(核心记忆):
∥ x − x ^ ∥ ∥ x ∥ ≲ κ ( A ) × (相对后向误差) ⏟ 看算法稳定性 . \frac{\|x-\hat x\|}{\|x\|}\;\lesssim\; \kappa(A)\times \underbrace{\text{(相对后向误差)}}_{\text{看算法稳定性}}. ∥x∥∥x−x^∥≲κ(A)×看算法稳定性 (相对后向误差).
读法:问题体质 κ \kappa κ × 算法"干净程度" 决定最终误差。
2. 基本矩阵运算的误差界
2.1 点积与矩阵--向量乘
-
点积 s ^ = fl ( x ⊤ y ) \hat s=\operatorname{fl}(x^\top y) s^=fl(x⊤y):
∣ s ^ − x ⊤ y ∣ ≤ γ n ∑ i ∣ x i y i ∣ \;|\hat s - x^\top y|\le \gamma_n \sum_i |x_i y_i| ∣s^−x⊤y∣≤γn∑i∣xiyi∣。
顺序影响大 :小数加到大数可能被吞。→ 用配对求和 或 Kahan 可显著降低误差。 -
矩阵--向量 z ^ = fl ( A x ) \hat z=\operatorname{fl}(Ax) z^=fl(Ax):每个输出元素是一个点积:
∥ z ^ − A x ∥ ≤ γ n ∥ ∣ A ∣ ∣ x ∣ ∥ \;\|\hat z - Ax\| \le \gamma_n \, \|\,|A|\, |x|\,\| ∥z^−Ax∥≤γn∥∣A∣∣x∣∥。
2.2 矩阵乘 C = A B C=AB C=AB
经典界(逐元素或范数):
∥ C ^ − A B ∥ ≤ γ k ∥ ∣ A ∣ ∥ ∥ ∣ B ∣ ∥ ( k = 内积长度 ) . \|\hat C - AB\| \;\le\; \gamma_k \, \|\,|A|\,\|\,\|\,|B|\,\| \quad (k=\text{内积长度}). ∥C^−AB∥≤γk∥∣A∣∥∥∣B∣∥(k=内积长度).
工程含义:分块/重排并不改变数学值,却改变累加路径 → 影响 γ k \gamma_k γk。高性能库(BLAS/GEMM)通过分块+FMA 降低误差与提升性能;混合精度时,低精乘 × 高精累加能稳很多。
3. 解线性方程与最小二乘的稳定性
3.1 正规方程的"放大器"
最小二乘 min x ∥ A x − b ∥ 2 \min_x \|Ax-b\|_2 minx∥Ax−b∥2。若用正规方程 ( A ⊤ A ) x = A ⊤ b (A^\top A)x=A^\top b (A⊤A)x=A⊤b,条件数平方:
κ ( A ⊤ A ) = κ ( A ) 2 . \kappa(A^\top A)=\kappa(A)^2. κ(A⊤A)=κ(A)2.
这会把病态问题变得更病态 (噪声和舍入都被放大),不推荐。
3.2 QR 分解(优选)
用正交 Q Q Q(不改变 2 范数)和上三角 R R R:
A = Q R , ⇒ R x = Q ⊤ b A=QR,\; \Rightarrow\; Rx=Q^\top b A=QR,⇒Rx=Q⊤b。
基于 Householder 反射 的 QR 后向稳定 :产生的 R ^ , Q ^ \hat R,\hat Q R^,Q^ 相当于计算了 A + E A+E A+E 的 QR,且 ∥ E ∥ ≲ γ n ∥ A ∥ \|E\|\lesssim \gamma_n\|A\| ∥E∥≲γn∥A∥。
3.3 SVD(最稳,最贵)
A = U Σ V ⊤ A=U\Sigma V^\top A=UΣV⊤,最小二乘解 x = V Σ + U ⊤ b x=V\Sigma^+U^\top b x=VΣ+U⊤b。SVD 直接拿到奇异值/秩信息,对病态问题稳如老狗,但成本最高。
3.4 LU 分解与主元选取
一般线性方程 A x = b Ax=b Ax=b:
- 带部分选主元的 LU(GEPP) 是工业常用。稳定性受增长因子影响,多数实际问题很好。
- Cholesky :当 A ≻ 0 A\succ 0 A≻0(对称正定),Cholesky 是后向稳定 且速度快一倍,优先用。
口诀:SPD → Cholesky ;最小二乘 → QR/SVD ;一般方程 → LU(带主元) ;别轻易用 A ⊤ A A^\top A A⊤A。
4. 正交化的数值差异
- 经典 Gram--Schmidt(CGS):易受消去影响,正交性差。
- 改进版 MGS:更稳一些,但仍可能退化(需要再正交)。
- Householder QR :最稳、代价略高,是推荐的默认选择。
- MGS + 再正交:在迭代 Krylov 子空间方法中常见的折中。
5. 特征值/奇异值的敏感性
5.1 对称(或正规)矩阵:稳
- Weyl 定理 :对称 A A A 加扰动 E E E,特征值偏差 ∣ λ ^ i − λ i ∣ ≤ ∥ E ∥ 2 |\hat\lambda_i-\lambda_i|\le \|E\|_2 ∣λ^i−λi∣≤∥E∥2。
- Davis--Kahan:特征子空间与扰动大小/谱间隙成反比,谱间隙越大越稳。
- 奇异值 也满足 Weyl: ∣ σ ^ i − σ i ∣ ≤ ∥ E ∥ 2 |\hat\sigma_i-\sigma_i|\le \|E\|_2 ∣σ^i−σi∣≤∥E∥2。
5.2 非正规(非正交可对角化)矩阵:可能很脆
非正常矩阵的特征向量不正交,小扰动会造成巨大前向误差 (伪谱大)。工程上尽量转为对称问题 (如用 A ⊤ A A^\top A A⊤A 得到奇异值/右奇异向量,或考虑正规化/预条件),避免直接做一般非对称的特征分解除非必要。
6. 混合精度与迭代精炼(Iterative Refinement)
思路:低精粗解 + 高精残差校正 。
步骤(解 A x = b Ax=b Ax=b):
- 在低精(如 fp16/bf16)用 LU/Cholesky 得到初解 x ^ \hat x x^。
- 用高精(fp32/fp64)计算残差 r = b − A x ^ r=b-A\hat x r=b−Ax^。
- 解校正方程 A Δ x = r A\Delta x=r AΔx=r(仍可低精解,但残差高精计算), x ^ ← x ^ + Δ x \hat x\leftarrow \hat x+\Delta x x^←x^+Δx。
- 重复至收敛。
收敛条件(直觉):低精舍入 u low u_{\text{low}} ulow 与 κ ( A ) \kappa(A) κ(A) 满足 κ ( A ) u low ≪ 1 \kappa(A)\, u_{\text{low}} \ll 1 κ(A)ulow≪1。
在大模型/科学计算中,这一招能把低精算力 转化为高精结果(前提是问题不太病态)。
7. 选择指南(中文流程)
Ax=b
是
否
最小二乘
是
否
是
否
确定问题类型
Ax=b 还是 最小二乘?
A 是否对称正定?
Cholesky
LU+部分选主元
病态/高精需求?
SVD
Householder QR
内存/速度限制?
混合精度+迭代精炼
直接高精实现
说明 :根据矩阵结构优先选择稳定分解 ;资源紧张时上混合精度 + 精炼。
8. 与机器学习的连接
- 线性回归/岭回归 :不要手写 x = ( A ⊤ A ) − 1 A ⊤ b x=(A^\top A)^{-1}A^\top b x=(A⊤A)−1A⊤b;用
lstsq(QR/SVD)或正规化的 Cholesky(对 A ⊤ A + λ I A^\top A+\lambda I A⊤A+λI)。 - PCA/SVD :用 SVD/随机 SVD,避免对协方差矩阵长链累加带来的误差;做中心化 并可能标准化。
- 归一化/标准化 改善 κ ( A ) \kappa(A) κ(A),提升求解质量;
- 混合精度训练 :矩阵乘可低精(bf16/fp16),归约/归一化/损失 保 FP32;出现 NaN/Inf 先看缩放/中心化 与损失放大。
- 图/核方法 :核矩阵常病态,优先 加核对角 λ I \lambda I λI + Cholesky ,或直接 SVD。
9. 代码骨架(安全替换件)
9.1 稳定最小二乘(PyTorch 思路)
python
import torch
def stable_lstsq(A, b, ridge=0.0):
# A: (n,d), b: (n,) 或 (n,k)
A = A - A.mean(0, keepdim=True) # 中心化有助于条件数
if ridge > 0:
# 解 (A^T A + λI)x = A^T b,用 Cholesky,更稳
AtA = A.T @ A
d = AtA.shape[0]
AtA = AtA + ridge * torch.eye(d, device=A.device, dtype=A.dtype)
L = torch.linalg.cholesky(AtA)
rhs = A.T @ b
y = torch.cholesky_solve(rhs, L) # 解 (AtA)x=rhs
return y
else:
# 直接最小二乘(QR/SVD 由框架选择)
# torch>=2.0: linalg.lstsq 使用稳健分解
return torch.linalg.lstsq(A, b).solution
9.2 混合精度矩阵乘 + FP32 归约(Numpy/伪)
python
import numpy as np
def matmul_mixed(A16, B16):
# A16,B16 为 float16/bfloat16,归约在 float32
A32 = A16.astype(np.float32)
B32 = B16.astype(np.float32)
return (A32 @ B32).astype(A16.dtype) # 或保留 FP32 输出做后续稳定运算
10. 工程清单(Checklist)
- 别 显式算逆,优先解线性系统/分解(
solve/lstsq)。 - 别 用 A ⊤ A A^\top A A⊤A 正规方程做最小二乘,优先 QR/SVD。
- SPD 问题优先 Cholesky ;一般方程用 LU+主元。
- 长链求和/点积用 配对求和/Kahan ;矩阵乘尽量走 高质量 BLAS。
- 做 中心化/标准化/缩放 降低条件数。
- 混合精度下:低精乘 + 高精累加,关键归约/正交/分解保 FP32。
- 观察 条件数 (SVD/
matrix_rank/最小奇异值)并在病态时加 正则。 - 用 迭代精炼 把低精的速度"换"成高精的解。
- 写边界单测:全零/共线列/极小奇异值/尺度差 10^k。
11. 练习(含提示)
- 为何正规方程会"变差" :证明 κ 2 ( A ⊤ A ) = κ 2 ( A ) 2 \kappa_2(A^\top A)=\kappa_2(A)^2 κ2(A⊤A)=κ2(A)2。
- Householder 稳定性:简述为何正交变换能保持 2 范数,从而提升后向稳定。
- 点积实验 :对 n = 10 6 n=10^6 n=106 个随机数,比较顺序求和/配对求和/Kahan 的误差(用高精作为真值)。
- 最小二乘对比:在高条件数数据上比较正规方程、MGS、Householder QR、SVD 的解残差。
- 迭代精炼:在 bf16(或模拟低精)上做 LU 求解,再用 fp32 残差修正,观察收敛条件与速度。
- PCA 稳定性:模拟中心化与未中心化对协方差矩阵的影响,并比较 SVD 得到的主成分稳定性。
12. 小结
- 误差两因素 :问题的 κ \kappa κ (体质) × 算法的 后向稳定性(手法)。
- 选择稳分解 :最小二乘 QR/SVD ;SPD Cholesky ;一般方程 LU+主元 ;避免 A ⊤ A A^\top A A⊤A。
- 混合精度也能稳 :低精乘 + 高精累加 + 迭代精炼 ,再配合缩放/中心化/正则,就能"又快又准"。