如何使用numpy.linalg.eig获取满秩线性无关特征向量矩阵
numpy.linalg.eig返回特征向量矩阵不满秩的成因与解决方法
从线性代数知识可知,任意对称矩阵(记为A)的特征向量满足正交归一性,也就是说若M是由全部特征向量拼装成的矩阵,应当满足|det(M)| = 1。实际测试numpy.linalg.eig对对称矩阵的求解结果时,会出现不符合该性质的表现,测试代码如下:
import numpy as np def get_det(A, func, decimals=12): eigenvectors = func(A)[1] return np.round(np.absolute(np.linalg.det(eigenvectors)), decimals=decimals) n = 100 x = np.meshgrid(* 2 * [np.linspace(0, 2 * np.pi, n)]) A = np.sin(x[0]) + np.sin(x[1]) A += A.T # 冗余步骤,仅用于明确矩阵为对称矩阵 print(get_det(A, np.linalg.eigh), get_det(A, np.linalg.eig))
运行输出:
>>> 1.0 0.0
结果显示numpy.linalg.eigh返回了符合正交归一性质的特征向量矩阵,而numpy.linalg.eig返回的特征向量矩阵行列式接近0,几乎不可逆。
两个接口结果差异的核心原因
差异来自两个函数的设计定位与底层算法逻辑区别:
numpy.linalg.eigh是专门为对称/厄米矩阵设计的特征值求解器,算法本身利用了对称矩阵的数学性质,会对退化(重复)特征值对应的特征子空间做正交归一化处理,因此无论是否存在重复特征值,返回的特征向量都构成正交归一基,对应矩阵行列式绝对值恒为1。numpy.linalg.eig是通用特征值求解器,不假设输入矩阵具有对称性,算法不会专门对重复特征值对应的特征向量做正交化处理。当矩阵存在重复或数值上非常接近的特征值时,返回的特征向量可能出现线性相关的情况,直接导致矩阵行列式接近0、不可逆。
该逻辑可以在无退化特征值的对称矩阵上得到验证:
import numpy as np n = 100 A = np.random.randn(n, n) A += A.T print(get_det(A, np.linalg.eigh), get_det(A, np.linalg.eig))
运行输出:
>>> 1.0 1.0
当对称矩阵的特征值互异时,eig返回的特征向量天然线性无关,归一化后自然满足行列式绝对值为1,和eigh结果一致。
近似对称矩阵的满秩特征向量获取方案
针对需要处理近似对称但非完全对称矩阵、要求特征向量矩阵满秩可逆的场景,可按实际情况选择方案:
- 若矩阵的非对称分量来自浮点计算误差,无实际数学/物理意义:最稳妥高效的方式是先对矩阵做对称化预处理,再调用
eigh求解,该方法的精度和数值稳定性远高于直接用eig求解非对称矩阵:
该方法得到的特征向量矩阵天然是正交矩阵,满秩可逆,行列式绝对值恒为1。A = (A + A.T.conj()) / 2 # 处理实矩阵时可去掉conj() eigenvalues, eigenvectors = np.linalg.eigh(A) - 若矩阵确实存在非对称分量,不能直接做对称化处理:先调用
eig得到特征向量矩阵,再对矩阵做QR分解提取列正交的满秩基:
需要注意:非对称矩阵如果存在退化特征值,本身不存在一组两两正交的严格特征向量,QR分解得到的是对应特征子空间的正交归一基,而非逐个对应特征值的严格特征向量,但完全可以满足后续计算对矩阵可逆、满秩的要求。eigenvalues, V = np.linalg.eig(A) # 对特征向量做QR正交化,得到列正交的满秩矩阵Q Q, R = np.linalg.qr(V) # Q即为特征子空间对应的正交归一基,|det(Q)|=1,满秩可逆
额外说明:只有对称矩阵、正规矩阵(满足A@A.H = A.H@A)的特征向量才满足正交归一性,普通非对称矩阵的特征向量矩阵本身不需要是正交矩阵,不需要强行追求行列式绝对值为1,正交化处理只是为了避免数值计算中出现奇异矩阵问题。
内容的提问来源于stack exchange,提问作者sams-studio
相关产品推荐
相关产品推荐

