Matlab - как вычислить PCA на огромном наборе данных

Возможный дубликат:
В MATLAB заканчивается память, но этого не должно быть

Я хочу выполнить анализ PCA на огромном наборе данных точек. Чтобы быть более конкретным, у меня есть size(dataPoints) = [329150 132], где 328150 — количество точек данных, а 132 — количество функций.

Я хочу извлечь собственные векторы и соответствующие им собственные значения, чтобы выполнить реконструкцию PCA.

Однако, когда я использую функцию princomp (т.е. [eigenVectors projectedData eigenValues] = princomp(dataPoints);, я получаю следующую ошибку:

>> [eigenVectors projectedData eigenValues] = princomp(pointsData);
Error using svd
Out of memory. Type HELP MEMORY for your options.

Error in princomp (line 86)
[U,sigma,coeff] = svd(x0,econFlag); % put in 1/sqrt(n-1) later

Однако, если я использую меньший набор данных, у меня нет проблем.

Как я могу выполнить PCA для всего моего набора данных в Matlab? Кто-нибудь сталкивался с этой проблемой?

Изменить:

Я изменил функцию princomp и попытался использовать svds вместо svd, но, тем не менее, получаю почти ту же ошибку. Я сбросил ошибку ниже:

Error using horzcat
Out of memory. Type HELP MEMORY for your options.

Error in svds (line 65)
B = [sparse(m,m) A; A' sparse(n,n)];

Error in princomp (line 86)
[U,sigma,coeff] = svds(x0,econFlag); % put in 1/sqrt(n-1) later

person Simon    schedule 02.10.2012    source источник
comment
Как насчет вашего прогресса? Интересно, помог ли какой-либо из ответов с вашей проблемой?   -  person petrichor    schedule 05.10.2012


Ответы (4)


Решение, основанное на собственном разложении

Вы можете сначала вычислить PCA на X'X, как сказал @david. В частности, см. сценарий ниже:

sz = [329150 132];
X = rand(sz);

[V D] = eig(X.' * X);

На самом деле, V содержит правильные сингулярные векторы и основные векторы, если вы поместите свои векторы данных в строки. Собственные значения, D, представляют собой дисперсии между каждым направлением. Сингулярные векторы, которые являются стандартными отклонениями, вычисляются как квадратный корень из дисперсий:

S = sqrt(D);

Затем левые сингулярные векторы U вычисляются по формуле X = USV'. Обратите внимание, что U относится к основным компонентам, если ваши векторы данных находятся в столбцах.

U = X*V*S^(-1);

Восстановим исходную матрицу данных и увидим ошибку восстановления L2:

X2 = U*S*V';
L2ReconstructionError = norm(X(:)-X2(:))

Это почти ноль:

L2ReconstructionError =
  6.5143e-012

Если ваши векторы данных находятся в столбцах, и вы хотите преобразовать свои данные в коэффициенты собственного пространства, вы должны сделать U.'*X.

Этот фрагмент кода занимает около 3 секунд на моем умеренном 64-битном рабочем столе.

Решение на основе рандомизированного PCA

В качестве альтернативы вы можете использовать более быстрый приближенный метод, основанный на рандомизированном PCA. См. мой ответ в перекрестной проверке. Вы можете напрямую вычислить fsvd и получить U и V вместо использования eig.

Вы можете использовать рандомизированный PCA, если размер данных слишком велик. Но я думаю, что предыдущий способ достаточен для размера, который вы указали.

person petrichor    schedule 03.10.2012
comment
Просто для пояснения, разве это не должны быть единичные значения, которые являются стандартными отклонениями? - person Shadow; 17.10.2014

Я предполагаю, что у вас есть огромный набор данных. Вам не нужны все коэффициенты svd. В этом случае используйте svds вместо svd :

Взято непосредственно из справки Matlab:

 s = svds(A,k) computes the k largest singular values and associated singular vectors of matrix A.

Из вашего вопроса я понимаю, что вы не звоните svd напрямую. Но вы также можете взглянуть на princomp (его можно редактировать!) и изменить строку, которая его вызывает.

person Andrey Rubshtein    schedule 02.10.2012

Вероятно, вам нужно было каким-то образом вычислить матрицу n на n в своих вычислениях, то есть:

329150 * 329150 * 8btyes ~ 866GB`

пространства, что объясняет, почему вы получаете ошибку памяти. Кажется, существует эффективный способ вычисления PCA с использованием princomp(X, 'econ'), который я предлагаю вам попробовать.

Подробнее об этом в stackoverflow и mathworks..

person none    schedule 02.10.2012
comment
329150 — это количество точек данных. У меня матрица 1321 features. So basically I have to compute a 132 на 132`. - person Simon; 03.10.2012
comment
у вас не будет нехватки памяти с матрицей 132 by 132. см. это, это и это для расчета требуемой памяти для PCA. вы можете просто попробовать то, что я сказал, или просто провести подвыборку ваших данных. - person none; 03.10.2012

Вручную вычислить X'X (132x132) и свд на нем. Или найдите скрипт NIPALS.

person Tae-Sung Shin    schedule 03.10.2012