numpy всегда получает сложные собственные значения и неправильные собственные векторы - PullRequest
2 голосов
/ 23 февраля 2020

Я работаю над выполнением простых линейных алгебраических манипуляций с numpy. Все было действительно здорово до сих пор, когда я беру простые матрицы 2x2, чьи собственные значения и векторы, которые я знаю, и проверяю numpy на них.

Например, в приведенной ниже примере матрицы есть единственное собственное значение e = 1 и один связанный собственный вектор [-3, 1]:

A = np.array([[-2, -9],
              [ 1,  4]])


vals, vects = np.linalg.eig(A)
vals2, vects2 = np.linalg.eigh(A)
vals3 = np.linalg.eigvals(A)

print("Eigenvalues (linalg.eig): \n", vals)
print("Eigenvalues (linalg.eigvals): \n", vals3)
print("Eigenvectors: \n", vects)

приводит к следующему:

Eigenvalues (linalg.eig):
 [1.+1.89953279e-08j 1.-1.89953279e-08j]

Eigenvalues (linalg.eigvals):
  [1.+1.89953279e-08j 1.-1.89953279e-08j]

Eigenvectors:
 [[ 0.9486833 +0.00000000e+00j  0.9486833 -0.00000000e+00j]
 [-0.31622777-2.00228337e-09j -0.31622777+2.00228337e-09j]] 

Я понимаю, что собственные векторы имеют формат столбца. Если вы пренебрегаете маленькими мнимыми частями, оба вектора являются ПОЧТИ скалярными кратными единственного правильного собственного вектора.

Моя матрица не является симметричной c или сопряженной симметрией c, и поэтому linalg.eigh не должна работать, но я все равно попробовал. Это дает мне реальные ценности, но они полностью поддельные.

Я также искал другие подобные вопросы и не нашел удовлетворительных ответов. Самый близкий из приведенных мною ответов - это один из ответов, в котором предлагается написать функцию для удаления собственных значений их маленьких мнимых частей. Это работает, но все еще оставляет неправильные собственные векторы.

Что здесь происходит? Как я могу это просто исправить? Кажется, немного сложно написать свои собственные функции для исправления такой хорошо зарекомендовавшей себя библиотеки, чтобы сделать ее правильной для простых вычислений.

Ответы [ 2 ]

1 голос
/ 23 февраля 2020

Здесь вы заметили относительную ошибку аппроксимации.

Numpy не вычисляет собственные значения и собственные векторы точно, а использует мощные и оптимизированные численные алгоритмы, которые приводят не к точным ответам, а к довольно близкие вместо этого. Для этих целей используется старая библиотека LAPACK dggev: http://www.netlib.org/lapack/double/dggev.f

Если вы ищете точный ответ, то Numpy не является решением для вас. Вместо этого взгляните на Симпи. Подобная проблема также обсуждается здесь: как вычисляются numpy собственные значения и собственные векторы

1 голос
/ 23 февраля 2020

Numpy возвращает нормализованный собственный вектор для каждого собственного значения; поскольку собственное значение здесь имеет кратность 2, оно возвращает один и тот же собственный вектор дважды. Вы можете использовать np.real_if_close для преобразования в реальное:

In [156]: A = np.array([[-2, -9],
     ...:               [ 1,  4]])
     ...: 
     ...: w, v = np.linalg.eig(A)
     ...: v = np.real_if_close(v, tol=1)
     ...: v
Out[156]: 
array([[ 0.9486833 ,  0.9486833 ],
       [-0.31622777, -0.31622777]])

Проверка работоспособности:

In [157]: v * 10**.5
Out[157]: 
array([[ 3.,  3.],
       [-1., -1.]])

Если вы хотите получить точные решения вместо этих, склонных к машинной ошибке, могу я предложить sympy:

In [159]: from sympy import Matrix
     ...: m = Matrix(A)
     ...: m.eigenvects()
Out[159]: 
[(1,
  2,
  [Matrix([
   [-3],
   [ 1]])])]

Где мы получаем собственное значение 1, его кратность 2 и собственный вектор, связанный с ним.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...