PCA(主分量分析)-转载

PCA--主成分分析

  通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分量,常用于高维数据的降维。可以用于特征提取。最常见的应用在人脸识别。

    把从混合信号中求出主分量(能量最大的成份)的方法称为主分量分析(PCA),而次分量(Minor Components,MCs)与主分量(Principal Components,PCs)相对,它是混合信号中能量最小的成分,被认为是不重要的或是噪声有关的信号,把确定次分量的方法称为次分量分析(MCA).

    PCA可以用于减少特征空间维数、确定变量的线性组合、选择最有用的变量、变量辨识、识别目标或是异常值分组等。主分量子空间提供了从高维数据到低维数据在均方误差意义下的数据压缩,它能最大程度地减少方差。

    由于PCA实际计算中只涉及到输入数据概率密度分布函数(Pdf)的二阶特性(协方差矩阵),所以解出的各主分量只互相正交(不相关),但并不满足相互独立。而且信号的大部分重要特征往往包含在Pdf的高阶统计特性中,所以只有多变量观测数据是由高斯分布的源信号构成,PCA方法才有效。

    非线性PCA(NLPCA)即将高阶累积量引入标准的PCA中,是由芬兰学者Karhunen和Oja首先提出并将其应用于ICA。它的可以完成对输入信号的盲分离。高阶累积量是以隐含的方式引入计算的,采用自适应迭代方法便于工程实现。标准的PCA基于信号的协方差矩阵仅能处理高斯信号,而NLPCA可以处理非高斯信号。

    PCA(Principal Component Analysis),即主成分分析,主要用于数据降维。
    对于一组样本的feature组成的多维向量,多维向量里的某些元素本身没有区分性,比如某个元素在所有的样本中都为1,或者与1差距不大,那么这个元素本身就没有区分性,用它做特征来区分,贡献会非常小。所以我们的目的是找那些变化大的元素,即方差大的那些维,而去除掉那些变化不大的维,从而使feature留下的都是最能代表此元素的“精品”,而且计算量也变小了。

     对于一个k维的feature来说,相当于它的每一维feature与其他维都是正交的(相当于在多维坐标系中,坐标轴都是垂直的),那么我们可以变化这些维的坐标系,从而使这个feature在某些维上方差大,而在某些维上方差很小。例如,一个45度倾斜的椭圆,在第一坐标系,如果按照x,y坐标来投影,这些点的x和y的属性很难用于区分他们,因为他们在x,y轴上坐标变化的方差都差不多,我们无法根据这个点的某个x属性来判断这个点是哪个,而如果将坐标轴旋转,以椭圆长轴为x轴,则椭圆在长轴上的分布比较长,方差大,而在短轴上的分布短,方差小,所以可以考虑只保留这些点的长轴属性,来区分椭圆上的点,这样,区分性比x,y轴的方法要好!

     所以我们的做法就是求得一个k维特征的投影矩阵,这个投影矩阵可以将feature从高维降到低维。投影矩阵也可以叫做变换矩阵。新的低维特征必须每个维都正交,特征向量都是正交的。通过求样本矩阵的协方差矩阵,然后求出协方差矩阵的特征向量,这些特征向量就可以构成这个投影矩阵了。特征向量的选择取决于协方差矩阵的特征值的大小。

     举一个例子:

     对于一个训练集,100个样本,feature是10维,那么它可以建立一个100*10的矩阵,作为样本。求这个样本的协方差矩阵,得到一个10*10的协方差矩阵,然后求出这个协方差矩阵的特征值和特征向量,应该有10个特征值和特征向量,我们根据特征值的大小,取前四个特征值所对应的特征向量,构成一个10*4的矩阵,这个矩阵就是我们要求的特征矩阵,100*10的样本矩阵乘以这个10*4的特征矩阵,就得到了一个100*4的新的降维之后的样本矩阵,每个样本的维数下降了。

     当给定一个测试的feature集之后,比如1*10维的feature,乘以上面得到的10*4的特征矩阵,便可以得到一个1*4的feature,用这个feature去分类。

     所以做PCA实际上是求得这个投影矩阵,用高维的特征乘以这个投影矩阵,便可以将高维特征的维数下降到指定的维数。

     在opencv里面有专门的函数,可以得到这个这个投影矩阵(特征矩阵)。

void cvCalcPCA( const CvArr* data, CvArr* avg, CvArr* eigenvalues, CvArr* eigenvectors, int flags );

     //简单使用 cvCalcPCA 计算主成分的代码如下:
            CvMat* pData = cvCreateMat(100, 2, CV_32FC1); //二维数据点
            for(int i = 0; i < 100; i++)
            {
                cvSet2D(pData, i, 0,cvRealScalar(i));
                cvSet2D(pData, i, 1,cvRealScalar(i));
            }

            CvMat* pMean = cvCreateMat(1, 2, CV_32FC1);
            CvMat* pEigVals = cvCreateMat(1, 2, CV_32FC1);
            CvMat* pEigVecs = cvCreateMat(2, 2, CV_32FC1);

            cvCalcPCA(pData, pMean, pEigVals, pEigVecs, CV_PCA_DATA_AS_ROW );

            float pp[100];
            memcpy(pp,pEigVals->data.fl,100 );
            memcpy(pp,pEigVecs->data.fl,100 );
            memcpy(pp,pMean->data.fl,100 );

 程序说明:y = pca(mixedsig),程序中mixedsig为 n*T 阶混合数据矩阵,n为信号个数,T为采样点数, y为 m*T 阶主分量矩阵。

程序设计步骤:

1、去均值

2、计算协方差矩阵及其特征值和特征向量

3、计算协方差矩阵的特征值大于阈值的个数

4、降序排列特征值

5、去掉较小的特征值

6、去掉较大的特征值(一般没有这一步)

7、合并选择的特征值

8、选择相应的特征值和特征向量

9、计算白化矩阵

10、提取主分量

function y = pca(mixedsig)

if nargin == 0

     error('You must supply the mixed data as input argument.');

end

if length(size(mixedsig))>2

     error('Input data can not have more than two dimensions. ');

end

if any(any(isnan(mixedsig)))

     error('Input data contains NaN''s.');

end

%——————————————去均值————————————

meanValue = mean(mixedsig')';

mixedsig = mixedsig - meanValue * ones(1,size(meanValue,2));

[Dim,NumofSampl] = size(mixedsig);

oldDimension = Dim;

fprintf('Number of signals: %d/n',Dim);

fprintf('Number of samples: %d/n',NumofSampl);

fprintf('Calculate PCA...');

firstEig = 1;

lastEig = Dim;

covarianceMatrix = cov(mixedsig',1);     %计算协方差矩阵

[E,D] = eig(covarianceMatrix);           %计算协方差矩阵的特征值和特征向量

%———计算协方差矩阵的特征值大于阈值的个数lastEig———

rankTolerance = 1e-5;

maxLastEig = sum(diag(D)) > rankTolerance;

lastEig = maxLastEig;

%——————————降序排列特征值——————————

eigenvalues = flipud(sort(diag(D)));

%—————————去掉较小的特征值——————————

if lastEig < oldDimension

     lowerLimitValue = (eigenvalues(lastEig) + eigenvalues(lastEig + 1))/2;

else

     lowerLimitValue = eigenvalues(oldDimension) - 1;

end

lowerColumns = diag(D) > lowerLimitValue;

%—————去掉较大的特征值(一般没有这一步)——————

if firstEig > 1

     higherLimitValue = (eigenvalues(firstEig - 1) + eigenvalues(firstEig))/2;

else

     higherLimitValue = eigenvalues(1) + 1;

end

higherColumns = diag(D) < higherLimitValue;

%—————————合并选择的特征值——————————

selectedColumns =lowerColumns & higherColumns;

%—————————输出处理的结果信息—————————

fprintf('Selected[ %d ] dimensions./n',sum(selectedColumns));

fprintf('Smallest remaining (non-zero) eigenvalue[ %g ]/n',eigenvalues(lastEig));

fprintf('Largest remaining (non-zero) eigenvalue[ %g ]/n',eigenvalues(firstEig));

fprintf('Sum of removed eigenvalue[ %g ]/n',sum(diag(D) .* (~selectedColumns)));

%———————选择相应的特征值和特征向量———————

E = selcol(E,selectedColumns);

D = selcol(selcol(D,selectedColumns)',selectedColumns);

%——————————计算白化矩阵———————————

whiteningMatrix = inv(sqrt(D)) * E';

dewhiteningMatrix = E * sqrt(D);

%——————————提取主分量————————————

y = whiteningMatrix * mixedsig;

%——————————行选择子程序———————————

function newMatrix = selcol(oldMatrix,maskVector)

if size(maskVector,1)~ = size(oldMatrix,2)

     error('The mask vector and matrix are of uncompatible size.');

end

numTaken = 0;

for i = 1:size(maskVector,1)

     if maskVector(i,1) == 1

         takingMask(1,numTaken + 1) == i;

         numTaken = numTaken + 1;

     end

end

newMatrix = oldMatrix(:,takingMask);

对图像表示和描述的思考:运用主分量进行描绘,使用主特征向量排列二维对象的概念在图像描述中起着重要的作用。图像的描述对于大小的变化、平移、旋转变化本应是尽可能独立的。使用对象的主轴校正能力为消除旋转变化的影响提供一种可靠的手段。特征值是沿着本征轴的方差,并可用于尺寸的归一化。平移带来的影响可以通过将对象的均值设定为中心来解决。

---------------------  
作者:wl_soft50  
来源:CSDN  
原文:https://blog.csdn.net/wl_soft50/article/details/6533937 

猜你喜欢

转载自www.cnblogs.com/ranchosevens/p/10658125.html