numpy.linalg.eigvals показывает разные значения для транспонирования матрицы - это из-за переполнения? - PullRequest
0 голосов
/ 17 октября 2018

Я получаю разные ответы от np.linalg.eigvals в зависимости от того, использую ли я транспонирование матрицы.

Для репликации:

mat = np.array([[ -7.00616288e-08,  -2.79704289e-09 ,  1.67598654e-10],
 [ -3.23676574e+07,  -1.58978291e+15,   0.00000000e+00],
 [  0.00000000e+00  , 1.80156232e-02 , -2.32851854e+07]])

print(np.linalg.eigvals(mat))
print(np.linalg.eigvals(mat.transpose()))

Я получаю:

[ -7.00616288e-08  -1.58978291e+15  -2.32851854e+07]
[ -1.58978291e+15   2.50000000e-01  -2.32851854e+07]

Обратите внимание, что эти значения разные.Поскольку собственные значения матрицы и ее транспонирование идентичны, я предполагаю, что эти проблемы связаны с переполнением.Есть ли какое-то максимальное значение, которое я должен ограничить, чтобы убедиться, что это всегда соответствует?

1 Ответ

0 голосов
/ 17 октября 2018

Не из-за переполнения.Переполнение легко обнаружить, и оно генерирует предупреждение.Проблема заключается в ограничении двойной точности: значимые цифры могут быть потеряны, когда числа очень разных величин сложены, а затем вычтены.Например, (1e20 + 1) - 1e20 == 0.

Второй результат с двумя отрицательными собственными значениями неверен, поскольку определитель вашей матрицы явно отрицателен: произведение основных диагональных элементов имеет величину 1e15 и доминирует над всеми другими членами в определителе с большойполе.Таким образом, знак детерминанта является знаком этого продукта, который является отрицательным.

Проблема в том, что mat.T имеет все крошечные записи в первом столбце, намного меньше, чем в других столбцах.При поиске пивота алгоритм может сканировать этот столбец и согласиться с тем, что там найдено.Это не обязательно, как работает .eigvals, но тот же принцип - алгоритмы числовой линейной алгебры имеют тенденцию исходить из верхнего левого угла, и поэтому лучше избегать небольших записей там.Вот один из способов:

mat1 = np.roll(mat, 1, axis=[0, 1])
print(np.linalg.eigvals(mat1))
print(np.linalg.eigvals(mat1.T))

печать

[-7.00616288e-08 -2.32851854e+07 -1.58978291e+15]
[-2.32851854e+07 -1.58978291e+15 -7.00616288e-08] 

, которые являются последовательными.Свертывание обеих осей означает сопряжение mat матрицей перестановок, которая не меняет собственных значений.Свернутая матрица -

[[-2.32851854e+07  0.00000000e+00  1.80156232e-02]
 [ 1.67598654e-10 -7.00616288e-08 -2.79704289e-09]
 [ 0.00000000e+00 -3.23676574e+07 -1.58978291e+15]]

, что дает NumPy довольно большое число для начала.

В идеале он бы делал что-то подобное, но никакой (практический) алгоритм не идеален для любой ситуации.

...