python - example - Obtener valores propios y vectores de sklearn PCA
pca python images (1)
Tu implementacion
Está calculando los vectores propios de la matriz de correlación , es decir, la matriz de covarianza de las variables normalizadas .
data/=np.std(data, axis=0)
no es parte del PCA clásico, solo centramos las variables. Por lo tanto, la PCA de sklearn no ofrece escalar los datos de antemano
Además, está en el camino correcto, si abstraemos el hecho de que el código que proporcionó no se ejecutó;). Sólo se confundió con los diseños de fila / columna. Sinceramente, creo que es mucho más fácil comenzar con X = data.T
y trabajar solo con X a partir de ahí. Agregué tu código ''arreglado'' al final de la publicación.
Obteniendo los valores propios
Ya clf.components_
que puedes obtener los vectores propios usando clf.components_
.
Así que tienes los componentes principales. Son vectores propios de la matriz de covarianza $ X ^ TX $.
Una forma de recuperar los valores propios desde allí es aplicar esta matriz a cada componente principal y proyectar los resultados en el componente. Sea v_1 el primer componente principal y lambda_1 el valor propio asociado. Tenemos:
y por lo tanto: ya que . (x, y) el producto escalar de los vectores x y y.
De vuelta en Python puedes hacer:
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)))
Y obtienes el valor propio asociado con el vector propio. Bueno, en mis pruebas resultó no funcionar con los valores propios de la pareja, pero lo atribuyo a mi ausencia de habilidades en estabilidad numérica.
Ahora esa no es la mejor manera de obtener los valores propios, pero es bueno saber de dónde vienen.
Los valores propios representan la varianza en la dirección del vector propio. Para que pueda obtenerlos a través del atributo pca.explained_variance_
:
eigenvalues = pca.explained_variance_
Aquí hay un ejemplo reproducible que imprime los valores propios que obtienes con cada método:
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)
Su código original, fijo
Si lo ejecutas verás que los valores son consistentes. No son exactamente iguales porque numpy y scikit-learn no están usando el mismo algoritmo aquí.
Lo principal era que estaba usando una matriz de correlación en lugar de covarianza, como se mencionó anteriormente. También obtuviste los vectores propios transpuestos de numpy lo que lo hizo muy confuso.
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)
Espero que esto ayude, no dude en pedir aclaraciones.
¿Cómo puedo obtener los valores propios y los vectores propios de la aplicación 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)
No lo encuentro en los docs .
1. No puedo "comprender" los diferentes resultados aquí.
Editar :
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)
- Deseo obtener todos los valores propios y vectores propios en lugar del conjunto reducido con la condición de convergencia.