用 Python 实现主成分分析(PCA):从高维到核心特征
一、前言
在数据分析中,我们经常面对这样的情况:
-
数据维度太多(几十上百个特征)
-
特征之间高度相关
-
模型训练速度慢、效果不稳定
这时候,主成分分析(Principal Component Analysis, PCA) 就能帮上大忙。
它能在不损失主要信息的前提下,把高维数据压缩为少量关键特征,既节省计算资源,又能让数据结构更清晰。
二、PCA 是什么?
PCA 是一种无监督的线性降维算法,核心思想是:
找出一组新的特征(称为主成分),这些主成分能最大程度保留原始数据的方差信息。
换句话说,PCA 就是在高维空间中找到最能代表数据结构的方向。
其步骤如下:
-
数据标准化;
-
计算协方差矩阵;
-
求解特征值与特征向量;
-
选择最大的几个特征值对应的主成分;
-
将数据投影到这些主成分上。
三、准备数据
我们先生成一个模拟高维数据集。
import pandas as pd from sklearn.datasets import make_classification X, y = make_classification( n_samples=200, n_features=5, n_informative=3, n_redundant=2, random_state=42 ) df = pd.DataFrame(X, columns=[f'Feature_{i}' for i in range(1,6)]) df.head()
四、标准化数据
在 PCA 中,标准化是必须的,因为不同维度的量纲会严重影响方差计算。
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(df)
五、执行 PCA 降维
from sklearn.decomposition import PCA # 降到 2 维 pca = PCA(n_components=2) X_pca = pca.fit_transform(X_scaled) print('各主成分的方差贡献率:', pca.explained_variance_ratio_)
输出示例:
各主成分的方差贡献率: [0.63 0.22]
这说明前两个主成分保留了约 85% 的信息量。
六、可视化主成分
import matplotlib.pyplot as plt plt.figure(figsize=(8,5)) plt.scatter(X_pca[:,0], X_pca[:,1], c=y, cmap='viridis', s=50) plt.xlabel('主成分 1') plt.ylabel('主成分 2') plt.title('PCA 降维结果可视化') plt.show()
🎨 不同颜色表示不同类别,可以看到经过 PCA 后,数据在二维空间中仍保持较好的可分性。
七、主成分数量选择
我们可以用累计方差贡献率来判断需要保留多少个主成分。
pca_full = PCA().fit(X_scaled) plt.plot(range(1,6), pca_full.explained_variance_ratio_.cumsum(), marker='o') plt.xlabel('主成分个数') plt.ylabel('累计方差贡献率') plt.title('累计方差贡献率曲线') plt.show()
📈 一般来说,当累计方差贡献率达到 85%-95% 时,说明信息保留得足够多。
八、实际应用场景
PCA 在企业和研究中有非常广泛的用途:
| 应用领域 | 作用 |
|---|---|
| 🎯 用户画像 | 从上百个行为指标中提取主要特征 |
| 📊 金融分析 | 压缩股票或基金多维指标 |
| 🧠 机器学习 | 提高模型训练速度、减少过拟合 |
| 🔬 图像识别 | 降低像素维度,提高分类性能 |
| 💡 传感器数据 | 提取最具代表性的信号模式 |
九、PCA + 聚类的组合应用
PCA 常与聚类算法(如 K-Means)配合使用。
from sklearn.cluster import KMeans kmeans = KMeans(n_clusters=3, random_state=42) labels = kmeans.fit_predict(X_pca) plt.scatter(X_pca[:,0], X_pca[:,1], c=labels, cmap='rainbow') plt.title('PCA + KMeans 聚类结果') plt.show()
这样可以在低维空间中更直观地分群,同时提升聚类效果。
更多推荐


所有评论(0)