scikit-learn 中的 PCA 投影和重建

PCA projection and reconstruction in scikit-learn

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

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

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

""" 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_: array, [n_components, n_features]

Principal axes in feature space, representing the directions of maximum variance in the data.

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

怎样才是正确的投影方式呢?

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

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

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

你可以做到

proj = pca.inverse_transform(X_train_pca)

这样你就不用担心如何做乘法了。

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

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

所以这里分三步来消歧。在这里,您可以逐步了解使用 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 获取您感兴趣的信号 space 中分量的投影

     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()

添加 @eickenberg 的 post,这里是如何对数字图像进行 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()