使用MKL LAPACK的sgeev函数计算特征向量结果异常的问题排查
首先别担心,你的sgeev调用其实是正确的——特征向量看起来不符合预期,本质是因为特征向量的非唯一性和LAPACK的输出规范导致的,具体来说有三个关键点:
1. 特征向量是「方向」而非「固定向量」
特征向量的定义是:若$A\mathbf{v} = \lambda\mathbf{v}$,则对于任意非零标量$k$,$k\mathbf{v}$也是对应$\lambda$的特征向量。同时,对于重特征值(比如你的例子中$\lambda=2$是二重根),特征向量构成一个线性空间,这个空间的基可以有多种不同的选择(只要线性无关),sgeev返回的基和你预期的只是不同的合法基而已。
比如你预期的$\lambda=2$的特征向量是$[-1,0,3]T$和$[1,1,0]T$,而sgeev返回的对应列是这两个向量的线性组合,同样满足$A\mathbf{v}=2\mathbf{v}$,完全正确。
2. sgeev返回的是归一化的特征向量
LAPACK的sgeev函数默认返回的特征向量是欧几里得范数为1的(即每个列向量的元素平方和等于1)。你预期的是未归一化的整数形式向量,只需要对sgeev的结果做缩放就能得到:
- 比如你预期的$\lambda=1$的特征向量$[1,1,1]^T$,归一化后就是$[1/\sqrt{3},1/\sqrt{3},1/\sqrt{3}] \approx [0.577,0.577,0.577]$,和你输出的vr第一列(符号相反,符号不影响,因为$-1\times\mathbf{v}$也是特征向量)一致。
3. 特征值的排序问题
LAPACK的sgeev返回的特征值是按实部从小到大排序的(实部相等时按虚部排序)。你的特征值$\lambda=1$实部小于2,所以会排在第一个位置,对应的特征向量是vr的第一列;而你预期的$\lambda=2$的向量排在前两位,这只是输出顺序的差异,不是错误。
验证你的结果是否正确
可以通过简单计算验证:取vr的任意一列,比如第一列$\mathbf{v} = [-0.577,-0.577,-0.577]^T$,计算$A\mathbf{v}$:
$$
A\mathbf{v} = \begin{bmatrix}-1&3&-1\-3&5&-1\-3&3&1\end{bmatrix} \begin{bmatrix}-0.577\-0.577\-0.577\end{bmatrix} = \begin{bmatrix}-0.577\-0.577\-0.577\end{bmatrix} = 1\times\mathbf{v}
$$
完全符合特征值1的定义,说明结果是对的。
如何得到你预期的特征向量形式
如果需要得到整数形式的特征向量:
- 先确认每个特征值对应的特征向量空间;
- 对sgeev返回的归一化向量进行缩放(乘以合适的标量),或者直接解线性方程组$(A-\lambda I)\mathbf{x}=0$得到你想要的基。
比如对于$\lambda=2$,解$(A-2I)\mathbf{x}=0$,即:
$$
\begin{bmatrix}-3&3&-1\-3&3&-1\-3&3&-1\end{bmatrix}\mathbf{x}=0
$$
可以得到两个线性无关的解,比如$[-1,0,3]T$和$[1,1,0]T$,这就是你预期的形式。
内容的提问来源于stack exchange,提问作者Laetis

