Python 从头开始的主成分分析的实现与scikit learn的数据定向不同

Python 从头开始的主成分分析的实现与scikit learn的数据定向不同,python,algorithm,numpy,scikit-learn,pca,Python,Algorithm,Numpy,Scikit Learn,Pca,基于该指南,我从零开始构建PCA算法,用于我的研究目的。类别定义为: 将numpy导入为np 类别PCA(对象): “使用主成分分析(PCA)进行降维” 正是计算主成分的过程解释了 使用较少组件的数据集的最大变化。 :类型n_组件:int,可选 PARAMNY组件:要考虑的组件数量,如果没有设置 `n_组件=最小值(n_样本,n_特征)`,其中 `n_samples`是样本数,并且 `n_features`是特征的数量(即。, 数据集的维度)。 属性 ========== :类型协方差\:np.

基于该指南,我从零开始构建PCA算法,用于我的研究目的。类别定义为:

将numpy导入为np
类别PCA(对象):
“使用主成分分析(PCA)进行降维”
正是计算主成分的过程解释了
使用较少组件的数据集的最大变化。
:类型n_组件:int,可选
PARAMNY组件:要考虑的组件数量,如果没有设置
`n_组件=最小值(n_样本,n_特征)`,其中
`n_samples`是样本数,并且
`n_features`是特征的数量(即。,
数据集的维度)。
属性
==========
:类型协方差\:np.ndarray
:参数协方差\协方差矩阵
:输入eig\u vals\uuu:np.ndarray
:param eig\u vals\计算的特征值
:键入eig_vecs_uu:np.ndarray
:param eig_vecs_:计算的特征向量
:已解释类型\u差异\uuu:np.ndarray
:参数解释的方差:每个主成分的解释方差
:类型与解释差异:np.ndarray
:参数和解释变量:累积解释变量
"""
def uuu init uuu(self,n_组件:int=None):
“”“初始化的默认构造函数”“”
self.n\u组件=n\u组件
def-fit_变换(self,X:np.ndarray):
“”“将PCA算法适配到数据集中”“”
如果不是self.n_组件:
self.n_组件=最小值(X.shape)
自协方差=np.cov(X.T)
#计算本征值
self.eig\u vals,self.eig\u vecs=np.linalg.eig(自协方差)
#解释差异
_tot_eig_vals=总和(self.eig_vals)
self.explained_variance_uuu=np.array([(i/_tot_eig_vals)*100表示已排序的i(self.eig_vals,reverse=True)])
自解释方差=np.cumsum(自解释方差)
#将“W”定义为“d x k”-维度
self.W=self.eig\u向量[:,:self.n\u组件]
打印(X形、自W形)
返回X.dot(self.W_)
iris数据集作为一个测试用例,PCA的实现和可视化如下:

将numpy导入为np
作为pd进口熊猫
导入seaborn作为sns
将matplotlib.pyplot作为plt导入
#加载iris数据,并进行规范化
从sklearn.dataset导入加载
iris=加载_iris()
从sklearn.preprocessing导入MinMaxScaler
十、 y=iris.data,iris.target
X=MinMaxScaler().fit_变换(X)
#使用PCA功能(定义见上文)
#要拟合X值,请变换X值
#将PCA对象命名为dPCA(d=已定义)
dPCA=PCA()
principalComponents=dPCA.fit_变换(X)
#为主要组件创建数据框架
#并使用散点图可视化数据
PCAResult=pd.DataFrame(主要组件,列=[f“PCA-{i}”表示范围(1,dPCA.n_组件+1)])
PCAResult[“target”]=y#可能是因为原始顺序没有改变
sns.散点图(x=“PCA-1”,y=“PCA-2”,数据=PCAResult,hue=“target”,s=50)
plt.show()
输出如下:

现在,我想验证输出,我使用了
sklearn
库,输出如下:

从sklearn.com导入PCA#注意相同的名称
考虑所有的组件
主分量=sPCA.fit\u变换(X)
PCAResult_uPd.DataFrame(主成分_Up,列=[f“PCA-{i}”表示范围(1,5)])
PCAResult_u[“target”]=y#可能是因为原始顺序没有改变
sns.散点图(x=“PCA-1”,y=“PCA-2”,data=PCAResult,hue=“target”,s=50)
plt.show()

我不明白为什么输出的方向不同,值略有不同。我研究了许多代码[,],它们都有相同的问题。我的问题是:

  • sklearn
    中有什么不同之处,即绘图不同?我也尝试过使用不同的数据集-同样的问题
  • 有没有办法解决这个问题
  • 我无法学习
    sklearn.decompose.PCA
    算法,因为我不熟悉python的OOPs概念

    塞巴斯蒂安·拉什卡(Sebastian Raschka)在博客文章中的输出也有微小的变化。下图:

    当计算特征向量时,您可能会发现该解也是有效的

    因此,任何PCA轴都可以反转,解决方案将是有效的


    然而,您可能希望将PCA轴与数据集中的一个原始变量进行正相关,如果需要,可以反转轴。

    在计算特征向量时,您可以这样做,并且解决方案也是有效的

    因此,任何PCA轴都可以反转,解决方案将是有效的


    然而,您可能希望将PCA轴与数据集中的一个原始变量进行正相关,如果需要,将轴反转。

    值的差异来自使用svd分解的sklearn的PCA。在sklearn中,有一个函数
    svd\u flip
    用于翻转电脑,这解释了为什么会看到这种翻转

    有关帮助的更多详细信息:

    它使用完整SVD或随机化SVD的LAPACK实现 使用Halko等人2009年的方法截断SVD,具体取决于 输入数据的形状和要提取的组件数

    你可以读到这段关系

    我们首先运行示例数据集:

    from sklearn.preprocessing import MinMaxScaler
    from sklearn.decomposition import PCA 
    from sklearn.datasets import load_iris
    from sklearn.utils.extmath import svd_flip
    import pandas as pd
    import numpy as np
    import scipy
    
    iris = load_iris()
    
    X, y = iris.data, iris.target
    X = MinMaxScaler().fit_transform(X)
    
    n_components = 4
    
    sPCA = PCA(n_components,svd_solver="full")
    sklearnPCs = pd.DataFrame(sPCA.fit_transform(X))
    
    我们现在在您的中心矩阵上执行SVD:

    U,S,Vt = scipy.linalg.svd(X - X.mean(axis=0))
    U = U[:,:n_components]
    U, Vt = svd_flip(U, Vt)
    
    svdPCs =  pd.DataFrame(U*S)
    
    结果是:

                0         1         2         3
    0   -0.630703  0.107578 -0.018719 -0.007307
    1   -0.622905 -0.104260 -0.049142 -0.032359
    2   -0.669520 -0.051417  0.019644 -0.007434
    3   -0.654153 -0.102885  0.023219  0.020114
    4   -0.648788  0.133488  0.015116  0.011786
    ..        ...       ...       ...       ...
    145  0.551462  0.059841  0.086283 -0.110092
    146  0.407146 -0.171821 -0.004102 -0.065241
    147  0.447143  0.037560  0.049546 -0.032743
    148  0.488208  0.149678  0.239209  0.002864
    149  0.312066 -0.031130  0.118672  0.052505
    
    
    svdPCs 
                0         1         2         3
    0   -0.630703  0.107578 -0.018719 -0.007307
    1   -0.622905 -0.104260 -0.049142 -0.032359
    2   -0.669520 -0.051417  0.019644 -0.007434
    3   -0.654153 -0.102885  0.023219  0.020114
    4   -0.648788  0.133488  0.015116  0.011786
    ..        ...       ...       ...       ...
    145  0.551462  0.059841  0.086283 -0.110092
    146  0.407146 -0.171821 -0.004102 -0.065241
    147  0.447143  0.037560  0.049546 -0.032743
    148  0.488208  0.149678  0.239209  0.002864
    149  0.312066 -0.031130  0.118672  0.052505
    

    您可以实现无翻转。这些值将是相同的,并且您的PCA将如另一个答案中所述有效。

    值的差异来自使用svd分解的sklearn的PCA。在sklearn中,有一个用于翻转电脑的函数