【问题标题】:PCA projection and reconstruction in scikit-learnscikit-learn 中的 PCA 投影和重建
【发布时间】:2016-08-02 16:28:32
【问题描述】:

我可以通过以下代码在 scikit 中执行 PCA: X_train 有 279180 行和 104 列。

from sklearn.decomposition import PCA
pca = PCA(n_components=30)
X_train_pca = pca.fit_transform(X_train)

现在,当我想将特征向量投影到特征空间时,我必须执行以下操作:

""" Projection """
comp = pca.components_ #30x104
com_tr = np.transpose(pca.components_) #104x30
proj = np.dot(X_train,com_tr) #279180x104 * 104x30 = 297180x30

但我对这一步犹豫不决,因为 Scikit documentation 说:

components_: 数组,[n_components, n_features]

特征空间中的主轴,表示数据中最大方差的方向。

在我看来,它已经被投影了,但是当我检查源代码时,它只返回特征向量。

投影的正确方法是什么?

最终,我的目标是计算重建的 MSE。

""" Reconstruct """
recon = np.dot(proj,comp) #297180x30 * 30x104 = 279180x104

"""  MSE Error """
print "MSE = %.6G" %(np.mean((X_train - recon)**2))

【问题讨论】:

    标签: python machine-learning scikit-learn pca


    【解决方案1】:

    你可以的

    proj = pca.inverse_transform(X_train_pca)
    

    这样您就不必担心如何进行乘法运算。

    您在pca.fit_transformpca.transform 之后获得的是通常称为每个样本的“载荷”,这意味着您需要使用components_ 的线性组合来最好地描述每个组件的多少(特征空间中的主轴)。

    您瞄准的投影又回到了原始信号空间。这意味着您需要使用组件和负载返回信号空间。

    所以这里有三个步骤来消除歧义。在这里,您可以逐步了解使用 PCA 对象可以做什么以及它的实际计算方式:

    1. pca.fit 估计组件(在居中的 Xtrain 上使用 SVD):

       from sklearn.decomposition import PCA
       import numpy as np
       from numpy.testing import assert_array_almost_equal
      
       #Should this variable be X_train instead of Xtrain?
       X_train = np.random.randn(100, 50)
      
       pca = PCA(n_components=30)
       pca.fit(X_train)
      
       U, S, VT = np.linalg.svd(X_train - X_train.mean(0))
      
       assert_array_almost_equal(VT[:30], pca.components_)
      
    2. pca.transform 按照您的描述计算载荷

       X_train_pca = pca.transform(X_train)
      
       X_train_pca2 = (X_train - pca.mean_).dot(pca.components_.T)
      
       assert_array_almost_equal(X_train_pca, X_train_pca2)
      
    3. pca.inverse_transform 获取到您感兴趣的信号空间中组件的投影

       X_projected = pca.inverse_transform(X_train_pca)
       X_projected2 = X_train_pca.dot(pca.components_) + pca.mean_
      
       assert_array_almost_equal(X_projected, X_projected2)
      

    您现在可以评估投影损失

    loss = np.sum((X_train - X_projected) ** 2, axis=1).mean()
    

    【讨论】:

    • 好的,所以我可以调用pca.fit 来计算分量,然后可以通过pca.fit_transform 计算投影(这也是我想进一步处理数据的时候 - 将它们提取到一些模型,因为降维了)。对于重建,我调用pca.invert_transform 来计算 MSE。对吗?
    • 这取决于你所说的投影。首先,请注意pca.fit_transform(X) 给出的结果与pca.fit(X).transform(X) 相同(这是一个优化的快捷方式)。其次,投影通常是从一个空间到同一个空间的东西,所以这里是从信号空间到信号空间,具有应用两次就像应用一次的性质。这里是f= lambda X: pca.inverse_transform(pca.transform(X))。你可以检查f(f(X)) == f(X). 所以我称之为投影。 pca.transform 正在获取负载。最后它只是术语
    • 超级棒的解释性答案
    • 只是想说assert_array_almost_equal(VT[:30], pca.components_) 并不总是正确的。在 PCA 的实现中,符号在 U 和 V 之间打乱。为了模仿这种打乱,将U, S, VT = np.linalg.svd(Xtrain - Xtrain.mean(0)) 替换为U, S, VT = np.linalg.svd(Xtrain - Xtrain.mean(0), full_matrices=False) 并插入from sklearn.utils.extmath import svd_flip,后跟U, VT = svd_flip(U, VT)
    • X_train in loss = ((X_train - X_projected) ** 2).mean() 是否替换了前面代码中定义的 Xtrain 变量?
    【解决方案2】:

    添加@eickenberg 的帖子,这里是如何对数字图像进行 pca 重建:

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.datasets import load_digits
    from sklearn import decomposition
    
    n_components = 10
    image_shape = (8, 8)
    
    digits = load_digits()
    digits = digits.data
    
    n_samples, n_features = digits.shape
    estimator = decomposition.PCA(n_components=n_components, svd_solver='randomized', whiten=True)
    digits_recons = estimator.inverse_transform(estimator.fit_transform(digits))
    
    # show 5 randomly chosen digits and their PCA reconstructions with 10 dominant eigenvectors
    indices = np.random.choice(n_samples, 5, replace=False)
    plt.figure(figsize=(5,2))
    for i in range(len(indices)):
        plt.subplot(1,5,i+1), plt.imshow(np.reshape(digits[indices[i],:], image_shape)), plt.axis('off')
    plt.suptitle('Original', size=25)
    plt.show()
    plt.figure(figsize=(5,2))
    for i in range(len(indices)):
        plt.subplot(1,5,i+1), plt.imshow(np.reshape(digits_recons[indices[i],:], image_shape)), plt.axis('off')
    plt.suptitle('PCA reconstructed'.format(n_components), size=25)
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 2021-05-28
      • 2013-11-24
      • 2015-06-19
      • 1970-01-01
      • 2020-09-05
      • 2015-06-22
      • 2019-03-05
      • 2018-05-26
      • 2014-10-17
      相关资源
      最近更新 更多