本站原创文章,转载请说明来自《老饼讲解-机器学习》ml.bbbdata.com
本文讲解主成份分析PCA中主成份系数矩阵是怎么求解出来的,
并用代码实现及验证与sklearn包的结果是否一致
PCA中的主成份系数矩阵A是怎么求解出来的?本节我们先梳理PCA问题的数学表达
PCA的数学表达
PCA就是求一个旋转变换,使变换之后每维之间不相关
即要求一个标准正交矩阵A,使得XA列列之间的协方差为0,
也即XA的协方差矩阵是对角矩阵
总的来说,PCA的数学问题表达如下
👉求一标准正交矩阵A,使它满足
PCA问题的简化
由于
上述第1到第2个等号中是需要证明的,这里省略
也即PCA问题可以化简为
👉求一个标准正交矩阵A,使得
✍️备注
这是一个经典的矩阵对角化问题
由于是对称矩阵,所以必能找到一个标准正交矩阵A,
本节讲解求解PCA问题的两种求解方法:特征值法及SVD法
方法一:使用特征值求解PCA
PCA问题的求解其实就是矩阵对角化的问题,
数学上常用的方法是先求出的特征值,再求得对应的特征向量,
将特征向量标准化后组合在一起就是所需求解的、让 对角化的标准正交矩阵A
备注:将特征向量组合成A的时候需要根据特征值由大到小对应的特征向量进行组合
具体操作这里不再细说,矩阵对角化,懂的都懂
方法二.通过SVD分解求解PCA
实际中更常用的是通过SVD分解来求得A,
SVD分解是指将一个m*n的矩阵分解成三个矩阵的积,
其中U、V分别是m*m、n*n的酉矩阵,是对角矩阵
注意到
只需将进行SVD分解,即有
易知,当时就是对角矩阵
如下
PCA的求解过程总结如下
将进行SVD分解,得到
(1)V就是所求A
(2)就是
本节编写代码实现PCA的求解,
先调sklearn包求解,再自行写代码求解,并比较结果是否一致
调用sklearn包求解PCA
下面先通过sklearn包求解PCA中的A,代码如下
# -*- coding: utf-8 -*-
"""
主成份分析求解DEMO(调用sklearn)
本代码来自老饼讲解-机器学习:ml.bbbdata.com
"""
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
# 加载数据
iris = load_iris()
X = iris.data # 样本X
x_mean = X.mean(axis=0) # 样本的中心
# 用PCA对X进行主成份分析
clf = PCA() # 初始化PCA对象
clf.fit(X) # 对X进行主成份分析
# 打印结果
print('主成份系数矩阵A:\n A=',clf.components_)
print('主成份方差var:',clf.explained_variance_)
print('主成份贡献占比(方差占比)Pr:',clf.explained_variance_ratio_)
# 获取主成份数据
y = clf.transform(X) # 通过调用transform方法获取主成份数据
y2= (X-x_mean)@clf.components_.T # 通过调用公式计算主成份数据
运行结果如下
主成份系数矩阵A:
A= [[ 0.36138659 0.65658877 -0.58202985 -0.31548719]
[-0.08452251 0.73016143 0.59791083 0.3197231 ]
[ 0.85667061 -0.17337266 0.07623608 0.47983899]
[ 0.3582892 -0.07548102 0.54583143 -0.75365743]]
主成份方差var: [4.22824171 0.24267075 0.0782095 0.02383509]
主成份贡献占比(方差占比)Pr: [0.92461872 0.05306648 0.01710261 0.00521218]
自写代码求解PCA
不借助sklearn包,自行编写代码求解PCA的python代码如下
import numpy as np
from sklearn.datasets import load_iris
# 加载数据
iris = load_iris()
X = iris.data
x_mean = X.mean(axis=0) # 样本的中心
# 通过SVD分解,得到A与XA每列的方差var
U,S,VT = np.linalg.svd((X-x_mean)/np.sqrt(X.shape[0]-1)) # 注意,numpy的SVD分解出的是US(VT)
A = VT.T # 主成份系数矩阵A
var = S*S # 方差
pr = var/var.sum() # 方差占比
#打印结果
print('主成份系数矩阵A:\n A=',A)
print('主成份方差var:',var)
print('主成份贡献占比(方差占比)Pr:',pr)
# 获取主成份数据
y= (X-x_mean)@A # 通过调用公式计算主成份数据
运行结果如下
主成份系数矩阵A:
A= [[ 0.36138659 -0.65658877 0.58202985 0.31548719]
[-0.08452251 -0.73016143 -0.59791083 -0.3197231 ]
[ 0.85667061 0.17337266 -0.07623608 -0.47983899]
[ 0.3582892 0.07548102 -0.54583143 0.75365743]]
主成份方差var: [4.22824171 0.24267075 0.0782095 0.02383509]
主成份贡献占比(方差占比)Pr: [0.92461872 0.05306648 0.01710261 0.00521218]
可以看到,自行编写代码的结果与调用sklearn包是一致的
没错,PCA的求解就是这么简单,仅是进行一下SVD分解即可
End