PCA в NumPy и Sklearn дает разные результаты

21

Я что-то неправильно понимаю. Это мой код

используя sklearn

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn import decomposition
from sklearn import datasets
from sklearn.preprocessing import StandardScaler

pca = decomposition.PCA(n_components=3)

x = np.array([
        [0.387,4878, 5.42],
        [0.723,12104,5.25],
        [1,12756,5.52],
        [1.524,6787,3.94],
    ])
pca.fit_transform(x)

Выход:

array([[ -4.25324997e+03,  -8.41288672e-01,  -8.37858943e-03],
   [  2.97275001e+03,  -1.25977271e-01,   1.82476780e-01],
   [  3.62475003e+03,  -1.56843494e-01,  -1.65224286e-01],
   [ -2.34425007e+03,   1.12410944e+00,  -8.87390454e-03]])

Используя наглые методы

x_std = StandardScaler().fit_transform(x)
cov = np.cov(x_std.T)
ev , eig = np.linalg.eig(cov)
a = eig.dot(x_std.T)

Выход

array([[ 0.06406894,  0.94063993, -1.62373172],
   [-0.35357757,  0.7509653 ,  0.63365168],
   [ 0.29312477,  0.6710958 ,  1.11766206],
   [-0.00361615, -2.36270102, -0.12758202]])
I have kept all 3 components but it doesnt seem to allow me to retain my original data.

Могу ли я знать, почему это так?

Если я хочу получить свою оригинальную матрицу, что мне делать?

aceminer
источник
Ваш код NumPy неверен IMHO (также он использует, Xкоторый не определен). Перепроверь свою математику .
Anony-Mousse -Восстановить Монику
Я использую ноутбук ipython, чтобы я мог копировать только по ячейкам. Моя математика не так? Какая часть @ Anony-Mousse
aceminer
@ Anony-Mousse Да, я понял свою ошибку, но она все еще не совпадает
aceminer
@aceminer Мне любопытно, почему вы вычисляете ковариационную матрицу x_std.T, а не x_std?
Евгений Набоков
@ EvgeniNabokov это было слишком долго. Извините, я уже не помню
aceminer

Ответы:

21

Разница в том, что decomposition.PCAне стандартизирует ваши переменные до выполнения PCA, тогда как при ручном вычислении вы вызываете StandardScalerстандартизацию. Следовательно, вы наблюдаете эту разницу: СПС по корреляции или ковариации?

Если вы замените

pca.fit_transform(x)

с

x_std = StandardScaler().fit_transform(x)
pca.fit_transform(x_std)

вы получите тот же результат, что и при ручном вычислении ...

... но только на заказ ПК. Это потому, что когда вы бежите

ev , eig = np.linalg.eig(cov)

вы получаете собственные значения не обязательно в порядке убывания. я получил

array([ 0.07168571,  2.49382602,  1.43448827])

Поэтому вы захотите заказать их вручную. Склеарн делает это для тебя.


Относительно восстановления исходных переменных см. Как изменить PCA и восстановить исходные переменные из нескольких основных компонентов?

амеба говорит восстановить монику
источник
Просто хотел бы проверить. Действительно ли необходимо стандартизировать матрицу по ее стандартному отклонению? Я видел примеры, где они этого не делают
aceminer
Это не обязательно , это всего лишь один из способов сделать это. Смотрите ссылку, которую я поместил в первом абзаце: stats.stackexchange.com/questions/53 - это действительно все об этом вопросе. Если вы стандартизируете, вы делаете PCA на корреляции. Если вы этого не сделаете, вы делаете PCA на ковариациях.
говорит амеба: восстанови монику
9

Вот хорошая реализация с обсуждением и объяснением PCA на python. Эта реализация приводит к тому же результату, что и PCA scikit. Это еще один показатель того, что ваш PCA не прав.

import numpy as np
from scipy import linalg as LA

x = np.array([
        [0.387,4878, 5.42],
        [0.723,12104,5.25],
        [1,12756,5.52],
        [1.524,6787,3.94],
    ])

#centering the data
x -= np.mean(x, axis = 0)  

cov = np.cov(x, rowvar = False)

evals , evecs = LA.eigh(cov)

вам нужно отсортировать собственные значения (и собственные векторы соответственно) по убыванию

idx = np.argsort(evals)[::-1]
evecs = evecs[:,idx]
evals = evals[idx]

a = np.dot(x, evecs) 

Как правило, я рекомендую вам проверить ваш код путем реализации простого примера (как можно более простого) и вычисления вручную правильных результатов (и промежуточных результатов). Это поможет вам определить проблему.

Николас Рибл
источник
1
Люблю этот ответ. Это решило мою проблему!
Цзиньхуа Ван,