2.6 降维PCA与LDA

1.为什么要降维:从一杯水说开去

说起来,我们前面讲了好几种经典算法了。2.1 节讲线性回归的时候,特征只有一两个,画在纸上是一条直线或者一个平面,看起来特别舒服。可现实里的数据多半没有这么温顺,特征一多起来,事情就完全不一样了。

降维说穿了就是把一份数据从很多很多维,压到几维甚至两维。这听起来像是在丢东西,可很多时候丢的恰恰是噪声和冗余,留下来的是真正有用的信号。这件事至少有四个用处。

第一是可视化。人眼看得懂两维三维,超过三维的散点图就得靠颜色、靠动画硬撑,到几十维的时候基本只能放弃。把高维数据降到两维画出来,分布的形状、有没有聚类、有没有离群点,一眼就大概清楚了。我记得有一本讲统计可视化的书里讲到,人眼对二维形状的识别能力远远超过对数字表格的识别能力,画图往往比算指标更早发现问题。

第二是去噪。原始数据里常常混着一堆跟任务无关的扰动,这些扰动往往散落在很多小方向上,能量很小。降维的时候把它们一并丢了,留下来的主方向反而更干净。

第三是加速训练。特征越多,矩阵越大,训练越慢,这件事不用多讲。把维度压下去之后,连2.1 节的线性回归、1.4 节的朴素贝叶斯都能明显跑得轻快些。

第四是缓解维度灾难。这个名字听起来挺吓人,其实道理并不复杂。维度越高,空间里两点之间的平均距离会被拉得越来越散,固定数量的样本在高维空间里变得稀稀拉拉,KNN(1.4 节讲过的近邻算法)那种靠距离判断的做法就失灵了,因为谁都算不上近邻。打个比方,十个人在一个小房间里随便一伸手就能摸到另一个人的肩膀,可放到一个足球场上,每个人都隔得老远,想凑到一起说话就费劲了。维度灾难差不多就是这个味道。

2.PCA:找方差最大的方向

PCA(Principal Component Analysis,主成分分析)是最常见的无监督降维方法。无监督的意思是它不看标签,只看数据本身的形状。它要做的,是找一组新的坐标轴,让数据在这些轴上看起来最有内容。

那什么叫有内容呢。PCA用的标准是方差。我们记单个数据点为 xxxx 是一个向量,里面装着这个样本在原始所有特征上的取值。PCA希望找到一个方向 wwww 是一个和 xx 维数相同的单位向量),让所有数据点投影到这个方向上之后,投影值 wTxw^T x 的方差尽量大。这里 wTxw^T x 就是 wwxx 的内积,几何上等于 xxww 方向上的投影长度(我们固定 ww 的长度为 11,所以这个内积恰好就是投影长度)。

方差大为什么就等于信息多呢。不妨想一个画面,假设手里有一组二维点,大致沿着一条斜线拉长分布。你要是沿着这条斜线的方向看,点的位置差别很大,从一头到另一头拉开了好远,这个方向上每个点都不一样,信息丰富。可你要是沿着和这条斜线垂直的那个短方向看,所有点几乎挤在一起,这个短方向上区分不出谁是谁,信息量就很小。所以PCA要找的,就是那些数据拉得最开、最分得清彼此的方向。说到底,方差大就代表这一维上的样本彼此有差别,差别就是信息。我之前看过一本讲江南园林的书,里面讲究借景和分景的手法,明明是同一片园子,从不同角度看进去层次完全不同,降维其实也有点这个意思,同一个高维数据,换一组坐标去看,结构就清清楚楚露出来了。

那具体怎么算呢。PCA的步骤大概是这样五步。

第一步,标准化。原始特征往往量纲差很多,比如身高用厘米、体重用千克、收入用元,数值范围一拉开,方差全被量纲大的特征占去了。所以要先对每个特征减去均值再除以标准差,写成公式是 xstd=(xμ)/σx_{std} = (x - \mu) / \sigma,其中 μ\mu 是这个特征的均值,σ\sigma 是这个特征的标准差,xstdx_{std} 就是标准化之后的取值。这一步把每个特征都拉到差不多同一个尺度上,均值大约是 00,方差大约是 11

第二步,算协方差矩阵。协方差矩阵记作 Σ\Sigma(大写的sigma),它是一个 d×dd \times d 的方阵,dd 是原始特征的个数。Σ\Sigma 的第 ii 行第 jj 列那个元素,记录的是第 ii 个特征和第 jj 个特征之间的协方差。对角线上是各特征自己的方差,非对角线上是特征之间的相关程度。协方差这个概念我们在讲特征工程的时候提过,两个特征一起涨一起落,协方差就是正的,一个涨一个落就是负的,没什么同步关系就接近零。Σ\Sigma 这个矩阵其实就是把所有特征两两之间的这种关系整齐地摆出来。

第三步,做特征值分解。这一步直接联系到1.3 节讲的特征值和特征向量。对协方差矩阵 Σ\Sigma 求它的特征值 λi\lambda_i 和对应的特征向量 viv_iii 是特征值的编号。λi\lambda_i 是一个数,viv_i 是一个方向。它们满足一个很漂亮的关系 Σvi=λivi\Sigma v_i = \lambda_i v_i,意思是矩阵 Σ\Sigma 作用在 viv_i 这个方向上,效果只是把这个方向拉长 λi\lambda_i 倍,方向不变。1.3 节里我们花了一整篇来讲这件事,这里正好用上。

为什么"找方差最大的方向"等价于"求协方差矩阵的最大特征向量"。 这一步是 PCA 的核心,我们把推导走完,免得心里留疙瘩。PCA 要找一个单位方向 www=1\|w\|=1),让投影 wxw^\top x 的方差最大。设数据已去均值(E[x]=0\mathbb E[x]=0),投影的方差是:

Var(wx)=E[(wx)2]=E[wxxw]=wE[xx]w=wΣw\operatorname{Var}(w^\top x)=\mathbb E[(w^\top x)^2]=\mathbb E[w^\top x x^\top w]=w^\top\mathbb E[xx^\top]w=w^\top\Sigma w

(最后一步用了协方差矩阵的定义 Σ=E[xx]\Sigma=\mathbb E[xx^\top]。)于是问题变成:在 w=1\|w\|=1 约束下最大化 wΣww^\top\Sigma w。这是个带等式约束的优化,用 1.5 节讲的拉格朗日乘子法,构造拉格朗日函数 L=wΣwλ(ww1)\mathcal L=w^\top\Sigma w-\lambda(w^\top w-1),对 ww 求导令其为零:

wL=2Σw2λw=0    Σw=λw\nabla_w\mathcal L=2\Sigma w-2\lambda w=0\;\Longrightarrow\;\Sigma w=\lambda w

这正是特征值方程!所以让方差最大的方向 ww,必须满足 Σw=λw\Sigma w=\lambda w,也就是协方差矩阵的特征向量。再代回去:Var(wx)=wΣw=wλw=λw2=λ\operatorname{Var}(w^\top x)=w^\top\Sigma w=w^\top\lambda w=\lambda\|w\|^2=\lambda。这就证明了"特征值 λi\lambda_i 恰好等于数据在 viv_i 方向上的方差"——所以挑最大的特征值,就是挑方差最大的方向。

第四步,挑前几个最大的特征值。把所有的特征值从大到小排一下,取前 kk 个最大的,对应的 kk 个特征向量就是我们要的新坐标轴。kk 是你想留下来的维度数,由你自己定。为什么要挑最大的呢,因为上面刚证明了特征值 λi\lambda_i 恰好等于数据在 viv_i 这个方向上的方差,特征值越大这个方向上的方差越大、信息越多。

第五步,投影。这里的 xx 指的是已经经过第一步标准化的 xstdx_{std}。把 kk 个特征向量拼成一个矩阵 WWWW 的每一列是一个 viv_i),新的低维表示就是 z=WTxstdz = W^T x_{std},其中 zz 是降维后的向量,长度是 kk

举个带数字的小例子。假设小张在一家券商实习,手里有一份股票数据,每只股票记录了五个指标,比如市盈率、市净率、换手率、振幅、成交量。五维画不出来,他想压到两维看看分布。先标准化,再算协方差矩阵得到一个 5×55 \times 5 的方阵,做特征值分解得到五个特征值,从大到小排是 2.12.11.61.60.70.70.40.40.20.2,加起来是 55。前两个加起来 3.73.7,占 74%74\%,说明这两个方向已经承载了大约七成四的总方差。小张就把这两个方向拿来当横纵坐标,画出一张散点图,能看出哪些股票聚在一起、哪些离群,挺直观的。剩下的 0.70.70.40.40.20.2 这三个特征值对应的方向方差小,多半是一些细碎的扰动,丢掉不太心疼。

PCA有个特别讨喜的性质,就是降维之后新的坐标两两之间是不相关的,协方差是零。这件事我们证一下。 协方差矩阵 Σ\Sigma 是对称矩阵,对称矩阵的特征向量可以选成彼此正交的,即 vivj=0v_i^\top v_j=0iji\neq j)。降维后的新坐标是 zi=vixz_i=v_i^\top xzj=vjxz_j=v_j^\top x,它们的协方差是 Cov(zi,zj)=E[vixxvj]=viΣvj\operatorname{Cov}(z_i,z_j)=\mathbb E[v_i^\top x x^\top v_j]=v_i^\top\Sigma v_j。把 Σvj=λjvj\Sigma v_j=\lambda_j v_j 代进去:viλjvj=λj(vivj)=0v_i^\top\lambda_j v_j=\lambda_j(v_i^\top v_j)=0。所以新坐标两两协方差为零,PCA 顺便把特征相关性也理顺了,新坐标是干净的。

工程上算 PCA 其实基本不上特征值分解,而是上 SVD。 这件事值得单独说清,免得你看代码时犯迷糊。1.3 节我们讲过 SVD:任意矩阵能分解成 A=UΣVA=U\Sigma V^\top。现在把去均值后的数据矩阵 XX(每行一个样本)做 SVD,得到 X=UΣVX=U\Sigma V^\top。关键的一条代数关系是:协方差矩阵 1nXX=1nVΣUUΣV=1nVΣΣV=VΛV\frac{1}{n}X^\top X=\frac{1}{n}V\Sigma^\top U^\top U\Sigma V^\top=\frac{1}{n}V\Sigma^\top\Sigma V^\top=V\Lambda V^\topUU 正交所以 UU=IU^\top U=I1nΣΣ=Λ\frac{1}{n}\Sigma^\top\Sigma=\Lambda 是特征值对角阵)。对比 Σ=VΛV\Sigma_{\text{协}}=V\Lambda V^\top 就明白:SVD 的右奇异矩阵 VV,正好就是协方差矩阵的特征向量矩阵;奇异值的平方除以 nn,正好就是特征值。 所以做一次 SVD 就同时拿到了 PCA 要的全部东西——主成分方向(VV 的列)和各方向方差(奇异值平方/nn)。工程上普遍用 SVD 而不是直接算 XXX^\top X 再特征分解,因为 XXX^\top X 会平方化条件数、数值上更不稳,SVD 直接对 XX 操作更准。

3.LDA:让同类靠近、异类分开

PCA只看形状不看标签,可有时候我们手头是有标签的,比如这批股票里哪些标记为上涨、哪些标记为下跌。这种时候光找方差大的方向不一定对分类最有利。LDA(Linear Discriminant Analysis,线性判别分析)就是一种有监督的降维方法,它会利用标签信息,找一个让分类更舒服的方向。

LDA的目标用一句话讲,就是让同类样本尽量靠在一起,不同类样本尽量分开。要量化这件事,得先定义两种散度。一种叫类内散度 SWS_W(W是within的缩写),衡量的是同一个类别内部样本围绕自己类别中心的分散程度,越小越好,越小同类越紧。一种叫类间散度 SBS_B(B是between的缩写),衡量的是各个类别中心彼此离得多远,越大越好,越大类别分得越开。LDA要做的,就是找一个投影方向 ww,让比值 J(w)=wTSBwwTSWwJ(w) = \frac{w^T S_B w}{w^T S_W w} 最大。这个 J(w)J(w) 就是投影之后的类间散度除以类内散度,分子是分得开不开,分母是同类紧不紧,整体越大越好。

这个式子看起来陌生,其实它和2.1 节线性回归里的优化目标是一类东西,都是一个要最大化或者最小化的目标函数。它的解为什么是个广义特征值问题,我们推一下。 J(w)=wSBw/(wSWw)J(w)=w^\top S_B w/(w^\top S_W w) 这种"两个二次型之比"的形式有个专门的名字,叫瑞利商(Rayleigh quotient)。它有个漂亮性质:J(w)J(w) 的值在缩放下不变(ww 乘个常数,分子分母同时平方,比值不变),所以我们可以加一个约束 wSWw=1w^\top S_W w=1(把分母固定为1),问题变成"在 wSWw=1w^\top S_W w=1 下最大化 wSBww^\top S_B w"。用拉格朗日乘子法,构造 L=wSBwλ(wSWw1)\mathcal L=w^\top S_B w-\lambda(w^\top S_W w-1),对 ww 求导令其为零:

2SBw2λSWw=0    SBw=λSWw2S_B w-2\lambda S_W w=0\;\Longrightarrow\;S_B w=\lambda S_W w

这就是广义特征值问题 SBv=λSWvS_B v=\lambda S_W v(比 PCA 的普通特征值问题 Σv=λv\Sigma v=\lambda v 多了等号左边的 SWS_W)。J(w)J(w) 的最大值恰好等于最大的广义特征值 λmax\lambda_{\max},对应的最优方向就是那个特征向量。这里的 λ\lambdavv 跟PCA里的特征值、特征向量是同一个意思,只不过现在等号左右各多了一个矩阵。最终我们同样挑前几个最大的特征值对应的特征向量,作为新的坐标轴。

LDA还有一个先天的小限制。它最多只能给出 c1c-1 个有效的判别方向,cc 是类别数。比如三类分类问题,LDA最多降成两维,再多出来的方向特征值就接近零、没什么意义了。这个限制是它把标签信息用进去的代价。PCA没有这个限制,你想压到几维都行。

举个医学上的小例子。小明在医院实习,要从一份基因表达数据里区分两类病人,每份数据有两千多个基因表达量,维度极高。他要是先做PCA,找到的方差最大方向可能是和病人分组无关的整体波动,比如不同批次、不同时间采的血造成的差异。可要是用LDA,LDA会主动找一个让两类病人分开最明显的方向,这一个方向往往就够后面接一个简单的逻辑回归或者KNN把分类做出来。这里PCA和LDA的差别就特别明显,PCA关心的是数据整体摊得开不开,LDA关心的是类别分得开不开。

4.PCA和LDA到底差在哪

说了这么多,这两个方法到底该怎么挑。不妨这样想。PCA完全不看标签,它问的问题只有一个,就是哪个方向上方差最大。LDA带着标签,它问的是哪个方向上类别分得最开。这两件事在大部分场景里得到的方向是不一样的,方差大的方向未必是分类最有用的方向。

什么时候用PCA呢。数据没标签的时候,PCA几乎是默认选择,比如做探索性分析、画图、做特征压缩预处理。数据有标签但你想先看一下整体结构、不想让标签带着偏见的时候,PCA也合适。还有一种是高维数据预处理,先把维度压到一个合理范围,再喂给后面的模型,能显著加速训练,还能顺带去相关。

什么时候用LDA呢。数据有标签、而且降维的最终目的就是分类的时候,LDA往往更对症。它直接奔着让类别分开这个目标去,找到的方向对后续分类器(比如朴素贝叶斯、逻辑回归、KNN)更友好。

实际工程里大家多半不会二选一。一个常见做法是先做一次PCA把维度从几千压到一百上下,再做LDA进一步压到 c1c-1 维。PCA负责大体上的去噪和压缩,LDA负责精细地把类别分开,两步配合,既稳又快。

举几个不同行业的画面。在餐饮行业,一家连锁店想把旗下门店按经营状况分群,手里有十几个指标,比如客单价、翻台率、坪效、复购率,用PCA降到两维画图,能看出哪些门店走的是同一套打法、哪些是异类。在体育领域,分析一支篮球队里几十名运动员的体能数据,PCA能帮你把速度类、力量类指标揉成一个综合得分轴,LDA则能进一步把不同位置的运动员(后卫、前锋、中锋)分开。在物流里,把上千条配送路线按耗时、油耗、弯道数、爬升高度等指标降维,PCA能迅速指出哪几条路线比较相似、哪几条是离群点。各行各业都有自己版本的高维数据,降维这套思路是通用的。

5.两个经典场景:高维可视化和人脸预处理

最后讲两个最常见的落地场景,帮大家把前面的概念串起来。

第一个是把高维数据降到两维来画图。这在EDA(探索性数据分析)里几乎是日常操作。小张之前在金融数据上做过这件事,五维的股票数据压到两维之后,散点图上一眼能看到三四个明显的簇,他还记得当时跟导师对着图讨论,哪些簇是行业属性相似的公司、哪些是市值接近的、哪些是异常涨跌的,效率比盯表格高太多。要特别提醒一句,降到两维毕竟只保留了一小部分方差(像前面那个例子大约七成多),所以图上看着离得近的点,在高维空间里未必真的近,把它当作初步线索就好,结论还得回去用原始特征或者更可靠的指标再核一遍。

第二个是人脸识别的预处理。经典的人脸图像哪怕是灰度图,每个像素都是一个特征,一张 100×100100 \times 100 的脸就是 1000010000 维,直接训练特别费劲。早期一个非常出名的做法叫特征脸(Eigenfaces),其实就是把PCA用在人脸图像上。先对齐归一化好的一大堆人脸图像做PCA,得到的前几个主成分,你把它们重新排成图像来看,居然长得有点像人脸的低频轮廓,比如一个平均脸的样子、一个明暗分布的样子。这些主成分就是特征脸,新来一张人脸,把它在这几个特征脸上投影,得到一小组系数,就可以当作这张脸的精简表示,再喂给后续的分类器去识别是谁。这个方法今天看起来朴素,可它把人脸识别从纯像素带进了子空间建模的思路,影响很深远。我记得某部讲人工智能的连续剧里有一个桥段,调查人员对着监控画面一张张比对人脸,背后用到的核心套路,其实就是这一类降维加分类的组合。

说起来,从这一篇开始我们慢慢进入了经典机器学习里偏无监督和有监督降维的部分。PCA教我们怎么用方差衡量信息,LDA教我们怎么用标签引导方向,这两套思路在深度学习里也常以自编码器和监督特征学习的面貌重新出现。理解了它们,后面再读那些复杂的表示学习论文,心里会踏实很多。

练习

Q1. PCA 和 LDA 一个无监督一个有监督,它们各自"问的问题"是什么?实际工程里怎么配合用?

PCA 不看标签,它问的只有"哪个方向上方差最大",关心的是数据整体摊得开不开。LDA 带着标签,它问的是"哪个方向上类别分得最开",让同类靠拢、异类分开,关心的是分类有没有利。实际工程里常两步配合:先做一次 PCA 把维度从几千压到一百上下(去噪 + 压缩 + 去相关),再做 LDA 进一步压到 c1c-1 维精细分开类别,既稳又快。

Q2. 股票五维数据,协方差矩阵的五个特征值是 2.12.11.61.60.70.70.40.40.20.2(加起来 55)。压到二维后,前两个主成分承载了多少比例的总方差?

前两个特征值之和是 2.1+1.6=3.72.1+1.6=3.7,占总和 553.7/5=74%3.7/5=74\%。也就是说这两个方向已经承载了大约七成四的总方差,剩下 0.70.70.40.40.20.2 对应的方向方差小、多半是细碎扰动,丢掉不太心疼。这也呼应了"特征值恰好等于数据在那个方向上的方差"这条性质。

Q3. LDA 最多能给出几个有效判别方向?为什么有这个限制,PCA 有没有?

LDA 最多只能给出 c1c-1 个有效判别方向,cc 是类别数(比如三类最多降到二维),再多出来的方向特征值就接近零、没什么意义。这是它把标签信息用进去的代价。PCA 没有这个限制,你想压到几维都行,因为它只管方差不管类别。

Q4.(面试题) 完整推导"PCA 找方差最大的方向"为什么等价于"求协方差矩阵的最大特征向量",并说明特征值 λi\lambda_i 和那个方向上的方差是什么关系。再说说工程上为啥用 SVD 而不是直接对协方差矩阵做特征值分解。

设数据已去均值,要找单位方向 www=1\lVert w\rVert=1)让投影 wxw^\top x 的方差最大。投影方差 Var(wx)=wΣw\operatorname{Var}(w^\top x)=w^\top\Sigma wΣ=E[xx]\Sigma=\mathbb{E}[xx^\top] 是协方差矩阵)。问题变成在 w=1\lVert w\rVert=1 约束下最大化 wΣww^\top\Sigma w,用拉格朗日乘子法构造 L=wΣwλ(ww1)\mathcal{L}=w^\top\Sigma w-\lambda(w^\top w-1),对 ww 求导令其为零得 2Σw2λw=02\Sigma w-2\lambda w=0,即 Σw=λw\Sigma w=\lambda w,这正是特征值方程。所以让方差最大的方向 ww 必须是协方差矩阵的特征向量;再代回去 Var(wx)=wΣw=wλw=λ\operatorname{Var}(w^\top x)=w^\top\Sigma w=w^\top\lambda w=\lambda,说明特征值 λi\lambda_i 恰好等于数据在 viv_i 方向上的方差,挑最大的特征值就是挑方差最大的方向。工程上之所以用 SVD,是因为直接算 XXX^\top X 再特征分解会平方化条件数、数值上更不稳,而 SVD 直接对去均值的数据矩阵 XX 操作更准:SVD 的右奇异矩阵 VV 正好就是协方差矩阵的特征向量,奇异值的平方除以 nn 正好就是特征值。

相关标签
机器学习降维PCALDA