第 1 站 · 留一个数
平面上的点要两个数才能记下,能不能只记一个?
假设你记下了一个物体在桌面上的 8 个位置。每个位置要两个数:横着多远,竖着多远。
可这 8 个点大致排成了一条斜线。它们主要只沿一个方向变化,第二个数好像有点浪费。
试试这样:拿一把尺子,穿过这些点的中心放好,再把每个点垂直地压到尺子上。点落在尺子的哪个刻度,就记下哪个数。8 个点,8 个数,一个点只要一个。
8 个模拟点,平均位置 (100, 100) mm。尺子水平时,垂线平均长 7.5 mm;顺着点的走向(45°)时,平均只有 2.83 mm。启用 JavaScript 后可以转动尺子。
压上去的位置和原来不一样,中间那段垂线,就是只记一个数要付出的代价。转一转尺子:横着放,垂线很长;顺着点的走向放,垂线短得多。
一个数能记下大部分位置,丢掉的是那些垂线。尺子怎么放,决定了丢多少。
下一站 · 怎样算好:丢掉的部分,怎样才算丢得最少? →第 2 站 · 怎样算好
丢掉的部分,怎样才算丢得最少?
上一站,每个点压到尺子上,都留下一段垂线。尺子换个角度,有的垂线变短,有的变长。要比较两种放法,得把 8 段垂线合成一个分数。
我们把每段垂线的长度平方,再求平均,叫它「丢掉的量」E。为什么用平方?因为它和勾股定理配得上,下面马上就用到。
看任意一个点。它到中心的距离 r 是一个直角三角形的斜边,两条直角边分别是它在尺子上的刻度 z 和那段垂线 d:
z2+d2=r2.尺子怎么转,r 都不变。所以留下的 z2 和丢掉的 d2 此消彼长:一边多一点,另一边就少一点。
尺子水平(0°)时,留下的平均 V = 66.5,丢掉的平均 E = 66.5;尺子 45° 时,V = 125,E = 8。两种情况都是 V + E = 133。启用 JavaScript 后可以逐点查看并拖动曲线。
对 8 个点都这样分账,再求平均:留下的平均 V 加上丢掉的平均 E,永远等于同一个总量 T。这组数据里 T=133,尺子放在 45° 时丢得最少,只丢 8。
还有一点:刻度 z 的平均是 0(尺子穿过中心),所以 V,也就是 z2 的平均,正是这些刻度的方差。
推导 · 任意维数
上面用的是平面上的 8 个点。换成 n 条记录、每条 d 个数,道理一样,下面一步步写出来。
记第 i 条记录为 xi,平均为 μ,偏移 x~i=xi−μ。尺子方向是单位向量 w(wTw=1)。刻度和垂线分别是
zi=x~iTw,di=x~i−ziw.垂线和尺子垂直:
wTdi=wTx~i−ziwTw=zi−zi=0.所以勾股定理成立,交叉项消失:
∥x~i∥2=∥ziw+di∥2=zi2+2ziwTdi+∥di∥2=zi2+∥di∥2.对 n 条记录求平均,得到留下的 V、丢掉的 E 和总量 T:
Tn1∑i∥x~i∥2=V(w)n1∑izi2+E(w)n1∑i∥di∥2.T 里没有 w,尺子怎么转都不变。于是
wminE(w)⟺wmaxV(w).刻度的平均是 0,因为偏移的平均是 0:n1∑izi=(n1∑ix~i)Tw=0。所以 V(w) 正是刻度 zi 的方差。
核对:这 8 个点 T=133。尺子在 45° 时 V=125、E=8,在 0° 时 V=E=66.5,两次相加都是 133。
让丢掉的最少,就是让留下的方差最大。PCA 讲「方差最大」,不是先规定方差重要,而是从「丢得最少」推出来的。
下一站 · 方向在哪:最好的方向,能不能直接算出来,而不是一个个试? →第 3 站 · 方向在哪
最好的方向,能不能直接算出来,而不是一个个试?
上一站知道了要找让 V 最大的方向。二维时把尺子转一圈,一个个角度试,总能找到。可一条记录有 8 个、100 个数的时候,方向多到试不完。我们需要一个能直接算的办法。
先把 V 写成能算的样子。它是每个点刻度平方的平均,展开以后,只用到这批数据的三个数:横向各自的方差 66.5、纵向各自的方差 66.5,以及横纵一起变化的程度 58.5(协方差)。把它们摆成一张 2×2 的表,就是协方差矩阵 C,任何方向的 V 都能直接算:
C=[66.558.558.566.5],V(w)=wTCw.换个角度看 C:它是一台机器,喂进去一个方向箭头 w,吐出来一个新箭头 Cw。而 V 正是 Cw 落在 w 上的影子长度。
w 在 0° 时,Cw = (66.5, 58.5),往逆时针偏了约 41°,影子 V = 66.5。w 在 45° 时,Cw = 125w,不拐弯,V = 125;在 135° 时,Cw = 8w,也不拐弯,V = 8。启用 JavaScript 后可以拖动箭头。
大多数方向,Cw 都会拐个弯,偏向点云拉长的那一边。这时只要把 w 顺着它偏的方向转一点,影子就会变长,说明还没到最好。
所以最好的方向一定不拐弯:Cw 和 w 同向,只是长度变了。这样的方向叫特征向量,长度变成的倍数叫特征值:
Cw=λw.这组数据里有两个不拐弯的方向:45°,特征值 125;135°,特征值 8。影子长度 V=wTCw=λ,所以特征值就是这个方向上留下的方差。
推导 · 任意维数
把 V(w) 写成矩阵。zi2=(x~iTw)2=wTx~ix~iTw,平均以后 w 可以提到外面:
V(w)C=wTCw,=n1i=1∑nx~ix~iT=n1XTX.X 是把偏移按行排成的 n×d 矩阵。C 是 d×d 的对称矩阵:第 j 行第 k 列是第 j、k 个特征乘积的平均,对角线是各自的方差。总量 T 就是对角线之和 trC。
要解的问题:
wmaxwTCws.t.wTw=1.用拉格朗日乘子把约束并进去,对 w 求导并令其为 0(C 对称,所以 ∇wwTCw=2Cw):
L(w,λ)∇wL⟹Cw=wTCw−λ(wTw−1),=2Cw−2λw=0=λw.最大值点一定是 C 的特征向量。这就是实验里「不拐弯」的意思。
在这样的点上,留下的方差就是特征值:
V(w)=wTCw=λwTw=λ.所以在所有特征向量里挑特征值最大的那个。
它确实是全局最大,不只是几个候选里最好的。对称矩阵有一组互相垂直的单位特征向量 v1,…,vd,特征值 λ1≥⋯≥λd≥0(非负,因为 wTCw 是平方的平均)。任何单位方向都能写成 w=∑jajvj,∑jaj2=1,于是
wTCw=j∑λjaj2≤λ1j∑aj2=λ1,等号在 w=v1 时取到。此时丢掉的最少,是 E=T−λ1。
核对:v1=(1,1)/2 时 Cv1=(125,125)/2=125v1;v2=(1,−1)/2 时 Cv2=8v2。trC=66.5+66.5=133=125+8,丢掉的最少是 133−125=8。
最好的方向,就是协方差矩阵特征值最大的那个特征向量,它留下的方差就等于这个特征值。不用再一个个试:维数再高,也只是解一个特征值问题。
下一站 · 留几个:特征多了以后,留几个新坐标才够? →第 4 站 · 留几个
特征多了以后,留几个新坐标才够?
二维的点只有两条主轴:45° 那条留下 125,和它垂直的 135° 那条留下 8。第二条为什么要垂直?第一条已经记下的变化,不该再记一遍。在垂直于第一条的方向里再找方差最大的,就是第二条,它恰好是另一个特征向量。
一条记录有 d 个数,就有 d 条互相垂直的主轴,按特征值从大到小排好。留下前 k 条,每条记录就从 d 个数变成 k 个数。
丢了多少,还是第 2 站那本账:总量 T 等于所有特征值之和,留下前 k 条以后,丢掉的 E 就是后面那些特征值之和。二维例子里 T=125+8=133,只留一条就丢掉 8。
到这里,原稿开头的三个词都有了着落:特征值是这条轴上留下的方差;贡献率是它占总量的比例;累积贡献率是前 k 条加起来的比例。
贡献率j=∑ℓλℓλj,累积贡献率k=∑ℓλℓλ1+⋯+λk.二维例子里,第一条轴的贡献率是 125/133,约 94%。原稿给了一条经验线:
通常,最好选择累积贡献超过70-80%的主要成分
这条线到底好不好用?拿三组八维数据试一试。
同一条 80% 的线:一个主导方向的数据留 1 条,缓慢衰减的留 5 条,接近平坦的留 7 条。启用 JavaScript 后可以切换数据、移动阈值。
同样是 80%,有的数据留 1 条就够,有的要留 7 条。阈值管的只是「最多丢掉多大比例」,管不了要留几条;留几条取决于特征值怎么分布,也取决于你要拿这些新坐标去做什么。
推导 · 任意维数
留 k 条轴,就是选 k 个互相垂直的单位向量,排成 d×k 的矩阵 W,WTW=I。每条记录存 k 个新坐标,还原时用它们把轴加回去,剩下的是垂线:
zix^idi=WTx~i,=Wzi,=x~i−Wzi.和第 2 站一样,垂线垂直于每一条轴:WTdi=zi−WTWzi=0。勾股定理照样成立,平均以后还是那本账:
T=V(W)∑l=1kwlTCwl+E(W).把 C 按特征向量展开,C=∑jλjvjvjT,于是 wlTCwl=∑jλj(vjTwl)2。把同一个 j 的项收在一起:
V(W)=j=1∑dλjpj,pj=l=1∑k(vjTwl)2.这些权重有两条限制。pj 是 vj 投影到这 k 条轴上的长度平方,不超过 vj 本身的长度 1;而对 j 求和,等于把每条 wl 在一组垂直基上的分量平方加起来:
0≤pj≤1,j∑pj=l∑∥wl∥2=k.总共 k 份权重,每个特征值最多分到 1 份。要让 ∑jλjpj 最大,就把权重全给最大的 k 个特征值:
V(W)E(W)≤λ1+⋯+λk,≥λk+1+⋯+λd.取 W=[v1,…,vk] 时等号成立。k=2 时就说明了正文那句话:第二条轴是第二大特征值的特征向量。
总量 T=trC=λ1+⋯+λd(第 3 站第 1 步)。所以累积贡献率就是留下的比例:
λ1+⋯+λdλ1+⋯+λk=TV=1−TE.「累积贡献超过 80%」,意思正是「丢掉的平方误差不超过总量的 20%」。
顺带一个性质:新坐标的协方差矩阵是
n1i∑ziziT=WTCW=diag(λ1,…,λk).对角线外都是 0,新坐标两两不相关。第 5 站的支线会说明,不相关还不等于独立。
核对:一个主导方向的数据,总量 10.5,留 1 条是 8.5/10.5≈80.95%,丢掉 2。缓慢衰减的数据,留 4 条 75.96%,留 5 条 84.75%,所以 80% 的线要留 5 条。接近平坦的数据,留 6 条 79.63%,留 7 条 90.12%,要留 7 条。
留几个没有通用的线。先看特征值一条条掉下来的样子:前面陡、后面平,常在拐弯处停下;一路平缓,说明数据本来就没有低维结构,PCA 省不了多少。
下一站 · 它看不见什么:方差最大,就一定是最重要的吗? →第 5 站 · 它看不见什么
方差最大,就一定是最重要的吗?
前四站,PCA 一直只做一件事:在平方误差的意义下,丢得最少。它只看数字散得有多开,不知道这些数字代表什么。这一站专门去找它的盲点。
纵坐标乘 0.1,主轴从 45° 转到 5°;乘 10,转到 85°;按列标准化后回到 45°。在 (25, −25) 加一个离群点,主轴翻到 135°。类别只取决于小方差方向时,PC1 留下 99.25% 的方差,却分不开两类。弯曲的点上,第一主轴只留下 53.5%。启用 JavaScript 后可以逐个试。
尺度。纵坐标换个单位,数字变小,PCA 就觉得纵向「不重要」,主轴倒向横轴。数据什么都没变。常见做法是先把每一列除以自己的标准差(标准化),可这等于换了一种量「丢多少」的尺子,问题本身也变了。
离群点。平方让远处的点代价特别大,一个记错的点就能把主轴拉走。
意义。两类点的区别全在纵向,纵向的变化却很小。第一主轴留下了 99% 以上的方差,偏偏把能区分两类的那一点丢了。PCA 不知道你关心什么。
形状。点沿一条弯线排开,本来一个数(沿线走了多远)就能描述,可直尺顺不了弯。
推导 · 它只看得见 μ 和 C
回头看前四站的推导,数据只通过两样东西进来:平均 μ 和协方差矩阵 C=n1∑ix~ix~iT。两批数据只要 μ 和 C 相同,PCA 给出的轴就完全一样。四个盲点都从这里来。
尺度。把第 j 个特征的单位换掉,相当于乘上一个倍数 sj。记 D=diag(s1,…,sd),则 x~i→Dx~i,
C→DCD.DCD 的特征向量一般不是 C 的特征向量乘上 D,轴会转。二维时可以写出来:方向角为 θ 时 V(θ)=c11cos2θ+2c12sinθcosθ+c22sin2θ,令导数为 0,
tan2θ=c11−c222c12.纵坐标乘 s 后,c12→sc12,c22→s2c22:
tan2θ=66.5−66.5s22⋅58.5s.标准化是取 sj=1/cjj,这时 DCD 的对角线全是 1,也就是相关系数矩阵。它和单位无关,但量「丢多少」的尺子换了,答案回答的是另一个问题。
离群点。一个点在 C 里的份额是 n1x~ox~oT。它让方向 u 上的方差多出
n(uTx~o)2,和它离中心的距离成平方关系。距离翻倍,影响变成 4 倍。
意义。目标函数 V(w)=wTCw 里只有 C,没有类别标签。不管标签怎么分,PCA 都给出同样的轴。要用标签,就得换一个把标签写进去的目标,比如线性判别分析:让两类中心沿 w 拉开,同时让每一类内部沿 w 尽量紧。
形状。只留 k 条轴时,还原出来的点 x^i=μ+WWTx~i 全落在一个过 μ 的平直子空间里(k=1 时是一条直线)。弯线上的点不在任何一条直线上,所以只留一条轴,误差不可能是 0。C 只记录「一起线性变化」的程度,弯曲这件事它记不下来。
核对:s=0.1 时 θ≈5.0∘,s=10 时 θ≈85.0∘。离群点放在 (25, −25),9 个点的中心移到 (2.78, −2.78),它的偏移 (22.2, −22.2) 正好朝 135°,单独给这个方向加了 31.42/9≈109.7;135° 的方差变成 130.6,超过 45° 的 125×8/9≈111.1,主轴翻转。类别那组 C=diag(132,1),第一主轴留下 132/133≈99.25%,区分两类的纵向只占 1。弯线那组 x 左右对称,c12=3n1∑ixi3=0,C=diag(13,14.95),第一主轴只留下 14.95/27.95≈53.5%。
PCA 回答的是一个很具体的问题:在给定的单位下,用一把直尺,让平方误差丢得最少。单位怎么选、离群点要不要、你在乎哪种差别、数据是不是弯的,这些它都不管,要你自己判断。