(增量)PCA的特征向量不是转置但应该是?

时间:2016-10-03 05:51:01

标签: scikit-learn pca

当我们发布关于PCA的homework assignment时,我们告诉课程参与者选择任何计算他们发现的特征向量的方法。他们找到了多种方式:eigeigh(我们最喜欢的是svd)。在后来的一项任务中,我们告诉他们使用scikit-learn中的PCA,并且惊讶于结果的差异比我们预期的要大得多。

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

一些显示此代码的代码:

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是有效的!根据{{​​3}}的定义,它非常有意义:X的SVD遵循X =UΣW T 其中

  

X的右奇异向量W等于X T X

的特征向量

因此,要获得特征向量,我们需要转换v的输出np.linalg.eig(...)

除非还有其他事情发生?无论如何,wikipediaPCA都显示错误的结果(或eig是错误的?我的意思是,转置产生相同的平等),并查看IncrementalPCA显示它们正如我最初做的那样:

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

components_ = V

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

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

nbviewer

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

comparison without transposition of SVD/PCAs

正如人们可以清楚地看到的那样,在上图中结果并不是很好,而较低的图像只是在一些符号上有所不同,从而在这里和那里反映了结果。

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

1 个答案:

答案 0 :(得分:1)

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