【问题标题】:Is there a way to compute the explained variance of PCA on a test set?有没有办法计算测试集上 PCA 的解释方差?
【发布时间】:2019-12-21 10:23:42
【问题描述】:

我想看看 PCA 处理我的数据的效果如何。

我将 PCA 应用于训练集,并使用返回的 pca 对象在测试集上进行转换。 pca 对象有一个变量pca.explained_variance_ratio_,它告诉我训练集的每个选定组件解释的方差百分比。应用 pca 变换后,我想看看它在测试集上的效果如何。我尝试了inverse_transform(),它返回了原始值的样子,但我无法比较它在训练集和测试集上的工作方式。

pca = PCA(0.99)
pca.fit(train_df)  
tranformed_test = pca.transform(test_df)
inverse_test = pca.inverse_transform(tranformed_test)
npt.assert_almost_equal(test_arr, inverse_test, decimal=2)

这会返回:

数组几乎不等于 2 位小数

transform() 后面有类似pca.explained_variance_ratio_ 的东西吗?

【问题讨论】:

  • 对不起,如果我没有正确理解,您想知道在应用 pca 之前和之后对同一数据集 (test_df) 中的每个变量解释的错误总和吗?
  • 是的,这也是值得探索的东西

标签: python python-3.x scikit-learn pca variance


【解决方案1】:

解释每个组件的差异

您可以手动计算。 如果组件X_i 是正交的(PCA 中就是这种情况),则X_iX 的解释方差为:1 - ||X_i - X||^2 / ||X - X_mean||^2

因此以下示例:

import numpy as np
from sklearn.decomposition import PCA

X_train = np.random.randn(200, 5)
X_test = np.random.randn(100, 5)
model = PCA(n_components=5).fit(X_train)

def explained_variance(X):
    result = np.zeros(model.n_components)
    for ii in range(model.n_components):
        X_trans = model.transform(X)
        X_trans_ii = np.zeros_like(X_trans)
        X_trans_ii[:, ii] = X_trans[:, ii]
        X_approx_ii = model.inverse_transform(X_trans_ii)

        result[ii] = 1 - (np.linalg.norm(X_approx_ii - X) /
                          np.linalg.norm(X - model.mean_)) ** 2
    return result


print(model.explained_variance_ratio_)
print(explained_variance(X_train))
print(explained_variance(X_test))
# [0.25335711 0.23100201 0.2195476  0.15717412 0.13891916]
# [0.25335711 0.23100201 0.2195476  0.15717412 0.13891916]
# [0.17851083 0.199134   0.24198887 0.23286815 0.14749816]

总方差解释 h1>

或者,如果您只关心总方差,则可以使用r2_score

from sklearn.metrics import r2_score

model = PCA(n_components=2).fit(X_train)
print(model.explained_variance_ratio_.sum())
print(r2_score(X_train, model.inverse_transform(model.transform(X_train)),
               multioutput='variance_weighted'))
print(r2_score(X_test, model.inverse_transform(model.transform(X_test)),
               multioutput='variance_weighted'))
# 0.46445451252373826
# 0.46445451252373815
# 0.4470229486590848

【讨论】:

  • 我最终使用均方误差,但这些选项似乎更好 - 非常感谢!! @TomDLT
猜你喜欢
  • 1970-01-01
  • 2019-12-09
  • 1970-01-01
  • 2019-05-05
  • 2017-09-30
  • 1970-01-01
  • 2016-01-30
  • 2015-05-13
  • 2015-06-19
相关资源
最近更新 更多