Взгляните на эту часть трассировки стека:
531 def _pre_compute_svd(self, X, y):
532 if sparse.issparse(X) and hasattr(X, 'toarray'):
--> 533 X = X.toarray()
534 U, s, _ = np.linalg.svd(X, full_matrices=0)
535 v = s ** 2
Используемый вами алгоритм использует линейные алгоритмы numpy для SVD. Но они не могут обрабатывать разреженные матрицы, поэтому автор просто преобразует их в обычные нерегулярные массивы. Первое, что должно произойти для этого, - выделить массив с нулевым нулем, а затем заполнить соответствующие пятна значениями, редко хранимыми в разреженной матрице. Звучит достаточно легко, но давайте математику. Поля float64 (используемый по умолчанию тип dtype, который вы используете, если вы не знаете, что используете), занимает 8 байтов. Таким образом, на основе формы массива, которую вы предоставили, новый нулевой массив будет:
183576 * 101507 * 8 = 149,073,992,256 ~= 150 gigabytes
Менеджер памяти вашей системы, вероятно, рассмотрел этот запрос на распределение и покончил жизнь самоубийством. Но что вы можете с этим поделать?
Во-первых, это похоже на довольно нелепое количество функций. Я ничего не знаю о вашей проблемной области или о том, что у вас есть, но моя реакция на гитаре заключается в том, что вам нужно сделать некоторое уменьшение размерности здесь.
Во-вторых, вы можете попытаться исправить неправильное неправильное использование алгоритма матрицы. Здесь удушение numpy.linalg.svd
, поэтому вы можете использовать scipy.sparse.linalg.svds
. Я не знаю алгоритм, о котором идет речь, но он может не поддаваться разреженным матрицам. Даже если вы используете соответствующие разреженные линейные алгоритмы, он может создавать (или использовать внутри) некоторые не разреженные матрицы с размерами, подобными вашим данным. Использование разреженного представления матрицы для представления нерезких данных приведет только к использованию большего пространства, чем было бы первоначально, поэтому такой подход может не работать. Соблюдайте осторожность.
Соответствующим вариантом является gcv_mode. Он может принимать 3 значения: «авто», «svd» и «собственный». По умолчанию установлено значение «auto», которое имеет следующее поведение: используйте режим svd, если n_samples> n_features, в противном случае используйте собственный режим.
Так как в вашем случае n_samples> n_features, режим svd выбран. Однако в настоящее время режим svd не обрабатывает разреженные данные должным образом. scikit-learn должен быть исправлен, чтобы использовать правильный разреженный SVD вместо плотного SVD.
В качестве обходного пути я заставил бы собственный режим gcv_mode = «собственный», так как этот режим должен правильно обрабатывать разреженные данные. Тем не менее, n_samples довольно велико в вашем случае. Поскольку собственная мода строит матрицу ядра (и, следовательно, имеет n_samples ** 2 сложности памяти), матрица ядра может не помещаться в память. В этом случае я бы просто уменьшил количество выборок (например, собственный режим может обрабатывать очень большое количество функций без проблем).
В любом случае, поскольку как n_samples, так и n_features достаточно велики, вы (даже с правильным разреженным SVD).
Также см. https://github.com/scikit-learn/scikit-learn/issues/1921