You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何NumPy与SymPy计算的特征向量存在差异?

特征值与特征向量计算:NumPy与SymPy结果差异原因分析

我正在开展一个涉及特征值(eigenvalues)与特征向量(eigenvectors)计算的项目。最初全程使用NumPy开发,但因多种原因不得不切换为SymPy。核心问题是,即使计算同一矩阵的特征向量,两者结果也不匹配。

NumPy实现与输出

原始NumPy代码:

import numpy as np
from numpy.linalg import inv, eig

T_num = np.array([[-0.873242282149309, 0.858808525419568, 0.00866025403784438, 0.00866025403784438], 
        [-0.858808525419568, 0.873242282149309, -0.00866025403784438, -0.00866025403784438], 
        [0.0360843918243516, 0.0360843918243516, -0.909326673973660, 0.822724133595217], 
        [-0.0360843918243516, -0.0360843918243516, -0.822724133595217, 0.909326673973660]])

eigenvalues, eigenvectors = np.linalg.eig(T_num)
vr = np.diag(eigenvalues)
Kr = eigenvectors

输出的特征向量矩阵Kr:

[[-0.16735621+0.00000000e+00j -0.54321448+5.43103641e-09j
  -0.54321448-5.43103641e-09j -0.10224205+0.00000000e+00j]
 [-0.10224205+0.00000000e+00j -0.54321448+0.00000000e+00j
  -0.54321448-0.00000000e+00j -0.16735621+0.00000000e+00j]
 [ 0.83678107+0.00000000e+00j -0.45267873+4.52586368e-09j
  -0.45267873-4.52586368e-09j  0.51121024+0.00000000e+00j]
 [ 0.51121024+0.00000000e+00j -0.45267873+4.96308368e-24j
  -0.45267873-4.96308368e-24j  0.83678107+0.00000000e+00j]]

SymPy实现与输出

我知晓NumPy的特征向量已归一化,SymPy的未归一化,因此使用.normalized()方法对SymPy结果进行归一化,代码如下:

import sympy as sp

T_sym = sp.Matrix([[-0.873242282149309, 0.858808525419568, 0.00866025403784438, 0.00866025403784438], 
        [-0.858808525419568, 0.873242282149309, -0.00866025403784438, -0.00866025403784438], 
        [0.0360843918243516, 0.0360843918243516, -0.909326673973660, 0.822724133595217], 
        [-0.0360843918243516, -0.0360843918243516, -0.822724133595217, 0.909326673973660]])

vr_sym = list(T_sym.eigenvals().keys())
eigenvectores = T_sym.eigenvects()
lista_vectp = []

for _, _, eigenvectors in eigenvectores:
    for vector in eigenvectors:
        normalized_vector = vector.normalized()
        lista_vectp.append(normalized_vector.T)
            
    Kr_sym = sp.Matrix(lista_vectp).T

输出结果:

[[-0.166635697352398 - 0.0155127875107584*I, -0.259982390116971 - 0.476960289513235*I, -0.214652107972921 + 0.499005456909564*I, 0.102242047382989 - 2.20934780343373e-64*I], 
[-0.101801866238621 - 0.00947714531910078*I, -0.259982395640837 - 0.476960299647248*I, -0.214652103412191 + 0.499005446307156*I, 0.167356213534108 - 2.62764866783283e-64*I], 
[0.83317848676198 + 0.077563937553791*I, -0.216651991764145 - 0.397466907927701*I, -0.178876756644103 + 0.415837880757976*I, -0.51121023691494 - 8.33146467644485e-65*I], 
[0.509009331193098 + 0.0473857265955033*I, -0.216651996367367 - 0.397466916372712*I, -0.178876752843495 + 0.415837871922635*I, -0.83678106767053 - 1.92452791847659e-64*I]]

可见SymPy计算出的特征向量虚部远大于NumPy的结果,请问这一差异产生的原因是什么?


原因分析

1. 数值计算与符号计算的核心差异

NumPy是数值计算库,基于浮点数近似求解特征值问题,采用的算法(如QR迭代)会自动将极小的虚部判定为浮点噪声,输出时直接显示为接近0的数值(比如你看到的1e-9、1e-24级别虚部)。而SymPy是符号计算库,会严格按照代数规则求解特征方程,哪怕输入矩阵存在微小的数值偏差(比如你输入的矩阵元素是截断后的近似小数,导致矩阵并非严格实对称),也会保留所有精确计算出的结果,包括这些偏差带来的虚部。

2. 特征向量的非唯一性

特征向量本身不唯一:对于同一特征值,其特征向量乘以任意非零标量(包括复数标量)后,仍然是该特征值的特征向量。NumPy输出的是实部主导、虚部可忽略的向量,而SymPy可能因求解路径不同,选择了不同的复数缩放形式,导致看起来差异较大,但本质上和NumPy的向量是等价的——你可以尝试将SymPy的特征向量乘以某个复数因子,或者取共轭,就能和NumPy的结果对齐。

3. 归一化的细节差异

虽然两者都做了L2归一化,但实现逻辑有区别:NumPy在归一化时会自动忽略极小的虚部(当作数值误差),而SymPy会严格保留所有计算出的虚部,哪怕这些虚部是由输入矩阵的微小非对称性导致的。


验证建议

  • 检查原始矩阵是否严格实对称:如果原始矩阵应该是对称的,输入时的小数截断可能导致了非对称,这是虚部产生的根源。
  • 对SymPy的结果取实部(或忽略极小虚部),再与NumPy结果对比,两者会高度接近。
  • 验证特征向量有效性:分别计算T @ v - λ*v(NumPy用数值精度,SymPy用符号精度),结果都应该接近零向量。

内容的提问来源于stack exchange,提问作者Ectobius Rex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:09:53