逆幂法
逆幂法(inverse iteration)反复求解同一个线性系统并归一化,以提取接近指定移位的特征值方向。它利用逆算子将靠近移位的特征值放大为占优模式。实际每轮解方程,不应显式形成矩阵的逆;移位的选择既影响收敛速度,也影响线性系统的条件性。
靠近一的特征方向被放大
取 ,其特征值为一和三。选择移位 ,从 开始,先解 这里 ,行列式为 ,解为 。按最大分量归一化后 ,下一轮为 ,迅速接近特征值一的方向 。
逆算子下的谱变换
若 且 不等于任何特征值,便有 特征向量不变,特征值距离的倒数成为新的放大倍数。假设 可对角化,有唯一特征值 距 最近,并且初始向量在其方向上的展开系数非零。连续求解得到 括号中的其他系数几何衰减,归一化后方向趋向 。这正是幂法作用在移位逆算子上的收敛证明。主例两个放大倍数为五和 ,方向误差比值为 ,比直接幂法的三分之一更小。[1]
特征值估计与主例的精确公式
获得方向后,仍可用原矩阵的 Rayleigh 商 估计原特征值,而非把逆算子的放大倍数当成答案。主例按上述归一化有 第一轮商为 ,第二轮为 。实际验收还应计算原残差 。近似解线性系统时的残差与特征对残差是两个不同量,均需要与容限匹配。
移位过近、等距与改变移位
移位越接近简单目标特征值,逆迭代的方向分离通常越快,但 越接近奇异。若移位正好等于特征值,普通求解式无法定义;有些专门特征向量算法会利用近奇异系统,但不能把它们当成本篇的普通逆迭代。
有解变式取 。它到一和三的距离都为一,逆矩阵为 ;从 出发在两个坐标轴之间交替,不能选择唯一方向。若初始向量本来就是目标特征向量,任意合法移位的一轮求解都只改变长度与符号,归一化后方向立即正确。
每轮用新 Rayleigh 商作为移位得到 Rayleigh 商迭代。它对实对称矩阵在简单特征向量附近可有很快的局部收敛,但移位改变后通常需要重新分解矩阵;不能同时宣称始终复用同一分解。对大稀疏系统,移位线性求解成本常是决定性因素。
可运行的固定移位逆迭代
代码输入实矩阵、非零初向量和固定移位,返回原特征值估计、单位方向及轮数,不修改输入。为简洁每轮调用 NumPy 通用求解,所以稠密 轮成本约 、存储 。生产实现应预先分解 ,将后续三角求解降为每轮 ,稀疏填充则另计。
import numpy as np
def inverse_iteration(A, start, shift, tol=1e-12, maxiter=100):
A, x = np.array(A, dtype=float, copy=True), np.array(start, dtype=float, copy=True)
shift = float(shift)
if x.ndim != 1 or not x.size or A.shape != (x.size, x.size):
raise ValueError("square matrix matching vector required")
if not np.isfinite(A).all() or not np.isfinite(x).all() or not np.isfinite(shift) or np.max(np.abs(x)) == 0:
raise ValueError("finite data and nonzero start required")
if not np.isfinite(tol) or tol <= 0 or not isinstance(maxiter, int) or maxiter < 0:
raise ValueError("positive tolerance and nonnegative integer limit required")
B = A-shift*np.eye(x.size)
if not np.isfinite(B).all():
raise ArithmeticError("shifted matrix outside floating-point range")
x /= np.max(np.abs(x)); x /= np.linalg.norm(x)
matrix_scale = float(np.max(np.abs(A)))
C = A/matrix_scale if matrix_scale > 0 else A.copy()
scale = max(1.0, np.linalg.norm(C))
threshold = tol*scale
if not np.isfinite(threshold):
raise ArithmeticError("nonfinite stopping threshold")
for k in range(maxiter+1):
mu_scaled = float(x@(C@x)); mu = mu_scaled*matrix_scale
residual = C@x-mu_scaled*x
if not np.isfinite(mu) or not np.isfinite(residual).all():
raise ArithmeticError("nonfinite eigenvalue or residual")
if np.linalg.norm(residual) <= threshold:
return mu, x, k
if k == maxiter:
break
w = np.linalg.solve(B, x)
magnitude = np.max(np.abs(w))
if magnitude == 0 or not np.isfinite(magnitude) or not np.isfinite(w).all():
raise ArithmeticError("nonfinite or zero inverse iterate")
w = w/magnitude
x = w/np.linalg.norm(w)
raise RuntimeError("original eigenpair residual did not reach tolerance")
print(inverse_iteration([[2, 1], [1, 2]], [1, 0], 0.8)[0]) # near 1
print(inverse_iteration([[2, 1], [1, 2]], [1, 0], 3.2)[0]) # near 3对非正规矩阵或近重特征值,方向误差与残差之间的关系可能较差;严格的误差解释需考虑条件数和谱间隔。求得某一个特征对也不等于找全靠近移位的全部特征值,多维子空间方法更适合成簇目标。
参考资料
- ↑ Tobin A. Driscoll, Richard J. Braun. Fundamentals of Numerical Computation: Inverse iteration,Theorem 8.3.1、§8.3.1 的移位线性求解和 §8.3.2 的收敛率。