Почему первый главный компонент показывает наименьшую разницу в моем PCA?

Я использую PCA для набора изображений лица в MatLab. Создание среднего лица и рандомизация других работают нормально.

В моей функции vectorComparison я хочу увидеть разницу в каждом векторе основного компонента при использовании стандартного отклонения. Но когда я использую eig_face_index = 1, я вижу меньше разницы, чем когда я использую 2 или 3 и т. д.

Кажется, что более высокие индексы также добавляют больше цвета, что может быть связано с шумом в собственных гранях, поскольку я использую пространство RGB.

Почему мой исходный вектор показывает наименьшую разницу. Разве не должно быть наоборот?

Вот весь код, который я использую:

основной.м

clear;clc;close all;
[imvecs,img] = loadImages();
meanval = meanValue(imvecs);
[T, D] = covarianceMatrix(imvecs, meanval);
[eigvecs, eigvals] = findEigVecs(imvecs, T, D);
eigenfaces = createEigenFaces(eigvecs, imvecs, img); 

%%
[mean_image] = createAverageFace(meanval, img);
%%
[stdev_vec] = createRandomFace(eigvals, eigvecs, imvecs, meanval, img);
%%
vectorComparison(meanval, eigvecs, stdev_vec, img, mean_image);

loadImages.m

function [imvecs,img] = loadImages()
images = dir('D:My\Path\*.png');  
imgPath = 'D:My\Path\';
img=imread([imgPath images(1).name]);
n=length(images);

for i = 1:n
    img = imread([imgPath images(i).name]);
    imvecs{i} = double(img(:));
end
return

среднее значение.м

function meanval = meanValue(imvecs, imageNr)
    %Creates the mean value from our images.
    sumvec=imvecs{1};

    for i = 2:(size(imvecs,2))
        sumvec = sumvec + imvecs{i};
    end
    meanval = sumvec ./(size(imvecs,2));
return

covarianceMatrix.m

function [T, D] = covarianceMatrix(imvecs, meanval)
    D = [];
    for i = 1:size(imvecs,2),
       diff = imvecs{i} - meanval;
       D = [D, diff];
    end
    %Dimensionality reduction
    T = (D' * D) ./ (size(imvecs,2));
return

найтиEigVecs.m

function [eigvecs, eigvals] = findEigVecs(imvecs, T, D)
    [U,eigvals,V] = svd( T );
    eigvecs = [];
    for i = 1:size(imvecs,2),
        eigvec = D * U(:,i);
        eigvec = eigvec ./ sum(eigvec);
        eigvecs = [eigvecs, eigvec];
    end
return

createEigenFaces.m

function [eigenfaces] = createEigenFaces(eigvecs, imvecs, img)
    for i = 1:size(imvecs,2),
        eigface =  reshape(eigvecs( : , i), size(img));
        eigface = eigface - min(min(min((eigface))));
        eigface = eigface ./ max(max(max((eigface))));
        eigenfaces{i}=eigface;
        %figure;imagesc(eigface);
    end
return

createAverageFace.m

function [mean_image] = createAverageFace(meanval, img)
    mean_image = reshape(meanval, size(img));
    figure;imagesc(mean_image./255);
    title('Average Face')
return

createRandomFace.m

function [stdev_vec] = createRandomFace(eigvals, eigvecs, imvecs, meanval, img)
    stdev_vec = sqrt(diag(eigvals));
    t = (100 * rand(size(imvecs,2),1) - 50) .* stdev_vec;
    new_face1 = meanval + (eigvecs * t);
    new_face1 = reshape(new_face1, size(img));

    figure;imagesc(new_face1./255);
    title('Random Face')
return

векторСравнение.м

function [] = vectorComparison(meanval, eigvecs, stdev_vec, img, mean_image)
    t = zeros(17,1);
    eig_face_index = 1;
    t(eig_face_index) = 1000;
    t = t.*stdev_vec;

    new_face1 = meanval + (eigvecs * t);
    new_face1 = reshape(new_face1, size(img));

    new_face2 = meanval - (eigvecs * t);
    new_face2 = reshape(new_face2, size(img));

    figure;
    title('PCA Comparison')
    subplot(3,1,1), subimage(new_face1./255)
    subplot(3,1,2), subimage(mean_image./255)
    subplot(3,1,3), subimage(new_face2./255)
return

person RKrogh    schedule 15.02.2016    source источник
comment
Я почти уверен, что обошёл это, уменьшив D до T, не так ли? Потому что у пользователя ссылки, похоже, не хватает памяти из-за его огромных векторов, требующих многих вычислений. И я могу распечатать изображения, так что я действительно вижу, как это работает. Однако разница в первом главном компоненте, по-видимому, меньше, чем во втором и так далее. Это противоположно тому, о чем PCA. Первый главный компонент должен содержать больше всего данных, т. е. больше различий из-за дисперсии, чем последующие компоненты. Мне просто непонятно, почему это кажется измененным.   -  person RKrogh    schedule 16.02.2016
comment
Суть вопроса и ответа не в этом. У него больше возможностей, чем наблюдений, поэтому ППШ не работает. Итак, сколько функций у вас есть и сколько наблюдений?   -  person Adriaan    schedule 16.02.2016
comment
Может быть, я неправильно понял здесь, так что терпите меня. У меня есть 17 изображений. Это дает мне 17 собственных векторов, то есть 17 признаков, не так ли? Где 16 векторов могут описать 100% моих данных, поскольку собственное значение последнего из них так близко к нулю. И я предполагаю, что мои наблюдения являются моими оригинальными изображениями? В данном случае это 17. Можно визуализировать каждую собственную грань. Первый выглядит так, как должен, а последний в основном шум.   -  person RKrogh    schedule 16.02.2016


Ответы (1)


Я нашел, что здесь не так. В моей функции findEigVals я делаю каждый вектор единичным вектором (длиной 1) путем деления на сумму самого вектора. Это возможно, если содержимое вектора находится в диапазоне положительных записей. Однако, поскольку мы не можем знать, есть ли у нас вектор в положительном или отрицательном направлении (оба одинаково допустимы), мы не можем использовать здесь sum.

Вместо этого нам нужно заменить это на norm, способ Matlab заявить нормализацию.

function [eigvecs, eigvals] = findEigVecs(imvecs, T, D)
    [U,eigvals,V] = svd( T );
    eigvecs = [];
    for i = 1:size(imvecs,2),
        eigvec = D * U(:,i);
        eigvec = eigvec ./ norm(eigvec);
        eigvecs = [eigvecs, eigvec];
    end
return

Если кто-то использует версию кода выше, обратите внимание, что функция случайного лица будет давать слишком сильные значения в rgb-пространстве. Замените createRandomFace следующим:

stdev_vec = sqrt(diag(eigvals));
min_range = 0;
max_range = 2;
t = ((max_range - min_range)*rand(n,1)) .* stdev_vec + min_range;
new_face1 = meanval + (eigvecs * t);
new_face1 = reshape(new_face1, size(img));

figure;imagesc(new_face1./255);
person RKrogh    schedule 29.02.2016