PCA у нумері та склеарні дає різні результати


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.

Чи можу я знати, чому так?

Якщо я хочу отримати свою оригінальну матрицю, що мені робити?


Ваш numpy-код неправильний IMHO (також він використовує, Xякий не визначений). Перевірте математику .
Anonymous-Mousse -Встановити Моніку

Я використовую ноутбук ipython, тому я можу копіювати лише клітинками. Моя математика неправильна? Яка частина @ Anonymous-Mousse
aceminer

@ Anonymous-Mousse Так, я зрозумів свою помилку, але вона все ще не відповідає
aceminer

@aceminer Мені цікаво, чому ви обчислюєте матрицю коваріації x_std.T, а не x_std?
Євген Набоков

@EvgeniNabokov це було занадто довго. Sry я вже не пам'ятаю
aceminer

Відповіді:


21

Різниця полягає в тому, що decomposition.PCAвін не стандартизує ваші змінні перед тим, як робити PCA, тоді як у ваших ручних обчисленнях ви закликаєте StandardScalerзробити стандартизацію. Отже, ви спостерігаєте цю різницю: PCA на кореляцію чи коваріацію?

Якщо ви заміните

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

Тож ви захочете замовити їх вручну. Sklearn робить це за вас.


Щодо реконструкції оригінальних змінних, див. Як відновити PCA та реконструювати оригінальні змінні з кількох основних компонентів?


Просто хотілося б перевірити. Чи дійсно потрібно стандартизувати матрицю за її стандартним відхиленням? Я бачив приклади, коли вони цього не роблять
aceminer

Це не обов'язково , це лише один із способів зробити це. Дивіться посилання, яке я виклав у першому абзаці: stats.stackexchange.com/questions/53 - це справді все в цьому питанні. Якщо ви стандартизуєте, ви робите PCA на кореляціях. Якщо ви цього не зробите, ви робите PCA на товаристві.
амеба каже, що повернеться до Моніки

9

Ось приємна реалізація з обговоренням та поясненням PCA в python. Ця реалізація призводить до того ж результату, що і scikit PCA. Це ще один показник того, що ваш 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
Люблю цю відповідь. Це вирішило мою проблему!
Jinhua Wang
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.