我想对大量数据点进行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
但是,如果我使用较小的数据集,我没有问题。
如何在Matlab中对我的整个数据集执行PCA?有人遇到过这个问题吗?
修改:
我修改了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
答案 0 :(得分:5)
基于特征分解的解决方案
你可以先在X'X
上计算PCA,如@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
。
此代码段在我的中等64位桌面上大约需要3秒钟。
基于随机PCA的解决方案
或者,您可以使用基于随机PCA的更快速的近似方法。请参阅my answer in Cross Validated。您可以直接计算fsvd
并获取U
和V
,而不是使用eig
。
如果数据量太大,您可以使用随机PCA。但是,我认为前面的方式对于你给出的大小就足够了。
答案 1 :(得分:1)
我的猜测是你拥有庞大的数据集。您不需要所有的svd系数。在这种情况下,请使用svds
代替svd
:
直接从Matlab帮助:
s = svds(A,k) computes the k largest singular values and associated singular vectors of matrix A.
根据您的问题,我们了解到您不直接致电svd
。但你也可以看看princomp
(它是可编辑的!)并改变调用它的行。
答案 2 :(得分:0)
您可能需要在计算中以某种方式计算 n by n 矩阵,即:
329150 * 329150 * 8btyes ~ 866GB`
空间解释了为什么会出现内存错误。似乎有一种使用princomp(X, 'econ')
计算pca的有效方法,我建议你试一试。
有关stackoverflow和mathworks ..
的详情答案 3 :(得分:0)
手动计算X'X(132x132)和svd。或者找到NIPALS脚本。