PCA dalam numpy dan sklearn menghasilkan hasil yang berbeda

21

Apakah saya salah memahami sesuatu. Ini kode saya

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

Keluaran:

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

Menggunakan metode numpy

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

Keluaran

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.

Bolehkah saya tahu mengapa begitu?

Jika saya ingin mendapatkan kembali matriks asli saya, apa yang harus saya lakukan?

pembuat aceminer
sumber
Kode numpy Anda salah IMHO (juga, ia menggunakan Xyang tidak didefinisikan). Periksa kembali matematika Anda .
Anony-Mousse -Reinstate Monica
Saya menggunakan notebook ipython jadi saya hanya bisa menyalin dengan sel. Matematika saya salah? Bagian mana @ Anony-Mousse
aceminer
@ Anony-Mousse Ya saya menyadari kesalahan saya tetapi masih belum cocok
aceminer
@aceminer Saya ingin tahu mengapa Anda menghitung matriks kovarians x_std.T, bukan x_std?
Evgeni Nabokov
@ EvgeniNabokov sudah terlalu lama. Sry saya tidak ingat sudah
aceminer

Jawaban:

21

Perbedaannya adalah karena decomposition.PCAtidak menstandardisasi variabel Anda sebelum melakukan PCA, sedangkan dalam perhitungan manual Anda menelepon StandardScaleruntuk melakukan standarisasi. Oleh karena itu, Anda mengamati perbedaan ini: PCA tentang korelasi atau kovarian?

Jika Anda mengganti

pca.fit_transform(x)

dengan

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

Anda akan mendapatkan hasil yang sama dengan perhitungan manual ...

... tetapi hanya sampai urutan PC. Itu karena ketika Anda berlari

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

Anda mendapatkan nilai eigen tidak harus dalam urutan menurun. saya mendapat

array([ 0.07168571,  2.49382602,  1.43448827])

Jadi, Anda ingin memesannya secara manual. Sklearn melakukan itu untukmu.


Mengenai merekonstruksi variabel asli, silakan lihat Cara membalikkan PCA dan merekonstruksi variabel asli dari beberapa komponen utama?

amuba kata Reinstate Monica
sumber
Hanya ingin memeriksa. Apakah benar-benar perlu untuk membakukan matriks dengan deviasi standarnya? Saya melihat contoh di mana mereka tidak melakukannya
aceminer
Itu tidak perlu , itu hanya satu cara untuk melakukannya. Lihat tautan yang saya letakkan di paragraf pertama: stats.stackexchange.com/questions/53 - ini semua tentang pertanyaan ini. Jika Anda melakukan standarisasi, Anda melakukan PCA pada korelasi. Jika tidak, Anda melakukan PCA pada kovarian.
Amoeba berkata Reinstate Monica
9

Berikut ini adalah implementasi yang bagus dengan diskusi dan penjelasan PCA dalam python. Implementasi ini mengarah ke hasil yang sama dengan scikit PCA. Ini adalah indikator lain bahwa PCA Anda salah.

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)

Anda perlu mengurutkan nilai eigen (dan vektor eigen sesuai) turun

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

a = np.dot(x, evecs) 

Secara umum, saya sarankan Anda untuk memeriksa kode Anda dengan menerapkan contoh sederhana (sesederhana mungkin) dan menghitung dengan tangan resuls yang benar (dan hasil antara). Ini membantu Anda mengidentifikasi masalah.

Nikolas Rieble
sumber
1
Sukai jawaban ini. Itu memecahkan masalah saya!
Jinhua Wang