Получать собственные значения и векторы из sklearn PCA

Как я могу получить собственные значения и собственные векторы приложения 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)

Я не могу найти его в документах.

1. Я "не" способен понять различные результаты здесь.

Изменить:

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. Я хочу получить все собственные значения и собственные векторы вместо только приведенного множества с условием сходимости.

Ответ 1

Ваша реализация

Вы вычисляете собственные векторы корреляционной матрицы, то есть ковариационную матрицу нормированных переменных.
data/=np.std(data, axis=0) не является частью классического PCA, мы data/=np.std(data, axis=0) только переменные. Таким образом, PCA sklearn не показывает масштаб данных заранее.

Кроме того, вы на правильном пути, если отвлечься от факта, что код, который вы предоставили, не запускался;). Вы только путались с макетами строк/столбцов. Честно говоря, мне гораздо легче начать с X = data.T и работать только с X оттуда. Я добавил ваш код "fixed" в конце сообщения.

Получение собственных значений

Вы уже заметили, что вы можете получить собственные векторы, используя clf.components_.

Таким образом, у вас есть основные компоненты. Они являются собственными векторами ковариационной матрицы $ X ^ TX $.

Способ извлечения собственных значений оттуда состоит в том, чтобы применить эту матрицу к каждому главному компоненту и проецировать результаты на компонент. Пусть v_1 - первый главный компонент и lambda_1 - соответствующее собственное значение. У нас есть:
eq и таким образом: eq2 с eq3. (x, y) - скалярное произведение векторов x и y.

Назад в Python вы можете сделать:

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

И вы получаете собственное значение, связанное с собственным вектором. Ну, в моих тестах оказалось, что не работать с парами последних собственных значений, но я бы отнесла это к отсутствию навыков в числовой стабильности.

Теперь это не лучший способ получить собственные значения, но приятно знать, откуда они взялись.
Собственные значения представляют собой дисперсию в направлении собственного вектора. Поэтому вы можете получить их через атрибут pca.explained_variance_:

eigenvalues = pca.explained_variance_

Вот воспроизводимый пример, который печатает собственные значения, которые вы получаете с каждым методом:

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)

Исходный код, исправленный

Если вы запустите его, вы увидите, что значения согласованы. Они не совсем равны, потому что numpy и scikit-learn не используют один и тот же алгоритм здесь.
Главное, чтобы вы использовали корреляционную матрицу вместо ковариации, как упоминалось выше. Также вы получали транспонированные собственные векторы из numpy, что делало его очень запутанным.

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)

Надеюсь, что это поможет, не стесняйтесь просить разъяснений.

Ответ 2

Я использовал функцию sklearn PCA. Возвращаемые параметры component_ являются собственными векторами, а объясненная переменная_ является собственными значениями. Ниже приведен мой тестовый код.

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