我试图用MATLAB'sprincomp
做维度降低,但我不确定我是否做得对。在MATLAB中使用princomp的PCA(用于人脸识别)
这里是我的只是用于测试的代码,但我不知道我在做正确的投影:
A = rand(4,3)
AMean = mean(A)
[n m] = size(A)
Ac = (A - repmat(AMean,[n 1]))
pc = princomp(A)
k = 2; %Number of first principal components
A_pca = Ac * pc(1:k,:)' %Not sure I'm doing projection right
reconstructedA = A_pca * pc(1:k,:)
error = reconstructedA- Ac
并采用ORL数据集我的面部识别码:
%load orl_data 400x768 double matrix (400 images 768 features)
%make labels
orl_label = [];
for i = 1:40
orl_label = [orl_label;ones(10,1)*i];
end
n = size(orl_data,1);
k = randperm(n);
s = round(0.25*n); %Take 25% for train
%Raw pixels
%Split on test and train sets
data_tr = orl_data(k(1:s),:);
label_tr = orl_label(k(1:s),:);
data_te = orl_data(k(s+1:end),:);
label_te = orl_label(k(s+1:end),:);
tic
[nn_ind, estimated_label] = EuclDistClassifier(data_tr,label_tr,data_te);
toc
rate = sum(estimated_label == label_te)/size(label_te,1)
%Using PCA
tic
pc = princomp(data_tr);
toc
mean_face = mean(data_tr);
pc_n = 100;
f_pc = pc(1:pc_n,:)';
data_pca_tr = (data_tr - repmat(mean_face, [s,1])) * f_pc;
data_pca_te = (data_te - repmat(mean_face, [n-s,1])) * f_pc;
tic
[nn_ind, estimated_label] = EuclDistClassifier(data_pca_tr,label_tr,data_pca_te);
toc
rate = sum(estimated_label == label_te)/size(label_te,1)
如果我选择了足够多的主要组件,它给了我相同的识别率。如果我使用少量的principal components(PCA),那么使用PCA的比率较差。
这里有一些问题:
- 是
princomp
功能利用MATLAB计算第一ķ主要成分的最佳方法是什么? - 使用PCA投影特征vs原始特征不提供额外的准确性,但只有更小的特征矢量大小? (比较特征向量更快)。
- 如何自动选择与原始特征向量相同精度的最小k(主要组件的数量)?
- 如果我有很大的一组样本,那么我可以只使用它们的子集,并且具有相当的精度?或者我可以在一些集合上计算PCA,然后“添加”一些其他集合(我不想重新计算set1 + set2的pca,但以某种方式迭代地将set2的信息添加到set1中的现有PCA)?
我也尝试使用简单的gpuArray
GPU版本:
%Test using GPU
tic
A_cpu = rand(30000,32*24);
A = gpuArray(A_cpu);
AMean = mean(A);
[n m] = size(A)
pc = princomp(A);
k = 100;
A_pca = (A - repmat(AMean,[n 1])) * pc(1:k,:)';
A_pca_cpu = gather(A_pca);
toc
clear;
tic
A = rand(30000,32*24);
AMean = mean(A);
[n m] = size(A)
pc = princomp(A);
k = 100;
A_pca = (A - repmat(AMean,[n 1])) * pc(1:k,:)';
toc
clear;
它工作得更快,但它不适合大矩阵。也许我错了?
如果我使用一个大的矩阵,它给了我:在设备上使用的内存gpuArray出
错误。
这些方法的内存消耗是多少? – mrgloom
对于MxN矩阵上的全SVD(即使用“princomp”或“svd”),您将需要存储稠密矩阵U和V,所以2 * M * N。当输入数据很大(并且因此存储在稀疏矩阵中)时,这是禁止的。使用svds或pca.m只需要存储k * max(M,N),其中k是您需要的维数。如果你的数据真的很大,你可以在Mahout中使用PCA实现(这只是我的答案中链接的论文的实现)https://builds.apache.org/job/Mahout-Quality/javadoc/org/apache /mahout/math/ssvd/SequentialOutOfCoreSvd.html – dranxo