第五课:模型补充
PCA主成分分析
【代码】PCA的求解及代码
作者 : 老饼 日期 : 2022-12-08 18:33:29 更新 : 2022-12-10 15:30:59
本站原创文章,转载请说明来自《老饼讲解-机器学习》ml.bbbdata.com



本文讲解主成份分析PCA中主成份系数矩阵是怎么求解出来的,

并用代码实现及验证与sklearn包的结果是否一致




    01.主成份PCA问题的数学表述    



 PCA中的主成份系数矩阵A是怎么求解出来的?本节我们先梳理PCA问题的数学表达



    PCA的数学表达   


PCA就是求一个旋转变换,使变换之后每维之间不相关
即要求一个标准正交矩阵A,使得XA列列之间的协方差为0,
也即XA的协方差矩阵是对角矩阵

  总的来说,PCA的数学问题表达如下
 👉求一标准正交矩阵A,使它满足    



     PCA问题的简化   


 由于
  
上述第1到第2个等号中是需要证明的,这里省略
  
  也即PCA问题可以化简为
 👉求一个标准正交矩阵A,使得
✍️备注
  这是一个经典的矩阵对角化问题
由于
是对称矩阵,所以必能找到一个标准正交矩阵A,




    02.主成份PCA问题的求解方法   


本节讲解求解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)
就是 
 




    03. PCA求解代码   


本节编写代码实现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 









联系老饼