均值为0时PCA与Truncated SVD投影结果不一致的原因及解决方法
问题原因分析
- 第一点是你对
StandardScaler的参数理解错误:你注释中写with_mean=False可以将特征均值置为0,实际刚好相反,with_mean=True时缩放器才会执行减去特征均值的中心化操作,你当前配置下X_scaled和原始数据完全一致,根本没有做到特征均值为0。 - 第二点是两个算法类的默认行为存在差异:scikit-learn的
PCA类默认会自动对输入数据做均值中心化,无论你输入是否提前做过处理;而TruncatedSVD不会对输入做任何中心化操作,直接对原始输入矩阵执行SVD分解。二者实际计算的输入矩阵不一致,输出结果自然存在明显差异。
修复方案
如果要验证「特征均值为0时PCA和SVD投影结果一致」的结论,修改代码如下即可:
from sklearn import datasets import numpy as np cancer = datasets.load_breast_cancer() from sklearn.preprocessing import StandardScaler # 正确执行均值中心化,只去均值不做标准差缩放 scaler = StandardScaler(with_mean=True, with_std=False) X_centered = scaler.fit_transform(cancer.data) from sklearn.decomposition import PCA # 关闭PCA自带的中心化,因为我们已经提前完成了处理 pca=PCA(n_components=3, svd_solver='randomized', center=False, random_state=42) X_pca=pca.fit_transform(X_centered) from sklearn.decomposition import TruncatedSVD svdm=TruncatedSVD(n_components=3, algorithm='randomized', random_state=42) X_svdm=svdm.fit_transform(X_centered)
修改后你可以通过print(np.allclose(np.abs(X_pca), np.abs(X_svdm)))验证结果一致性,返回True即说明二者投影结果仅存在符号差异,本质等价。
注:随机SVD算法的奇异向量符号是随机的,只要设置相同的随机种子即可保证符号也完全一致。
内容的提问来源于stack exchange,提问作者Thomas Iskandar
相关产品推荐
相关产品推荐

