今天师妹突然问起PCA变换,只好硬着头皮用R语言演示了一下,不过对于做图像的来说,PCA变换用于图像上,所以似乎有点没有转过这个弯,今天也就好好的演示了一下,总的来说PCA变换实际上是一个用途很广的线性变换方法,它结构简单容易理解,另外对于大部分问题实际上也很有效,所以还是值得好好记录一下。
为什么要做PCA,我觉得这个问题问的没有什么意义,PCA变换最大的意义在于集中信息,另外一个重大的意义就是去相关,当然针对特定的应用还有不同的用法,不过主流的两个就是集中信息和去相关,对于这两个目标,我觉得还是很有必要强调一下去相关,这是因为很多时候我们没有考虑变量之间的相关性,而大多数时候变量之间存在相关,而不考虑相关性的情况下得到的结果可能存在问题因此变量去相关是很重要的处理步骤。下面介绍一下PCA变换的理论依据:
$x(x_1,x_2,x_3…x_n)$ x为样本,其中 $(x_1,x_2,x_3…x_n)$ 为样本的变量,实际上在求协防差矩阵的时候求的是变量的协防差矩阵,则:$\Sigma=E{(X-E[X])(X-E[X])^T}$,求出变量的协防差矩阵后求协防差矩阵的特征值和特征向量,特征值和特征向量的求法为:$\Sigma \vec{x}=\lambda \vec{v}$,其中 $\lambda$ 为特征值,$\vec{v}$ 为特征向量,实际上由于协防差矩阵为对阵矩阵,因此特征向量和特征值可以通过雅克比矩阵进行求解,最后得到最大特征值对应的特征向量为第一主成分,然后分别按照特征值大小排列得到各个主成分的投影方向。
最后为了直观的表示PCA变换,使用R语言编写了简单的PCA变换的代码如下:

matrix(rnorm(1000,0,1), ncol=2) -> data
##中心化,使每个属性的均值为0
for(i in c(1,2)){data[,i] <- data[,i] - mean(data[, i])}
##求协方差矩阵
cov(data) -> cov_data
##特征值
eigen(cov_data) -> e_cov_data
##主成分
data%*%e_cov_data$vectors -> res
plot(data,pch='*')

x <- 10.*e_cov_data$vectors[,1]
y <- c(0, 0)
points(rbind(x,y),type='l',col='red')
x <- 10.*e_cov_data$vectors[,2]
y <- c(0, 0)
points(rbind(x,y),type='l',col='green')
data%*%e_cov_data$vectors -> res
#plot(res,col='red')
e_cov_data$vectors

首先随机生成了一个二维正态分布的散点数据如图:

<img src =https://lh3.googleusercontent.com/-j2Zt67hpc54/WQnYRVMP-HI/AAAAAAAACM8/Y3T86NjSam8o52KfI_dvoaR-EJNYnkiXQCLcB/s0/pca.png “pca.png”>

其中散点为生成的散点图,然后对数据进行中心化变换,中心化则是将所有的数据减去均值,中心化后有助于减小数据的数量级,防止由于数据值过大而引起数据溢出,由此造成求解结果存在异常,中心化后求协防差矩阵,最后得到协防差矩阵的特征值和特征向量,特征向量为变换的投影方向,上图中红色和来绿色的直线分别表示两个主方向。
本身PCA变换的理论并没有什么难度,线性变换看作投也是很好理解的,但是PCA变换毕竟是经典的变换,可以用在各个方面,除了能够对信息进行集中之外,PCA变换还能够去相关,这个是很重要的一点需要注意,另外获取主方向也是很有用的一个点需要注意,另外做这一件事情也是为了锻炼自己使用R的熟练度,毕竟再linux下没有matlab这样进行统计的工具了,所以一切只能靠R了,对我来说把R使用的熟练一些应该是很有意义的一件事情吧,如果想要长期的再linux下学习和工作的话。