机器学习_第十篇_PCA降维

20261020-183745

什么是降维? 说白了,就是把一份"样本 × 很多特征"的数据,过滤分类成"样本 × 较少特征",同时尽量不丢关键信息。原来用 50 个特征描述一个人,降维后可能只用 5 个合成指标就能表达得差不多。它不改变样本本身,只是换一种更紧凑的"说法"去描述同一批数据。

什么是 PCA 降维? PCA 是降维方法里最经典、最常用的一把——属于"线性"降维。它的思路是:不看原始特征轴,而是重新找一组互相垂直的新轴(主成分),让数据投影到第一根轴上时散得最开(方差最大),第二根在剩余方向上散得最开……依此类推。前几根轴就装下了绝大部分信息,把后面的扔掉,维度就降下来了。整篇文章主要介绍的就是把这个"找轴、排序、砍轴"的过程,以及它背后的坑和边界。

一、先说清楚:降维到底解决什么问题

复杂的案例数据往往是高维的——几十上百个特征稀松平常。高维带来的麻烦很具体:

  • 维度灾难:样本在高维空间里极度稀疏,距离度量失效,模型要么过拟合要么学不动。
  • 冗余特征:很多特征高度相关(比如"身高 cm"和"身高 m"),占着维度却不提供新信息。
  • 噪声:测量误差、无关特征会淹没真实信号。
  • 不可见:超过三维,人眼没法直接看数据分布。

PCA 干的事,是把数据投影到一个新的坐标系,让前几个坐标轴就装下绝大部分信息,后面的轴可以直接扔掉。

二、PCA 的核心直觉:找"最能拉开数据"的方向

PCA 找一组互相垂直的新坐标轴,第一个轴让数据投影后方差最大,第二个轴在垂直于第一个的前提下方差最大,依此类推。

为什么盯住方差?因为方差衡量数据的分散程度,分散越大说明这个方向上携带的信息越多。把数据投到方差最大的方向上,丢的信息最少。

这里说的"轴",在 PCA 里叫主成分(Principal Component,缩写 PC)。第 1 个轴就是 PC1,第 2 个轴是 PC2,第 k 个轴是 PCk:

  • PC1 是数据方差最大的方向——它抓住全局最"散"的那一维信息。
  • PC2 是在与 PC1 垂直(正交)的剩余空间里,方差最大的方向。它和 PC1 不打架,互不重叠。
  • PC3、PC4…… 以此类推,每一根都在"垂直于前面所有 PC"的子空间里取最大方差。

"垂直"到底指什么? 它就是几何里最朴素的"两根轴成 90°、互不倾斜"。展开讲有三层意思:

  • 几何层:PC1 和 PC2 是两条从原点出发、夹角 90° 的箭头。所谓"在垂直于 PC1 的方向里再找方差最大",翻译成人话就是:你已经在 PC1 这条线上把数据的信息榨了一遍,剩下还没被榨干净的信息,只可能藏在"和 PC1 成 90°、完全不歪向它"的那些方向里——PCA 就在那个 90° 的"侧壁"上继续找最散的方向。
  • 数据层(最关键):两根轴垂直,等价于"一个样本在 PC1 上的坐标,和它在 PC2 上的坐标毫无关联(协方差为 0)"。你只知道某个人在 PC1 上排第几,完全猜不出他在 PC2 上排第几——两条轴描述的是数据不重叠的两个侧面。这恰好和上面的"互不冗余"对上:冗余就是"两条轴说了同一件事",而垂直从根上杜绝了这种重叠。
  • 为什么 PCA 天然保证垂直,不是硬凑的? 这来自线性代数的一个定理:协方差矩阵是对称矩阵,它的不同特征值对应的特征向量天生就互相垂直。PCA 第 3 步对它做特征分解,分解出来的特征向量天然正交——所以 PC 之间垂直不是算法"刻意要求"的,而是"在前面所有方向上都榨干方差、下一个方向必须不重复用前面的信息"这个约束,在数学上自然导出的结果。你不用额外写一句"让它们垂直"的代码,它自动就是垂直的。

顺着上面"PCn 垂直于前面所有 PC",你大概率会接着想一个问题——PCn 是不是都建在 PC(n−1) 上?PC(n−1) 错了后面的轴是不是全错?它到底是不是后面轴的前提? 这是个特别容易想歪、但想通了会很踏实的点。先拍结论:标准 PCA 不是一层层叠上去的,整组 PC 是一次性从同一个协方差矩阵里"同时"解出来的。

  • 从"计算"看:不是嵌套,是 simultaneous。 第三节第 3 步走的是对协方差矩阵 \(C\) 做一次特征分解(或 SVD),分解出来一整组特征向量 \(v_1, v_2, \dots, v_d\),按对应特征值从大到小排,就是 PC1、PC2、…、PCd。它们都来自同一个矩阵 \(C\),不存在"先有 PC1 才能算 PC2"的依赖链。所以不用担心"PC1 算错了 → PC2 跟着错 → 全错"这种雪崩——因为压根没有先后计算顺序,它们是同一次分解的产物。

  • 从"定义/表述"看:确实是嵌套的。 "PC2 是在垂直于 PC1 的方向里方差最大""PCn 是垂直于前 \(n-1\) 个的方向里方差最大"——这句话是对的,但它描述的是"结果长什么样",不是"算法怎么算"。数学上可以证明:对称矩阵 \(C\) 的特征向量按特征值排序后,第 \(n\) 个恰好满足"在垂直于前 \(n-1\) 个的子空间里方差最大"。所以"嵌套"是结果的等价刻画,不是计算的前置条件。

  • 那"PC(n−1) 是后面轴的前提"对不对? 准确说,前提是协方差矩阵 \(C\),不是上一个 PC。只要 \(C\) 是对的,整组 PC 就定了;上一个 PC 只是 \(C\) 的一个特征向量,它"对不对"取决于 \(C\) 对不对,而不是反过来。如果硬要说"前提",前提永远是那张协方差矩阵,不是前一根轴。

但你这个直觉不是完全没道理,两个真实场景确实会"连环翻车",得认清楚:

  1. 数值上挤在一起的特征值(\(\lambda\) 接近):如果 \(\lambda_1 \approx \lambda_2\),PC1 和 PC2 的方向其实分得不清,数据里加一点噪声,这俩就可能互换或一起旋转(在它们俩的二维子空间里打转)。但这是"一对相邻的 PC 一起抖",不是从 PC1 一路往下传染——PC3、PC4 照样各算各的,不会因为 PC1/PC2 打转就跟着错。

  2. 用了"逐次剔除(deflation)"类算法:有些 PCA 实现(尤其是流式/增量 PCA,或"幂迭代 + 剔除"写法)真的是先估 PC1、从数据里减掉它、再用剩下的残差估 PC2……这种写法里,PC1 估计偏了,后面确实会跟着偏。但标准批量 PCA(对整块数据做一次特征分解/SVD)不走这条路,所以没有这种级联。前面"有限数据"那一节说的估计不稳定,讲的是样本噪声带来的整体误差,也不是 PC 之间的顺序传染。

简言之:PC 之间是"同时出生、座次只是按方差排",不是"一个接一个盖楼"。前一个错了后面不一定错,真正的前提永远是那个协方差矩阵本身。

顺着"前提是协方差矩阵"这句话,自然又冒出一个很实际的问题:样本越攒越多,PCA 是不是得从头重算? 先拍结论:标准批量 PCA——是,得重算,但不是你以为的那种"重训一个模型"。

  • 为什么标准 PCA 必须重算? 前面说过,整组 PC 来自同一份协方差矩阵 \(C\) 的一次分解。你多塞进一批样本,\(C\) 就变了(均值、方差、两两协方差全变),那基于旧 \(C\) 解出来的 PC,对新数据就不再是"方差最大的方向"了。它的"最优"是绑定在"当时那份数据"上的,数据基准一变,最优解就漂移——所以没错,得用新数据重新算一遍。

  • 但这"重算"没那么高成本,别把它想成神经网络那种训练。 它就是一个闭式矩阵分解(特征分解 / SVD),没有迭代收敛、没有随机初始化、没有训练轮数。数据量从 1 万涨到 2 万,重算成本大致是 \(O(\min(n,d)^2 \cdot d)\) 量级,跑一次也就毫秒到秒级,远不像重训模型那么重。实务里常见的做法是:攒够一批新数据,离线重算一次,把新 PC 换上去,而不是每条样本来了就重算。

  • 想避免"每次都重读全部数据",有两条路:

    1. 在线更新协方差矩阵,再分解:协方差可以增量维护(Welford / 递推均值方差公式),新样本来了只更新 \(C\),最后对更新后的 \(C\) 分解一次。省的是"重读历史数据"这一步,不是省"重分解"。
    2. 增量 PCA(Incremental PCA):sklearn 的 IncrementalPCA 就是干这个的——分块(mini-batch)喂数据,逐块更新内部状态,内存放不下的超大数据集或流式数据(日志、传感器)也能压。代价是结果只是批量 PCA 的近似,且对喂数据顺序略敏感、要调块大小;如果数据分布本身在漂移(concept drift),那重算也救不了,得重新审数据而不是重算 PCA。
  • 最后认清楚两点,免得又想歪: ①"重算"指的是整组 PC 重新求解,不是"在旧 PCk 后面续算 PC(k+1)"——这正好呼应上面"PCA 不是盖楼":你不是接着盖,是推倒按新地基重组。②加少量样本后,PC 通常只是微调(方向小幅转),不会天翻地覆;除非新数据带来了旧数据没有的结构,那才叫"分布真的变了",这种时候重算也是应该的。

几个关键点:每个 PC 都是原始特征的线性组合;PC 之间两两正交,所以彼此不冗余——这正是 PCA "去冗余"的数学表达。PC 的编号本身就是信息量排序:PC1 携带最多,越往后信息越少,所以才能放心砍掉后面的。

"方差最大"这句话怎么形象理解呢?打个比方:

把这批数据点想象成空中飘的一团椭圆形雾(大多数真实数据都这样:沿某个方向拉得长、垂直方向挤得扁)。你拿手电筒从侧面照它,墙上会投出一道"影子"——这道影子就是数据投影到某条轴之后的样子。手电筒的角度你可以随便转,转动时会发生两件事:

  • 光从椭圆的长边方向照过去,墙上的影子被拉得最长最散,每个点投上去都分得开 → 这就是 PC1,投影方差最大,信息保得最多。
  • 光从椭圆的短边方向照过去,影子被压成一小撮,所有点挤在一起分不清 → 这个方向方差最小,投影几乎丢了全部信息,直接扔。

所以"第一个轴让投影后方差最大",翻译成人话就是:PCA 在帮数据找那束"能把影子拉得最长"的光——影子越长,说明这个方向上原本的点分布得越开、信息越多,砍掉它最可惜。

看到这儿,你很可能会想歪两点,先堵上:

① "方差最大"不是真把数据拉长,PCA 也不会算不完

那团"椭圆雾被手电筒照出长影子"只是帮你理解"选哪个方向"的比喻,不是算法在反复拉伸数据。PCA 是一次性闭式求解:中心化 → 算协方差矩阵 → 对它做特征分解(或 SVD)→ PC1 就是最大特征值对应的特征向量。

有限数据的方差是有界的——它等于协方差矩阵的最大特征值,一个有限的数。不存在"越拉越大、拉到停不下来"的情况。所以别把 PC1 理解成迭代逼近的过程,它就是一次矩阵分解的产物,算完即止。上面那张图看的就是这个闭式流程,没有循环。

② "拉长/压扁"的度,你控制的是"留几个轴",不是"把轴拉多长"

PCA 本身不改造数据,它只是把坐标轴按信息量排了个序。所谓"度",其实是你决定保留前 \(k\) 个主成分、扔掉后面的:\(k\) 越大保留越多、压得越轻;\(k\) 越小压得越狠。具体选多少,看累计解释方差(第五节),没有统一硬度。

还有一种"被某个特征带偏"的情况容易被误当成"无限拉长":如果某个特征数值量级远大于其他(比如"收入(元)"和"年龄(岁)"放一起),它的方差天然巨大,PC1 会几乎完全贴着它走——这是量纲问题,不是 PCA 算爆了。解法是先标准化(第六节),把所有特征拉到同一量纲再降维,否则"拉长/压扁"的度全被那个大连量级特征劫持了。

下面这张图把"数据团 → 它的两条主成分轴 → 各自投影分布"一次讲清:

image

flowchart TD A[原始数据矩阵 X<br/>n 行样本 × d 列特征] --> B[逐特征中心化<br/>每列减去均值] B --> C[计算协方差矩阵<br/>C = XᵀX / n] C --> D[特征值分解<br/>C = VΛVᵀ] D --> E[特征值降序排列<br/>取前 k 个特征向量] E --> F[投影 Z = XW<br/>得到 n×k 降维矩阵]

三、推导:四步。

先说清楚这一节"推导"的到底是什么——不然看到四步容易不知道在算什么。PCA 的最终产物有两样:

  1. 一组新坐标轴 \(W\)(也就是主成分 PC1、PC2……),它们是原始 \(d\) 维特征空间里重新选出来的方向;
  2. 降维后的数据 \(Z = XW\),把每个样本从原来的 \(d\) 维坐标,换成这 \(k\) 个新轴上的坐标。

所谓"推导",就是从原始数据矩阵 \(X\) 出发,经过下面四步运算,把 \(W\) 和 \(Z\) 算出来。

这四步背后藏着一个数学结论(不用自己证,记住就行):"让投影后方差最大的方向"恰好是协方差矩阵最大特征值对应的特征向量。所以第 3 步是对协方差矩阵做特征分解——分解出来的特征向量就是主成分方向,特征值就是该方向上的方差大小。四步只是把这个结论落成可执行的算法。

1. 中心化

把每个特征(每一列)减去它自己的均值,让数据中心落在原点。

"均值"指的是每个特征在所有样本上的算术平均,而且各特征独立计算、互不干扰。假设数据矩阵 \(X\) 有 \(n\) 行样本、\(d\) 列特征,第 \(j\) 列的均值就是:

\[\mu_j = \frac{1}{n}\sum_{i=1}^{n} x_{ij} \]

"怎么获得"很简单:对 \(X\) 的每一列求平均,得到 \(d\) 个数 \(\mu_1,\dots,\mu_d\)(一行代码 X.mean(axis=0) 就能拿到)。然后对每个样本的第 \(j\) 个特征值做替换 \(x_{ij} \leftarrow x_{ij} - \mu_j\)。这一步只是把整团数据平移到以原点为中心,不做任何旋转或缩放;做完后每一列的均值恰好都是 0。

举个小例子(4 个样本、2 个特征,比如身高 / 体重):

样本 特征 x1 特征 x2
1 170 65
2 160 55
3 180 75
4 150 50
列均值 μ 165 61.25

\(\mu_1 = (170+160+180+150)/4 = 165\),\(\mu_2 = (65+55+75+50)/4 = 61.25\) —— 两列各算各的。中心化就是把每个值减掉它所在列的均值:

样本 x1' = x1 − 165 x2' = x2 − 61.25
1 5 3.75
2 −5 −6.25
3 15 13.75
4 −15 −11.25
新列均值 0 0

注意中心化前后数据形状完全没变(点之间的相对位置不动),只是整体挪了位置,让重心落在原点。

这一步不能省——协方差矩阵的定义依赖零均值。如果不中心化,PCA 找到的"最大方差方向"会被数据中心相对原点的偏移量带偏,反映的不是数据本身的散布形状,结果失真。

2. 协方差矩阵

对中心化后的数据 \(X\)(每行一个样本),协方差矩阵是:

\[C = \frac{1}{n} X^T X \]

它是一个 \(d \times d\) 的对称矩阵,对角线是各特征的方差,非对角线是特征间的协方差。PCA 要找的方向,就藏在它的特征向量里。

这看起来像巧合,其实是定义本身就这么构造的,把 \(C = \frac{1}{n}X^T X\) 摊开看就明白了。记 \(X\) 是 \(n \times d\)(每行一个样本、每列一个特征),那么 \(X^T X\) 的第 \((p,q)\) 个元素,正是第 \(p\) 列和第 \(q\) 列的点积:

\[C_{pq} = \frac{1}{n}\sum_{i=1}^{n} x_{ip}\, x_{iq} \]

  • 当 \(p = q\)(对角元)时,上式退化成 \(\frac{1}{n}\sum_{i} x_{ip}^2\)——这恰好就是特征 \(p\) 的(样本)方差定义。前提是第一步已经中心化(均值 = 0),此时"平方的平均"才等于方差。所以对角线上躺着各特征的方差,纯粹是矩阵乘法把"每一列和自己点积"算到了对角线上,不是碰巧。
  • 当 \(p \neq q\)(非对角元)时,上式是 \(\frac{1}{n}\sum_{i} x_{ip}x_{iq}\),正是特征 \(p\) 与 \(q\) 的协方差(中心化后,协方差 = 乘积的平均)。
  • 至于对称:\((X^T X)^T = X^T X\),所以 \(C\) 天然对称,对应的就是 \(\text{Cov}(p,q)=\text{Cov}(q,p)\)。

简言之:协方差矩阵就是用一次矩阵乘法,把"所有特征两两之间的方差和协方差"一次性全算出来了——对角是自己和自己的协方差(即方差),非对角是两两之间的协方差。

3. 特征值分解

把 \(C\) 分解成 \(C = V\Lambda V^T\),其中 \(V\) 的列是单位特征向量,\(\Lambda\) 的对角线是对应特征值。特征值的物理意义很直接:数据投影到对应特征向量方向上之后的方差。

4. 取前 k 个

把特征值从大到小排,取前 \(k\) 个特征向量组成投影矩阵 \(W\)(\(d \times k\))。降维后的数据就是 \(Z = XW\)。

工程上 \(d\) 很大时别直接算 \(X^T X\) 再分解——数值更稳的做法是用 SVD:\(X = U\Sigma V^T\),右奇异向量就是我们需要的特征向量。用截断 SVD 能直接拿到前 \(k\) 个,省内存也省算力。

一个常被搞混的点:PCA 丢弃的是"方向",不是"特征"

你可能会以为"取前 \(k\) 个、丢掉后面的"等于"删掉了 \((d-k)\) 个特征列"。不是。

  • PCA 做的是投影变换,不是特征选择。丢掉的是信息量最小的那几个主成分(方向)——\(PC_{k+1}\) 到 \(PC_d\)——也就是把数据在这些方向上的分量抹成 \(0\)。
  • 而每个保留下来的主成分,本身是所有 \(d\) 个原始特征的线性组合(权重就是特征向量里对应的分量,也叫 loading)。所以你没法说"PCA 把第 3 个特征删了";真实情况是:每个原始特征都带着某种权重,参与了每一个保留下来的 PC。
  • 真正被"丢弃"的信息,是"各特征按特定比例混合后、方差最小的那部分信号"——它分散在所有特征里,不归任何一个特征独有。

这和第七节讲的"特征选择"(Lasso、树重要性、方差过滤)是两件完全不同的事:特征选择是真·删列,直接把某个特征整列拿掉;PCA 只是换了一套坐标系、再砍掉最不重要的轴。

代价也在这:正因为每个 PC 都混了所有原始特征,降维后的维度没法一对一映射回某个原始特征,可解释性差——这就是把"砍方向"误解成"砍特征"时,顺带要接受的代价(第六节细说)。

那 PC1~PCk 找到之后,怎么归纳它们"到底指什么"?

PCA 不会自动给你贴语义标签,它只给你一组权重。要归纳某个 PC 的含义,看的正是这些权重——学术上叫载荷(loading),也就是特征向量里对应的分量。

"PC1 载荷"这个数值到底指什么? 它至少有三层互相等价、但角度不同的理解,搞清楚任意一层,"载荷"就不再是个黑盒:

  • 数学层:它就是特征向量 \(W\) 里第 \(p\) 行、第 \(j\) 列的那个分量 \(w_{pj}\)。比如"身高的 PC1 载荷 = 0.62",说的就是特征向量第一列里、对应"身高"那一行的值是 0.62。它就是个坐标系数,没别的神秘。
  • 几何层:把原始特征轴 \(x_p\) 和主成分轴 \(PC_j\) 都从原点画出来,载荷 \(w_{pj}\) 在数值上等于这两个轴夹角的余弦 \(\cos\theta\)。\(\cos\theta\) 越接近 \(\pm1\),说明该特征几乎"躺"在这个主成分方向上、贡献越大;越接近 0,说明两根轴基本垂直、这个特征对这个 PC 几乎没贡献。所以载荷本质上量的是"特征 \(x_p\) 有多顺着 PC\(_j\) 这个方向"。
  • 统计层:在标准化数据上,载荷 \(w_{pj}\) 和"特征 \(x_p\) 与主成分得分 \(PC_j\) 的相关系数"成正比(比例因子只差一个特征值平方根的缩放,不影响大小排序和符号)。换句话说,载荷衡量的是特征 \(x_p\) 和这个主成分 \(PC_j\) 之间线性相关的强弱——正号同向、负号反向。

一个极容易混的点:载荷(loading)≠ 得分(score),两个东西经常被当成一回事。

  • 载荷在"特征 → 主成分"那一端:描述"原始特征 \(x_p\) 朝 PC\(_j\) 方向贡献了多少",落在特征向量矩阵 \(W\) 里(\(\dim = d \times k\))。
  • 得分在"样本 → 主成分"那一端:描述"某个样本在第 \(j\) 个 PC 上的坐标是多少",落在降维后的数据矩阵 \(Z = XW\) 里(\(\dim = n \times k\))。
  • 一句话区分:载荷回答"这个轴由哪些特征构成",得分回答"每个样本在这个轴上排哪儿"。 上一节说"PC1 载荷 0.62"是前者;"某个人的 PC1 得分是 1.3"是后者。

所以回头看上面那句话——"体重的 PC1 载荷 0.58"——它的完整含义是:体重这个特征,和 PC1 这个方向高度同向(夹角小、余弦大),是撑起 PC1 的主要特征之一。第 \(j\) 个主成分写成原始特征的线性组合就是:

\[PC_j = w_{1j}x_1 + w_{2j}x_2 + \dots + w_{dj}x_d \]

解读方法只有一条:看哪些原始特征的 \(|w|\) 最大。绝对值大的特征,对这个 PC 的贡献就大,这个 PC 大体上就是这些特征的"合力方向"。

举个载荷表(假设 PC1 在 4 个特征上的权重):

原始特征 PC1 载荷 \(w\) 大致角色
身高 0.62 主导
体重 0.58 主导
年龄 0.30 次要
性别 0.12 几乎无关

那 PC1 就可以归纳成"体型大小"轴——身高、体重说了算,年龄、性别基本不参与。载荷的正负号只表示方向(正的那端是"高值"、负的那端是"低值"),不影响"谁更重要"的判断。

把"归纳含义"做成可操作的一步法:别只盯绝对值最大的那一个。实务上会先定个门槛(比如 \(|w| \ge 0.3\) 或 \(0.5\),看特征数和数据量),把一批超过门槛的特征拎出来,看它们共同在描述什么。还是上面的例子,PC1 上身高、体重都高,就叫"体格"轴;如果另有 PC2 上"阅读速度、词汇量、理解分"都高,就叫"语文能力"轴。一个 PC 往往对应一组"平时就一起动"的特征,给它起个名,比盯单个最大权重更贴合业务。

更进一步:PCA 还能帮你看出特征之间的关联性——这其实是它的隐藏价值。它对角化的是协方差矩阵(第三节第 2 步说过,非对角元就是两两协方差),所以本来高度相关的特征,会被自动"收编"到同一个主成分上、且载荷同号。

拿一张两轴载荷表看就更直观:

特征 PC1 载荷 PC2 载荷
身高 0.62 0.10
体重 0.58 0.05
训练量 0.05 0.71
体脂率 0.08 −0.66

读关联有三句真言:

  • 同一 PC 上、同号高载荷的两个特征 → 正相关:它们平时一起涨一起跌。表里身高(0.62)和体重(0.58)同号高载荷落 PC1,就是典型的"长得高的人往往也重"。
  • 同一 PC 上、异号高载荷 → 负相关:一个涨另一个跌。表里训练量(0.71)和体脂率(−0.66)落 PC2 两端,说明练得越多体脂越低。
  • 载荷都很小、散落在多个 PC 上 → 基本相互独立:不在任何明显"团伙"里,是单干户。

想看得更直观,可以画双标图(biplot)/ 相关圆:图里每个特征是一支从原点出发的向量,长度代表它对当前 PC 的贡献强度,夹角代表相关性——夹角小(趋同)≈ 正相关,接近 90° ≈ 不相关,接近 180° ≈ 负相关。样本点也画在同一张图里,能同时看"谁和谁像、哪组特征绑在一起"。

这种归纳仍需关注的注意点:

  • 载荷往往是"摊"在好几个特征上的混合,尤其当特征间高度相关时,一个 PC 很少干净地对应一个概念,它本质是多个特征被搅在一起。
  • 小样本下载荷不稳定:换一个随机子集重算,权重的排序甚至正负号都可能翻转。
  • 如果业务真需要"这个维度 = 某个明确特征"的清晰归因,PCA 其实不是最合适的工具——第七节讲的 Lasso / 树重要性那种特征选择,或因子分析里的旋转(varimax),才是为可解释性专门设计的。PCA 的强项是抓方差结构、压缩维度,不是给特征贴语义标签。

四、几何直观:方差最大 = 投影最分散

下面这张图说明 PC1 为什么是那条斜线:所有点投影到 PC1 上之后,投影点的散布(红色连线和红点)比投到任何别的方向都宽。投到 PC2 上就窄得多,说明第二主成分信息量小,可砍。

image

五、选几个主成分:k 预先定还是按公式算?

先直接回答:PCA 里没有"唯一正确的 k",也没有一个放之四海皆准的神谕公式。 k 的确定大致走三条路子,实务里常常是"先用公式给个候选,再按用途拍板":

  1. 按数据规律用公式 / 准则给候选(最常见):累计解释方差阈值、Kaiser 准则、碎石图拐点——这些都不需要你先拍脑袋定 k,它们吃的是同一份东西:协方差矩阵的特征值谱 \(\lambda_1 \ge \lambda_2 \ge \dots\)。每个 PC 的解释方差 = \(\lambda_i \big/ \sum_j \lambda_j\)。
  2. 直接预先定好(合法,且很常见):纯粹为了画图,就锁 \(k=2\) 或 \(3\);下游模型吃不下太多维,就按它的容量反推一个上限。这不算偷懒,是"用途驱动"。
  3. 按下游任务表现反选(最讲道理,但需要标签 / 目标):既然"方差保住 ≠ 任务有用"(见末尾提醒),那就直接拿降维后的数据去跑真实模型,选让验证集指标最好的那个 k。

一个结构上限先说清楚:主成分最多只有 \(\min(n, d)\) 个——你不可能搞出比"特征数"或"样本数"还多的 PC。所以 k 的天花板是数据的 shape,不是你想要多大就多大。

每个主成分带走一部分方差,比值就是它的解释方差(上面第 1 类准则的原材料)。把所有主成分的解释方差累加,得到累计曲线。具体怎么用这几条路子:

  • 累计解释方差阈值:选到累计解释方差 ≥ 0.95(或 0.9)的前 \(k\) 个,剩下的方差占比小的当噪声砍掉。这是工程默认做法,门槛高低看你对信息损失的容忍度。
  • Kaiser 准则(硬公式):标准化数据下,所有特征值的平均值恰好是 1,所以只保留特征值 \(\lambda_i > 1\) 的主成分——因为 \(\lambda_i \le 1\) 意味着这个方向解释的方差还不如"一个平均特征"多,不值得留。这是少数能直接写成硬规则的选法,但机械套用在维度很高时往往留太多,当粗筛可以。
  • 碎石图(scree plot)拐点:把特征值从大到小画成折线,形状像"悬崖 → 碎石坡",保留拐点之前的那几个。本质是肉眼找"再往后特征值就平了"的位置,带主观性,但和累计阈值互相印证。
  • 用途预设:可视化 \(k=2/3\);建模按下游模型容量。
  • 交叉验证 / 下游指标:在第 3 类路子下,扫一遍不同的 k,取验证集上模型效果最好的那个——这是化解"方差保住 ≠ 任务有用"那层矛盾最实在的办法。

解释方差高 ≠ 对目标任务有用。PCA 是无监督的,它只管"总方差",不管"和标签的相关性"。如果你的目标是分类,降维后总方差保住了,但类别边界可能被压没了——这种时候 LDA 或带正则的模型可能更靠谱;而"按下游任务反选 k"正是为化解这层矛盾而存在的。

六、实践中的注意点

  1. 必须标准化(StandardScaler)。PCA 对量纲极度敏感。一个特征单位是"万元"、另一个是"米",方差大的那个会直接 dominate 第一主成分。先 \((x-\mu)/\sigma\) 再喂进去。

  2. 线性相关假设。PCA 只能抓线性关系。特征间如果是非线性流形(比如瑞士卷),PCA 会把流形压扁成一团,信息全丢。这种得上核 PCA 或 t-SNE / UMAP。

  3. 异常值敏感。方差被离群点牵着走,主成分会歪向异常值。先清洗,或上 RobustPCA。

  4. 稀疏数据别硬上。文本 TF-IDF、One-hot 这类稀疏矩阵,PCA 投影后变稠密,内存和语义双双爆炸。用 TruncatedSVD(直接对稀疏矩阵做,不必中心化)。

  5. 可解释性代价。降维后的轴是原始特征的线性组合,不再有业务含义。"主成分 3"你没法跟业务方解释它代表什么。要解释性就慎用,或配合载荷矩阵(loading)做成分解读。

七、PCA 之外:主流降维方法怎么选

PCA 只是降维家族里最主流的一个,但它有两条硬约束——线性、无监督。真实数据里这两点常常不成立,于是有了其它路线。按"是否线性"和"是否用标签"两路分:

flowchart LR A[降维方法] --> B[线性] A --> C[非线性] B --> B1[PCA · 无监督] B --> B2[LDA · 有监督] C --> C1[核PCA · 核技巧] C --> C2[t-SNE / UMAP · 流形可视化] C --> C3[IsoMap / LLE · 流形学习] C --> C4[自编码器 · 神经网络]

各自的取舍:

  • LDA(线性判别分析):和 PCA 一样线性,但有监督——它找的方向是"类间散度最大、类内散度最小",专为分类服务。目标是分得好,LDA 通常比 PCA 更对口。代价是要标签,且最多降到(类别数 − 1)维。

  • 核 PCA(Kernel PCA):用核技巧先把数据映射到高维再线性降维,等于在原始空间里学到了非线性投影。适合 PCA 把流形压扁的场景。代价是计算量上去了,且没有显式投影矩阵,新样本要单独算。

  • t-SNE / UMAP:流形可视化的两把刷子,擅长把高维簇在 2D/3D 里摊开看。t-SNE 保局部邻域但不保全局距离(簇间远近别当真);UMAP 更快、保更多全局结构。两者都不适合当建模前端的降维,只适合看分布,且对超参敏感、结果带随机性。

  • IsoMap / LLE:经典流形学习,靠"测地距离"或"局部线性重构"还原非线性流形。理论漂亮,但新样本难投影、对噪声和参数都敏感,实战用得越来越少,多被 UMAP 取代。

  • 自编码器(Autoencoder):用神经网络学一个编码器把数据压成低维、解码器再还原,非线性能力最强,能处理极复杂结构,还可以直接拿到新样本的编码。代价是要训练、要调参、要数据量。

  • 特征选择(不算投影降维,但达到类似目的):Lasso 回归、树模型特征重要性、方差阈值过滤——它们挑出原始特征子集而非构造新轴,最大好处是可解释,留下的每个维度业务方都认得。很多时候这比 PCA 更合适。这三种具体是:

    • Lasso 回归(套索回归,Least Absolute Shrinkage and Selection Operator):普通线性回归加上 L1 惩罚项 \(\alpha\sum_j|\beta_j|\)。L1 罚项的脾气是"把不重要的系数精确压成 0"——训练完哪些 \(\beta_j \neq 0\),哪些特征就被留下,等于一边建模一边做特征选择。留下来的还是原始特征列,业务方认得,不像 PCA 那样把所有特征搅成一锅。代价是:正则强度 \(\alpha\) 要调参;特征高度相关时 Lasso 会随机留一个、扔其余(不稳定);它本质线性,抓不了非线性关系。
    • 树模型特征重要性:随机森林 / 梯度提升树这类集成树,训练完能直接给每个特征打"对预测贡献多大"的分。常用两种口径——① 不纯度减少(Gini / 信息增益)汇总,训练时特征用来切分降低了多少不纯度就记多少;② 排列重要性(permutation importance,打乱某特征看指标掉多少,更稳但更贵)。看排名砍掉垫底、得分≈0 的特征即可。关键它是有监督的——重要性 = "对预测目标的贡献",所以"对任务没用的特征"能被识别出来,正好补 PCA 无监督的短板(呼应第八节随机森林)。代价是:高基数 / 连续特征在口径①上容易虚高,相关特征会分摊彼此的重要性。
    • 方差过滤(Variance Threshold):最朴素的无监督粗筛——直接算每个特征的方差,把方差低于阈值的删掉。方差 ≈ 0 的特征在所有样本上几乎不变,带不来任何区分信息,留着纯占维度。它只看特征自身分布、不看标签,所以有可能误删"方差小但对预测极关键"的特征(和 PCA 一样有无监督盲点),只能当第一道粗筛,最好和 Lasso / 树重要性配合。阈值难定,且对量纲敏感(要先标准化,否则大数值特征永远不过滤)。

PCA 是默认起手式;要保类别用 LDA;要非线性用核 PCA 或自编码器;要看分布用 UMAP;要解释性用特征选择。

八、PCA vs 随机森林:两条不同的路

常有人问:高维数据到底该先用 PCA 压一压,还是直接丢随机森林?这俩不是替代关系,是两种处理高维的哲学。

PCA 是预处理:它不管你要解决什么任务,先把数据投影到方差最大的低维空间,再交给下游模型。随机森林是模型本身:它靠 bagging + 特征随机子集 + 决策树集成,在高维里天然抗过拟合,还能直接输出特征重要性,等于边训练边帮你"挑特征"。

核心区别:PCA 无监督,连"和标签相关的方向"也可能被它当噪声牺牲掉;随机森林有监督,它衡量的"重要"始终是对预测目标的贡献。

维度 PCA 降维 随机森林
本质 无监督预处理(投影变换) 有监督模型(集成决策树)
处理高维的方式 压缩成少数主成分 原生支持,靠随机特征子集抗过拟合
是否用标签 否 是
输出可解释性 低(主成分是原特征的线性组合) 中(特征重要性可排序,但非业务语义)
能否抓非线性 只能抓线性(核 PCA 才行) 天然非线性(树分裂)
是否做特征选择 否,构造新轴 是,可输出重要性做筛选
规模敏感点 协方差矩阵 \(d^2\),超高维吃内存 树多也吃算力,但可并行
适合场景 去冗余 / 去噪 / 可视化 / 降维前端 直接建模 / 要特征排名 / 非线性边界
典型风险 压掉与标签相关的方向、量纲敏感 无正则时易过拟合噪声特征、黑箱

怎么选:

  • 先 PCA 再建模:特征高度冗余、维度极大想降内存/提速、要做可视化、或下游是个对共线性敏感的线性模型(如逻辑回归)。
  • 直接随机森林:你就是想建一个预测模型、数据非线性、且想知道哪些特征重要。它不需要你先做 PCA,盲目 PCA 反而可能把它的非线性边界压坏。
  • 两者结合:用随机森林算特征重要性 → 砍掉不重要的特征(可解释的特征选择)→ 再对剩下的跑 PCA 去冗余。这是实战里很顺手的组合。

一个常见误区:以为"维度高就一定要先 PCA"。随机森林在高维上往往表现不差,盲目 PCA 反而可能损失信息。先想清楚下游任务和是否要可解释,再决定。

九、PCA 的局限性与弊端

前面第六节是"操作时要注意的坑",这里说的是方法本身的天花板——有些限制不是你用错了,是 PCA 的假设就长那样。

  • 方差最大 ≠ 对任务有用(最致命)。PCA 无监督,只优化"总方差",完全不看标签。结果就是:那个真正能把类别分开的方向,可能方差很小,被它当噪声扔了。拿 PCA 压完再分类,有时反而比不压更差。这是它用在预测任务上最大的坑(第五节、第八节都点过)。

  • 只认线性结构。PCA 找的是"直"的轴,沿直线最大化方差。如果数据真实结构是弯的(流形、弧形分布),一条斜直线轴会把流形压扁、搅成一团。要看非线性得换核 PCA、UMAP 或自编码器(第七节)。

  • 对量纲和异常值脆弱(结构性)。PCA 最小化 L2 重建误差,所以天生怕离群点——几个坐标很大的异常值就能把 PC1 整个拽过去;一个数值量级大的特征也会独吞 PC1。这不是手滑,是平方和项的公式决定的。对策在第六节(标准化 + 去异常值),但根子在这。

  • 可解释性是硬伤。每个 PC 是所有特征的混合,加上特征向量符号/朝向任意、小样本下载荷还会晃,你很难干净地说"PC1 就是身高"。业务方要的是"哪个特征重要",PCA 给的是"一堆特征的搅和",天然不对口(见 PC 归纳那段)。

  • 小样本下估计不可靠。当样本数 \(n\) 没比特征数 \(d\) 大多少时,样本协方差矩阵本身噪声很大,算出来的"最大方差方向"可能主要就是抽样噪声。随机矩阵理论(Marchenko–Pastur)早就证明:高维小样本下最大特征值会被噪声整体抬高。所以前面说"有限数据方差有界、能算完",但"算完"不等于"算对"。

  • 正交约束不一定最优。PCA 强制各主成分两两正交。对很多真实结构(几个相互独立的信号源),非正交的基(如 ICA 独立成分分析)反而更能把结构拆开。

  • 有损,且不可无损还原。丢掉后面的主成分,原始数据就无法精确还原——适合压缩,但后续若还要拿回精确原始值,PCA 不行。

  • 不适合稀疏 / 计数 / 二值数据。在词袋、one-hot、计数这类数据上,PCA 会产出带负值的稠密混合分量,既无物理意义也难解释(第六节也点过)。

简言之:PCA 强在"抓全局方差结构、顺手压缩",弱在"不看任务、不认非线性、不好解释、怕异常值和量纲"。知道它弱在哪,第十节先讲怎么验证它没翻车,第十一节"用与不用"才好做决定。

十、降维之后,怎么验证它是对的?

先泼一句清醒的:PCA 是无监督的,不存在一个"标准答案"让你逐一对错。所以"验证降维正确"其实拆成两件事:① 这次变换数值上算对没有(可严格验证);② 降维结果对得起你的业务目的没有(只能靠下游指标佐证,没有绝对标准)。两层都过,才算稳。

flowchart TD A[降维结果 Z] --> B{数值正确性} B --> B1[重建误差 ≈ 丢弃成分方差] B --> B2[WᵀW ≈ I 正交单位化] B --> B3[解释方差自洽] A --> C{任务充分性} C --> C1[下游模型对比] C --> C2[邻域 / 结构保持] C --> C3[类别结构保留] B --> D[数学错 → 查中心化/标准化/库调用] C --> E[任务掉点 → 调 k 或换方法]

第一层:数值正确性(transform 到底算对没)

这一层是硬验证,错就是对错了,没有灰色地带:

  • 重建误差检验:用保留的 PC 把数据反投影回原空间 \(\hat X = Z W^T + \mu\),和原始 \(X\) 算均方误差。关键点在于——这个重建误差,理论上恰好等于被你丢弃的那些成分所携带的总方差。所以它能一箭双雕:既验证"降维 ↔ 重建"这条链路没断,又顺手验证你报告的解释方差数对不对。如果 MSE 明显大于 \((1 - \text{累计解释方差}) \times \text{总方差}\),八成是忘了中心化、或标准化 / scaler 用串了、或库调用姿势不对。
  • 正交单位化检验:主成分构成的矩阵 \(W\) 应当满足 \(W^T W \approx I\)——每一列是单位向量、列与列两两正交(呼应第二节讲的"垂直")。验算一下能确认库没给你一套歪掉的基。
  • 解释方差自洽:工具报的 explained_variance_ratio_ 之和,应当等于你自己用特征值算的 \(\sum_{i=1}^{k}\lambda_i \big/ \sum_{j=1}^{d}\lambda_j\)。两边对不上,说明特征分解那步或你读数的姿势有问题。
  • 符号任意性:特征向量乘 \(-1\) 还是同一条轴,所以 PC 的方向符号可正可负,换次运行甚至都能翻。验证时别因为"符号反了"就以为算错:下游模型不 care 符号,只有你人工读载荷、贴语义标签时才要注意统一方向。

第二层:任务充分性(降维对不对得起你的目的)

这一层没有"对 / 错",只有"值不值",靠对比说话:

  • 下游模型对比:同一份数据,一份用原始 \(d\) 维特征训练,一份用降维后的 \(k\) 维训练,比验证集指标。降维后不掉点甚至更好 → 降维有效、还省了算力;掉很多 → 你砍掉了任务真正依赖的信息(这正是第九节说的"方差最大 ≠ 对任务有用")。这是最实在的一票。
  • 邻域 / 结构保持:降维最容易偷偷搞坏的是"局部结构"——原本挨得近的点,压完可能分开了。可以用 trustworthiness / continuity 这类指标,或简单比一比降维前后 k 近邻集合的重合率、pairwise 距离的相关系数(Spearman),看"近的还近不近"。
  • 类别 / 簇结构保留:分类或聚类任务里,直接看降维后各类的 silhouette,或把前 2 个 PC 画散点看类别还分不分得开。类别边界被压没了,就是降维过度或 PCA 不合适(第九节第一点的具象化)。

第三层(顺手):诊断降维到底值不值得做

  • 看碎石图形状:有明显拐点 → 低维表示存在、降维有意义;谱线接近平坦(特征值都差不多大)→ 数据接近各向同性噪声,PCA 压不出什么油水,降维价值本身就低(呼应第五节选 k、第九节局限)。
  • 查单特征独吞 PC1:如果第一个主成分几乎只由一个特征主导,说明量纲没处理好(第六节的标准化没做或做错),这正是该回头查预处理,而不是怀疑 PCA 本身。

简言之:数值正确性靠"重建误差 = 丢弃方差 + \(W^T W \approx I\)"三板斧严格卡;任务充不充分靠"下游模型对比 + 结构保持"说话;两者之间没有"标准答案",只有"够不够用"。

十一、什么时候用,什么时候别用

用它:数据冗余高、想提速/降内存、预处理去噪、把高维拉到 2D/3D 看分布、作为其他模型的降维前端。

别迷信它:目标任务对非线性结构敏感、需要可解释特征、数据稀疏、或者你其实只是想做特征选择(那该用 Lasso / 树模型重要性,而不是 PCA)。

PCA 是工具箱里最顺手的那把螺丝刀,但不是万能的。理解它每一步在丢什么、保什么,你才能在模型出问题的时候,而不是之前,说清楚原因。

十二、总结

  • PCA 作用:把数据从原始特征坐标系,旋转到一组新的正交轴(主成分)上,按"投影后方差最大"给轴排座次,砍掉后排的、留前排的——本质是换坐标系 + 丢最不散的方向,不是删特征列。
  • 三个最容易想歪的点:①"方差最大"是闭式分解出来的,不是反复拉伸、不会算不完;② PC 是同时出生、座次按方差排,不是一层层盖楼;③ 数据变多要重算,因为它是绑定当时那份协方差矩阵的,但只是重做一次矩阵分解、不是重训模型。
  • 两条必须做的动作:先标准化(否则大连量级特征劫持 PC1),再选 k(累计解释方差 / Kaiser / 下游反选,没有唯一神谕公式)。
  • 它的天花板:无监督——方差最大 ≠ 对任务有用;只认线性、怕异常值和量纲、可解释性硬伤、小样本下估计会飘。要保类别用 LDA,非线性用核 PCA / 自编码器,看分布用 UMAP,要解释性用特征选择。
  • 验证它没"标准答案":数值正确性靠"重建误差 = 丢弃方差 + \(W^T W \approx I\)"三板斧硬卡;任务充不充分,靠下游模型对比和结构保持说话。

—— 与君共勉~ ——

posted @ 2026-10-20 18:36  昂流  阅读(16)  评论(0)    收藏  举报
//替换成自己路径的js文件 hhttp(s)://static.tctip.com/tctip-1.0.4.min.js