2

MATLAB の を使用して次元削減を試みていますprincompが、正しく行っているかどうかはわかりません。

テスト用のコードは次のとおりですが、投影を正しく行っているかどうかはわかりません。

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)

十分な数の主成分を選択すると、同等の認識率が得られます。少数の主成分(PCA) を使用すると、PCA を使用した率は低くなります。

ここにいくつかの質問があります:

  1. 関数は、MATLAB を使用して最初のk主成分をprincomp計算する最良の方法ですか?
  2. PCA 投影された機能と生の機能を使用しても、精度は向上しませんが、機能のベクトル サイズが小さくなるだけですか? (特徴ベクトルを比較する方が速い)。
  3. 生の特徴ベクトルと同じ精度を与える最小k (主成分の数) を自動的に選択する方法は?
  4. 非常に大きなサンプル セットがある場合、同等の精度でそれらのサブセットのみを使用できますか? または、あるセットで PCA を計算し、後で別のセットを「追加」できますか (set1 + set2 の pca を再計算したくありませんが、set2 の情報を set1 の既存の PCA に繰り返し追加します)。

また、次を使用して単純に GPU バージョンを試しましたgpuArray

%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 の使用エラー デバイスのメモリが不足しています。

4

1 に答える 1

1

「princomp 関数は、MATLAB を使用して最初の k 主成分を計算する最良の方法ですか?」

完全な SVD を計算しているため、大規模なデータセットでは遅くなります。最初に必要な次元数を指定し、部分的な svd を計算することで、これを大幅に高速化できます。部分的な svd の matlab 関数は次のとおりですsvds

svds の速度が十分でない場合は、より最新の実装がここにあります。

http://cims.nyu.edu/~tygert/software.html (matlab バージョン: http://code.google.com/p/framelet-mri/source/browse/pca.m )

(アルゴリズムについて説明している論文http://cims.nyu.edu/~tygert/blanczos.pdfを参照)

計算される特異ベクトルの数を増やすことで、近似の誤差を制御できます。リンクされた論文には正確な境界があります。次に例を示します。

>> A = rand(40,30); %random rank-30 matrix
>> [U,S,V] = pca(A,2); %compute a rank-2 approximation to A
>> norm(A-U*S*V',2)/norm(A,2) %relative error               

ans =

    0.1636

>> [U,S,V] = pca(A,25); %compute a rank-25 approximation to A
>> norm(A-U*S*V',2)/norm(A,2) %relative error                 

ans =

    0.0410

大きなデータとスパース行列がある場合、因子がスパースになることはないため、完全な SVD を計算することはしばしば不可能です。この場合、メモリ内に収まるように部分 SVD を計算する必要があります。例:

>> A = sprandn(5000,5000,10000);
>> tic;[U,S,V]=pca(A,2);toc;
no pivots
Elapsed time is 124.282113 seconds.
>> tic;[U,S,V]=svd(A);toc;   
??? Error using ==> svd
Use svds for sparse singular values and vectors.

>> tic;[U,S,V]=princomp(A);toc;
??? Error using ==> svd
Use svds for sparse singular values and vectors.

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

>> tic;pc=princomp(A);toc;     
??? Error using ==> eig
Use eigs for sparse eigenvalues and vectors.

Error in ==> princomp at 69
        [coeff,~] = eig(x0'*x0);
于 2013-07-07T21:34:43.340 に答える