You need to enable JavaScript to run this app. 从零实现的PCA与scikit-learn输出存在方向差异的原因及解决方法
优惠活动
大模型
产品
解决方案
定价
更多

从零实现的PCA与scikit-learn输出存在方向差异的原因及解决方法

1 sklearn PCA与手写实现的核心差异

导致输出不一致的原因主要有3个:

  • 特征向量的排序逻辑错误
    你当前手写实现里只对特征值做了降序排序计算解释方差,但是numpy.linalg.eig返回的特征值默认不是按大小排序的,你直接取eig_vecs_[:, :self.n_components]并没有对应调整特征向量的顺序,和sklearn严格按特征值降序取主成分的逻辑不一致,会导致主成分顺序错乱、数值差异。
  • 特征向量的符号处理差异
    特征向量乘以任意正负号都不改变其对方差的解释能力,属于PCA的合理歧义。numpy.linalg.eig返回的特征向量符号没有统一规则,而sklearn的PCA内部会对特征向量做符号归一:确保每个主成分的特征向量中绝对值最大的元素为正,避免符号随机翻转。
  • 底层计算逻辑不同
    sklearn的PCA没有采用协方差矩阵特征分解的方案,而是直接对中心化后的数据做奇异值分解(SVD),数值稳定性远高于先算协方差矩阵再做特征分解的方案,两者的数值计算误差有差异,会带来结果的微小数值区别。

2 对齐两者输出的修复方案

按以下步骤修改你的PCA类即可对齐sklearn的输出:

  1. 同步排序特征值与对应特征向量:计算得到特征值、特征向量后,按特征值降序同时重排两者,而不是仅排序特征值。
  2. 统一特征向量符号:对每个特征向量,判断其绝对值最大的元素的符号,如果为负则将整个特征向量乘以-1,和sklearn的处理逻辑对齐。
  3. 显式对输入数据做中心化,和sklearn的预处理逻辑完全对齐。

修改后的fit_transform核心代码参考:

def fit_transform(self, X : np.ndarray):
    if not self.n_components:
        self.n_components = min(X.shape)
    # 显式中心化,和sklearn逻辑一致
    X_centered = X - np.mean(X, axis=0)
    self.covariance_ = np.cov(X_centered.T)

    # 计算特征值、特征向量
    self.eig_vals_, self.eig_vecs_ = np.linalg.eig(self.covariance_)
    
    # 按特征值降序同步排序特征值和特征向量
    sorted_idx = np.argsort(self.eig_vals_)[::-1]
    self.eig_vals_ = self.eig_vals_[sorted_idx]
    self.eig_vecs_ = self.eig_vecs_[:, sorted_idx]

    # 统一特征向量符号:每个主成分最大绝对值元素为正
    for i in range(self.eig_vecs_.shape[1]):
        max_abs_idx = np.argmax(np.abs(self.eig_vecs_[:, i]))
        if self.eig_vecs_[max_abs_idx, i] < 0:
            self.eig_vecs_[:, i] *= -1

    # 计算解释方差
    _tot_eig_vals = sum(self.eig_vals_)
    self.explained_variance_ = np.array([(i / _tot_eig_vals) * 100 for i in self.eig_vals_])
    self.cum_explained_variance_ = np.cumsum(self.explained_variance_)

    self.W_ = self.eig_vecs_[:, :self.n_components]
    return X_centered.dot(self.W_)

修改后再测试鸢尾花数据集,输出和sklearn PCA的结果就会几乎完全一致,散点图也不会出现方向翻转的问题。

内容的提问来源于stack exchange,提问作者Mr. Hobo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 14:45:08