定义
主成分分析是一种降维算法,它能将多个指标转换为少数几个主成分,这些主成分是原始变量的线性组合,且彼此之间互不相关,其能反映出原始数据的大部分信息。一般来说,当研究的问题涉及到多变量且变量之间存在很强的相关性时,我们可考虑使用主成分分析的方法来对数据进行简化。
数据降维的作用
降维是将高维度的数据(指标太多)保留下最重要的一些特征,去除噪声和不重要的特征,从而实现提升数据处理速度的目的。在实际的生产和应用中,降维在一定的信息损失范围内,可以为我们节省大量的时间和成本。降维也成为应用非常广泛的数据预处理方法。
降维具有如下一些优点:
1.使得数据集更易使用;
2.降低算法的计算开销;
3.去除噪声;
4.使得结果容易理解。
主成分分析的思想
假设有n个样本,p个指标,则可以构成大小为n*p的样本矩阵x:
假设我们相找到新的一组变量z1,z2…zm(m<=p),且他们满足:
PCA的计算步骤
假设有n个样本,p个指标,则可以构成大小为n*p的样本矩阵x:
1.我们首先对其进行标准化处理:
2.计算标准化样本的协方差矩阵:
3.计算R的特征值和特征向量:
4.计算主成分贡献率以及累计贡献率:
5.写出主成分:
6.根据系数分析主成分代表的意义:
对于某个主成分而言,指标前面的系数越大,代表该指标对于该主成分的影响越大。
7.利用主成分的结果进行后续的分析:
1.主成分得分千万别用于评价类模型。
2. 主成分可用于聚类分析。
3. 主成分可用于回归分析。
例题
1.计算关键变量:
2.写出主成分并简要分析:
第一主成分F1对所有(标准化)原始变量都有近似相等的正载荷(系数),故第一主成分为(身材)大小成分。
第二主成分F2在X3,X5,X6上有中等程度的正载荷,而在X1,X2,X4上有中等程度的负载荷,称第二主成分为形状成分(或胖瘦成分)。
第三主成分F3在X2上有大的正载荷,在X4上有大的负载荷,而在其余变量上的载荷都较小,可称第三成分为臂长成分。
注:由于第三成分的贡献度不高,且实际意义也不太重要,因此我们也可以考虑只取前两个主成分进行分析。
主成分分析的说明
在主成分分析中,我们首先应保证所提取的前几个主成分的累计贡献率达到一个较高的水平,其次对这些被提取的主成分必须都能够给出符合实际背景和意义的解释。主成分的解释其含义一般多少带有点模糊性,不像原始变量的含义那么清楚、确切,这是变量降维过程中不得不付出的代价。 因此,提取的主成分个数m通常应明显小于原始变量个数p(除非p本身较小),否则维数降低的“利”可能抵不过主成分含义不如原始变量清楚的“弊”。如果原始变量之间具有较高的相关性,则前面少数几个主成分的累计贡献率通常就能达到一个较高水平,也就是说,此时的累计贡献率通常较易得到满足。主成分分析的困难之处主要在于要能够给出主成分的较好解释,所提取的主成分中如有一个主成分解释不了,整个主成分分析也就失败了。主成分分析是变量降维的一种重要、常用的方法,简单的说,该方法要应用得成功,一是靠原始变量的合理选取,二是靠“运气“。
代码
[n,p] = size(x); % n是样本个数,p是指标个数
%% 第一步:对数据x标准化为X
X=zscore(x); % matlab内置的标准化函数(x-mean(x))/std(x)
%% 第二步:计算样本协方差矩阵
R = cov(X);
%% 注意:以上两步可合并为下面一步:直接计算样本相关系数矩阵
R = corrcoef(x);
disp('样本相关系数矩阵为:')
disp(R)
%% 第三步:计算R的特征值和特征向量
% 注意:R是半正定矩阵,所以其特征值不为负数
% R同时是对称矩阵,Matlab计算对称矩阵时,会将特征值按照从小到大排列哦
% eig函数的详解见第一讲层次分析法的视频
[V,D] = eig(R); % V 特征向量矩阵 D 特征值构成的对角矩阵
%% 第四步:计算主成分贡献率和累计贡献率
lambda = diag(D); % diag函数用于得到一个矩阵的主对角线元素值(返回的是列向量)
lambda = lambda(end:-1:1); % 因为lambda向量是从小大到排序的,我们将其调个头
contribution_rate = lambda / sum(lambda); % 计算贡献率
cum_contribution_rate = cumsum(lambda)/ sum(lambda); % 计算累计贡献率 cumsum是求累加值的函数
disp('特征值为:')
disp(lambda') % 转置为行向量,方便展示
disp('贡献率为:')
disp(contribution_rate')
disp('累计贡献率为:')
disp(cum_contribution_rate')
disp('与特征值对应的特征向量矩阵为:')
% 注意:这里的特征向量要和特征值一一对应,之前特征值相当于颠倒过来了,因此特征向量的各列需要颠倒过来
% rot90函数可以使一个矩阵逆时针旋转90度,然后再转置,就可以实现将矩阵的列颠倒的效果
V=rot90(V)';
disp(V)
%% 计算我们所需要的主成分的值
m =input('请输入需要保存的主成分的个数: ');
F = zeros(n,m); %初始化保存主成分的矩阵(每一列是一个主成分)
for i = 1:m
ai = V(:,i)'; % 将第i个特征向量取出,并转置为行向量
Ai = repmat(ai,n,1); % 将这个行向量重复n次,构成一个n*p的矩阵
F(:, i) = sum(Ai .* X, 2); % 注意,对标准化的数据求了权重后要计算每一行的和
end