Scikit-Learn PCA

14

我正在使用这里的输入数据(请参见第3.1节)。

我试图使用scikit-learn复现它们的协方差矩阵、特征值和特征向量。然而,我无法复现数据源中呈现的结果。我还在其他地方看到过这个输入数据,但我无法确定是scikit-learn、我的步骤还是数据源的问题。

data = np.array([[2.5,2.4],
                 [0.5,0.7],
                 [2.2,2.9],
                 [1.9,2.2],
                 [3.1,3.0],
                 [2.3,2.7],
                 [2.0,1.6],
                 [1.0,1.1],
                 [1.5,1.6],
                 [1.1,0.9],
                 ]) 

centered_data = data-data.mean(axis=0)
pca = PCA()
pca.fit(centered_data)
print(pca.get_covariance()) #Covariance Matrix

array([[ 0.5549,  0.5539],
   [ 0.5539,  0.6449]])

print(pca.explained_variance_ratio_) #Eigenvalues (normalized)

[ 0.96318131  0.03681869]

print(pca.components_) #Eigenvectors

[[-0.6778734  -0.73517866]
 [ 0.73517866 -0.6778734 ]]

令人惊讶的是,这些预测与上述数据源的结果相匹配。

print(pca.transform(centered_data)) #Projections

array([[-0.82797019,  0.17511531],
   [ 1.77758033, -0.14285723],
   [-0.99219749, -0.38437499],
   [-0.27421042, -0.13041721],
   [-1.67580142,  0.20949846],
   [-0.9129491 , -0.17528244],
   [ 0.09910944,  0.3498247 ],
   [ 1.14457216, -0.04641726],
   [ 0.43804614, -0.01776463],
   [ 1.22382056,  0.16267529]])

以下是我不明白的问题:

  1. 为什么协方差矩阵不同?
  2. 更新:我如何从scikit-learn获得未经过归一化的特征值?

1
好的,我认为我意识到"explained_variance_ratio_"并不等同于特征值。相反,它们似乎是在特征值总和上进行了归一化处理。因此,"explained_variance_ratio_"本质上是用于屏幕图的归一化特征值。虽然,目前还不清楚我如何使用scikit-learn获取特征值。 - slaw
2个回答

15

对这些数据进行正确的协方差矩阵计算:

numpy.cov(data.transpose())
array([[ 0.61655556,  0.61544444],
       [ 0.61544444,  0.71655556]])
偏误协方差矩阵(即“不正确”,使用错误的标准化项,并低估数据集中的方差):

numpy.cov(data.transpose(), bias=1)
array([[ 0.5549,  0.5539],
       [ 0.5539,  0.6449]])
Numpy知道你需要将数据居中,所以你不需要。
PCA组件与特征值不是一一对应的。
正确的特征值分解:
numpy.linalg.eig(numpy.cov(data.transpose()))
(array([ 0.0490834 ,  1.28402771]),
 array([[-0.73517866, -0.6778734 ],
        [ 0.6778734 , -0.73517866]]))
使用有偏估计器会产生不同的特征值(再次低估方差),但是相同的特征向量:
(array([ 0.04417506,  1.15562494]), ...
请注意,特征向量尚未按最大特征值排序。 正如pca.explained_variance_ratio_的名称所示,这些不是特征值。它们是比率。如果我们取(有偏差的、低估的)特征值,并将它们归一化为总和为1,我们得到
s/sum(s)
array([ 0.03681869,  0.96318131])
此外,scipy 的 pca.transform 方法显然没有应用缩放。在我看来,当使用 PCA 时,通常也会对每个组件进行缩放,使它们具有单位方差。这显然不适用于此输出。然后结果将是(两列已互换,我没有费心去更改)
s, e = numpy.linalg.eig(numpy.cov(data.transpose()))
o=numpy.argsort(s)[::-1]
(data-mean).dot(e[:,o]) / numpy.sqrt(s[o])
array([[-0.73068047, -0.79041795],
       [ 1.56870773,  0.64481466],
       [-0.87561043,  1.73495337],
       [-0.24198963,  0.58866414],
       [-1.47888824, -0.94561319],
       [-0.80567404,  0.79117236],
       [ 0.08746369, -1.57900372],
       [ 1.01008049,  0.20951358],
       [ 0.38657401,  0.08018421],
       [ 1.08001688, -0.73426743]])

(正如您所看到的,PCA只需要三行numpy代码,因此您不需要为此编写函数。)

我为什么认为这是正确的结果?因为生成的数据集具有一个特性,即协方差矩阵(除了舍入误差)是单位矩阵。 如果不进行缩放,则协方差矩阵是numpy.diag(s[o])。但是也可以认为,通过应用缩放,我“丢失”了本应保留的方差信息。

我认为scipy使用错误(有偏)的协方差,而numpy是正确的。

但更常见的情况是,这并不重要。在上述比率中,偏差被抵消。如果您有一个大型数据集,使用朴素的1/n和无偏的1/(n-1)之间的差异最终变得微不足道。但是,这种差异也没有实际的CPU成本,因此您可以使用无偏的方差估计。


你想使用“有偏差”的版本的原因是通过减去数据的平均值,你失去了一个自由度。换句话说:拥有N个数据点就有N个自由度(每个都独立变化)。现在减去所有数据点的平均值。然后想象一下,你只知道N-1个数据点。你能够得到第N个数据点的值吗?当然可以,因为你知道平均值和其他N-1个值。因此,只有N-1个自由度,这就是你必须考虑的偏差。 - Jesper - jtk.eth
@denvar,“自由度”解释似乎并不被广泛接受为正确。此外,您混淆了有偏和无偏。/N有偏的(因为它系统地低估),而/(N-1)是无偏的。 - Has QUIT--Anony-Mousse
感谢指出有偏见的问题。你能否提供任何关于这个说法不被广泛接受的参考资料? - Jesper - jtk.eth
或者它是在加权样本的情境下。自由度概念崩溃了,但你仍然有偏差。 - Has QUIT--Anony-Mousse
@Anony-Mousse 为什么在使用 sklearn.decomposition.PCA 或者 np.cov 前不必要对数据进行中心化处理呢?另外,我还注意到你在最后使用 (data-mean).dot(e[:,o]) / numpy.sqrt(s[o]) 时进行了中心化处理,并且除以了 sqrt(s[0]),请问这里为什么需要中心化处理并除以该值呢?谢谢! - O.rka
协方差的定义已经包括了居中。但是,如果要使用结果矩阵进行投影,仍然需要居中。 - Has QUIT--Anony-Mousse

1
(1)的简短回答是,当您对去均值数据应用PCA时,您已经对其进行了旋转,并且新向量空间表示具有不同协方差的新随机变量。答案(2)是,如果您想要非归一化特征值,只需对数据的协方差矩阵进行特征分解即可。

更多信息:

使用scipy计算特征值:http://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.eigvals.html

您还可以计算数据矩阵(而不是协方差)的SVD并查看奇异值:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.svd.html

显然,scikit-learn有不同的SVD类型可供尝试。

1
你知道"explained_variance_"是什么意思以及它与特征值的关系吗?看起来"explained_variance_"和"explained_variance_ratio_"通过一个归一化常数相关联,但前者与特征值不匹配。我也找不到任何其他关于使用PCA的例子在互联网上。 - slaw
@slaw请查看帖子。 - Lord Henry Wotton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接