跳到正文

求解线性方程组与矩阵逆

量化金融中的大多数问题——从期权定价到投资组合优化——最终都归结为求解线性方程组。理解何时能求解 Ax = b 以及如何求解,是基础性的。

第 2 篇 · 共 6 篇 约 3 分钟

一般线性方程组

具有 mm 个方程和 nn 个未知数的线性方程组可以简洁地写成:

Ax=b\mathbf{A}\mathbf{x} = \mathbf{b}

其中 A\mathbf{A} 是 m×nm \times n 系数矩阵,x\mathbf{x} 是 nn 维未知向量,b\mathbf{b} 是 mm 维右端向量。

A\mathbf{A} 的形状决定了是否存在解以及存在什么样的解:

  • 方阵(m=nm = n,可逆): 存在唯一解,x=A−1b\mathbf{x} = \mathbf{A}^{-1}\mathbf{b}。
  • 超定(m>nm > n): 方程多于未知数——通常没有精确解。使用最小二乘法。
  • 欠定(m<nm < n): 方程少于未知数——无穷多解。选择范数最小的那个。

当方程组为方阵且可逆时

如果 A\mathbf{A} 是方阵且所有列线性独立(满秩),则 A−1\mathbf{A}^{-1} 存在,解唯一。

经典高斯消元算法通过执行将 A\mathbf{A} 化为上三角矩阵的行运算来求解此类方程组,然后进行回代。这就是 numpy.linalg.solve 在底层所做的:

import numpy as np


#  3x +  y +  z = 12
#   x + 2y + 3z = 14
#   x +  y -  z =  2

A = np.array([[3, 1, 1],
              [1, 2, 3],
              [1, 1, -1]])

b = np.array([12, 14, 2])

x = np.linalg.solve(A, b)
print(f"解: x={x[0]:.2f}, y={x[1]:.2f}, z={x[2]:.2f}")

# 验证
print("验证 A @ x:", A @ x)
print("与 b 匹配:", np.allclose(A @ x, b))

提示词

用 numpy.linalg.solve 解 3×3 线性方程组,用 np.allclose 验证解是否正确。

LU 分解:将 A 分解成碎片

对于相同 A\mathbf{A} 但不同 b\mathbf{b} 值的重复求解,高效的做法是一次分解 A\mathbf{A}:

A=LU\mathbf{A} = \mathbf{L}\mathbf{U}

其中 L\mathbf{L} 是下三角矩阵,U\mathbf{U} 是上三角矩阵。一旦有了 L\mathbf{L} 和 U\mathbf{U},求解 Ax=b\mathbf{A}\mathbf{x} = \mathbf{b} 需要两次前向/回代,而非完整的高斯消元。这在投资组合优化中很重要,因为你会用不同的目标收益反复求解相同的方程组结构。

SciPy 提供了这个功能:

import scipy.linalg as la

A = np.array([[3, 1, 1],
              [1, 2, 3],
              [1, 1, -1]])

P, L, U = la.lu(A)
print("L:\n", L)
print("U:\n", U)
print("P @ L @ U:\n", P @ L @ U)

提示词

用 scipy.linalg.lu 做 LU 分解,打印 L、U、P@L@U 验证重构。

超定方程组:最小二乘

当你有比未知数更多的方程时——如在有许多观测值的回归中——通常不存在精确解。目标变为找到使 Ax\mathbf{A}\mathbf{x} 在最小二乘意义上尽可能接近 b\mathbf{b} 的 x\mathbf{x}:

最小化∥Ax−b∥2\text{最小化} \quad \|\mathbf{A}\mathbf{x} - \mathbf{b}\|^2

该问题的解由正规方程给出:

(A⊤A)x=A⊤b(\mathbf{A}^\top\mathbf{A})\mathbf{x} = \mathbf{A}^\top\mathbf{b}

如果 A⊤A\mathbf{A}^\top\mathbf{A} 可逆,解为:

x=(A⊤A)−1A⊤b\mathbf{x} = (\mathbf{A}^\top\mathbf{A})^{-1}\mathbf{A}^\top\mathbf{b}

然而,直接计算 (A⊤A)−1(\mathbf{A}^\top\mathbf{A})^{-1} 在数值上是不稳定的,舍入误差会累积。QR 分解是首选方法:

A=QR\mathbf{A} = \mathbf{Q}\mathbf{R}

其中 Q\mathbf{Q} 是正交的(Q⊤Q=I\mathbf{Q}^\top\mathbf{Q} = \mathbf{I}),R\mathbf{R} 是上三角的。解为 x=R−1Q⊤b\mathbf{x} = \mathbf{R}^{-1}\mathbf{Q}^\top\mathbf{b},通过回代计算,数值稳定性强得多。

import numpy as np

# 超定:10 个观测值,2 个未知数
np.random.seed(42)
x_obs = np.linspace(0, 5, 10)
y_obs = 2.5 * x_obs + 1.5 + np.random.randn(10) * 0.5

# 构建 A:每个观测值的 [x, 1]
A = np.column_stack([x_obs, np.ones(10)])
b = y_obs

# 求解最小二乘
x_ls, residuals, rank, s = np.linalg.lstsq(A, b, rcond=None)
print(f"最小二乘解: slope={x_ls[0]:.3f}, intercept={x_ls[1]:.3f}")

# 与 np.polyfit 比较
slope, intercept = np.polyfit(x_obs, y_obs, 1)
print(f"numpy.polyfit: slope={slope:.3f}, intercept={intercept:.3f}")

提示词

用 numpy.linalg.lstsq 和 np.polyfit 拟合带噪声的线性数据,对比两种最小二乘方法的结果。

欠定方程组:最小范数

当方程少于未知数时,存在无穷多解。最小范数解选择欧几里得范数 ∥x∥\|\mathbf{x}\| 最小的解。对于满行秩的欠定情况:

x=A⊤(AA⊤)−1b\mathbf{x} = \mathbf{A}^\top(\mathbf{A}\mathbf{A}^\top)^{-1}\mathbf{b}

在实践中,numpy.linalg.lstsq 处理所有三种情况——方阵、超定和欠定——在适用时返回最小范数解。

金融应用

线性回归是最小二乘问题。在回归文章中,你通过求解正规方程来拟合 Y=β0+β1X+εY = \beta_0 + \beta_1 X + \varepsilon。xx 值是自变量的观测值,yy 值是因变量的观测值。解给出回归系数。

投资组合优化约束通常产生线性方程组。当你建立寻找达到目标收益且方差最小的权重问题时,return 约束的一阶条件会产生一个关于权重和 return 约束拉格朗日乘子的线性方程组。

期权定价在二项模型中需要求解一个线性方程组,该方程组通过树向后传播价格。

import numpy as np

# 显式模拟线性回归问题
np.random.seed(0)
n = 100
X = np.random.randn(n, 3)
y = X @ [1.5, -0.8, 2.1] + np.random.randn(n) * 0.5

# 构建 A = X, b = y,通过正规方程求解
A = X
b = y

# 使用 lstsq(稳定)
beta, residuals, rank, s = np.linalg.lstsq(A, b, rcond=None)

# 与已知真实系数 [1.5, -0.8, 2.1] 比较
print(f"估计值: {beta}")
print(f"真实值:      [1.5, -0.8, 2.1]")

提示词

用 numpy.linalg.lstsq 做多元线性回归:模拟 y = X @ 已知系数 + 噪声,求解后对比估计和真实系数。

参考文献

Strang, Introduction to Linear Algebra, 5th edition, Wellesley-Cambridge Press, Chapters 2–3. ISBN: 978-0980232776.

Golub & Van Loan, Matrix Computations, 4th edition, Johns Hopkins University Press, Chapter 3. ISBN: 978-1421407944.