我的问题是:在有矩阵的情况下我们想要开启PCA,其中特征的数量大大超过试验次数,为什么prcomp没有按预期运行(或者我错过了什么)?< / p>
以下是该问题的摘要,full code is here,compressed 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方法的正确方法是什么,必须有一种方法,对吗?
答案 0 :(得分:1)
哇,答案根本不是一个有趣的,而是与prcomp
方法中的默认参数有关:
要解决这个问题,首先,我查看了the R source of prcomp并看到旋转矩阵应该等于svd(X)$v
。在R命令行上检查这一点证明了我的X(data here)没有。这是因为即使存在默认参数scale = F
到prcomp
,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
的列,然后一切都会工作根据需要!