线性代数:数值稳定性与条件数
本节目标
数学上“可逆”不等于计算上“可靠”。浮点数只能近似表示实数,近线性相关的特征会放大输入误差和舍入误差。本节帮助你区分秩不足与病态、理解条件数的用途,并为回归、Embedding 变换和神经网络计算选择更稳妥的求解方式。
三件不同的事
- 奇异(singular):矩阵丢失方向,方阵不可逆;某些方程没有唯一解。
- 病态(ill-conditioned):矩阵在精确数学中可能可逆,但很小的输入变化会造成很大的解变化。
- 算法不稳定:某种计算步骤额外放大本可避免的舍入误差。
这三者会相互影响,却不能混为一谈。换更好的算法可以减少额外误差,但不能凭空恢复数据中缺失的独立方向。
浮点数为何带来误差
计算机通常用有限位二进制浮点数保存数值。很多十进制小数不能被精确表示,长串运算还会累计舍入。两个大小接近的数相减时,有效数字可能大量抵消,称为 catastrophic cancellation。
因此判断浮点结果时通常比较容差,而不是要求所有理论上为 0 的量逐位等于 0.0。容差要结合数值尺度和问题风险,不能永远硬编码同一个绝对阈值。
条件数:问题对扰动有多敏感
对可逆方阵,在选定范数下:
在 2-范数下,还可写为最大与最小奇异值之比:
条件数接近 1 表示各方向缩放较均衡;数值很大表示某些方向几乎被压扁,输入的小扰动可能被显著放大。奇异矩阵的条件数视为无穷大。条件数是敏感度警告,不是“结果必错”的概率,也不存在适用于所有 dtype、尺度和任务的单一危险阈值。
一个可验证的敏感性例子
考虑两条几乎平行的方程:
当 时解为 。若 很小,右端只有微小扰动 ,参数也可能大幅变化。
def solve_2x2(matrix: tuple[tuple[float, float], tuple[float, float]],
target: tuple[float, float]) -> tuple[float, float]:
(a, b), (c, d) = matrix
e, f = target
determinant = a * d - b * c
if determinant == 0.0:
raise ValueError("matrix is singular")
x = (e * d - b * f) / determinant
y = (a * f - e * c) / determinant
return x, y
delta = 1e-10
for epsilon in (1e-4, 1e-8, 1e-10):
solution = solve_2x2(
((1.0, 1.0), (1.0, 1.0 + epsilon)),
(2.0, 2.0 + epsilon + delta),
)
print(epsilon, solution)随着 接近扰动尺度,解会从接近 (1,1) 变到明显不同。这里用显式二阶公式只是展示敏感性,不是推荐的通用线性方程求解器。
为什么不默认求逆
要求解 ,工程上优先表达为“解线性系统”,而不是先计算 再乘 。显式求逆通常增加计算与舍入误差,也会掩盖秩和条件问题。
最小二乘的正规方程:
便于理解投影,但在 2-范数意义下,满列秩时 的条件数约为 ,会放大病态。实际库通常使用 QR 或 SVD 路径。NumPy 官方 linalg.lstsq 直接求最小二乘解,并返回秩与奇异值;其小奇异值截断规则由 rcond 控制,语义可能随版本变化,使用时应记录版本和参数。
缩放、中心化与正则化
- 中心化:减去均值,常让截距和斜率计算更清晰,也减少大偏移引发的抵消。
- 缩放:让特征处于相近量级,改善优化和数值条件;但不消除严格线性依赖。
- 删除或合并冗余特征:直接处理重复信息。
- 正则化:改变目标问题,用偏差换稳定性;不是对原问题的无损修复。
- 更高精度:可缓解舍入,却不能修复错误数据或不可识别参数。
预处理必须在训练数据上拟合,并把相同参数应用到验证和线上数据;否则会产生数据泄漏或训练/服务偏差。
线性代数 API 检查表
- 写清输入 shape、dtype、单位和数值范围。
- 检查
NaN、无穷值、重复列和近常量列。 - 选择
solve、lstsq、QR 或 SVD,而不是无条件inv。 - 记录秩判定阈值、
rcond、库版本与硬件 dtype。 - 检查残差、相对误差和对轻微扰动的敏感性。
- 在降维或正则化后重新做真实任务评测。
- 不把“算法返回了结果”当作“问题可识别且结果可信”。
常见误区
- “行列式不为 0,所以一定稳定。”
- “增加更多小数位就能恢复丢失的特征方向。”
- “标准化后所有线性相关都会消失。”
- “条件数大说明模型一定泛化差。”条件数描述数值/问题敏感性,泛化还取决于数据、目标、正则化与评测。
- “SVD 自动找到有业务意义的语义方向。”SVD 找的是代数方向,解释仍需外部证据。
练习与自测
- 运行敏感性代码,分别令
delta=0、1e-12和1e-8,记录参数变化。 - 解释为什么复制同一特征会导致秩不足,而加入一个几乎相同的特征会导致病态。
- 比较“用正规方程理解最小二乘”和“用 QR/SVD 求解”的角色。
- 为一个
float16神经网络推理问题列出 shape、尺度、溢出和容差检查。 - 说明正则化为什么改变了问题,而不只是“让求解器更聪明”。
- 我能区分奇异、病态和算法不稳定。
- 我能用奇异值直觉解释条件数。
- 我知道为什么不应默认显式求逆。
- 我会检查秩、残差、尺度、dtype 和扰动敏感性。
上一节:正交、投影与最小二乘|下一节:特征值、SVD 与项目。
参考资料
核验日期:2026-07-14。