机器学习入门教程

【代码】PCA的求解原理与代码

作者 : 老饼 发表日期 : 2023-12-10 13:08:54 更新日期 : 2025-03-30 14:00:23
本站原创文章,转载请说明来自《老饼讲解-机器学习》www.bbbdata.com



PCA主成份分析是一种常用的降维算法,一般使用SVD法来进行求解

本文讲解主成份分析PCA中主成份系数矩阵的求解原理,以及如何用代码具体实现

通过本文,可以了解PCA中的系数矩阵是怎么求解出来的,加深对PCA的理解





    01. PCA主成份-数学表述    





 在讲解PCA中的主成份系数矩阵A的求解方法前,本节先PCA的数学表达






      PCA的数学表述     


PCA就是对样本进行旋转,使旋转后的样本每维之间互不相关
 
从样本旋转理解PCA 
PCA的模型表示

由于旋转变换在数学中就是一个标准正交矩阵A
因此,PCA的模型表达式为:
 
 
其中,A为标准正交矩阵
 ✍️
解释:它代表先将数据进行中心化,然后再进行旋转
PCA的求解目标
 
由于PCA要求旋转后的样本每个维度互不相关,即Y的协方差矩阵为对角矩阵
因此,PCA的求解目标函数为
 
  
 其中, 为对角矩阵 





      PCA问题的简化     


,则有:
  
 第2个等号中是需要证明的,即证明,这里省略
  因此,PCA中的系数矩阵A的求解,可以化简为:
  求一个标准正交矩阵A,使得:
 
 
  这是一个经典的矩阵对角化问题
由于是对称矩阵,所以必存在一个标准正交矩阵A







    02. PCA主成份-SVD求解法    




本节讲解如何使用SVD法求解PCA主成份系数矩阵A





        PCA主成份-SVD求解法      


PCA的求解实际是矩阵对角化问题,理论上它可以通过特征值法来求解
但在实际中,更常用的是通过SVD分解来求得A
 SVD分解是指将一个m*n的矩阵分解成三个矩阵的积
其中U、V分别是m*m、n*n的酉矩阵,
是对角矩阵
 SVD法求解PCA的原理如下:
1. 注意到:                                                                                
               
2. 只需将进行SVD分解,即有:                            
   
3. 由于SVD分解中的V是酉矩阵,易知:                                 
  当时,就是对角矩阵,如下       
               






        PCA主成份-求解流程(SVD法)      


PCA的求解过程总结如下:
 
PCA主成份求解过程
进行SVD分解,得到
 其中,1.就是所求                       
2.
就是              








    03. PCA求解代码   




本节讲解求解PCA的系数矩阵A的代码实现





      求解PCA-调用sklearn     


下面先通过sklearn包求解PCA中的系数矩阵A
 具体代码实现如下:
"""
主成份分析求解DEMO(调用sklearn)
本代码来自老饼讲解-机器学习:www.bbbdata.com
"""
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
# 加载数据
iris   = load_iris()                                                  # 加载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_)                       # 打印主成份方差var
print('主成份贡献占比(方差占比)Pr:',clf.explained_variance_ratio_)    # 主成份贡献占比(方差占比)Pr:

# 获取主成份数据
y  = clf.transform(X)                                                 # 通过调用transform方法获取主成份数据  
y2 = (X-x_mean)@clf.components_.T                                     # 通过调用公式计算主成份数据 
运行结果如下:
用sklearn实现PCA的代码






      求解PCA-自实现     


下面不借助sklearn包,自行编写代码求解PCA的系数矩阵A
具体代码实现如下:
"""
主成份分析求解(自实现)
本代码来自老饼讲解-机器学习:www.bbbdata.com
"""
import numpy as np
from sklearn.datasets import load_iris

# 加载数据
iris   = load_iris()                                                  # 加载iris数据
X      = iris.data                                                    # 样本X
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)                                           # 打印主成份方差var
print('主成份贡献占比(方差占比)Pr:',pr)                               # 主成份贡献占比(方差占比)Pr:

# 获取主成份数据
y = (X-x_mean)@A                                                      # 通过调用公式计算主成份数据 
运行结果如下:
自实现PCA-代码运行结果 
可以看到,自行编写代码的结果与调用sklearn包是一致的
 没错,PCA的求解就是这么简单,仅是进行一下SVD分解即可






好了,以上就是PCA的求解方法以及代码实现了~










 End 






联系老饼