2-2、PCA降维

版权声明:本文为博主原创文章,如需转载请联系博主。 https://blog.csdn.net/GregoryHanson/article/details/77943897

主成分分析法(Principal Component Analysis——PCA)

一、 方法引入

在数学建模中,经常会遇到研究多个变量的问题,而且在多数情况下,多个变量之间常常存在一定的相关性,比如在研究上海世界博览会的影响力评价时,就需要考虑多个评价变量。当变量个数较多且变量之间存在复杂关系时,会显著增加分析问题的复杂性。如果有一种方法可以将多个变量综合为少数几个代表性变量,使这些变量既能够代表原始变量的绝大多数信息又互不相关,那么这样的方法无疑有助于对问题的分析和建模。主成分分析法正是这样一种方法。(《Matlab在数学建模中的应用第二版》)

二、 实现步骤

有关PCA的理论推导或者数学原理的介绍,有兴趣的朋友可以在网上浏览相关文章。本文分享内容侧重于如果用PCA解决实际问题。
这里使用Matlab基于各个步骤进行讲解。

第一步:标准化矩阵

这里使用Z-score标准化方法对矩阵进行标准化处理。
可以直接使用Matlab中已经封装好的函数zscore()

第二步:计算相关系数矩阵

这里直接使用Matlab中的函数corrcoef()来进行处理,得到相关系数矩阵
记得输入的矩阵是标准化处理后的矩阵,而不是原始的样本矩阵。

第三步:计算特征向量和特征值

这里通过调用eig()函数来进行处理,得到特征向量矩阵和特征值矩阵。

第四步:计算贡献率

通过贡献率的定义来对贡献率进行求解。

Matlab本身已经有封装好了的princomp()函数和pcacov()函数来进行PCA求解。非常方便。但是我们也不妨自己写一写PCA的代码,更有助于对该方法的理解。

三、 步骤分析

(1)协方差矩阵:

假设有一个含有n个样本的集合,依次给出数理统计中的一些相关概念:

均值:

X¯¯¯=Σni=1Xin

标准差:
s=Σni=1(XiX¯¯¯)2n1

方差:
s2=Σni=1(XiX¯¯¯)2n1

既然已学过这么多描述数据之间关系的统计量,为什么我们还要用协方差来刻画他们的关系呢?我们应该注意到,标准差和方差一般是用来描述一维数据的,但现实生活我们常常遇到含有多维数据的数据集。最简单的大家上学时免不了要统计多个学科的考试成绩。面对这样的数据集,我们当然可以按照每一维独立的计算其方差,但是通常我们还想了解这几科成绩之间的关系,这时,我们就要用协方差。协方差是一种用来度量两个随机变量关系的统计量,其定义为:

cov(X,Y)=Σni=1(XiX¯¯¯YiY¯¯¯n1

从协方差的定义上我们也可以看出一些显而易见的性质,如:

cov(X,X)=var(X)
cov(X,Y)=cov(Y,X)
其中var(x)表示方差

需要注意的是,协方差也只能处理二维问题,那维数多了自然就需要计算多个协方差,比如n维的数据集就需要计算 n!(n2)!2 个协方差,那自然而然的我们会想到使用矩阵来组织这些数据。给出协方差矩阵的定义:

Cnn=(ci,j,ci,j=cov(Dimi,Dimj))

这个定义还是很容易理解的,我们可以举一个简单的三维的例子,假设数据集有 x,y,z 三个维度,则协方差矩阵为

C=cov(x,x)cov(y,x)cov(z,x)cov(x,y)cov(y,y)cov(z,y)cov(x,z)cov(y,z)cov(z,z)

可见,协方差矩阵是一个对称的矩阵,而且对角线是各个维度上的方差。

(2)协方差矩阵的求法:

协方差矩阵计算的是不同维度之间的协方差,而不是不同样本之间的。下面我们将在matlab中用一个例子进行详细说明:

首先,随机产生一个10*3维的整数矩阵作为样本集,10为样本的个数,3为样本的维数。

MySample = fix(rand(10,3)*50)

这里写图片描述

根据公式,计算协方差需要计算均值,那是按行计算均值还是按列呢,我一开始就老是困扰这个问题。前面我们也特别强调了,协方差矩阵是计算不同维度间的协方差,要时刻牢记这一点。样本矩阵的每行是一个样本,每列为一个维度,所以我们要按列计算均值。为了描述方便,我们先将三个维度的数据分别赋值:

dim1 = MySample(:,1);
dim2 = MySample(:,2);
dim3 = MySample(:,3);

计算dim1与dim2,dim1与dim3,dim2与dim3的协方差:

sum( (dim1-mean(dim1)) .* (dim2-mean(dim2)) ) / ( size(MySample,1)-1 ) % 得到  74.5333
sum( (dim1-mean(dim1)) .* (dim3-mean(dim3)) ) / ( size(MySample,1)-1 ) % 得到  -10.0889
sum( (dim2-mean(dim2)) .* (dim3-mean(dim3)) ) / ( size(MySample,1)-1 ) % 得到  -10***000

搞清楚了这个后面就容易多了,协方差矩阵的对角线就是各个维度上的方差,下面我们依次计算:

std(dim1)^2 % 得到   108.3222
std(dim2)^2 % 得到   260.6222
std(dim3)^2 % 得到  94.1778

这样,我们就得到了计算协方差矩阵所需要的所有数据,调用Matlab自带的cov函数进行验证:

cov(MySample)

这里写图片描述

可以看到跟我们计算的结果是一样的,说明我们的计算是正确的。但是通常我们不用这种方法,而是用下面简化的方法进行计算:

先让样本矩阵中心化,即每一维度减去该维度的均值,然后直接用新的到的样本矩阵乘上它的转置,然后除以(N-1)即可。其实这种方法也是由前面的公式通道而来,只不过理解起来不是很直观而已。大家可以自己写个小的矩阵看一下就明白了。其Matlab代码实现如下:

X = MySample – repmat(mean(MySample),10,1);    % 中心化样本矩阵
C = (X’*X)./(size(X,1)-1)

四、 基于Matlab的程序设计

这里借用《Matlab在数学建模中的应用第二版》一书中的例子

为了系统地分析某IT类企业的经济效益,选择了8个不同的利润指标,对15假企业进行了调研,并得到如表所示的数据。请根据这些数据对着15家企业进行综合实力排序。

这里写图片描述

代码:

clear
clc
List = [40.4 24.7 7.2 6.1 8.3 8.7 2.442 20;
        25 12.7 11.2 11 12.9 20.2 3.542 9.1;
        13.2 3.3 3.9 4.3 4.4 5.5 0.578 3.6;
        22.3 6.7 5.6 3.7 6 7.4 0.176 7.3;
        34.3 11.8 7.1 7.1 8 8.9 1.726 27.5;
        35.6 12.5 16.4 16.7 22.8 29.3 3.017 26.6;
        22 7.8 9.9 10.2 12.6 17.6 0.847 10.6;
        48.4 13.4 10.9 9.9 10.9 13.9 1.772 17.8;
        40.6 19.1 19.8 19 29.7 39.6 2.449 35.8;
        24.8 8 9.8 8.9 11.9 16.2 0.789 13.7;
        12.5 9.7 4.2 4.2 4.6 6.5 0.874 3.9;
        1.8 0.6 0.7 0.7 0.8 1.1 0.056 1;
        32.3 13.9 9.4 8.3 9.8 13.3 2.126 17.1;
        38.5 9.1 11.3 9.5 12.2 16.4 1.327 11.6;
        26.2 10.1 5.6 15.6 7.7 30.1 0.126 25.9];
%1:导入数据

a = size(List,1);
b = size(List,2);
%2:确认导入数矩阵的行数和列数

SA = zscore(List);
%3:调用zscore函数标准化处理矩阵

CM = corrcoef(SA);
%4:计算相关系数矩阵

[V, D] = eig(CM);
for j = 1:b
    DS(j,1) = D(b + 1 - j,b + 1 - j);
end
%5:计算特征值和特征向量,并按降序进行排序

for i = 1:b
    DS(i,2) = DS(i,1) / sum(DS(:,1));
    DS(i,3) = sum(DS(1:i,1)) / sum(DS(:,1));
end
%6:计算贡献率

T = 0.9;
for K = 1:b
    if DS(K,3) >=T
        Com_num = K;
        break;
    end
end
%7:确定主成分信息保留率T,并进行筛选

for j = 1:Com_num
    PV(:,j) = V(:,b + 1 - j);
end
%8:提取主成分对应的特征向量

new_score = SA * PV;
for i = 1:a
    total_score(i,2) = sum(new_score(i,:));
    total_score(i,2) = i;
end
result_report = sortrows([new_score,total_score],-4);
%9:计算各评价对象的主成分得分,并进行降序排序

disp('特征值及其贡献率、累计贡献率')
DS
disp('信息保留率T对应的主成分数与特征向量')
Com_num
PV
disp('主成分得分及排序(按第4列的总分进行降序排序,前3列为各主成分得分,第5列为企业编号)')
result_report
%10:输出并显示相关内容

当然也可以直接使用

[COEFF,SCORE,LATENT] = princomp(zscore(List));

来进行PCA分析

其中COEFF是X矩阵所对应的协方差阵V的所有特征向量组成的矩阵,即变换矩阵或称投影矩阵
SCORE是对主分的打分,也就是说原X矩阵在主成分空间的表示。
LATENT是协方差矩阵的特征值。

PCA使用也是比较普遍的,不仅仅是Matlab,类似R和SPSS都有封装好的函数直接进行PCA分析。

猜你喜欢

转载自blog.csdn.net/GregoryHanson/article/details/77943897
今日推荐