Sklearn TruncatedSVD 没有按降序显示解释的方差比,或者第一个数字有其他含义?

Sklearn TruncatedSVD not showing explained variance ration in descending order, or first number means something else?

from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.decomposition import TruncatedSVD 

digits = datasets.load_digits()
X = digits.data
X = X - X.mean() # centering the data

#### svd
svd = TruncatedSVD(n_components=5)
svd.fit(X)
print(svd.explained_variance_ration)

####  PCA
pca = PCA(n_components=5)
pca.fit(X)
print(pca.explained_variance_ratio_)

svd 输出为:

array([0.02049911, 0.1489056 , 0.13534811, 0.11738598, 0.08382797])

pca 输出为:

 array([0.14890594, 0.13618771, 0.11794594, 0.08409979, 0.05782415])

TruncatedSVD 实现中是否存在错误?或者为什么第一个解释的方差 (0.02...) 表现得像这样?或者是什么意思

总结:

那是因为TruncatedSVDPCA使用了不同的SVD函数!

注意:您的案例是由于下面的原因 2,但我为未来的读者提供了另一个原因。

详情:

原因1:用户在每个算法中设置的求解器不同:

PCA 内部使用 scipy.linalg.svd 对奇异值进行排序,因此 explained_variance_ratio_ 被排序。

PCA 的部分 Scikit 实现:

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

components_ = Vt

# Get variance explained by singular values
explained_variance_ = (S ** 2) / (n_samples - 1)
total_var = explained_variance_.sum()
explained_variance_ratio_ = explained_variance_ / total_var

上面的截图scipy.linalg.svd link:

另一方面,TruncatedSVD 使用 scipy.sparse.linalg.svds,它依赖于 ARPACK 解算器进行分解。

上面的截图scipy.sparse.linalg.svds link:


原因 2:TruncatedSVD 的运行方式与 PCA 不同:

在您的情况下,您在两种算法中都选择了 randomized 作为求解器(默认设置),但您在方差阶数方面获得了不同的结果。

那是因为在PCA中,方差是从已经排序的实际奇异值(在Scikit-Learn实现中称为SigmaS)中获得的:

另一方面,TruncatedSVD 中的方差是从 X_transformed 中获得的,它是数据矩阵乘以分量的结果。后者不一定保留顺序,因为数据不居中,也不是 TruncatedSVD 的目的,它首先用于稀疏矩阵:

现在,如果您将数据居中,就会对它们进行排序(请注意,您没有正确居中数据,因为居中需要除以标准差):

from sklearn import datasets
from sklearn.decomposition import TruncatedSVD
from sklearn.preprocessing import StandardScaler

digits = datasets.load_digits()
X = digits.data

sc = StandardScaler()
X = sc.fit_transform(X)

### SVD
svd = TruncatedSVD(n_components=5, algorithm='randomized', random_state=2021)
svd.fit(X)
print(svd.explained_variance_ratio_)

输出

[0.12033916 0.09561054 0.08444415 0.06498406 0.04860093]

Important: Further read.