web-dev-qa-db-fra.com

Projection et reconstruction PCA dans Scikit-Learn

Je peux effectuer PCA dans scikit par le code ci-dessous: X_train a 279180 lignes et 104 colonnes.

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

Maintenant, quand je veux projeter les vecteurs propres sur l'espace d'entité, je dois faire ce qui suit:

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

Mais j'hésite avec cette étape, car Scikit documentation dit:

components_: array, [n_components, n_features]

Axes principaux dans l'espace d'entités , représentant les directions de variance maximale dans les données.

Il me semble qu'il est déjà projeté, mais lorsque j'ai vérifié le code source, il ne renvoie que les vecteurs propres.

Quelle est la bonne façon de le projeter?

En fin de compte, je vise à calculer le MSE de la reconstruction.

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

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

Tu peux faire

proj = pca.inverse_transform(X_train_pca)

De cette façon, vous n'avez pas à vous soucier de la façon de faire les multiplications.

Ce que vous obtenez après pca.fit_transform ou pca.transform sont ce que l'on appelle généralement les "chargements" pour chaque échantillon, ce qui signifie la quantité de chaque composant dont vous avez besoin pour le décrire le mieux en utilisant une combinaison linéaire de components_ (les principaux axes de l'espace d'entités).

La projection que vous visez est de retour dans l'espace du signal d'origine. Cela signifie que vous devez retourner dans l'espace des signaux en utilisant les composants et les chargements.

Il y a donc trois étapes pour lever l'ambiguïté ici. Voici, étape par étape, ce que vous pouvez faire en utilisant l'objet PCA et comment il est réellement calculé:

  1. pca.fit estime les composants (en utilisant un SVD sur le Xtrain centré):

    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 calcule les chargements comme vous le décrivez

    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 obtient la projection sur les composants de l'espace signal qui vous intéressent

    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)
    

Vous pouvez maintenant évaluer la perte de projection

loss = ((X_train - X_projected) ** 2).mean()
29
eickenberg

Ajout sur le post de @ eickenberg, voici comment faire la reconstruction pca des images des chiffres:

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

enter image description here

enter image description here

1
Sandipan Dey