使用 PCA 进行降维
Scikit-learn - 使用 PCA 进行降维
Section titled “Scikit-learn - 使用 PCA 进行降维”降维 (Dimensionality reduction) 是通过获得一组主变量来减少考虑的随机变量(特征)数量的过程。它是机器学习中用于可视化、提高计算效率和缓解“维度灾难”的关键技术。主成分分析 (Principal Component Analysis, PCA) 是最流行的线性降维算法之一。
PCA 旨在找到最大化数据方差的方向(主成分),并将数据投影到由这些主成分形成的新低维子空间上。
精确 PCA
Section titled “精确 PCA”标准 PCA 使用数据的奇异值分解 (Singular Value Decomposition, SVD) 执行线性降维,将其投影到较低维度的空间。默认情况下,PCA 会对数据进行中心化(从每个特征中减去均值),但在应用 SVD 之前不会对其进行缩放。如果特征具有不同的单位或比例,通常建议将缩放(例如,使用 StandardScaler)作为预处理步骤。
Scikit-learn 的 sklearn.decomposition.PCA 模块实现为一个 transformer 对象。它在其 fit() 方法中学习主成分,然后可以使用 transform() 将数据投影到这些主成分上。
示例:在 Wine 数据集上应用 PCA
Section titled “示例:在 Wine 数据集上应用 PCA”Wine 数据集有 13 个特征。我们将使用 PCA 将其降维到较少数量的主成分,并检查解释的方差。
from sklearn.datasets import load_winefrom sklearn.preprocessing import StandardScalerfrom sklearn.decomposition import PCAimport numpy as np
# Load the Wine datasetwine = load_wine()X, y = wine.data, wine.target
# It's good practice to scale data before PCAscaler = StandardScaler()X_scaled = scaler.fit_transform(X)
# Apply PCA, let's reduce to 3 componentspca = PCA(n_components=3)pca.fit(X_scaled) # Fit PCA on scaled dataX_pca = pca.transform(X_scaled) # Transform data to principal components
print(f"Original shape: {X_scaled.shape}")print(f"Reduced shape after PCA: {X_pca.shape}")
print(f"\nExplained variance ratio by each component: {pca.explained_variance_ratio_}")print(f"Total explained variance by 3 components: {np.sum(pca.explained_variance_ratio_):.4f}")
# The components themselves (eigenvectors)# print(f"\nPrincipal components (eigenvectors):\n{pca.components_}")输出 (解释的方差可能因实现细节略有差异,但总体趋势一致)
Section titled “输出 (解释的方差可能因实现细节略有差异,但总体趋势一致)”Original shape: (178, 13)Reduced shape after PCA: (178, 3)
Explained variance ratio by each component: [0.36198848 0.1920749 0.11123631]Total explained variance by 3 components: 0.6653explained_variance_ratio_ 属性显示了每个选定主成分解释的方差百分比。如果 n_components 设置为整数,则指定主成分的数量。如果它是一个介于 0 和 1 之间的浮点数(例如 0.95),PCA 将选择足够数量的主成分,使得需要解释的方差量大于指定的百分比。
增量 PCA (IPCA)
Section titled “增量 PCA (IPCA)”增量主成分分析 (Incremental Principal Component Analysis, IPCA) 对于无法完全载入内存的大型数据集非常有用。它允许对 mini-batches(小批量)数据进行部分计算,使其适用于外存学习 (out-of-core learning)。IPCA 使用其 partial_fit() 方法分块处理数据。
Scikit-learn 提供了 sklearn.decomposition.IncrementalPCA。与 PCA 类似,IPCA 会对数据进行中心化,但不会对其进行缩放。
示例:在 Digits 数据集上应用 IPCA
Section titled “示例:在 Digits 数据集上应用 IPCA”我们将使用 Digits 数据集来演示 IPCA。
from sklearn.datasets import load_digitsfrom sklearn.preprocessing import StandardScalerfrom sklearn.decomposition import IncrementalPCA
# Load digits datasetX, y = load_digits(return_X_y=True)
# Scale datascaler = StandardScaler()X_scaled = scaler.fit_transform(X)
# Initialize IPCA# n_components: target number of components# batch_size: number of samples to use for each batchipca = IncrementalPCA(n_components=10, batch_size=200)
# Fit IPCA incrementally (or use fit() which handles batching)# For demonstration, explicitly using partial_fit (not strictly necessary if using fit() later)# for batch in np.array_split(X_scaled, len(X_scaled) // 200):# ipca.partial_fit(batch)
X_ipca = ipca.fit_transform(X_scaled) # fit() can also handle batching internally
print(f"Original shape: {X_scaled.shape}")print(f"Reduced shape after IPCA: {X_ipca.shape}")print(f"Total explained variance by 10 components (IPCA): {np.sum(ipca.explained_variance_ratio_):.4f}")Original shape: (1797, 64)Reduced shape after IPCA: (1797, 10)Total explained variance by 10 components (IPCA): 0.5338核 PCA (KPCA)
Section titled “核 PCA (KPCA)”核主成分分析 (Kernel Principal Component Analysis, KPCA) 是 PCA 的扩展,它使用核函数实现非线性降维。通过核函数将数据映射到更高维度的特征空间,KPCA 可以找到线性 PCA 无法发现的非线性关系。
Scikit-learn 提供了 sklearn.decomposition.KernelPCA。关键参数包括 n_components、kernel(例如,‘linear’、‘rbf’、‘poly’、‘sigmoid’)以及核特有参数,如 gamma 或 degree。
示例:在 Digits 数据集上应用核 PCA
Section titled “示例:在 Digits 数据集上应用核 PCA”from sklearn.datasets import load_digitsfrom sklearn.preprocessing import StandardScalerfrom sklearn.decomposition import KernelPCA
# Load digits datasetX, y = load_digits(return_X_y=True)
# Scale datascaler = StandardScaler()X_scaled = scaler.fit_transform(X)
# Initialize Kernel PCA# Using 'rbf' kernel, a common choice for non-linear mappingskpca = KernelPCA(n_components=10, kernel='rbf', gamma=None, random_state=42)# gamma=None will use 1/n_features
X_kpca = kpca.fit_transform(X_scaled)
print(f"Original shape: {X_scaled.shape}")print(f"Reduced shape after Kernel PCA: {X_kpca.shape}")# Note: explained_variance_ratio_ is not directly available for KernelPCA in the same way as PCA# Eigenvalues can be accessed via kpca.eigenvalues_Original shape: (1797, 64)Reduced shape after Kernel PCA: (1797, 10)KPCA 的计算成本可能比线性 PCA 高,特别是对于大型数据集。核函数的选择及其参数对于良好性能至关重要。
使用随机 SVD 的 PCA
Section titled “使用随机 SVD 的 PCA”对于非常大的数据集(样本数和/或特征数很多),计算完整的 SVD 可能很慢。随机 SVD 提供了一种有效的方法来近似最重要的奇异值和奇异向量。Scikit-learn 的 PCA estimator 通过设置 svd_solver='randomized' 参数可以使用随机 SVD。当要保留的主成分数量 (n_components) 远小于特征数或样本数时,这尤其有用。
示例:在 Wine 数据集上应用随机 PCA
Section titled “示例:在 Wine 数据集上应用随机 PCA”from sklearn.datasets import load_winefrom sklearn.preprocessing import StandardScalerfrom sklearn.decomposition import PCAimport numpy as np
# Load the Wine datasetwine = load_wine()X, y = wine.data, wine.target
# Scale datascaler = StandardScaler()X_scaled = scaler.fit_transform(X)
# Apply PCA with randomized SVD# This is often faster for large datasets when n_components is smallr_pca = PCA(n_components=3, svd_solver='randomized', random_state=42)r_pca.fit(X_scaled)X_rpca = r_pca.transform(X_scaled)
print(f"Original shape: {X_scaled.shape}")print(f"Reduced shape after Randomized PCA: {X_rpca.shape}")
print(f"\nExplained variance ratio (Randomized PCA): {r_pca.explained_variance_ratio_}")print(f"Total explained variance by 3 components (Randomized PCA): {np.sum(r_pca.explained_variance_ratio_):.4f}")输出 (对于较小的数据集,结果应与精确 PCA 非常相似)
Section titled “输出 (对于较小的数据集,结果应与精确 PCA 非常相似)”Original shape: (178, 13)Reduced shape after Randomized PCA: (178, 3)
Explained variance ratio (Randomized PCA): [0.36198848 0.1920749 0.11123631]Total explained variance by 3 components (Randomized PCA): 0.6653其他 svd_solver 选项包括 ‘auto’ (默认,根据数据大小和 n_components 选择求解器)、‘full’ (精确的完整 SVD) 和 ‘arpack’ (适用于稀疏数据或当 n_components 相对于 min(n_samples, n_features) 非常小时)。