PCA algorithm(Principal Components Analysis Algorithm)主成分分析算法适用于当样本中包含多个变量而变量之间强耦合时,将强耦合的变量综合成一个或几个变量,这样减少了样本的维度,以节约计算资源以及减少过拟合。
1. 关于PCA algorithm
这个PCA algorithm的原理就是用较少的变量来表示原来较多的变量,所以这些较少的变量里面蕴含了和自己相关性高的变量的信息,以达到降维的目的。
那么,如何将几个相关度高的变量综合成一个变量呢?思路是用其他几个变量来表示这个变量。如何表示?用相关系数矩阵,那么到底是协方差矩阵还是Pearson相关系数矩阵呢?我个人理解都可以。因为PCA第一步会将数据进行标准差标准化,数据进行标准差标准化的公式是:
进行标准差标准化之后的数据,它们的协方差矩阵和Pearson相关系数矩阵是相同的。这是因为,我们来看一下协方差阵和Pearson相关系数阵的公式:
协方差阵:
Pearson相关系数矩阵:
可以发现,标准差标准化后的变量求标准差为1,所以进行标准差标准化之后的数据,它们的协方差矩阵和Pearson相关系数矩阵是相同的。
第二步是求它们的协方差矩阵,用来表示变量之间的关系,协方差阵的公式上面已经给出了。
第三步是求解协方差阵的特征向量和特征值,为什么呢?我们来看:
假设矩阵是X(维度n*m),协方差矩阵是C(m*m),对X进行投影变换,我们直接用协方差阵合适吗?
这是不合适的。因为这个协方差中的每一列并不是相互正交的,也就是说,首先原来的数据经过变换以后首先维度没下降,其次变换后的数据每一列并不相互独立,其间有着千丝万缕的关系,所以要怎么做?一个,让这个协方差阵C每一列变得正交;另一个,减少它的列数。那么同时综合了多个变量信息为少个,并且信息间相互独立没有冗余。怎么达到?求特征向量和特征值。咱么求特征值是为了看每一个特征向量对于这次数据综合的贡献有多大,求特征向量是为了让数据列之间相互独立,如果不是独立的,那数据信息杂糅在一起,那就等于没有综合啊,我们是要让几个变量综合成一个,再让几个综合成一个。。。到这一步我们做到了让投影矩阵正交,即是协方差阵的特征向量,下一步我们要减少特征向量构成的阵的列数。
第四步,我们根据每个特征向量的贡献度,来选择需要降低的维度。每个特征向量的贡献度,可以根据它的特征值来进行衡量。在特征空间中,特征值大小可以用速度来比喻,而特征向量可以用方向来比喻。我们有以下公式来衡量贡献度,
将所有特征值和特征向量按照贡献度从高到低排列,从中选取贡献度高的,根据需求选择前K个特征值和对应的特征向量(特征向量是按列取的,前K列)。由选择的特征向量构成映射矩阵P。(需求一般可以是90%,95%等等都可以,贡献度满足需求就是选择特的征向量的贡献度总和满足需求)
第五步,根据映射矩阵将原数据矩阵降维。
以上就是PCA algorithm运行的过程。
2. PCA algorithm案例
导入MATLAB内部数据'hald',对它进行降维,贡献率选择90%。
新建m-file,取名pca_algo.m,内容如下:
--------------------------------------------------------------------------------------------------
% 任务目标:实现pca主成分分析,选取rate内的成分,根据贡献率进行矩阵降维
% 输入:原矩阵mat,一列是一个变量;贡献率rate,0-1
% 输出:进行主成分分析后的矩阵mat_ret
function mat_ret = pca_algo(mat,rate)
% 数据标准化 采用标准差标准化即z-score标准化
normlized_mat = zscore(mat);
% 求协方差矩阵
cov_mat = cov(normlized_mat);
% 求协方差阵特征值和特征向量,使用svd奇异值分解,[u,s,v],u是特征向量,列为一组
% s是对角阵,存储特征值
[feature_vector,eigenvalues,~] = svd(cov_mat);
eigenvalues = diag(eigenvalues);
% 根据贡献率选择特征向量个数num_vec rate_contribute存储贡献率 P为选择的特征向量
sum_eigenvalues = eval('sum(eigenvalues)');
rate_contribute = eigenvalues/sum_eigenvalues;
lin = size(rate_contribute,1);
sum = 0;
for i = 1:lin,
sum = sum + rate_contribute(i);
if sum > rate,
break;
end
end
num_vec = i;
P = feature_vector(:,1:num_vec);
% 根据特征向量进行映射得到变换后的矩阵 X*P
mat_ret = mat*P;
end
----------------------------------------------------------------------------------------------------------------
运行测试代码,新建m-file,取名pca_algo_test.m,内容:
----------------------------------------------------------------------------------------------------------------
% 导入matlab内部数据
load hald
mat = ingredients;
% 测试自己的pca函数
mat_ret = pca_algo(mat,0.9)
----------------------------------------------------------------------------------------------------------------
原始数据:
降维后的数据:
注意,以上接口是用svd(),奇异值分解来求解特征值和特征向量的,求出来的结果是按照降序自动排列好,如果读者要看每个成分的贡献度和主成分是哪些,则自行改成eig()函数,并加以修改接口输出每个成分的贡献度,人性化地输出主要成分和对应贡献度,以及我们的选择。参考前面几篇博客的输出方法易实现。
PS: 此博文允许任何人转载。