Спектральная кластеризация с помощью sklearn и большой матрицы сходства

Я пытаюсь использовать метод спектральной кластеризации, предоставленный scikit-learn для объединения строк моего набора данных (которых всего 16000). Моя проблема возникает после того, как я предварительно вычислил матрицу сходства (матрица с плавающей запятой 16000x16000), которая выделяет более или менее 3 гигабайта (максимум я могу достичь до 8 ГБ), метод, вызываемый на этой матрице, с решателем argpack требует гораздо больше памяти и процессор теряет так много времени, пытаясь поменять местами вещи в памяти и из памяти, что вычисления замедляются до смерти. Я также пытался вызвать сборщик мусора перед методом, но безуспешно:

import gc
gc.collect()

Как я могу получить точную схему происходящего? Это известная проблема? Есть ли какие-либо альтернативы в python для выполнения спектральной кластеризации из коробки?

Я могу опубликовать минимальный рабочий пример, если это необходимо.

ОБНОВЛЕНИЕ Я ошибся в отношении решателя lobpcg, сначала кажется, что он использует всю мою память, но затем стабилизируется около 5 Гб, и процесс продолжается, но возникает другая проблема. Кажется, что вычисление приводит к некоторым числовым неточностям, которые в конце концов генерируют Nans или ошибку, подобную этой (возникающая ошибка изменяется, в то время как матрица сходства немного изменяется, см. Ниже):

File "/usr/local/lib/python3.4/dist-packages/sklearn/cluster/spectral.py", line 255, in spectral_clustering
eigen_tol=eigen_tol, drop_first=False)
File "/usr/local/lib/python3.4/dist-packages/sklearn/manifold/spectral_embedding_.py", line 303, in spectral_embedding
largest=False, maxiter=2000)
File "/usr/local/lib/python3.4/dist-packages/scipy/sparse/linalg/eigen/lobpcg/lobpcg.py", line 449, in lobpcg
assert np.allclose(gramA.T, gramA)
AssertionError

Моя метрика подобия представляет собой ядро ​​Гаусса exp(-((X_1 - x_2)^2/2*sigma^2)), и результаты сильно различаются при использовании разных значений сигмы. Я могу понять, что некоторые неточности могут возникнуть, когда некоторые записи близки к нулю, но это не тот случай, когда я использую большие значения для сигмы (= 5,0), вместо этого приближая их к 1,0.

Теперь я предполагаю, что я упускаю какой-то момент или делаю что-то неправильно в процессе, поэтому я обновляю этот вопрос с новой целью.

Для справки, вот как я вычисляю матрицу сходства:

 pairwise_dists = \
      scipy.spatial.distance.squareform(
           scipy.spatial.distance.pdist(data_slice,'sqeuclidean'))
 similarity_matrix = scipy.exp(-pairwise_dists /(2 * self._sigma ** 2))

где data_slice - это массив numpy, строки которого являются моими экземплярами, а self._sigma хранит параметр гауссовой сигмы.


person rano    schedule 19.09.2014    source источник
comment
вы пробовали с уменьшенным подмножеством, скажем, 10x10, 100x100, 1Kx1K? Спектральный анализ основан на вычислении собственных векторов, что является сложной операцией. Переход от небольшого набора данных к большому может помочь вам определить ожидаемое время для исходного набора данных.   -  person Picarus    schedule 19.09.2014
comment
Я пробовал с синтетическими небольшими наборами данных (200-400 строк), но не прогрессивно. Это правда, что я мог бы определить жизнеспособное измерение, но я не нашел бы решения для использования спектральной кластеризации в исходном наборе данных (и что именно идет не так)   -  person rano    schedule 19.09.2014
comment
Можете ли вы сказать, какая операция является заменой? Можно было бы использовать другой собственный решатель или использовать float32. Почему вы говорите слишком много памяти в названии? у вас меньше чем в три раза больше памяти для хранения матрицы для выполнения собственного разложения. Это не кажется ужасно неправильным. Сколько кластеров вы пытаетесь получить? Если кластеров мало, то и собственных векторов должно быть мало.   -  person Andreas Mueller    schedule 19.09.2014
comment
Кстати, вы пробовали другие методы кластеризации или уменьшения размерности?   -  person Andreas Mueller    schedule 19.09.2014
comment
@AndreasMueller, как здесь может помочь уменьшение размерности?   -  person Has QUIT--Anony-Mousse    schedule 20.09.2014
comment
Ну, не для применения спектральной кластеризации, а для получения информации о наборе данных или применения других методов кластеризации в первичном виде.   -  person Andreas Mueller    schedule 21.09.2014


Ответы (1)


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

Эта матрица имеет размер O(n^2), поэтому почти любая реализация потребует O(n^2) памяти.

16000 x 16000 x 4 (при условии хранения данных с плавающей запятой и без служебных данных) составляет около 1 ГБ. Вероятно, ему нужна рабочая копия (такие методы, как scipy.exp, вероятно, создадут копию вашей матрицы и, возможно, с двойной точностью) и некоторые накладные расходы, поэтому вы в конечном итоге используете 3 ГБ...

Этот алгоритм просто неприменим для больших данных, как и любой другой алгоритм, требующий памяти O(n^2). Выберите другой алгоритм; возможно, тот, который можно ускорить с помощью индексных структур. Или уменьшите размер набора данных, например, путем выборки.

person Has QUIT--Anony-Mousse    schedule 20.09.2014
comment
Как я понял вопрос был, почему не работает с 8гб ОЗУ если матрица разнородности 3гб но может я неправильно понял. - person Andreas Mueller; 21.09.2014
comment
Я обновил вопрос. Изменение собственного решателя смягчает проблему с памятью, но вносит числовые ошибки. Мне интересно, делаю ли я что-то не так. - person rano; 22.09.2014
comment
Чтобы сэкономить память, можно (в принципе) вычислить действие матрицы на векторы на лету и использовать это в итерационных методах для вычисления собственных векторов. Тогда потребуется только O (n) памяти, но это займет гораздо больше времени. - person Nick Alger; 22.11.2015