我正试图跟随Abdi&Williams-Principal Component Analysis(2010),并使用numpy.linalg.svd通过SVD构建主要组件.

当我用sklearn显示拟合PCA的components_属性时,它们的大小与我手动计算的完全相同,但some(不是全部)的符号相反.这是什么原因?

Update:我下面的(部分)答案包含一些额外的信息.

以以下数据为例:

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]]

推荐答案

正如你在回答中所指出的,奇异值分解(SVD)的结果在奇异向量方面不是唯一的.实际上,如果X的SVD是\sum_1^r\s_i u i v_i^ \top:

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

这表明SVD是独一无二的up to a change in sign in pairs of left and right singular vectors.

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

正如你看到的阅读the source:首先,他们用linalg.svd()计算U和V.然后,对于每个向量u_i(即u的行),如果其绝对值中的最大元素为正,则它们什么也不做.否则,它们将u_i更改为-u_i,并将相应的左奇异向量v_i更改为-v_i.如前所述,这不会更改奇异值分解公式,因为减号会抵消.然而,现在可以保证,由于符号上的不确定性已被删除,因此在此处理后返回的U和V始终相同.

Python-3.x相关问答推荐

Pandas—在特定列上比较两行双框,并根据特定条件保留其中一行?

如果行在所有上级索引中都为0,如何删除下级索引行?

使用 iloc 或 loc 对多列进行过滤

如何将函数映射到所有命名元组的元素?

python 分代垃圾收集:get_count 没有报告正确的对象创建数?

无法使用 curve_fit() 在 python 中复制高斯函数的曲线拟合

在 pytest 中,如何测试 sys.exit('some error message')?

将两列合并为一列,将它们制成字典 - pandas - groupby

包含值超出范围的 ID 的新 DataFrame 列?

为什么 Sympy 不能解决我的非线性系统? Python 解释器一直在执行,直到我终止进程

在python中循环处理时并行写入文件

在 sklearn.decomposition.PCA 中,为什么 components_ 是负数?

全局捕获快速 api 中的异常

tensorflow 中 numpy.newaxis 的替代方案是什么?

用 numpy nan 查找列表的最大值

使用 Tensorflow 2.0 在 MNIST 上实现自定义神经网络?

如何替换 Python pathlib.Path 中的子字符串?

我可以替换 Python 中对象的现有方法吗?

哪个更有效:Python 文档字符串还是类型提示?

在 Meta 中创建具有动态模型的通用序列化程序