【问题标题】:Why does the first principal component show least difference in my PCA?为什么我的 PCA 中第一个主成分的差异最小?
【发布时间】:2016-02-15 18:25:14
【问题描述】:

我在 MatLab 中的一组面部图像上使用 PCA。 创建一张普通的脸并随机分配其他人脸效果很好。

在我的函数 vectorComparison 中,我想查看使用标准差时每个主成分向量的差异。但是当我使用 eig_face_index = 1 时,我看到的差异比使用 2 或 3 等时要小。

较高的索引似乎也增加了更多的颜色,这可能是由于特征面中的噪声,因为我使用的是 RGB 空间。

为什么我的初始向量显示的差异最小。不应该反过来吗?

这是我正在使用的所有代码:

main.m

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);

加载图像.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

平均值.m

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

协方差矩阵.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

findEigVecs.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

vectorComparison.m

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

【问题讨论】:

  • 你确定你有more observations than features in you data吗? IE。行多于列?否则这将永远无法工作,请参阅链接。
  • 我很确定我通过将 D 减少到 T 来解决这个问题,不是吗?因为链接的用户似乎内存不足,因为他的巨大向量需要进行多次计算。而且我可以打印图像,所以我实际上可以看到它在工作。但是,第一个主成分的差异似乎比第二个主成分的差异小,依此类推。它与 PCA 的含义相反。第一个主成分应该是包含最多数据的主成分,即比以下成分更多的差异。我只是不清楚为什么它似乎受到尊重。
  • 这不是问题的重点,也不是答案的重点。他的特征多于观察,因此 PCA 不起作用。那么你有多少特征,有多少观察?
  • 也许我在这里误解了所以请耐心等待。我有 17 张图片。这给了我 17 个特征向量,即 17 个特征,不是吗?其中 16 个向量可以描述 100% 的数据,因为最后一个的特征值非常接近于零。我猜我的观察结果是我的原始图像?在这种情况下意味着 17。可以可视化每个特征面。第一个看起来“应该”,最后一个主要是噪音。

标签: matlab image-processing pca eigenvector eigenvalue


【解决方案1】:

我发现这里出了什么问题。 在我的函数 findEigVals 中,我通过除以向量本身的 sum 使每个向量成为单位向量(长度为 1)。只要向量的内容确实范围为正条目,这是可能的。 但是,由于我们不知道我们是否有一个 pos 或 neg 方向的向量(两者都同样有效),所以我们不能在这里使用 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);

【讨论】:

    猜你喜欢
    • 2018-09-06
    • 1970-01-01
    • 1970-01-01
    • 2012-09-05
    • 1970-01-01
    • 2021-07-19
    • 2019-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多