大家好,今天我们来讲讲主成分分析。主成分分析就是一种通过降维技术把多个原始变量重新组合成少数几个互不相关的主成分(综合变量)的统计方法。这些主成分能够反映原始变量的绝大部分信息,通常表示为原始变量的某种线性组合。
一、总体主成分
1.1 从协方差矩阵出发进行主成分分析
实例:设x=(x1,x2,x3)T为40个随机生成的三维数据,其中x1~N(0,4),x2~N(2,1),x3~N(1,10)。试对该数据做主成分分析,求出x的特征值、特征向量及主成分的贡献率。
用Python计算出协方差矩阵:
import numpy as np
#读取数据
random = np.loadtxt("D:/data/random.csv",delimiter = ",").T
# 计算协方差矩阵Covariance Matrix
cov_mat = np.cov(random)
print('协方差矩阵:\n', cov_mat)
结果输出:
协方差矩阵:
[[ 2.31472802 -0.01659731 -0.1117694 ]
[-0.01659731 0.99550289 0.10692141]
[-0.1117694 0.10692141 7.63116319]]
用Python计算本例特征值及特征向量:
# 计算特征值和特征向量
eig_val_cov, eig_vec_cov = np.linalg.eig(cov_mat)
print('特征值:', eig_val_cov)
print('特征向量:\n', eig_vec_cov)
结果输出:
特征值:[7.6352442 2.31253533 0.99361458]
特征向量:
[[ 0.02105023 -0.99971552 -0.01121415]
[-0.0161502 0.01087515 -0.99981043]
[-0.99964797 -0.02122735 0.01591668]]
从结果可得出,相应的主成分为:
y1=0.021*x1−0.016*x2−0.1000*x3
y2=−1.000*x1+0.011*x2−0.021*x3
y3=−0.011*x1−1.000*x2+0.016*x3
进一步用Python计算各主成分的贡献率及前m个主成分的累计贡献率:
# 计算贡献率
for i in range(0, len(eig_val_cov)):
contribution = eig_val_cov[i]/sum(eig_val_cov)
print('第{}主成分的贡献率:{}'.format(i+1,contribution))
# 计算累计贡献率
for i in range(1, len(eig_val_cov)):
accumulated_contribution = sum(eig_val_cov[:i])/sum(eig_val_cov)
print('前{}个主成分的累计贡献率:{}'.format(i, accumulated_contribution))
输出结果:
第1主成分的贡献率:0.6978310194227292
第2主成分的贡献率:0.2113565513772344
第3主成分的贡献率:0.0908124292000363
前1个主成分的累计贡献率:0.6978310194227292
前2个主成分的累计贡献率:0.9091875707999637
1.2 从相关矩阵出发进行主成分分析
常有两种情形不适合直接从协方差矩阵出发进行主成分分析:
一种是各变量的单位不全相同的情形;另一种是各变量的单位虽相同,但其变量方差的差异很大的情形。
对这两种情形,通常首先将原始变量进行标准化处理,然后从标准化变量(一般已无单位)的协方差矩阵出发求主成分。
用Python计算40个三维数据的相关矩阵:
import numpy as np
#读取数据
random = np.loadtxt("D:/data/random.csv",delimiter = ",").T
# 计算相关矩阵Correlation Matrix
cor_mat = np.corrcoef(random)
print('相关矩阵:\n', cor_mat)
结果输出:
相关矩阵:
[[ 1. -0.01093368 -0.02659363]
[-0.01093368 1. 0.03879252]
[-0.02659363 0.03879252 1. ]]
用Python计算特征值及特征向量:
# 计算特征值和特征向量
eig_val_cor, eig_vec_cor = np.linalg.eig(cor_mat)
print('特征值:', eig_val_cor)
print('特征向量:\n', eig_vec_cor)
结果输出:
特征值:[1.05254481 0.98988025 0.95757494]
特征向量:
[[-0.4594177 0.83233046 0.31009898]
[ 0.58744661 0.54659054 -0.59677908]
[ 0.66621458 0.09200427 0.74006307]]
从结果可得出,相应的主成分为:
![](https://i-blog.csdnimg.cn/blog_migrate/bed7635e12531eb630c08198166a2314.png)
进一步用Python计算各主成分的贡献率及前m个主成分的累计贡献率:
# 计算贡献率
for i in range(0, len(eig_val_cor)):
contribution = eig_val_cor[i]/sum(eig_val_cor)
print('第{}主成分的贡献率:{}'.format(i+1,contribution))
# 计算累计贡献率
for i in range(1, len(eig_val_cor)):
accumulated_contribution = sum(eig_val_cor[:i])/sum(eig_val_cor)
print('前{}个主成分的累计贡献率:{}'.format(i, accumulated_contribution))
结果输出:
第1主成分的贡献率:0.35084827032278515
第2主成分的贡献率:0.32996008411552574
第3主成分的贡献率:0.31919164556168905
前1个主成分的累计贡献率:0.35084827032278515
前2个主成分的累计贡献率:0.6808083544383109
比较从相关矩阵R出发求主成分与从协方差矩阵Σ出发求主成分的计算结果,可以发现,从R出发求得的主成分有y1*的贡献率与从Σ出发求得的主成分y1的贡献率存在明显差异。
二、样本主成分
在实际问题中,总体的协方差矩阵Σ和相关矩阵R都是未知的,需要通过样本来进行估计,此时求出的主成分称为样本主成分。
实例:在某中学的某年级随机抽取30名学生,测量其身高(x1)、体重(x2)、胸围(x3)和坐高(x4),其中前10名中学生的数据如下表所示。请对这30名中学生的身体4项指标数据做主成分分析。
![](https://i-blog.csdnimg.cn/blog_migrate/1ca274179354f0e71d5f0b75183ac039.png)
各变量的单位虽相同,但其变量方差的差异较大,即各变量数据间的数值大小相差大,所以这里从相关矩阵出发求样本主成分:
import numpy as np
# 读取数据
student = np.loadtxt('D:/data/student.csv', delimiter = ',',
skiprows = 1, usecols = (1,2,3,4))
# 计算相关矩阵Correlation Matrix
cor_mat = np.corrcoef(student.T)
print('相关矩阵:\n', cor_mat)
# 计算特征值和特征向量
eig_val_cor, eig_vec_cor = np.linalg.eig(cor_mat)
print('特征值:', eig_val_cor)
print('特征向量:\n', eig_vec_cor)
# 把特征值从大到小排序
eig = eig_val_cor[np.argsort(-eig_val_cor)]
print('排序后的特征值:\n', eig)
# 计算贡献率
for i in range(0, len(eig)):
contribution = eig[i]/sum(eig)
print('第{}主成分的贡献率:{}'.format(i+1,contribution))
# 计算累计贡献率
for i in range(1, len(eig)):
accumulated_contribution = sum(eig[:i])/sum(eig)
print('前{}个主成分的累计贡献率:{}'.format(i, accumulated_contribution))
输出结果:
相关矩阵:
[[1. 0.86316211 0.73211187 0.92046237]
[0.86316211 1. 0.89650582 0.88273132]
[0.73211187 0.89650582 1. 0.78288269]
[0.92046237 0.88273132 0.78288269 1. ]]
特征值:[3.541098 0.31338316 0.06610989 0.07940895]
特征向量:
[[ 0.49696605 0.54321279 0.50574706 -0.44962709]
[ 0.51457053 -0.2102455 -0.69084365 -0.46233003]
[ 0.48090067 -0.7246214 0.46148842 0.17517651]
[ 0.50692846 0.36829406 -0.2323433 0.74390834]]
排序后的特征值:
[3.541098 0.31338316 0.07940895 0.06610989]
第1主成分的贡献率:0.8852744992809177
第2主成分的贡献率:0.07834578938104812
第3主成分的贡献率:0.019852238408582423
第4主成分的贡献率:0.016527472929451805
前1个主成分的累计贡献率:0.8852744992809177
前2个主成分的累计贡献率:0.9636202886619658
前3个主成分的累计贡献率:0.9834725270705482
根据代码的结果可得到数据的特征值、特征向量及贡献率。
由计算结果可知,前两个主成分的累计贡献率已经达到96.4%,所以舍去后两个主成分可以达到降维的目的。前两个主成分分别为:
![](https://i-blog.csdnimg.cn/blog_migrate/4122a40099abbea78a589f8c021e449e.png)