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

Bra*_*mon 13 python numpy pca python-3.x scikit-learn

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

当我components_从带有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]]
Run Code Online (Sandbox Code Playgroud)

P. *_*eri 8

正如您在答案中所发现的那样,奇异值分解(SVD)的结果在奇异向量方面并不是唯一的.实际上,如果X的SVD是\ sum_1 ^ r\s_i u_i v_i ^\top: 在此输入图像描述

随着s_i以递减方式排序,那么您可以看到您可以更改说u_1和v_1的符号(即"翻转"),减号将取消,因此公式仍将保留.

这表明SVD 在左右奇异向量对的符号变化中是唯一的.

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

正如你所看到的阅读来源:第一,他们计算U和V带linalg.svd().然后,对于每个向量u_i(即U行),如果其绝对值中的最大元素是正数,则它们不做任何事情.否则,它们将u_i改为 - u_i,并将相应的左奇异向量v_i改为 - v_i.如前所述,由于减号取消,因此不会改变SVD公式.但是,现在可以保证在此处理之后返回的U和V总是相同的,因为已经消除了符号上的不确定性.