scikit-learn 内核 PCA 解释方差

Posted

技术标签:

【中文标题】scikit-learn 内核 PCA 解释方差【英文标题】:scikit-learn kernel PCA explained variance 【发布时间】:2015-06-19 03:33:22 【问题描述】:

我一直在使用来自 scikit-learn 的普通 PCA,并且没有任何问题地获得每个主成分的方差比。

pca = sklearn.decomposition.PCA(n_components=3)
pca_transform = pca.fit_transform(feature_vec)
var_values = pca.explained_variance_ratio_

我想使用内核 PCA 探索不同的内核,并且还想要解释的方差比,但我现在看到它没有这个属性。有谁知道如何获取这些值?

kpca = sklearn.decomposition.KernelPCA(kernel=kernel, n_components=3)
kpca_transform = pca.fit_transform(feature_vec)
var_values = kpca.explained_variance_ratio_

AttributeError: 'KernelPCA' 对象没有属性 'explained_variance_ratio_'

【问题讨论】:

【参考方案1】:

我知道这个问题很老,但是当我意识到pca.explained_variance_ 只是组件的方差时,我遇到了同样的“问题”并找到了一个简单的解决方案。您可以通过以下方式简单地计算解释的方差(和比率):

kpca_transform = kpca.fit_transform(feature_vec)
explained_variance = numpy.var(kpca_transform, axis=0)
explained_variance_ratio = explained_variance / numpy.sum(explained_variance)

作为奖励,获得解释方差的累积比例(通常用于选择组件和估计空间的维度):

numpy.cumsum(explained_variance_ratio)

【讨论】:

很好的发现!只是一个简短的说明:这仅在您考虑 n-1 个组件时才有效。其中 n 是数据集中的特征数。 @yellow01 如果我考虑少于 n-1 个组件,为什么我没有收到错误消息? 我认为这是不对的。我相信@Krishna Kalyan 是对的(答案如下) 这个答案肯定是错误的,根本原因是:如果你在 KPCA 中给出 N 个分量,那么前 N 个分量不计入 100% 方差。但是您的代码只是给出了这样的结果。【参考方案2】:

K-PCA 没有explained_variance_ratio_ 的主要原因是因为在内核转换后您的数据/向量存在于不同的特征空间中。因此,K-PCA 不应该像 PCA 那样被解释。

【讨论】:

【参考方案3】:

我也对此很感兴趣,所以我做了一些测试。下面是我的代码。

这些图将显示 kernelpca 的第一个组件是数据集的更好鉴别器。但是,当根据@EelkeSpaak 解释计算解释的方差比率时,我们看到只有 50% 的方差解释比率没有意义。因此,我倾向于同意@Krishna Kalyan 的解释。

#get data
from sklearn.datasets import make_moons 
import numpy as np
import matplotlib.pyplot as plt

x, y = make_moons(n_samples=100, random_state=123)
plt.scatter(x[y==0, 0], x[y==0, 1], color='red', marker='^', alpha=0.5)
plt.scatter(x[y==1, 0], x[y==1, 1], color='blue', marker='o', alpha=0.5)
plt.show()

##seeing effect of linear-pca-------
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
x_pca = pca.fit_transform(x)

x_tx = x_pca
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(7,3))
ax[0].scatter(x_tx[y==0, 0], x_tx[y==0, 1], color='red', marker='^', alpha=0.5)
ax[0].scatter(x_tx[y==1, 0], x_tx[y==1, 1], color='blue', marker='o', alpha=0.5)
ax[1].scatter(x_tx[y==0, 0], np.zeros((50,1))+0.02, color='red', marker='^', alpha=0.5)
ax[1].scatter(x_tx[y==1, 0], np.zeros((50,1))-0.02, color='blue', marker='o', alpha=0.5)
ax[0].set_xlabel('PC-1')
ax[0].set_ylabel('PC-2')
ax[0].set_ylim([-0.8,0.8])
ax[1].set_ylim([-0.8,0.8])
ax[1].set_yticks([])
ax[1].set_xlabel('PC-1')
plt.show()

##seeing effect of kernelized-pca------
from sklearn.decomposition import KernelPCA
kpca = KernelPCA(n_components=2, kernel='rbf', gamma=15)
x_kpca = kpca.fit_transform(x)


x_tx = x_kpca
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(7,3))
ax[0].scatter(x_tx[y==0, 0], x_tx[y==0, 1], color='red', marker='^', alpha=0.5)
ax[0].scatter(x_tx[y==1, 0], x_tx[y==1, 1], color='blue', marker='o', alpha=0.5)
ax[1].scatter(x_tx[y==0, 0], np.zeros((50,1))+0.02, color='red', marker='^', alpha=0.5)
ax[1].scatter(x_tx[y==1, 0], np.zeros((50,1))-0.02, color='blue', marker='o', alpha=0.5)
ax[0].set_xlabel('PC-1')
ax[0].set_ylabel('PC-2')
ax[0].set_ylim([-0.8,0.8])
ax[1].set_ylim([-0.8,0.8])
ax[1].set_yticks([])
ax[1].set_xlabel('PC-1')
plt.show()

##comparing the 2 pcas-------

#get the transformer
tx_pca = pca.fit(x)
tx_kpca = kpca.fit(x)

#transform the original data
x_pca = tx_pca.transform(x)
x_kpca = tx_kpca.transform(x)

#for the transformed data, get the explained variances
expl_var_pca = np.var(x_pca, axis=0)
expl_var_kpca = np.var(x_kpca, axis=0)
print('explained variance pca: ', expl_var_pca)
print('explained variance kpca: ', expl_var_kpca)

expl_var_ratio_pca = expl_var_pca / np.sum(expl_var_pca)
expl_var_ratio_kpca = expl_var_kpca / np.sum(expl_var_kpca)

print('explained variance ratio pca: ', expl_var_ratio_pca)
print('explained variance ratio kpca: ', expl_var_ratio_kpca)

【讨论】:

将图添加到答案中 这是 SO 中需要的证明类型!【参考方案4】:

使用特征值,它会提供您需要的类似信息和直觉:

pca = KernelPCA(n_components=30, kernel="rbf")
pca.fit(x)
var_values = pca.eigenvalues_ / sum(pca.eigenvalues_)
print(sum(var_values))
plt.plot(np.arange(1, pca.n_components + 1), var_values, "+", linewidth=2)
plt.ylabel("PCA explained variance ratio")
plt.show()

【讨论】:

以上是关于scikit-learn 内核 PCA 解释方差的主要内容,如果未能解决你的问题,请参考以下文章

sklearn 中的因子分析:解释方差

机器学习实战—降维

使用 scikit-learn PCA 找到具有最高方差的维度

最大方差和最小协方差解释(线性代数看PCA)

Pyspark 和 PCA:如何提取此 PCA 的特征向量?我如何计算他们解释的方差有多大?

R语言进行主成分分析(PCA):使用prcomp函数来做主成分分析使用summary函数查看主成分分析的结果计算每个主成分解释方差的每个主成分解释的方差的比例以及多个主成分累积解释的方差比例