scipy.linalg.eig возвращать комплексные собственные значения для ковариационной матрицы? - PullRequest
15 голосов
/ 07 января 2012

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

Однако взгляните на следующий эксперимент со Сципи:

>>> a=np.random.random(5)
>>> b=np.random.random(5)
>>> ab = np.vstack((a,b)).T
>>> C=np.cov(ab)
>>> eig(C)
7.90174997e-01 +0.00000000e+00j,
2.38344473e-17 +6.15983679e-17j,
2.38344473e-17 -6.15983679e-17j,
-1.76100435e-17 +0.00000000e+00j,   
5.42658040e-33 +0.00000000e+00j

Однако , воспроизведение приведенного выше примера в Matlab работает правильно:

a = [0.6271, 0.4314, 0.3453, 0.8073, 0.9739]
b = [0.1924, 0.3680, 0.0568, 0.1831, 0.0176]
C=cov([a;b])
eig(C)
-0.0000
-0.0000
 0.0000
 0.0000
 0.7902

Ответы [ 2 ]

27 голосов
/ 07 января 2012

Вы подняли два вопроса:

  1. Собственные значения, возвращаемые scipy.linalg.eig, не являются реальными.
  2. Некоторые из собственных значений отрицательны.

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

Теперь, для более интересного аспекта проблемы: почему результат Matlab реален, тогда как результат SciPy имеет некоторые сложные компоненты?

Matlab's eig определяет, является ли входная матрица реальной симметричной или эрмитовой, и использует факторизацию Холецкого, когда она есть. См. Описание аргумента chol в документации eig . Это не делается автоматически в SciPy.

Если вы хотите использовать алгоритм, который использует структуру реальной симметричной или эрмитовой матрицы, используйте scipy.linalg.eigh. Для примера в вопросе:

>>> eigh(C, eigvals_only=True)
array([ -3.73825923e-17,  -1.60154836e-17,   8.11704449e-19,
         3.65055777e-17,   7.90175615e-01])

Этот результат такой же, как у Matlab, если вы округлите до того же числа цифр точности, которое напечатал Matlab.

5 голосов
/ 07 января 2012

То, что вы испытываете, это численная нестабильность из-за ограничений на точность с плавающей запятой.

Обратите внимание, что:

(1) MATLAB также возвращает отрицательные значения, но формат печати установлен на short, и вы не видите полную точность двойного, сохраненного в памяти.Используйте format long g для печати большего количества десятичных знаков

(2) Все мнимые части, возвращаемые linalg.eig numpy, близки к точности станка.Таким образом, вы должны считать их нулем.

...