Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在sklearn.decomposition.PCA中,为什么组件为负?_Python_Python 3.x_Numpy_Scikit Learn_Pca - Fatal编程技术网

Python 在sklearn.decomposition.PCA中,为什么组件为负?

Python 在sklearn.decomposition.PCA中,为什么组件为负?,python,python-3.x,numpy,scikit-learn,pca,Python,Python 3.x,Numpy,Scikit Learn,Pca,我正试图跟随Abdi&Williams-(2010)并通过SVD使用构建主要组件 当我使用sklearn显示拟合PCA中的属性时,它们的大小与我手动计算的值完全相同,但一些(并非全部)的符号相反。这是什么原因造成的 更新:下面我的(部分)答案包含一些附加信息 以以下数据为例: from pandas_datareader.data import DataReader as dr import numpy as np from sklearn.decomposition import PCA fr

我正试图跟随Abdi&Williams-(2010)并通过SVD使用构建主要组件

当我使用sklearn显示拟合PCA中的属性时,它们的大小与我手动计算的值完全相同,但一些(并非全部)的符号相反。这是什么原因造成的

更新:下面我的(部分)答案包含一些附加信息

以以下数据为例:

from pandas_datareader.data import DataReader as dr
import numpy as np
from sklearn.decomposition import PCA
from sklearn.preprocessing import scale

# sample data - shape (20, 3), each column standardized to N~(0,1)
rates = scale(dr(['DGS5', 'DGS10', 'DGS30'], 'fred', 
           start='2017-01-01', end='2017-02-01').pct_change().dropna())

# with sklearn PCA:
pca = PCA().fit(rates)
print(pca.components_)
[[-0.58365629 -0.58614003 -0.56194768]
 [-0.43328092 -0.36048659  0.82602486]
 [-0.68674084  0.72559581 -0.04356302]]

# compare to the manual method via SVD:
u, s, Vh = np.linalg.svd(np.asmatrix(rates), full_matrices=False)
print(Vh)
[[ 0.58365629  0.58614003  0.56194768]
 [ 0.43328092  0.36048659 -0.82602486]
 [-0.68674084  0.72559581 -0.04356302]]

# odd: some, but not all signs reversed
print(np.isclose(Vh, -1 * pca.components_))
[[ True  True  True]
 [ True  True  True]
 [False False False]]

在3维的PCA中,您基本上可以迭代地找到:1)保留最大方差的1D投影轴2)垂直于1中的1)最大方差保留轴。第三个轴自动与前两个轴垂直


根据解释的差异列出了成分。第一个解释了最大的差异,依此类推。请注意,根据PCA操作的定义,当您试图在第一步中找到用于投影的向量时(这将最大化保留的方差),向量的符号并不重要:让M作为您的数据矩阵(在您的情况下,形状为(20,3))。假设v1是在投影数据时保持最大方差的向量。当您选择-v1而不是v1时,您将获得相同的方差。(你可以看看这个)。然后,当选择第二个向量时,设v2为垂直于v1并保持最大方差的向量。同样,选择-v2而不是v2将保持相同的差异量。然后,v3可以选择为-v3或v3。这里,唯一重要的是v1、v2、v3构成数据M的正交基。符号主要取决于算法如何解决PCA操作背后的特征向量问题。特征值分解或奇异值分解的解可能有不同的符号。

经过一些挖掘,我已经澄清了一些,但不是全部,我在这方面的困惑。stats.stackexchange中已介绍了此问题。数学上的答案是“PCA是一种简单的数学变换。如果更改分量的符号,则不会更改第一个分量中包含的方差。”然而,在这种情况下(使用
sklearn.PCA
),歧义的来源更为具体:在来源()对于
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
svd\u flip
,依次定义。但我不确定为什么这些标志会被改变为“确保产出”。(此时已找到U、S、V…)。因此,虽然sklearn的实现并不错误,但我认为它并不那么直观。熟悉贝塔(系数)概念的金融界人士都会知道,第一个主成分很可能类似于广义市场指数。问题是,
sklearn
实现将给第一个主组件带来强大的负负载


我的解决方案是一个简化版,它不实现
svd\u flip
。它没有
sklearn
参数,例如
svd\u solver
,但确实有许多专门针对这一目的的方法。

正如您在回答中所指出的,奇异值分解(svd)的结果在奇异向量方面不是唯一的。事实上,如果X的SVD是\sum\u 1^r\s\u i v\u i^ \top:

随着s_i以递减的方式排序,你可以看到你可以改变符号(即“翻转”),比如u_1和v_1,减号会取消,所以公式仍然成立

这表明SVD是唯一的,直到左右奇异向量成对出现符号变化

由于PCA只是X的SVD(或X^\top X的特征值分解),因此不能保证每次执行PCA时不会在同一X上返回不同的结果。可以理解,scikit learn实现想要避免这种情况:它们通过强制(任意)U_i的绝对值中的最大系数为正来保证返回的左奇异向量和右奇异向量(存储在U和V中)总是相同的


如您所见:首先,他们使用
linalg.svd()
计算U和V。然后,对于每个向量u_i(即u的行),如果其绝对值中的最大元素为正,则它们不做任何事情。否则,它们将u_i更改为-u_i,并将相应的左奇异向量v_i更改为-v_i。如前所述,这不会改变SVD公式,因为减号会抵消。但是,现在可以保证在处理后返回的U和V始终是相同的,因为符号上的不确定性已被删除。

对于那些关心目的而不是数学部分的人来说,这是一个简短的通知


尽管某些组件的符号是相反的,但这不应被视为问题。事实上,我们真正关心的(至少在我看来)是轴的方向。最终,组件是在使用pca变换输入数据后识别这些轴的向量。因此,无论每个组件指向哪个方向,我们的数据所在的新轴都是相同的

以下是使用R包进行PCA的解释。按照惯例,这些奇异值都是正数,并按大小排序。@Aryamcarthy我不确定我是否理解你的意思,你能进一步解释一下吗?奇异值为
S
。如果查看PCA,则未触及
S
向量。(在
U,s,V=linalg.svd(X,full_matrices=False)
第391行之后,它已经是正的。正是
U
V
被操纵,以“强制确定性输出”即使已经找到了一个解决方案,如果可以的话,在哪种情况下,非确定性的结果有用?这些仍然是确定性的——这只是一个问题