web-dev-qa-db-fra.com

Obtenir des valeurs propres et des vecteurs de sklearn PCA

Comment puis-je obtenir les valeurs propres et les vecteurs propres de l'application PCA?

from sklearn.decomposition import PCA
clf=PCA(0.98,whiten=True)      #converse 98% variance
X_train=clf.fit_transform(X_train)
X_test=clf.transform(X_test)

Je ne le trouve pas dans docs .

1.Je ne suis "pas" en mesure de comprendre les différents résultats ici.

Modifier :

def pca_code(data):
    #raw_implementation
    var_per=.98
    data-=np.mean(data, axis=0)
    data/=np.std(data, axis=0)
    cov_mat=np.cov(data, rowvar=False)
    evals, evecs = np.linalg.eigh(cov_mat)
    idx = np.argsort(evals)[::-1]
    evecs = evecs[:,idx]
    evals = evals[idx]
    variance_retained=np.cumsum(evals)/np.sum(evals)
    index=np.argmax(variance_retained>=var_per)
    evecs = evecs[:,:index+1]
    reduced_data=np.dot(evecs.T, data.T).T
    print(evals)
    print("_"*30)
    print(evecs)
    print("_"*30)
    #using scipy package
    clf=PCA(var_per)
    X_train=data.T
    X_train=clf.fit_transform(X_train)
    print(clf.explained_variance_)
    print("_"*30)
    print(clf.components_)
    print("__"*30)
  1. Je souhaite obtenir toutes les valeurs propres et vecteurs propres au lieu de simplement l'ensemble réduit avec la condition de convergence.
28
Abhishek Bhatia

Votre implémentation

Vous calculez les vecteurs propres de la matrice de corrélation , c'est-à-dire la matrice de covariance des variables normalisées.
data/=np.std(data, axis=0) ne fait pas partie de l'APC classique, nous centrons uniquement les variables. Ainsi, le sklearn PCA ne propose pas de mise à l'échelle des données au préalable .

En dehors de cela, vous êtes sur la bonne voie, si nous faisons abstraction du fait que le code que vous avez fourni ne s'est pas exécuté;). Vous avez seulement été confondu avec les dispositions de ligne/colonne. Honnêtement, je pense qu'il est beaucoup plus facile de commencer par X = data.T et travailler uniquement avec X à partir de là. J'ai ajouté votre code "fixe" à la fin du post.

Obtention des valeurs propres

Vous avez déjà noté que vous pouvez obtenir les vecteurs propres en utilisant clf.components_.

Vous avez donc les principaux composants. Ce sont des vecteurs propres de la matrice - covariance $ X ^ T X $.

Un moyen de récupérer les valeurs propres à partir de là est d'appliquer cette matrice à chaque composant principal et de projeter les résultats sur le composant. Soit v_1 le premier composant principal et lambda_1 la valeur propre associée. On a:
eq et donc: eq2 depuis eq3 . (x, y) le produit scalaire des vecteurs x et y.

De retour en Python vous pouvez faire:

n_samples = X.shape[0]
# We center the data and compute the sample covariance matrix.
X -= np.mean(X, axis=0)
cov_matrix = np.dot(X.T, X) / n_samples
for eigenvector in pca.components_:
    print(np.dot(eigenvector.T, np.dot(cov_matrix, eigenvector)))

Et vous obtenez la valeur propre associée au vecteur propre. Eh bien, dans mes tests, il s'est avéré ne pas fonctionner avec les dernières valeurs propres du couple, mais j'attribuerais cela à mon absence de compétences en stabilité numérique.

Ce n'est pas la manière la meilleure d'obtenir les valeurs propres mais c'est bien de savoir d'où elles viennent.
Les valeurs propres représentent la variance dans la direction du vecteur propre. Vous pouvez donc les faire passer par le pca.explained_variance_ attribut:

eigenvalues = pca.explained_variance_

Voici un exemple reproductible qui imprime les valeurs propres que vous obtenez avec chaque méthode:

import numpy as np
from sklearn.decomposition import PCA
from sklearn.datasets import make_classification


X, y = make_classification(n_samples=1000)
n_samples = X.shape[0]

pca = PCA()
X_transformed = pca.fit_transform(X)

# We center the data and compute the sample covariance matrix.
X_centered = X - np.mean(X, axis=0)
cov_matrix = np.dot(X_centered.T, X_centered) / n_samples
eigenvalues = pca.explained_variance_
for eigenvalue, eigenvector in Zip(eigenvalues, pca.components_):    
    print(np.dot(eigenvector.T, np.dot(cov_matrix, eigenvector)))
    print(eigenvalue)

Votre code d'origine, corrigé

Si vous l'exécutez, vous verrez que les valeurs sont cohérentes. Ils ne sont pas exactement égaux car numpy et scikit-learn n'utilisent pas le même algorithme ici.
L'essentiel était que vous utilisiez la matrice de corrélation au lieu de la covariance, comme mentionné ci-dessus. De plus, vous obteniez les transposés vecteurs propres de numpy, ce qui était très déroutant.

import numpy as np
from scipy.stats.mstats import zscore
from sklearn.decomposition import PCA

def pca_code(data):
    #raw_implementation
    var_per=.98
    data-=np.mean(data, axis=0)
    # data/=np.std(data, axis=0)
    cov_mat=np.cov(data, rowvar=False)
    evals, evecs = np.linalg.eigh(cov_mat)
    idx = np.argsort(evals)[::-1]
    evecs = evecs[:,idx]
    evals = evals[idx]
    variance_retained=np.cumsum(evals)/np.sum(evals)
    index=np.argmax(variance_retained>=var_per)
    evecs = evecs[:,:index+1]
    reduced_data=np.dot(evecs.T, data.T).T
    print("evals", evals)
    print("_"*30)
    print(evecs.T[1, :])
    print("_"*30)
    #using scipy package
    clf=PCA(var_per)
    X_train=data
    X_train=clf.fit_transform(X_train)
    print(clf.explained_variance_)
    print("_"*30)
    print(clf.components_[1,:])
    print("__"*30)

J'espère que cela vous aide, n'hésitez pas à demander des clarifications.

49
ldirer

J'ai utilisé la fonction sklearn PCA. Les paramètres de retour "composants_" sont des vecteurs propres et "explication_variance_" sont des valeurs propres. Voici mon code de test.

from sklearn.decomposition import PCA
import numpy as np


def main():
    data = np.array([[2.5, 2.4], [0.5, 0.7], [2.2, 2.9], [1.9, 2.2], [3.1, 3.0], [2.3, 2.7], [2, 1.6], [1, 1.1], [1.5, 1.6], [1.1, 0.9]])
    print(data)
    pca = PCA()
    pca.fit(data)

    print(pca.components_)
    print(pca.explained_variance_)



if __name__ == "__main__":
    main()
0
Lee