3.4 降维任务 本节摘要:降维解决的是"特征太多"带来的麻烦——高维数据又稀疏又难算,距离还会失效,这就是维度灾难。本节把降维分成两条路:特征选择是挑出有用的原特征,特征提取是把原特征变换成新的低维表示。重点讲 PCA、LDA、t-SNE 三者面向目标的差异:PCA 找方差最大的方向、LDA 找类别分得开的方向、t-SNE 专做可视化。学完你能在"去噪压缩"和"画图探索"之间选对工具。
本节摘要:降维解决的是"特征太多"带来的麻烦——高维数据又稀疏又难算,距离还会失效,这就是维度灾难。本节把降维分成两条路:特征选择是挑出有用的原特征,特征提取是把原特征变换成新的低维表示。重点讲 PCA、LDA、t-SNE 三者面向目标的差异:PCA 找方差最大的方向、LDA 找类别分得开的方向、t-SNE 专做可视化。学完你能在"去噪压缩"和"画图探索"之间选对工具。
阅读完本节,你应当能够:
高维到底有多麻烦?一个直观的感受是:维度越高,空间越"空",样本之间的距离都趋近相等,基于距离的算法全都会失灵。降维就是在这个麻烦变得不可收拾之前,把维度压下去。
from sklearn.datasets import load_iris from sklearn.decomposition import PCA X, y = load_iris(return_X_y=True) pca = PCA(n_components=2) X2 = pca.fit_transform(X) print(pca.explained_variance_ratio_)
鸢尾花从 4 维压到 2 维,explained_variance_ratio_ 告诉你前两个主成分各自解释了原始数据多少比例的方差。就这个例子,第一个主成分往往能解释九成以上——四个特征里其实大部分信息挤在一条主轴上。
特征选择保留原始特征,只是删掉没用的。好处是新变量还是原来那批,可解释性一点没丢。三种典型做法:
方差阈值最简单——一个特征如果取值几乎不变,方差极低,对模型没区分度,直接删。它不看标签,是无监督的筛选。
单变量检验(SelectKBest)看每个特征和目标之间的统计相关性,用卡方检验、F 检验或互信息打分,选得分最高的 k 个。它需要标签,是有监督的。
基于模型的选择(SelectFromModel)先训练一个模型,看它给每个特征的重要性或系数,保留超过阈值的。树模型给特征重要性,线性模型给系数,都很现成。
from sklearn.feature_selection import VarianceThreshold, SelectKBest, f_classif VarianceThreshold(threshold=0.1).fit_transform(X) SelectKBest(score_func=f_classif, k=2).fit_transform(X, y)
特征提取是造新特征,新变量是原特征的线性或非线性组合。它更省心,但新特征往往说不清含义。
PCA 无监督,找方差最大的方向作为主轴,把数据投影上去。它适合去噪、压缩、做下游任务的预处理,也常用来把高维数据压到二维先看一眼整体分布。代价是新轴是原特征的线性组合,可解释性差。
LDA 有监督,目标不是方差最大,而是"类间分得开、类内聚得紧"。它需要标签,降维后的分量天然为分类服务。注意 LDA 能保留的分量数受类别数限制——最多类别数减一,所以二分类只能降到一维。
t-SNE 是另一类东西。它非线性地把高维相似度搬到低维,专长是把聚类结构画得清清楚楚,但它有两个硬伤:结果依赖随机初始化,每次跑都不同;而且不保留全局距离,轴上的数值没有物理意义。所以它只用于可视化探索,别把它当成特征工程再喂给下游模型。

| 方法 | 监督性 | 线性 | 主要用途 |
|---|---|---|---|
| PCA | 无监督 | 线性 | 去噪、压缩、预处理 |
| LDA | 有监督 | 线性 | 分类特征提取 |
| t-SNE | 无监督 | 非线性 | 可视化、揭示聚类 |
⚠️ 常见坑:拿 t-SNE 的结果做特征再训练模型。它不保留全局结构、结果不稳定,作为下游特征会引入一堆不必要的不确定性。可视化就让它老老实实做可视化。
⚠️ 常见坑:PCA 前不标准化。PCA 对尺度极敏感,量纲大的特征会吞掉量纲小的,主轴被单个特征带跑。先 StandardScaler 再 PCA 是标配。
💡 关键直觉:降维不是"越少越好",而是"在保留信息的前提下越少越好"。用解释方差比率或交叉验证来定保留多少维,而不是拍脑袋砍到二。
💡 关键直觉:选特征还是造特征,看你要不要"可解释"。业务方要听你解释"哪个变量在起作用"时用特征选择;你只关心模型效果和画图时,特征提取更省心。
维度灾难不是修辞,是真实的现象。随着维度增加,数据点之间的距离会趋于相等,最近邻和最远邻的区分度下降,基于距离的算法像 KNN 会直接失效;要填满高维空间需要的样本量呈指数增长。所以"特征越多越好"是错的,降维在很多高维场景是生存前提。
PCA 背后的做法可以这样想:它计算特征的协方差矩阵,找出方差最大的那些方向作为主轴。第一个主成分是方差最大的方向,第二个在第一个的垂直方向上继续找方差最大,以此类推。每个主成分解释多少方差,就是 explained_variance_ratio_ 里那串数,把前几个累加起来就是"保留了多少信息"。选多少维,看累计解释方差到没到你能接受的阈值,比如九成五。除了给整数,还可以给一个 0 到 1 的小数,表示"保留能解释这么多方差的分量",比如 n_components 设 0.95 就是自动保留解释九成五方差的最少分量数,比拍脑袋写 2 更工程化。
t-SNE 有个关键参数 perplexity,中文叫困惑度,它控制每个点把多少邻居当"近邻"来看。取值太小,只看身边一两个点,结构碎;太大,把远处也拉进来,全局结构被扭曲。经验值在 5 到 50 之间,通常取样本量平方根附近。因为结果对随机种子敏感,重要的图最好多跑几次,看结构是否稳定。
特征选择的价值在可解释性:删完之后剩下的还是原来那些变量,业务方听得懂。代价是它只能做减法,如果信息分散在多个原始特征的组合里,单个特征都不显著,特征选择就无能为力,这时需要特征提取。SelectFromModel 的阈值可以设成字符串,mean 表示保留重要性高于平均值的特征,median 表示高于中位数,也可以给具体数值;树模型给特征重要性,线性模型给系数绝对值,都能直接排序。
除了 PCA,还有两个常用的线性提取方法。非负矩阵分解要求数据和结果都非负,适合词频这类天然非负的矩阵,分解出的主题更直观。截断奇异值分解适合稀疏矩阵,文本的 TF-IDF 特征往往就是稀疏的,用它比 PCA 更高效。
特征提取的本质是换坐标系。原特征还是那些,但经过线性或非线性变换被重组成几个新变量,数量更少、彼此更不相关,代价是失去原来的业务含义。
降维在真实项目里随处可见。图像上,PCA 用来做人脸识别的特征脸,把成千上万的像素压成几十个主成分;文本上,奇异值分解类的方法把高维词频矩阵压到几百维再喂分类器;基因表达数据动辄上万维,PCA 几乎是预处理标配。共同逻辑都是先把维度降到算法能承受、又不丢太多信息的大小,再谈建模。
降维不是免费午餐,两个代价要提前想清楚。一是可解释性没了:PCA 造出的主成分是原特征的线性组合,业务方问"这个 0.3 代表什么",你只能含糊地说它大致反映了几个特征的混合,说不出某个具体变量的含义。二是信息有损,投影会丢掉主成分之外的方向,压缩得越狠丢得越多,这能在解释方差比率里量化,但"丢掉的那点信息到底重不重要"往往测不出来——有时被丢掉的反而是业务真正关心的那个小信号。所以降维之前先问一句:特征真的多到影响算法了吗?如果本来只有十几个特征、样本也不算少,树模型和带正则的线性模型自己就能扛,硬做 PCA 反而平白损失解释性。反过来,上千维的文本或基因数据、或者只是要画一张二维散点图时,降维才真正划算。判断标准就一条:维度带来的麻烦,是不是已经超过了降维带来的信息损失。
没法直接解释。每个主成分是原始特征的线性组合,你可以看主成分里哪些原始特征权重最大,来概括它"主要反映了什么",但这是近似解读,不是精确语义。
有标签、且目标是分类时,LDA 通常更合适,因为它直接优化类别可分性。但 LDA 假设各类近似高斯分布、协方差相近,这些不满足时,PCA 加分类器反而更稳。
要谨慎。t-SNE 的簇大小、簇间距离都没有绝对意义,只有"哪些点聚在一起"这个局部结构相对可靠。它能给线索,但下结论前要用原始特征上的距离或聚类结果验证。
方差阈值不看标签,只删方差极低的特征,是无监督的粗筛;SelectKBest 看每个特征和目标的相关性,是有监督的精选。两者可以先后用,先粗筛再精选。
能,而且是常见组合。先用方差阈值或 SelectKBest 粗筛一遍,删掉明显无用的,再用 PCA 或树模型做精细提取。顺序上粗筛在前、提取在后,避免噪声混进主成分。
会,所以降维是取舍。PCA 用解释方差比率量化丢了什么;特征选择要回头验证模型效果。永远拿"保留信息与模型表现"这把尺子量,而不是追求维度数字本身。如果下游要还原,优先 PCA,它有逆变换,虽然还原结果不等于原始数据。
会,尤其 SelectKBest 这种单变量方法,只看单个特征和目标的关系,忽略了特征之间的组合。用交叉验证来评估特征选择后的模型效果,而不是只看选出来的分数。
特征提取比如 PCA,要在切分之后、只在训练集上 fit,再用同样的变换应用到测试集。切分之前就在全量数据上 fit,等于把测试集信息泄露进训练。
均匀流形逼近与投影,是一种比 t-SNE 更快、且能兼顾全局结构的非线性降维方法,常和 t-SNE 一起被用来做可视化对比。它不是 Scikit-learn 核心库的一部分,需要额外安装。
一个常见的流程模板:切分数据,训练集上先标准化,再做 PCA,然后喂分类器。这几步用管道串起来,交叉验证时每一步都只在训练折叠里拟合,不会泄露。
下一节我们把这些训练好的模型保存下来、部署出去,让它们在真实系统里跑起来。