PCA 解释的方差在数据排列上是相同的

PCA explained variance is the same on permutations of data

我正在学习本教程,该教程将一个数据集的前 50 个 PC 的解释方差与同一数据集的几个排列的前 50 个 PC 的解释方差进行了比较。看来它们只按列排列。

https://towardsdatascience.com/how-to-tune-hyperparameters-of-tsne-7c0596a18868

我试图在 python 中复制它,但我得到了所有排列的完全相同的解释方差。有人可以帮助我理解为什么我的排列数据的排列解释方差完全相同吗?

def exp_var_perm_data(data, n_permutations=1):
    """
        data: Assumed to be a pandas dataframe, object that has a .shape attribute
        n_permutations: Integer. Number of permutations to perform
    """    
    df = pd.DataFrame(columns=["Dim%d" % i for i in range(0, data.shape[1])])
    for k in range(0,n_permutations):
        pca_permuted = PCA()
        data_permuted = data.sample(frac=1).reset_index()
        pca_permuted.fit(data_permuted)
        df.loc[k] = pca_permuted.explained_variance_ratio_
    return df

from sklearn import datasets
import pandas as pd

iris_data = datasets.load_iris()
iris_data = iris_data.data

exp_var_perm = exp_var_perm_data(pd.DataFrame(iris_data), 10)
print(exp_var_perm)

输出:

       Dim0      Dim1      Dim2      Dim3
0  0.879444  0.093535  0.021659  0.005363
1  0.879444  0.093535  0.021659  0.005363
2  0.879444  0.093535  0.021659  0.005363
3  0.879444  0.093535  0.021659  0.005363
4  0.879444  0.093535  0.021659  0.005363
5  0.879444  0.093535  0.021659  0.005363
6  0.879444  0.093535  0.021659  0.005363
7  0.879444  0.093535  0.021659  0.005363
8  0.879444  0.093535  0.021659  0.005363
9  0.879444  0.093535  0.021659  0.005363

我一直在学习相同的教程。

我刚刚编写了一个函数来按照教程中的说明打乱数据:

def shuffle_by_rows(data):
   shuffled = np.zeros((data.shape[0],data.shape[1]))
   for i,row in enumerate(data):
      shuffled[i] = random.sample(row.tolist(),len(row))
   return shuffled

对我产生了影响。 更好的是,sklearn 和 numpy 可以通过以下方式找到最佳数量的组件:

pca = PCA()
pca.fit(data)
cumsum = np.cumsum(pca.explained_varaince_ratio_)
d = np.argmax(cumsum>=.95)+1

这是为了获得最多占数据方差 95% 的分量的最佳数量。

教程独立排列每一列,据我所知 R 代码:

expr_perm <- apply(expr,2,sample)

这似乎是合理的,因为目标是在零协方差的原假设下生成数据。

然而,问题中的相应代码排列了整个数据框(所有列在一起):

data_permuted = data.sample(frac=1).reset_index(drop=True)

与 R 代码类似,我们可以使用 apply 来排列每一列(使用一个小的辅助函数来进行排列):

data_permuted = data.apply(permute, axis=1, raw=True)

这是完整的示例:

from sklearn.decomposition import PCA
from sklearn import datasets
import pandas as pd
import numpy as np


def exp_var_perm_data(data, n_permutations=1):
    """
        data: Assumed to be a pandas dataframe, object that has a .shape attribute
        n_permutations: Integer. Number of permutations to perform
    """    
    df = pd.DataFrame(columns=["Dim%d" % i for i in range(0, data.shape[1])])
    for k in range(0,n_permutations):
        pca_permuted = PCA()
        data_permuted = data.apply(permute, axis=1, raw=True)
        pca_permuted.fit(data_permuted)
        df.loc[k] = pca_permuted.explained_variance_ratio_
    return df


def permute(x):
    """Create a randomly permuted copy of x"""
    x = x.copy()
    np.random.shuffle(x)
    return x


iris_data = datasets.load_iris()
iris_data = iris_data.data

exp_var_perm = exp_var_perm_data(pd.DataFrame(iris_data), 10)
print(exp_var_perm)