Кластеризация среднего сдвига Python для массива комплексных чисел

Я унаследовал некоторый код, который был написан около года назад, поэтому я думаю, что тогда он использовал numpy 1.13 (сейчас v1.15.2), scipy 1.00rc (сейчас v1.1.0) и sklearn 0.19 (сейчас v.0.20).0).

Он реализует LDA Фишера, чтобы уменьшить n- мерное пространство до 1… n- 1-мерного пространства, которое в результате приводит к массиву массивов комплексных чисел (из-за неточности с плавающей запятой). Этот массив затем подбирается и подается в sklearn.cluster.MeanShift который сразу выбрасывает исключение:

  File "/…/lib/python3.6/site-packages/sklearn/cluster/mean_shift_.py", line 416, in fit
    X = check_array(X)
  File "/…/lib/python3.6/site-packages/sklearn/utils/validation.py", line 531, in check_array
    _ensure_no_complex_data(array)
  File "/…/lib/python3.6/site-packages/sklearn/utils/validation.py", line 354, in _ensure_no_complex_data
    "{}\n".format(array))
ValueError: Complex data not supported

Я все еще изучаю математические детали того, что здесь происходит, но мне кажется странным, что этот код был объявлен "работоспособным".

Я что-то здесь упускаю? Произошли ли изменения версии в результате этой регрессии, или есть более фундаментальный недостаток кода? Как бы я решил эту проблему?

1 ответ

В комментариях / чате мы определили, по крайней мере, одну проблему, которая заключается в том, что численное собственное разложение

(cov_w + I)^-1 @ cov_b                       (1)

не является реальным, как следует, но возвращает значительные мнимые компоненты. Здесь @ - умножение матриц, cov_w и cov_b - ковариационные матрицы, а I - единичная матрица. Это можно исправить, вычислив квадратный корень из матрицы (cov_w + I)^-1, назовем его SQ, а затем используем тот факт, что (1) аналогично

SQ @ cov_b @ SQ                              (2)

следовательно, имеет те же собственные значения, и если V являются собственными векторами (2), то (правые) собственные векторы (1) равны SQ @ V.

Мы получили то, что, поскольку (2) является симметричной матрицей, ее собственное разложение может быть вычислено с использованием numpy.linalg.eigh что гарантирует чисто реальные результаты. eigh также может использоваться для вычисления SQ, см. здесь. Обязательно обходите обратное и применяйте eigh прямо на cov_w + I или даже cov_w,

Другие вопросы по тегам