核 PCA#
本示例展示了主成分分析 (PCA
) 与其核化版本 (KernelPCA
) 之间的区别。
一方面,我们展示了 KernelPCA
能够找到数据的投影,该投影可以线性分离它们,而 PCA
则不能。
最后,我们展示了反转此投影对于 KernelPCA
是一种近似,而对于 PCA
则是精确的。
# Authors: Mathieu Blondel
# Andreas Mueller
# Guillaume Lemaitre
# License: BSD 3 clause
投影数据:PCA
与 KernelPCA
#
在本节中,我们将展示在使用主成分分析 (PCA) 投影数据时使用核的优势。我们创建一个由两个嵌套圆组成的数据集。
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split
X, y = make_circles(n_samples=1_000, factor=0.3, noise=0.05, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=0)
让我们先快速浏览一下生成的数据集。
import matplotlib.pyplot as plt
_, (train_ax, test_ax) = plt.subplots(ncols=2, sharex=True, sharey=True, figsize=(8, 4))
train_ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train)
train_ax.set_ylabel("Feature #1")
train_ax.set_xlabel("Feature #0")
train_ax.set_title("Training data")
test_ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test)
test_ax.set_xlabel("Feature #0")
_ = test_ax.set_title("Testing data")
每个类的样本不能线性分离:没有直线可以将内部集的样本与外部集的样本分开。
现在,我们将使用带核和不带核的 PCA 来查看使用这种核的效果。这里使用的核是径向基函数 (RBF) 核。
fig, (orig_data_ax, pca_proj_ax, kernel_pca_proj_ax) = plt.subplots(
ncols=3, figsize=(14, 4)
)
orig_data_ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test)
orig_data_ax.set_ylabel("Feature #1")
orig_data_ax.set_xlabel("Feature #0")
orig_data_ax.set_title("Testing data")
pca_proj_ax.scatter(X_test_pca[:, 0], X_test_pca[:, 1], c=y_test)
pca_proj_ax.set_ylabel("Principal component #1")
pca_proj_ax.set_xlabel("Principal component #0")
pca_proj_ax.set_title("Projection of testing data\n using PCA")
kernel_pca_proj_ax.scatter(X_test_kernel_pca[:, 0], X_test_kernel_pca[:, 1], c=y_test)
kernel_pca_proj_ax.set_ylabel("Principal component #1")
kernel_pca_proj_ax.set_xlabel("Principal component #0")
_ = kernel_pca_proj_ax.set_title("Projection of testing data\n using KernelPCA")
我们记得 PCA 对数据进行线性变换。直观地说,这意味着坐标系将居中,并在每个分量上相对于其方差重新缩放,最后旋转。从这种变换获得的数据是各向同性的,现在可以投影到其*主成分*上。
因此,查看使用 PCA 进行的投影(即中间图),我们发现缩放方面没有变化;实际上,数据是两个以零为中心的同心圆,原始数据已经是各向同性的。但是,我们可以看到数据已经旋转。总而言之,我们发现,如果定义线性分类器来区分来自两个类的样本,这种投影将无济于事。
使用核允许进行非线性投影。在这里,通过使用 RBF 核,我们期望投影将展开数据集,同时保持近似保留原始空间中彼此接近的数据点对的相对距离。
我们在右图中观察到这种行为:给定类的样本彼此之间的距离比来自相反类的样本更近,从而解开了两个样本集。现在,我们可以使用线性分类器来分离来自这两个类的样本。
投影到原始特征空间#
使用 KernelPCA
时要记住的一个特殊性与重建(即在原始特征空间中的反向投影)有关。使用 PCA
,如果 n_components
与原始特征的数量相同,则重建将是精确的。在本例中就是这种情况。
我们可以研究一下,当使用 KernelPCA
进行反向投影时,是否可以获得原始数据集。
X_reconstructed_pca = pca.inverse_transform(pca.transform(X_test))
X_reconstructed_kernel_pca = kernel_pca.inverse_transform(kernel_pca.transform(X_test))
fig, (orig_data_ax, pca_back_proj_ax, kernel_pca_back_proj_ax) = plt.subplots(
ncols=3, sharex=True, sharey=True, figsize=(13, 4)
)
orig_data_ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test)
orig_data_ax.set_ylabel("Feature #1")
orig_data_ax.set_xlabel("Feature #0")
orig_data_ax.set_title("Original test data")
pca_back_proj_ax.scatter(X_reconstructed_pca[:, 0], X_reconstructed_pca[:, 1], c=y_test)
pca_back_proj_ax.set_xlabel("Feature #0")
pca_back_proj_ax.set_title("Reconstruction via PCA")
kernel_pca_back_proj_ax.scatter(
X_reconstructed_kernel_pca[:, 0], X_reconstructed_kernel_pca[:, 1], c=y_test
)
kernel_pca_back_proj_ax.set_xlabel("Feature #0")
_ = kernel_pca_back_proj_ax.set_title("Reconstruction via KernelPCA")
虽然我们看到使用 PCA
可以完美地重建,但我们观察到 KernelPCA
的结果不同。
实际上,inverse_transform
不能依赖分析反向投影,因此不能进行精确的重建。相反,在内部训练 KernelRidge
来学习从核化 PCA 基到原始特征空间的映射。因此,这种方法在原始特征空间中进行反向投影时会引入小的差异,从而产生近似值。
为了改进使用 inverse_transform
进行的重建,可以在 KernelPCA
中调整 alpha
,它是控制在映射训练期间对训练数据的依赖程度的正则化项。
**脚本总运行时间:**(0 分钟 0.709 秒)
相关示例