关于numpy.linalg.eig()与eigh()对同一厄米特矩阵返回不同特征向量的疑问(原系误解)
关于numpy.linalg.eig()与eigh()返回特征向量差异的解答
注:本问题源于一处误解,详见下方分析。
用户发现numpy.linalg模块的eig()与eigh()函数针对同一个厄米特矩阵返回的特征向量似乎不同,复现代码如下:
import numpy as np H = [[0.6 , -1j, 0], [1j, 0.4, 0], [0, 0, -1]] evals, evects = np.linalg.eig(H) print('\nOutput of the eig function') for i in range(0,3): print('evect for eval=',evals[i],'\n',evects[i,0],'\n',evects[i][1],'\n',evects[i][2]) evals, evects = np.linalg.eigh(H) print('\nOutput of the eigh function') for i in range(0,3): print('evect for eval=',evals[i],'\n',evects[i,0],'\n',evects[i][1],'\n',evects[i][2])
问题根源
代码的核心错误是错误读取了特征向量的存储维度:
- numpy的
eig()和eigh()函数返回的特征向量矩阵中,每一列对应一个特征向量,而非每一行。原代码按行索引(evects[i,0]、evects[i][1]等)读取,相当于把特征向量矩阵的行当成了特征向量,自然得到错误的结果。 - 此外,
eigh()会自动将厄米特矩阵的特征值按从小到大排序,而eig()的特征值顺序是未排序的,这进一步加剧了两者输出的视觉差异。
修正后的验证代码
import numpy as np H = [[0.6 , -1j, 0], [1j, 0.4, 0], [0, 0, -1]] # 正确读取eig的特征向量(列向量) evals_eig, evects_eig = np.linalg.eig(H) print('\neig函数输出(正确读取特征向量):') for i in range(3): print(f'特征值 {evals_eig[i]} 对应的特征向量:') print(evects_eig[:, i]) # 正确读取eigh的特征向量(列向量) evals_eigh, evects_eigh = np.linalg.eigh(H) print('\neigh函数输出(正确读取特征向量):') for i in range(3): print(f'特征值 {evals_eigh[i]} 对应的特征向量:') print(evects_eigh[:, i])
补充说明
对于厄米特矩阵,eig()和eigh()返回的特征向量本质是等价的:
- 两者的特征向量可能存在全局相位差异(复数向量乘以模为1的复数后,依然是原矩阵的特征向量),这是数值计算中的正常现象。
eigh()专门针对厄米特/对称矩阵优化,计算效率更高且数值稳定性更好,建议优先使用。
内容的提问来源于stack exchange,提问作者Billy Gatto
相关产品推荐
相关产品推荐

