PCA,全称是Principal component analysis,中文叫做主成分分析,是一种常用的数据处理手段。
直观的说,PCA是一种降维的手法。比如现在我们有1000个数据点,每个数据点是一个128维的向量,存储上可以是一个1000×128维的数组。经过PCA处理,我们仍然得到1000个数据点,但是每个数据点是一个小于128维的向量,比如我们用PCA将128维的数据降到64维。
PCA可以保证,在降维之后,数据表示的信息损失最小。
“损失最小”具体怎么定义?
还是以1000个128维的点为例,这1000个点,也就是1000个向量在一个128维的空间中。从在任何一维,也就是一个方向上来看,如果在这个方向上,各个向量大小差异很大,那么这个方向是很重要的。
也就是,反过来看,如果在某个方向上,每一个向量大小都很接近,那么如果不考虑这个方向,也就是去掉这一维的数据,对我们分析这1000个点并没有多大的影响。所以,“损失最小”对应着“差异最小”。
那么具体怎么做呢?
这里是两种常用的方法: SVD分解和EIG分解(特征值分解)。
共同点在于先从数据得到一个矩阵M,M的特征值个数对应着数据的维度,特征值越大那么对应的这一维越重要,也就是“差异越大”。
SVD分解, matlab
sub_input_data = (input_data - repmat(mean(input_data),count,1))/sqrt(count-1);
[U,S,V] = svd(sub_input_data);
% First out_dim columns as PCA bases
pcaV = V(:,1:out_dim);
output_data = input_data * pcaV;
EIG分解, matlab
mean_input_data = mean(input_data);
sub_input_data = input_data - repmat(mean_input_data, count,1);
mean_mat = sub_input_data' * sub_input_data ./ (count - 1);
cov_mat = mean_mat;
[V D] = eig(cov_mat);
% Last out_dim columns as PCA bases
pcaV = V(:,in_dim - out_dim + 1: in_dim);
output_data = input_data * pcaV;
如果用C++的话,OpenCV本身就提供PCA,当然也可以自己实现。
OpenCV下可以用这个方法做EIG分解。
cv::eigen(covMat, eigenValues, eigenVectors);
具体Matlab代码也比较简单,放在Github上了。
MatlabPCA
原始数据:
PCA之后:
http://grapeot.me/post/2010/12/23/Computing-e58685e7a7afe79a84e58a9be9878f(2)-e28094e28094-e58685e7a7afefbc8ce58d8fe696b9e5b7aee5928cPCA.aspx
这个也许有用~
Cool, 解释的相当清楚,谢啦
你好,你用PCA处理过具体的数据没,我处理了一些三维坐标点(三维骨骼动画数据),维度只能降低 1/4 到 1/3 ,应该说效果一般
Hello,做图像分类的时候时常会用PCA把128维的SIFT降到64维。
我不太懂,三维的点不应该是只能降到两维或者一维吗?
是这样的,每个文件会有很多帧(行),每一帧有很多列(多个骨骼,每个骨骼有三个数据,分别为该骨骼的坐标点 x,y,z),列数就是维度,为了压缩数据 采用了降维
原来是因为有多个骨骼,如果PCA没办法降多少维的话说明所有骨骼都动的很厉害 XD