【问题标题】:Bug in Scikit-Learn PCA or in Numpy Eigen Decomposition?Scikit-Learn PCA 或 Numpy Eigen 分解中的错误?
【发布时间】:2019-03-05 01:29:10
【问题描述】:

我有一个包含 400 个特征的数据集。

我做了什么:

# approach 1
d_cov = np.cov(d_train.transpose())
eigens, mypca = LA.eig(d_cov) # assume sort by eigen value also/ LA = numpy linear algebra

# approach 2 
pca = PCA(n_components=300)
d_fit = pca.fit_transform(d_train)
pc = pca.components_

现在,这两个应该是一样的,对吧?因为 PCA 只是协方差矩阵的特征分解。

但在我的情况下这些有很大不同吗?

怎么可能,我在上面做错了什么?

比较差异:

import numpy as np
LA = np.linalg
d_train = np.random.randn(100, 10)
d_cov = np.cov(d_train.transpose())
eigens, mypca = LA.eig(d_cov)

import matplotlib.pyplot as plt


from sklearn.decomposition import PCA
pca =  PCA(n_components=10)
d_fit = pca.fit_transform(d_train)
pc = pca.components_
ve = pca.explained_variance_
#mypca[0,:], pc[0,:] pc.transpose()[0,:]

plt.plot(list(range(len(eigens))), [ x.transpose().dot(d_cov).dot(x) for x,y  in zip(mypca, eigens) ])
plt.plot(list(range(len(ve))), ve)
plt.show()

print(mypca, '\n---\n' , pc)

【问题讨论】:

  • 能否请您出示您的进口声明?
  • 你试过pc.transpose()吗?
  • @P.Camilleri 但即使是差异也不一样?至少由 PC 和特征向量解释的方差应该是 sam,对吧?请查看编辑。
  • 仅供参考,使用 pc.T 而不是 pc.transpose(),它更短,您可以避免创建新数组

标签: numpy scikit-learn linear-algebra pca


【解决方案1】:

我不是 PCA 方面的专家,但如果我转置其中一个矩阵,我似乎会得到类似的值。

>>> import numpy as np
>>> LA = np.linalg
>>> d_train = np.random.randn(100, 10)
>>> d_cov = np.cov(d_train.transpose())
>>> eigens, mypca = LA.eig(d_cov)
>>> from sklearn.decomposition import PCA
>>> pca =  PCA(n_components=10)
>>> d_fit = pca.fit_transform(d_train)
>>> pc = pca.components_
>>> mypca[0,:]
array([-0.44255435, -0.77430549, -0.14479638, -0.06459874,  0.24772212,
        0.20780185,  0.22388151, -0.05069543, -0.14515676, -0.03385801])
>>> pc[0,:]
array([-0.44255435, -0.24050535, -0.17313927,  0.07182494,  0.09748632,
        0.17910516,  0.26125107,  0.71309764,  0.17276004,  0.25095447])
>>> pc.transpose()[0,:]
array([-0.44255435,  0.77430549,  0.14479638, -0.06459874,  0.24772212,
       -0.20780185,  0.22388151, -0.03385801,  0.14515676,  0.05069543])
>>> list(zip(pc.transpose()[:,0], mypca[:,0]))
[(-0.44255435328718207, -0.44255435328718096),
 (-0.24050535133912765, -0.2405053513391287),
 (-0.17313926714559819, -0.17313926714559785),
 (0.07182494253930383, 0.0718249425393035),
 (0.09748631534772645, 0.09748631534772684),
 (0.17910516453826955, 0.17910516453826758),
 (0.2612510722861703, 0.2612510722861689),
 (0.7130976419217306, 0.7130976419217326),
 (0.17276004381786172, 0.17276004381786136),
 (0.25095447415020183, 0.2509544741502009)]

【讨论】:

  • 它们不一样,见:0.20780185和-0.20780185
  • @mourinho 看到我标记的重复问题,执行 PCA 时存在符号歧义
【解决方案2】:

您需要更仔细地阅读文档。 numpy 的文档很棒而且非常透彻,很多时候你只有通过阅读才能找到解决问题的方法。

这是您的代码的修改版本(在 sn-p 之上导入,使用 .T 而不是 .transpose(),pep8。)

import matplotlib.pyplot as plt
import numpy as np
from sklearn.decomposition import PCA

from numpy import linalg as LA

d_train = np.random.randn(100, 10)
d_cov = np.cov(d_train.transpose())
eigens, mypca = LA.eig(d_cov)

pca = PCA(n_components=10)
d_fit = pca.fit_transform(d_train)
pc = pca.components_
explained = pca.explained_variance_

my_explained = np.sort([x.T.dot(d_cov).dot(x) for x in mypca.T])[::-1]

plt.close('all')
plt.figure()
plt.plot(my_explained, label='me')
plt.plot(explained, label='sklearn')
plt.legend()
plt.show(block=False)

两条曲线完全相同。 重要的是我迭代的是 my_pca.T,而不是 my_pca。

Signature: np.linalg.eig(a)
Docstring:
Compute the eigenvalues and right eigenvectors of a square array.

Parameters
----------
a : (..., M, M) array
    Matrices for which the eigenvalues and right eigenvectors will
    be computed

Returns
-------
w : (..., M) array
    # not important for you

v : (..., M, M) array
    The normalized (unit "length") eigenvectors, such that the
    column ``v[:,i]`` is the eigenvector corresponding to the
    eigenvalue ``w[i]``.

特征向量作为my_pca 的列返回,而不是行。 for x in my_pca 正在遍历行。

【讨论】:

    猜你喜欢
    • 2017-12-24
    • 2015-06-19
    • 2013-11-24
    • 1970-01-01
    • 2018-03-23
    • 2016-08-02
    • 2020-11-23
    • 2017-09-10
    • 1970-01-01
    相关资源
    最近更新 更多