您发布的教程的第 13-20 页提供了关于 PCA 如何用于降维的非常直观的几何解释。
您提到的 13x13 矩阵可能是“加载”或“旋转”矩阵(我猜您的原始数据有 13 个变量?)可以用两种(等效)方式之一解释:
加载矩阵的(的绝对值)列描述了每个变量按比例“贡献”到每个组件的程度。
旋转矩阵将您的数据旋转到旋转矩阵定义的基础上。因此,如果您有二维数据并将数据乘以旋转矩阵,则新的 X 轴将是第一个主成分,新的 Y 轴将是第二个主成分。
编辑:这个问题被问了很多,所以我只想对我们使用 PCA 进行降维时发生的情况进行详细的视觉解释。
考虑从 y=x + 噪声生成的 50 个点的样本。第一个主成分将位于 y=x 线上,第二个主成分将位于 y=-x 线,如下所示。
纵横比有点搞砸了,但相信我的话,组件是正交的。应用 PCA 将旋转我们的数据,使组件成为 x 和 y 轴:
变换前的数据为圆形,变换后的数据为十字。在这个特定的例子中,数据并没有被旋转太多,而是在 y=-2x 线上翻转,但是我们可以很容易地反转 y 轴以使其真正成为旋转而不失一般性,如此处所述.
大部分方差,即数据中的信息,沿着第一个主成分(在我们转换数据后由 x 轴表示)传播。第二个分量(现在是 y 轴)有一点点变化,但我们可以完全删除这个分量而不会丢失大量信息。因此,为了将其从二维折叠为 1,我们让数据投影到第一个主成分上完全描述了我们的数据。
我们可以通过将原始数据旋转(好的,投影)回原始轴来部分恢复原始数据。
深蓝色点是“恢复”数据,而空点是原始数据。如您所见,我们丢失了原始数据中的一些信息,特别是第二主成分方向的方差。但出于许多目的,这种压缩描述(使用沿第一主成分的投影)可能适合我们的需要。
这是我用来生成此示例的代码,以防您想自己复制它。如果减少第二行中噪声分量的方差,PCA 变换丢失的数据量也会减少,因为数据将收敛到第一个主分量上:
set.seed(123)
y2 = x + rnorm(n,0,.2)
mydata = cbind(x,y2)
m2 = colMeans(mydata)
p2 = prcomp(mydata, center=F, scale=F)
reduced2= cbind(p2$x[,1], rep(0, nrow(p2$x)))
recovered = reduced2 %*% p2$rotation
plot(mydata, xlim=c(-1.5,1.5), ylim=c(-1.5,1.5), main='Data with principal component vectors')
arrows(x0=m2[1], y0=m2[2]
,x1=m2[1]+abs(p2$rotation[1,1])
,y1=m2[2]+abs(p2$rotation[2,1])
, col='red')
arrows(x0=m2[1], y0=m2[2]
,x1=m2[1]+p2$rotation[1,2]
,y1=m2[2]+p2$rotation[2,2]
, col='blue')
plot(mydata, xlim=c(-1.5,1.5), ylim=c(-1.5,1.5), main='Data after PCA transformation')
points(p2$x, col='black', pch=3)
arrows(x0=m2[1], y0=m2[2]
,x1=m2[1]+abs(p2$rotation[1,1])
,y1=m2[2]+abs(p2$rotation[2,1])
, col='red')
arrows(x0=m2[1], y0=m2[2]
,x1=m2[1]+p2$rotation[1,2]
,y1=m2[2]+p2$rotation[2,2]
, col='blue')
arrows(x0=mean(p2$x[,1])
,y0=0
,x1=mean(p2$x[,1])
,y1=1
,col='blue'
)
arrows(x0=mean(p2$x[,1])
,y0=0
,x1=-1.5
,y1=0
,col='red'
)
lines(x=c(-1,1), y=c(2,-2), lty=2)
plot(p2$x, xlim=c(-1.5,1.5), ylim=c(-1.5,1.5), main='PCA dimensionality reduction')
points(reduced2, pch=20, col="blue")
for(i in 1:n){
lines(rbind(reduced2[i,], p2$x[i,]), col='blue')
}
plot(mydata, xlim=c(-1.5,1.5), ylim=c(-1.5,1.5), main='Lossy data recovery after PCA transformation')
arrows(x0=m2[1], y0=m2[2]
,x1=m2[1]+abs(p2$rotation[1,1])
,y1=m2[2]+abs(p2$rotation[2,1])
, col='red')
arrows(x0=m2[1], y0=m2[2]
,x1=m2[1]+p2$rotation[1,2]
,y1=m2[2]+p2$rotation[2,2]
, col='blue')
for(i in 1:n){
lines(rbind(recovered[i,], mydata[i,]), col='blue')
}
points(recovered, col='blue', pch=20)