Day 87:【99天精通Python】机器学习进阶 - PCA 降维 - 抓住数据的"主干"
前言
欢迎来到第87天!
在机器学习中,我们经常遇到高维数据。比如,一张 100x100 像素的图片,拉平后就是 10000 个特征;一份用户调查问卷,可能有上百个问题。
特征太多会带来维度灾难 (Curse of Dimensionality):
- 计算量大:模型训练极慢。
- 过拟合:模型学到了太多噪声,泛化能力差。
- 无法可视化:超过三维的数据,人类就看不懂了。
降维 (Dimensionality Reduction)就是在尽可能保留原始信息的前提下,用更少的特征来表示数据。主成分分析 (Principal Component Analysis, PCA)是最经典、最常用的降维方法。
本节内容:
- PCA 原理:旋转坐标轴
- Sklearn 中的
PCA - 如何选择降维后的维度 (n_components)
- 可视化降维效果
- 实战练习:手写数字降维与重建
一、PCA 原理:找到最重要的方向
PCA 的目标是找到一个新的坐标系,在这个坐标系下,数据点的方差最大。方差越大,代表信息量越丰富。
这些新的坐标轴,就叫做主成分 (Principal Components)。
[外链图片转存中…(img-1L5jRPDv-1768773842454)]
上图中,PC1 是方差最大的方向(第一个主成分),PC2 是与 PC1 正交且方差次大的方向。
如果我们只想保留一维,那么所有点都投影到 PC1 轴上,这就是降维。
二、Sklearn 实现
我们用一个三维数据来演示。
importnumpyasnpfromsklearn.decompositionimportPCAimportmatplotlib.pyplotasplt# 1. 创建一个 3D 数据集np.random.seed(42)X=np.dot(np.random.rand(2,2),np.random.randn(2,200)).T X[:,1]+=0.5*X[:,0]X=np.hstack([X,0.1*np.random.randn(200,1)])# 增加一个噪声维度# 2. 初始化 PCA# n_components=2: 我们想降到 2 维pca=PCA(n_components=2)# 3. 训练并转换X_2d=pca.fit_transform(X)# 4. 查看结果print(f"原始形状:{X.shape}")# (200, 3)print(f"降维后形状:{X_2d.shape}")# (200, 2)# 可视化对比fig=plt.figure(figsize=(10,5))ax1=fig.add_subplot(121,projection='3d')ax1.scatter(X[:,0],X[:,1],X[:,2])ax1.set_title("Original 3D Data")ax2=fig.add_subplot(122)ax2.scatter(X_2d[:,0],X_2d[:,1])ax2.set_title("PCA to 2D")# plt.show()三、如何选择降维的维度?
通常我们不会直接指定n_components=2,而是让 PCA 帮我们决定。
一个常见的做法是:保留 95% 的信息。
3.1 解释方差比 (Explained Variance Ratio)
# 初始化时不指定 n_componentspca=PCA()pca.fit(X)# 查看每个主成分能解释的方差比例print(pca.explained_variance_ratio_)# 查看累计方差比cumulative_variance=np.cumsum(pca.explained_variance_ratio_)plt.plot(range(1,len(cumulative_variance)+1),cumulative_variance,marker='o')plt.xlabel("Number of Components")plt.ylabel("Cumulative Explained Variance")plt.grid(True)# plt.show()3.2 自动选择
我们可以直接在 PCA 中设置保留的方差比例。
# 自动选择能保留 95% 方差的主成分数量pca=PCA(n_components=0.95)X_reduced=pca.fit_transform(X)print(f"保留95%信息后,维度变为:{X_reduced.shape[1]}")四、实战:MNIST 降维与可视化
手写数字图片是 28x28 = 784 维的,我们无法直接可视化。
我们可以用 PCA 把它降到 2 维,然后画出来,看看不同数字是否能自动分开。
fromsklearn.datasetsimportfetch_openmlfromsklearn.preprocessingimportStandardScaler# 1. 加载数据 (只取 5000 个,否则太慢)X,y=fetch_openml('mnist_784',version=1,return_X_y=True,as_frame=False)X,y=X[:5000],y[:5000]# 2. 标准化scaler=StandardScaler()X_scaled=scaler.fit_transform(X)# 3. PCA 降维pca=PCA(n_components=2)X_pca=pca.fit_transform(X_scaled)# 4. 可视化plt.figure(figsize=(10,8))y_numeric=y.astype(int)plt.scatter(X_pca[:,0],X_pca[:,1],c=y_numeric,cmap=plt.cm.get_cmap('jet',10),alpha=0.6)plt.colorbar(label='Digit Label')plt.xlabel("Principal Component 1")plt.ylabel("Principal Component 2")plt.title("PCA of MNIST Dataset")# plt.show()从图中可以看出,PCA 成功地把一些相似的数字(如 1 和 7)在二维空间中分开了。
五、降维 vs 特征选择
- 特征选择 (Feature Selection):从原有特征中挑选出一部分(如 100 个特征里选 10 个)。
- PCA 降维:将原有特征线性组合,创造出全新的、更少的主成分特征。
PCA 保留了所有特征的信息(只是权重不同),而特征选择会完全丢弃某些特征。
六、常见问题
Q1:PCA 需要标准化吗?
必须!PCA 是基于方差的。如果某个特征的数值范围特别大(如收入),它会主导整个 PCA 的计算,导致其他特征被忽略。
Q2:降维后能恢复吗?
可以,但会丢失一部分信息。X_reconstructed = pca.inverse_transform(X_reduced)
Q3:PCA 是最好的降维方法吗?
不是。PCA 只能做线性降维。对于复杂的非线性结构(如瑞士卷),需要用t-SNE或UMAP。
七、小结
关键要点:
- PCA是处理高维数据的利器,能有效减少计算量和噪声。
- 降维前必须对数据进行标准化。
- 通过
explained_variance_ratio_可以判断降维保留了多少信息。
八、课后作业
- 图像压缩:读取一张灰度图片,将其
reshape成一个长向量,用 PCA 降维(保留 80% 信息),然后再inverse_transform恢复成图片,看看和原图有多大差别。 - t-SNE:查阅
sklearn.manifold.TSNE,用它来对 MNIST 数据进行降维,并与 PCA 的结果进行对比。 - 人脸识别:加载 sklearn 自带的
fetch_lfw_people数据集,使用 PCA + SVM 进行人脸识别分类。
下节预告
Day 88:实战篇总结与项目复盘- 我们的实战篇(Day 46-87)即将结束。明天我们将对数据分析和机器学习部分进行全面复盘,并展望最终的项目篇(二)!
系列导航:
- 上一篇:Day 86 - K-Means聚类
- 下一篇:Day 88 - 实战篇总结(待更新)