【问题标题】:(Incremental)PCA's Eigenvectors are not transposed but should be?(增量)PCA 特征向量不转置但应该转置?
【发布时间】:2016-10-03 05:51:00
【问题描述】:

当我们发布关于 PCA 的 homework assignment 时,我们告诉课程参与者选择任何计算他们发现的特征向量的方法。他们找到了多种方法:eig、eigh(我们最喜欢的是svd)。在后来的任务中,我们告诉他们使用 scikit-learn 的 PCA - 结果与我们预期的相差很大。

我玩弄了一下,我们向参与者发布了一个解释,即两种解决方案都是正确的,并且可能只是算法中的数值不稳定。然而,最近我在与一位同事的讨论中再​​次选择了该文件,我们很快发现有一个有趣的微妙变化可以使所有结果几乎相等:转置从 SVD 获得的特征向量(因此从PCA)。

一些代码来显示这个:

def pca_eig(data):
    """Uses numpy.linalg.eig to calculate the PCA."""
    data = data.T @ data
    val, vec = np.linalg.eig(data)
    return val, vec

对

def pca_svd(data):
    """Uses numpy.linalg.svd to calculate the PCA."""
    u, s, v = np.linalg.svd(data)
    return s ** 2, v

不会产生相同的结果。但是,将 pca_svd 的返回值更改为 s ** 2, v.T 有效!遵循wikipedia 的定义非常有意义:X 的 SVD 遵循 X=UΣWT where

X的右奇异向量W等价于X的特征向量TX

所以为了得到特征向量,我们需要转置输出v 的np.linalg.eig(...)。

除非有其他事情发生?无论如何,PCA 和IncrementalPCA 都显示错误的结果(或者eig 是错误的?我的意思是,转置产生相同的相等性),并且查看the code for PCA 表明他们正在这样做,就像我最初所做的那样:

U, S, V = linalg.svd(X, full_matrices=False)
# flip eigenvectors' sign to enforce deterministic output
U, V = svd_flip(U, V)

components_ = V

我创建了一个小 gist 来展示差异 (nbviewer),第一个使用 PCA 和 IncPCA(也没有 SVD 的转置),第二个使用转置的特征向量:

没有转置 SVD/PCA 的比较(标准化数据)

与 SVD/PCA 转置的比较(标准化数据)

可以清楚地看到,上图的结果并不是很好,而下图只是在一些符号上有所不同,因此到处反映了结果。

这真的是错误的还是 scikit-learn 中的错误?我更有可能使用错误的数学 - 但什么是正确的?你能帮帮我吗?

【问题讨论】:

    标签: scikit-learn pca


    【解决方案1】:

    如果您查看文档,从形状可以很清楚地看出特征向量在行中,而不是在列中。 sklearn PCA的重点是可以使用transform方法进行正确的转换。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-01
      • 2015-06-30
      • 1970-01-01
      • 2019-09-24
      • 2022-01-20
      相关资源
      最近更新 更多