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))
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é:
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_)
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)
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()
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()