NumPy eigh() 给出不正确的特征向量
NumPy eigh() gives incorrect eigenvectors
我一直在使用 NumPy 来做一些线性代数,但我遇到了 eigh() 似乎返回不正确的特征向量的问题。 Here 是我正在使用的对称矩阵(481 x 481)。看下面的代码:
import numpy as np
c = np.load('C.npy')
eigenvectors_h = np.linalg.eigh(c)[1]
c.dot(eigenvectors_h[:, 0]) / eigenvectors_h[:, 0]
c
是实数,绝对是对称的,因为 np.allclose(c, c.T)
returns True
.
我没有得到一个由重复 481 次的特征值组成的数组,而是看到了看起来像随机数的东西:
-1.03913672e+04 1.70145524e-15 -6.30342977e-16 -5.80181781e-15
2.43586988e-15 1.02142854e-13 -1.59100453e-13 6.34768223e-14
1.47793139e-14 5.19832084e-15 1.23786159e-14 -6.89332604e-14
3.35120474e-14 -5.55497774e-14 3.35912194e-14 2.41599711e-14
-8.10853045e-15 3.39728566e-14 1.66605768e-14 -4.62536283e-14
4.78158644e-15 1.05840004e-14 2.49968277e-14 6.37161752e-14
-8.29049452e-15 7.69540224e-13 -1.41737099e-14 -2.04904903e-14
-2.02649833e-14 8.75614182e-15 -6.43718154e-14 -6.71884701e-15
2.89567850e-15 -1.93639427e-14 2.05961830e-15 -2.82825321e-14
-2.99156760e-14 -1.17149803e-14 -1.00413883e-13 2.81365540e-15
-1.47420105e-14 -1.54638301e-14 2.97770540e-14 9.42616109e-14
-2.18819275e-13 6.23156105e-13 -1.14148906e-14 1.97147438e-14
-5.04103330e-14 -1.39415849e-13 -6.78032159e-14 -2.18085326e-14
-1.36511305e-14 3.09529929e-14 -9.42922227e-15 -1.80013713e-14
-3.34989389e-14 -1.31399506e-15 3.86915434e-14 7.43430828e-15
3.00681063e-14 3.15599077e-15 1.77696288e-14 -5.33198194e-15
-3.03304561e-14 1.74254787e-13 -3.31735946e-14 3.02816694e-14
-1.79965325e-14 -6.03794643e-13 -2.70964350e-14 1.13476801e-14
-1.31756179e-14 1.23490868e-14 1.31665400e-14 -4.82723158e-15
-6.80123679e-14 1.01616264e-13 -3.26409876e-14 5.00897081e-15
8.01025834e-14 -5.50605097e-13 3.03059609e-15 5.55524078e-14
1.76830600e-14 5.82590991e-14 -4.07471685e-14 -1.74936332e-14
3.67006376e-14 1.23210295e-14 4.54025070e-14 -1.37452957e-13
5.68932273e-15 3.59057575e-14 7.52501521e-15 -8.21274824e-15
2.86056181e-13 2.12632482e-14 9.50056403e-14 2.80131245e-14
...
但是,它与 eig()
一起工作正常:
eigenvectors = np.linalg.eig(c)[1]
c.dot(eigenvectors[:, 0]) / eigenvectors[:, 0] #[126.56622721] * 481
我想使用 eigh()
因为它看起来更快并且 returns 实数值而不是复数值,但它似乎不起作用。谁能解释这是为什么或我做错了什么?
独立示例
此示例演示了自包含代码中的相同行为(使用基本上为 1 阶的随机矩阵,数字工件除外)。
import numpy as np
u = np.random.uniform(size=(100,))
c = np.outer(u, u)
eigenvectors_h = np.linalg.eigh(c)[1]
print(c.dot(eigenvectors_h[:, 0]) / eigenvectors_h[:, 0])
eigenvectors = np.linalg.eig(c)[1]
print(c.dot(eigenvectors[:, 0]) / eigenvectors[:, 0])
eigh
比 eig
没有任何问题。如果您使用列表末尾的特征向量测试 eig
,您将得到类似的 "random" 数字:try
print(c.dot(eigenvectors[:, -10]) / eigenvectors[:, -10])
这是正在发生的事情:
- 矩阵的大部分特征值与 0 没有区别,它们的大小为 1e-16 或更小。
- 方法
eigh
returns 最小特征值(及其特征向量)优先。
- 方法
eig
returns 最大 特征值(及其特征向量)优先。
- 您仅测试返回的第一个特征向量。
因此您看到 eig
和 eigh
的行为差异实际上并不存在。
实际上,您的矩阵似乎是低秩 + 数值噪声。因此,较小的特征值可能应该为 0,在这种情况下,特征向量的计算基本上是彩票;有一个巨大的线性子空间几乎被矩阵杀死,来自该子空间的任何东西都可以作为特征向量传递。乘法 c*eigenvector
的结果只是一堆数字噪音。
寓意:不要忘记看全貌。
eigenvalues_h, eigenvectors_h = np.linalg.eigh(c)
print(eigenvalues_h)
eigenvalues, eigenvectors = np.linalg.eig(c)
print(eigenvalues)
我一直在使用 NumPy 来做一些线性代数,但我遇到了 eigh() 似乎返回不正确的特征向量的问题。 Here 是我正在使用的对称矩阵(481 x 481)。看下面的代码:
import numpy as np
c = np.load('C.npy')
eigenvectors_h = np.linalg.eigh(c)[1]
c.dot(eigenvectors_h[:, 0]) / eigenvectors_h[:, 0]
c
是实数,绝对是对称的,因为 np.allclose(c, c.T)
returns True
.
我没有得到一个由重复 481 次的特征值组成的数组,而是看到了看起来像随机数的东西:
-1.03913672e+04 1.70145524e-15 -6.30342977e-16 -5.80181781e-15
2.43586988e-15 1.02142854e-13 -1.59100453e-13 6.34768223e-14
1.47793139e-14 5.19832084e-15 1.23786159e-14 -6.89332604e-14
3.35120474e-14 -5.55497774e-14 3.35912194e-14 2.41599711e-14
-8.10853045e-15 3.39728566e-14 1.66605768e-14 -4.62536283e-14
4.78158644e-15 1.05840004e-14 2.49968277e-14 6.37161752e-14
-8.29049452e-15 7.69540224e-13 -1.41737099e-14 -2.04904903e-14
-2.02649833e-14 8.75614182e-15 -6.43718154e-14 -6.71884701e-15
2.89567850e-15 -1.93639427e-14 2.05961830e-15 -2.82825321e-14
-2.99156760e-14 -1.17149803e-14 -1.00413883e-13 2.81365540e-15
-1.47420105e-14 -1.54638301e-14 2.97770540e-14 9.42616109e-14
-2.18819275e-13 6.23156105e-13 -1.14148906e-14 1.97147438e-14
-5.04103330e-14 -1.39415849e-13 -6.78032159e-14 -2.18085326e-14
-1.36511305e-14 3.09529929e-14 -9.42922227e-15 -1.80013713e-14
-3.34989389e-14 -1.31399506e-15 3.86915434e-14 7.43430828e-15
3.00681063e-14 3.15599077e-15 1.77696288e-14 -5.33198194e-15
-3.03304561e-14 1.74254787e-13 -3.31735946e-14 3.02816694e-14
-1.79965325e-14 -6.03794643e-13 -2.70964350e-14 1.13476801e-14
-1.31756179e-14 1.23490868e-14 1.31665400e-14 -4.82723158e-15
-6.80123679e-14 1.01616264e-13 -3.26409876e-14 5.00897081e-15
8.01025834e-14 -5.50605097e-13 3.03059609e-15 5.55524078e-14
1.76830600e-14 5.82590991e-14 -4.07471685e-14 -1.74936332e-14
3.67006376e-14 1.23210295e-14 4.54025070e-14 -1.37452957e-13
5.68932273e-15 3.59057575e-14 7.52501521e-15 -8.21274824e-15
2.86056181e-13 2.12632482e-14 9.50056403e-14 2.80131245e-14
...
但是,它与 eig()
一起工作正常:
eigenvectors = np.linalg.eig(c)[1]
c.dot(eigenvectors[:, 0]) / eigenvectors[:, 0] #[126.56622721] * 481
我想使用 eigh()
因为它看起来更快并且 returns 实数值而不是复数值,但它似乎不起作用。谁能解释这是为什么或我做错了什么?
独立示例
此示例演示了自包含代码中的相同行为(使用基本上为 1 阶的随机矩阵,数字工件除外)。
import numpy as np
u = np.random.uniform(size=(100,))
c = np.outer(u, u)
eigenvectors_h = np.linalg.eigh(c)[1]
print(c.dot(eigenvectors_h[:, 0]) / eigenvectors_h[:, 0])
eigenvectors = np.linalg.eig(c)[1]
print(c.dot(eigenvectors[:, 0]) / eigenvectors[:, 0])
eigh
比 eig
没有任何问题。如果您使用列表末尾的特征向量测试 eig
,您将得到类似的 "random" 数字:try
print(c.dot(eigenvectors[:, -10]) / eigenvectors[:, -10])
这是正在发生的事情:
- 矩阵的大部分特征值与 0 没有区别,它们的大小为 1e-16 或更小。
- 方法
eigh
returns 最小特征值(及其特征向量)优先。 - 方法
eig
returns 最大 特征值(及其特征向量)优先。 - 您仅测试返回的第一个特征向量。
因此您看到 eig
和 eigh
的行为差异实际上并不存在。
实际上,您的矩阵似乎是低秩 + 数值噪声。因此,较小的特征值可能应该为 0,在这种情况下,特征向量的计算基本上是彩票;有一个巨大的线性子空间几乎被矩阵杀死,来自该子空间的任何东西都可以作为特征向量传递。乘法 c*eigenvector
的结果只是一堆数字噪音。
寓意:不要忘记看全貌。
eigenvalues_h, eigenvectors_h = np.linalg.eigh(c)
print(eigenvalues_h)
eigenvalues, eigenvectors = np.linalg.eig(c)
print(eigenvalues)