Я пытаюсь уменьшить размерность, используя MATLAB'sprincomp
, но я не уверен, что делаю это правильно.PCA с использованием princomp в MATLAB (для распознавания лиц)
Вот мой код только для тестирования, но я не уверен, что я делаю проекционное право:
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 против сырых функций не дает дополнительной точности, но только меньшие возможности векторного размера? (быстрее сравнивать векторы признаков).
- Как автоматически выбрать min k (количество основных компонентов), которые дают такую же точность, что и исходный вектор функции?
- Что делать, если у меня есть очень большой набор образцов, я могу использовать только их подмножество с сопоставимой точностью? Или я могу вычислить PCA на каком-то множестве, а потом «добавить» другой набор (я не хочу перекомпилировать pca для set1 + set2, но каким-то образом итеративно добавить информацию из set2 в существующую PCA из set1)?
Я также попробовал версию 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 из памяти на устройстве.
Каково потребление памяти этими методами? – mrgloom
Для полного SVD на матрице MxN (т. Е. Используя «princomp» или «svd») вам нужно будет хранить плотные матрицы U и V, поэтому 2 * M * N. Это недопустимо, когда входные данные большие (и, следовательно, они хранятся в разреженной матрице). Использование svds или pca.m требует только сохранения k * max (M, N), где k - количество необходимых вам измерений. Если ваши данные действительно велики, вы можете использовать реализацию PCA в Mahout (это всего лишь реализация документа, связанного в моем ответе) https://builds.apache.org/job/Mahout-Quality/javadoc/org/apache /mahout/math/ssvd/SequentialOutOfCoreSvd.html – dranxo