主成分分析与核主成分分析的对比

机器学习领域,数据降维是一个重要的步骤,它可以帮助减少模型的复杂度,提高计算效率。主成分分析(PCA)是一种常用的线性降维技术,而核主成分分析(KernelPCA)则是其非线性版本的扩展。本文将通过一个具体的例子,展示这两种技术在处理非线性可分数据集时的不同表现。

数据集的生成与初步观察

首先,生成了一个包含两个嵌套圆的数据集。这个数据集的特点是,内部的圆完全被外部的圆所包围,因此使用线性方法无法将两个类别的数据点分开。使用matplotlib库来可视化这个数据集,以便更直观地理解数据的分布情况。

from sklearn.datasets import make_circles from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt X, y = make_circles(n_samples=1000, 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) fig, (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("特征 #1") train_ax.set_xlabel("特征 #0") train_ax.set_title("训练数据") test_ax.scatter(X_test[:,0], X_test[:,1], c=y_test) test_ax.set_xlabel("特征 #0") test_ax.set_title("测试数据")

通过上述代码,可以看到,训练数据和测试数据都显示了两个类别的数据点是相互重叠的,这意味着不能通过一条直线来区分这两个类别。

PCA与KernelPCA的投影效果对比

接下来,将使用PCA和KernelPCA对数据进行投影,并比较两者的效果。在PCA中,数据将被线性变换,而在KernelPCA中,将使用径向基函数(RBF)核来实现非线性变换。

from sklearn.decomposition import PCA, KernelPCA pca = PCA(n_components=2) kernel_pca = KernelPCA(n_components=None, kernel="rbf", gamma=10, fit_inverse_transform=True, alpha=0.1) X_test_pca = pca.fit(X_train).transform(X_test) X_test_kernel_pca = kernel_pca.fit(X_train).transform(X_test) 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("特征 #1") orig_data_ax.set_xlabel("特征 #0") orig_data_ax.set_title("测试数据") pca_proj_ax.scatter(X_test_pca[:,0], X_test_pca[:,1], c=y_test) pca_proj_ax.set_ylabel("主成分 #1") pca_proj_ax.set_xlabel("主成分 #0") pca_proj_ax.set_title("使用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("主成分 #1") kernel_pca_proj_ax.set_xlabel("主成分 #0") kernel_pca_proj_ax.set_title("使用KernelPCA的测试数据投影")

在PCA的投影结果中,可以看到数据并没有发生明显的分离,因为原始数据已经是各向同性的,即两个圆心都位于原点。然而,通过KernelPCA的非线性投影,成功地将两个类别的数据点分开了,这表明KernelPCA在处理非线性可分数据集时具有明显的优势。

数据的反向投影

在使用KernelPCA时,需要注意的是,反向投影(即从投影空间回到原始特征空间)可能不会像PCA那样精确。这是因为KernelPCA的反向投影依赖于一个内部训练的KernelRidge模型,这个模型学习从核化PCA基到原始特征空间的映射。因此,反向投影的结果会有一定的近似误差。

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("特征 #1") orig_data_ax.set_xlabel("特征 #0") orig_data_ax.set_title("原始测试数据") pca_back_proj_ax.scatter(X_reconstructed_pca[:,0], X_reconstructed_pca[:,1], c=y_test) pca_back_proj_ax.set_xlabel("特征 #0") pca_back_proj_ax.set_title("通过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("特征 #0") kernel_pca_back_proj_ax.set_title("通过KernelPCA的重构")

通过上述代码,可以看到PCA的反向投影结果与原始数据完全一致,而KernelPCA的反向投影则存在一定的误差。这种误差可以通过调整KernelPCA中的正则化项alpha来减小,从而提高反向投影的精度。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485