PCA是一种能够通过提取数据主成分达到数据降维目的的无监督算法。

因为数据之间(如自然图像的像素值)间都是存在冗余的,通过PCA可以将维度为256降到一个较低的近似向量。

通过一个2D降到1D的例子来理解一下PCA的原理。假设有如下一堆二维数据,我们通过SVD奇异值变换可以找到,代表这堆数据的两个方向(特征向量的方向,为什么是特征向量,特征值呢?)

 

怎么进行SVD变换呢?我们先计算这堆数据的协方差矩阵如下:

数据变化的主方向就是sigma的主特征向量,次方向就是sigma的次特征向量。接下来我们计算旋转后的数据(也就是说把数据投影到以这两个特征方向为坐标轴的坐标平面内)

\begin{align}
x_{\rm rot} = U^Tx = \begin{bmatrix} u_1^Tx \\ u_2^Tx \end{bmatrix} 
\end{align}

如图:

PCA-rotated.png

 

当我们只选取前面的k个主特征向量时,我们转换后就得到的是数据的主成分。PCA就是这样达到数据降维的。这里k=1,即选取主特征向量,得到数据的近似表示如下:、

PCA-xhat.png

 

一般我们根据近似误差的要求来选取k。\textstyle \lambda_1, \lambda_2, \ldots, \lambda_n代表sigma协方差矩阵的特征值,一般地选择k保留百分之90的方差:

\begin{align}
\frac{\sum_{j=1}^k \lambda_j}{\sum_{j=1}^n \lambda_j} \geq 0.99. 
\end{align}

 

PCA经常和白化一起对图像进行预处理。PCA消除了输入特征间相关性。而白化之前要求的特征之间的低相关性要求正好就满足了。通过白化可以降低数据之间的冗余性。为了使得输入特征具有单位方差,我们利用\textstyle 1/\sqrt{\lambda_i}作为缩放因子对\textstyle x_{{\rm rot},i}进行缩放。得到:

\begin{align}
x_{{\rm PCAwhite},i} = \frac{x_{{\rm rot},i} }{\sqrt{\lambda_i}}.   
\end{align}在实际中,我们往往给分母加入一个常量。

\begin{align}
x_{{\rm PCAwhite},i} = \frac{x_{{\rm rot},i} }{\sqrt{\lambda_i + \epsilon}}.
\end{align}

 

 

本文参照斯坦福UFLDL教程。http://deeplearning.stanford.edu/wiki/index.php/Exercise:PCA_in_2D

在matlab上实现这个例子代码如下:

close all
%%===============================================================
%%step0:Load data
% x is a 2*45 matrix,where the kth column x(:,k) corresponds to the
% kth data point.Here we provide the code to load natural image into x.
% You do not need to change the code below.

x = load('pcaData.txt','-ascii');
figure(1);
scatter(x(1,:),x(2,:));
title('Raw data');

%%=====================================================================
%step1a:Implement PCA to obtain U


u = zeros(size(x,1));%you need to campute this
[n m] = size(x);
x=x-repmat(mean(x,2),1,m);%预处理,均值为0
sigma = (1.0/m)*x*x'
[u s v]=svd(sigma);%svd函数其实计算的是矩阵的奇异值和奇异矩阵,但就半正定矩阵来说,它们对应于特征值和特征向量,
%那么矩阵U将包含sigma的特征向量(一个向量一列,从主向量开始排序),矩阵S对角线上的元素包含对应的特征值。矩阵V等于U的转制

hold on
plot([0 u(1,1)],[0 u(2,1)])%画第一条线
plot([0 u(1,2)],[0 u(2,2)])%画第二条线

%====================================================================
%step1b:compute xRot,the projection on to the eigenbasis
%Now,compute xRot by projecting the data on to the basis defined by
%U.Visualize the points by performing a scatter plot.

xRot = zeros(size(x));
xRot =u'*x;

%Visualize the covariance matrix.You should see a line across the diagonal
%against a blue backgroud.

figure(2);
scatter(xRot(1,:),xRot(2,:));
title('xRot');


%%=============================================================================
%step2;Reduce the number of dimensions from 2 to 1.
%Compute xRot again (this time project to 1 dimension)
%then,compute xHat by projecting the xRot back onto the original axes to
%see the effect of dimension reduction

k=1;%Use k=1 and project the data onto the first eigenbasis
xHat= zeros(size(x));
xHat = u*([u(:,1),zeros(n,1)]'*x);

figure(3);
scatter(xHat(1,:),xHat(2,:));
title('xHat');

%%===========================================================================
%step3:PCA Whitening
%compute xPCAWhite and plot the results.

epsilon = 1e-5;
xPCAWhite = zeros(size(x));
xPCAWhite = diag(1./sqrt(diag(s)+epsilon))*u'*x;

figure(4);
scatter(xPCAWhite(1,:),xPCAWhite(2,:));
title('xPCAWhite');

%%===========================================================================
%step3:ZCA Whitening
%Compute xZCAWhite and plot the results

xZCAWhite = zeros(size(x));
xZCAWhite = u*diag(1./sqrt(diag(s)+epsilon))*u'*x;

%-------------------------------------
figure(5);
scatter(xZCAWhite(1,:),xZCAWhite(2,:));
title('xZCAWhite');

 

posted on 2013-04-29 10:27  ahujack  阅读(1012)  评论(0编辑  收藏  举报