numpy和sklearn中的PCA产生不同的结果


20

我误会了吗。这是我的代码

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

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

输出量

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代码是错误的恕我直言(也使用X未定义的代码)。重新检查数学
Anony-Mousse-恢复Monica

我正在使用ipython笔记本,因此只能按单元复制。我的数学错了吗?哪一部分@ Anony-Mousse
aceminer

@ Anony-Mousse是的,我意识到我的错误,但是仍然不匹配
aceminer

@aceminer我很好奇为什么要计算x_std.T而不是x_std的协方差矩阵?
叶夫根尼·纳博科夫

@EvgeniNabokov太久了。
对不起,

Answers:


21

区别在于,decomposition.PCA在执行PCA之前不会对变量进行标准化,而在手动计算中,您需要StandardScaler进行标准化。因此,您正在观察这种差异:PCA是相关性还是协方差?

如果您更换

pca.fit_transform(x)

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

您将获得与手动计算相同的结果...

...但仅限于PC的订购。那是因为当你跑步时

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

您得到的特征值不一定按降序排列。我懂了

array([ 0.07168571,  2.49382602,  1.43448827])

因此,您将需要手动订购。Sklearn为您做到了。


关于重构原始变量,请参阅如何反转PCA并从几个主要组件重构原始变量?


只是想检查一下。是否真的有必要通过标准差对矩阵进行标准化?我看到了一些他们不这样做的例子
aceminer 16/09/20

必要,这只是一种方法。请参阅我在第一段中输入的链接:stats.stackexchange.com/questions/53-确实所有关于此问题的信息。如果进行标准化,则对相关性进行PCA。如果不这样做,则对协方差执行PCA。
变形虫说恢复莫妮卡

9

是一个很好的实现,其中包含对python中PCA的讨论和解释。此实现产生的结果与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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.