不准确吗? R lang PCA用于特征脸

时间:2014-08-24 04:36:28

标签: r pca svd eigenvector

我的问题是:在有矩阵的情况下我们想要开启PCA,其中特征的数量大大超过试验次数,为什么prcomp没有按预期运行(或者我错过了什么)?< / p>

以下是该问题的摘要,full code is herecompressed 7MB data source is here(未解压缩55MB),target image is here

我的确切情况是我有一个矩阵p乘n矩阵X(p =特征,n =试验),其中试验是面部照片,特征是照片中的像素(所以32256乘148矩阵)。我想要做的是找到该矩阵的主成分得分向量。由于找到协方差矩阵XX ^ T太昂贵,一个简单的解决方案是找到X ^ TX的特征向量(v_i)并将它们转换为X(Xv_i)more info

XTX <- t(X) %*% X # missing the 1 / n - 1 for cov matrix b/c we normalize later anyway
eigen <- eigen(XTX)
eigenvectors.XTX.col <- eigen$vectors

principal.component.scores <- apply(eigenvectors.XTX.col, 2, function(c) {
  normalize.vector(X %*% matrix(c, ncol = 1))
})

在我的情况下,主成分得分是特征脸,可以用来成功重建目标面,如下所示:http://cl.ly/image/260w0N0u0Z3y(参考我的full code for how

将X传递给prcomp应该做同等的事情,但结果与上述本土方式不同:

pca <- prcomp(X)
pca$x # right size, but wrong pc scores

在重建面部时使用pca$x的结果不是完全废话,而是更糟糕:http://cl.ly/image/2p19360u2P43

我还检查过在prcomp上使用t(x)产生了一个不同的旋转矩阵,所以prcomp做了一些奇特的事情,但是引人注目的是一些神秘的东西。我从here知道prcomp正在使用SVD来计算主成分加载向量而不是特征分解,但这不应该导致任何错误(或者我认为......)。< / p>

使用内置prcomp方法的正确方法是什么,必须有一种方法,对吗?

1 个答案:

答案 0 :(得分:1)

哇,答案根本不是一个有趣的,而是与prcomp方法中的默认参数有关:

要解决这个问题,首先,我查看了the R source of prcomp并看到旋转矩阵应该等于svd(X)$v。在R命令行上检查这一点证明了我的X(data here)没有。这是因为即使存在默认参数scale = Fprcomp,prcomp仍会运行R scale方法,如果只是为了使矩阵居中,那么默认为True {{{ 3}}。在我的情况下,这是不好的,因为我传递了已经居中的数据(减去平均图像)。

因此,使用prcomp(X, center = F)重新运行将产生一个等于svd(X)$v的旋转矩阵。从现在开始,构造prcomp时唯一的“错误”prcomp(X, center = F)$x会导致不对列进行规范化,因此它们每个都只是来自principal.component.scores矩阵的标量倍数在我的代码中引用上面。如果没有标准化prcomp(X, center = F)$x,结果会更好,但不会很大,如下所示: here

但是在通过pca.x.norm <- apply(pca$x, 2, normalize.vector)进行标准化后,prcomp在重建面部时的结果是相同的: http://cl.ly/image/3u2y3m1h2S0o

tl; dr - prcomp意外地使用参数scale = F将数据居中,加上为了特征脸的目的,你需要规范化prcomp(X, center = F)$x的列,然后一切都会工作根据需要!