PCA降维实操五步:从标准化到定主成分个数

数据集的特征列一多,麻烦就跟着来:训练慢、过拟合风险高,特征之间还互相纠缠。PCA 给出的答案是换一套坐标系——把数据投到少数几个「信息量最大」的新轴上,每个轴按解释的方差大小排队,取前几个就完成任务。下面用五个步骤把整个流程跑通,不碰数学推导,跑完就能套到自己的数据上。

先对齐三个词

降维说的是压缩特征空间:原来 13 列数据,压成 3 列之后信息还在,这买卖就算划算。

主成分是 PCA 找到的新轴,排序依据是「数据在上面铺得开不开」——第一主成分方向上方差最大,第二个是与它正交的次大方向,依次排下去。

方差解释比(explained variance ratio)衡量每个主成分分走了多少方差,累计值是决定留几个成分的硬依据,实践中累计到八成到九成就可以收手。

实现层面提一句:Scikit-Learn 内部走 SVD(奇异值分解)路径而非协方差矩阵特征值分解,这层被库封装死了,日常使用不受影响,只是读源码时别找错地方。

第一步:加载数据

演示用 Scikit-Learn 自带的 wine 数据集:178 条样本、13 个化学特征,规模不大,秒级出结果:

from sklearn import datasets
wine_data = datasets.load_wine(as_frame=True)
df = wine_data.data
print(df.shape)   # (178, 13)

特征涵盖酒精度、苹果酸、灰分、镁这类指标,数值范围从个位数跨到上百,量纲不齐是这份数据的显著特点——这也是下一步必须处理的问题。

第二步:标准化,不能省的一步

尺度问题是 PCA 的头号杀手。两个特征一个在 0~1000 区间、一个在 0~1,前者的方差天然占优,主成分方向基本被它一个人决定。所以拟合之前先把所有特征拉平:

from sklearn.preprocessing import StandardScaler
std_scaler = StandardScaler()
scaled_df = std_scaler.fit_transform(df)

这一步省略的后果不是「精度略降」,而是「主成分方向被量纲最大的特征绑架」——酒精度这种十几量级的特征可能压过所有上百量级的成分,降维结果只反映一个特征的分布。新手最常踩的就是这个坑,养成习惯先 scaler 走一遍,没有副作用。

第三步:拟合变换

from sklearn.decomposition import PCA
pca = PCA(n_components=3)
pca.fit_transform(scaled_df)

协方差矩阵、SVD 分解、特征向量求解全部封装在 fit_transform() 一个方法里。

第四步:看两个关键属性

components_ 存主成分方向向量(3×13 矩阵,每行一个主成分);explained_variance_ratio_ 给出每个主成分的方差占比:

print(sum(pca.explained_variance_ratio_))
# 0.6653...

3 个主成分合计保住约 66.5% 的方差,三分之一的信息被舍弃。这笔账划不划算要看下游任务,嫌丢得多就往上调。

第五步:定主成分个数

把 n_components 从 1 遍历到最大值,画累积方差解释比曲线,找「拐点」:

import numpy as np
import matplotlib.pyplot as plt
var_ratio = []
for num in range(14):
    pca = PCA(n_components=num)
    pca.fit(scaled_df)
    var_ratio.append(np.sum(pca.explained_variance_ratio_))
plt.plot(range(14), var_ratio, marker='o')
plt.xlabel('n_components')
plt.ylabel('Explained Variance Ratio')
plt.grid(True)

wine 数据上累积曲线在第 6 个主成分附近越过 80% 线——用不到一半的维度锁住八成信息。经验上 80%~90% 都是可以接受的落点。

一个更省事的写法:n_components 直接传浮点数,比如 PCA(n_components=0.95),库会自动选能保留 95% 方差的最少成分数,连曲线都省得画。阈值定多高看下游用途——做可视化压到 2~3 个成分就够,做建模前置的降噪则倾向 90%~95%。

补充三件实操上的事

一、大矩阵的求解器选择。样本量大、维度高时给 PCA 传 svd_solver='randomized',随机化 SVD 明显更快,精度损失在可接受范围;默认的 auto 会按数据形状自己挑。

二、降维损失可以量化。PCA 对象支持 inverse_transform(),把降维后的数据映射回原空间,与原始数据算均方误差,这个数就是降维代价的直接度量——比只看方差解释比更贴业务。

三、边界要清楚。PCA 是线性方法,主成分是原始特征的线性组合,本身没有明确物理含义,需要强可解释特征选择时用 Lasso 或树模型的重要性排序更合适;数据存在明显非线性结构(比如卷曲流形)时,换 t-SNE 或 UMAP。类别型特征占大头的表格数据,先 One-Hot 再标准化,不过 One-Hot 会抬维度,这时候 PCA 的压缩价值反而更突出。

0

评论0

请先
显示验证码
没有账号?注册  忘记密码?