PCA:讓資料自己說出該用什麼座標軸
玩完這關,你會知道找到特徵向量之後到底能幹嘛 —— 以及一團二維資料算出來的兩根新軸,各自在講人話裡的什麼事。
① 這關在解什麼問題
04 關你已經拿到刀了:給一個矩陣,找出它作用下不會被轉歪的那幾個方向。 但那時候的矩陣是我隨手寫的 —— 真實世界沒有人會遞一個矩陣給你,遞給你的是一張 CSV。
這關就是把那把刀對準 03 關「從資料自己長出來」的那個矩陣:共變異數矩陣。 順便把 03 關結尾那個鉤子拔掉 —— 我當時說「非對角線總有辦法變成 0」,這關現場做給你看。
先講具體的麻煩。你手上有 12 個人的身高與體重,你想回答一個很自然的問題: 這群人之間,真正的差異在哪裡?
結果你一開表就卡住:身高高的人體重也重,相關係數 0.92。這兩欄根本是同一件事的兩種說法。
- 你看「身高」這一欄的變化 —— 裡面混著「這個人整體多大隻」。
- 你看「體重」這一欄的變化 —— 裡面也混著「這個人整體多大隻」。
- 兩欄一起看,你會把同一件事數兩遍;只看一欄,你會漏掉「同身高下有人壯有人瘦」這件真實存在的差異。
問題不在資料,在座標軸。公分和公斤這兩根軸是量測儀器給你的, 不是這群人真正散開的方向。這關給你的工具叫 PCA(主成分分析): 它讓資料自己指出「我是往哪幾個方向散開的」,然後你就用那幾個方向當新軸。
② 從你已經會的東西開始:幫這團資料量身訂做一把尺
你量過腰圍。量腰圍的時候,你不會拿一把固定釘在牆上的直尺去量 —— 你會把軟尺繞著腰轉到對的方向。 尺本身沒變,變的是你怎麼擺它。
資料也一樣。③ 那團身高/體重的點就是斜著散開的, 而斜著散開這件事,用公分和公斤這兩根軸根本描述不出來:
用「量身訂做的尺」量: 第一根軸 = 資料最長的那個方向、第二根軸 = 垂直於它 → 兩根軸各管一件事
PCA 就是把尺轉到資料真正散開的方向,一句話講完。剩下的都是怎麼找到那個方向 —— 而你已經有全部零件了:
- 01 關的投影:一個點在某個方向上的座標 = 內積。
- 02 關的變異數:一串數字散不散開。
- 03 關的共變異數矩陣:把「往哪散」整包裝進一個 2×2。
- 04 關的特徵向量:矩陣的自然方向。
把這四個接起來,就是這關的全部內容。
先把這一頁會出現的符號一次講完
接下來每一節都會冒出字母。你不用背,但看到的時候要知道它是誰。 這張表就放在這裡,哪個符號忘了是什麼,隨時捲回來看:
| 符號 | 讀作 | 它是什麼(白話) |
|---|---|---|
| X | 大寫 X | 整張資料表本身:12 列(12 個人)× 2 欄(身高、體重),而且每一欄都已經減掉自己的平均(這叫去中心化,③ 的第 2 步在做)。 |
| n | n | 有幾筆資料。這一頁 n = 12 個人。 |
| C | C(來自 covariance) | 共變異數矩陣,一張 2×2 的小表。對角線=「每一欄自己有多散」,非對角線=「兩欄一起變動的程度」。就是 03 關造出來的那個。 |
| XTX / (n − 1) | X 轉置乘 X,再除以 n 減 1 | 這就是 C 的算式,不是新東西。除以 n − 1 是樣本變異數的慣例(02 關講過),全站統一。 |
| u | u | 你手上那根可以隨便轉的候選方向,長度固定為 1。④ 的滑桿轉的就是它。 |
| θ | theta(希臘字母,讀「西塔」) | u 的角度。θ = 0° 是正右邊(等於只看身高那一欄),90° 是正上方(只看體重那一欄)。 |
| uTCu | u 轉置、C、u | 一個吃「方向」吐「一個數字」的函數,那個數字是:把資料投影到 u 之後,那串數字的變異數。④ 的大字讀數就是它。 |
| v1 v2 | v one、v two | C 的特徵向量,也就是 PCA 挑出來的兩根新軸的方向(各是一支長度 1 的箭頭)。v1 叫主軸、v2 叫次軸,兩根一定互相垂直。 |
| λ1 λ2 | lambda one、lambda two | C 的特徵值。在這一頁,λ 的單位就是「變異數」 —— λ₁ = 資料沿著 v₁ 有多散、λ₂ = 沿著 v₂ 有多散。這份資料是 λ₁ = 205.55、λ₂ = 8.45(單位是身高/體重那種混合的平方單位,所以絕對值不用細究,看比例就好)。 |
| PC1 PC2 | PC one、PC two | 某一個人在新軸上的座標,是一個數字。PC1 = 他在 v₁ 上的位置、PC2 = 在 v₂ 上的位置。留意差別:v 是「軸」(整團資料共用一根),PC 是「某個人在那根軸上的分數」(每人一個)。 |
| 載荷 / loading | 載荷 | 新軸是舊欄位的加權組合,那一組權重就叫載荷。數值上它就是特徵向量的分量(v₁ 的 x 分量=身高的權重)。⑤ 整節在讀它。 |
| k | k | 你決定留幾根軸。k = 2 是原封不動換軸,k = 1 才是降維(⑥)。 |
| SSE | Sum of Squared Errors | 降維之後,每個人的「重建位置」離「真實位置」有多遠,距離平方之後全部加起來。0 = 完全沒損失。 |
| RMSE | Root Mean Squared Error | SSE 除以人數再開根號 → 平均每個人差多遠。單位跟原始座標一樣,比 SSE 好讀。 |
所以這一段的結論是:PCA 就是把尺轉到資料自己散開的方向;上面那一整排字母, 全部都只是在描述「那把尺轉去哪、轉過去之後量到多少」。
③ 主實驗:PCA 的五個步驟,一步一步按下去
資料是 12 個人的身高(cm)與體重(kg)。
合成資料,不是真人;數字是我照著「身高體重高相關、但同身高下仍有胖瘦差異」湊出來的。
想換成你自己的資料,改檔案裡 RAW 這個陣列就行。
你會看到什麼:12 顆青色圓點=12 個人(左右=身高,上下=體重)。 按到第 4 步之後會多出三樣東西:紫箭頭 v₁(主軸)、 桃箭頭 v₂(次軸)、以及一圈紫色虛線橢圓 —— 那圈橢圓叫 1σ 輪廓,兩個半徑正好是 √λ₁ = 14.34 與 √λ₂ = 2.91。 第 3 步起右邊還會出現一張四格熱力圖,那就是共變異數矩陣 C 本人(顏色越濃=那一格的絕對值越大)。
你可以動什麼:上面那排 1~5 號按鈕就是 PCA 的五個步驟,按下去看畫面怎麼變(也可以用「上一步/下一步」)。 任何一顆青點都可以直接用滑鼠拖(只有第 5 步旋轉檢視中不能拖)。 「+ 加一個怪咖」會塞一個違反趨勢的人進去 —— 拖點跟加怪咖都會讓下面每一節的數字跟著重算。
要看出什麼:盯著熱力圖右上角那一格:第 3 步它是 98.55(不是 0,代表兩欄糾纏在一起), 第 5 步轉到新軸之後同一格掉到 0。這五步在做的就是把「斜的資料」轉正,讓兩根軸各管一件事。
④ 為什麼是「特徵向量」?自己轉一圈找答案
上面第 4 步我直接說「取共變異數矩陣的特徵向量就是主軸」。憑什麼?
這一節不用相信我。你自己轉:下面的滑桿控制一個方向 u, 所有點會投影到那個方向上(綠色落點), 然後我把那串投影數字的變異數算給你看。你的任務只有一個 —— 把變異數轉到最大。
別急著看圖。先手算三個最簡單的方向,你就知道「往某個方向看過去有多散」到底是什麼意思:
θ = 0°(正右邊):這個方向等於只看身高那一欄 → 投影出來的就是每個人的身高偏差, 變異數 = 106.18。而這個數字剛好就是 C 左上角那一格 var(身高)。
θ = 90°(正上方):只看體重那一欄 → 變異數 = 107.82,就是 C 右下角那一格。
θ = 45°(斜著看):這時候身高與體重會一起被算進去,變異數暴衝到 205.55 —— 比只看單一欄的任一個都大快一倍。這就是「斜的方向才是這團資料真正散開的方向」的第一個證據。
下面的滑桿只是把這件事從 3 個角度變成 360 個角度,一個都不漏而已。
你會看到什麼:淡青點=12 個人(已經扣掉平均,所以圖的原點就是重心); 綠箭頭 u=你正在測試的方向,綠點=每個人垂直落到 u 上的位置; 紫色虛線花瓣=玫瑰圖。 玫瑰圖不是資料 —— 它上面一顆點都不是人。 它是「每個角度各自的變異數」畫成的花瓣:往某個方向量出來的變異數越大,花瓣在那個方向就伸得越遠。 所以看圖的規則只有一句:離中心越遠的方向,就是資料在那個方向越散。
你可以動什麼:滑桿控制 θ(也就是 u 的角度,0°~180°); 「自動掃一圈」讓它自己轉完 180° 給你看;「跳到最佳角度」直接跳到答案。
要看出什麼:右邊那個大數字(=uTCu,投影後那串數字的變異數) 在 θ ≈ 45.24° 衝到最大 205.55,而那個角度正好就是花瓣最長的那隻角的方向 —— 也正好是 C 的特徵向量 v1 的方向。三件事是同一件事。
橫軸是角度 θ(0° 到 180°),縱軸是「那個角度量到的變異數」。 換句話說:曲線上的每一點,都是你把上面滑桿轉到那個角度時,右邊大數字會顯示的值。 它跟玫瑰圖是同一份計算的兩種畫法 —— 玫瑰圖用「離中心的距離」表示大小,這條曲線用「高度」表示大小。
所以要看的是兩個極值:曲線的最高點就是 λ₁(205.55,主軸上的變異數)、最低點就是 λ₂(8.45,次軸上的變異數), 而兩個極值相隔正好 90°(這正是「兩根新軸互相垂直」那句話在這張圖上的樣子)。 綠色垂直虛線是你現在滑桿的位置,紫點標的是最高點。
曲線長成一條漂亮的正弦波不是巧合:把 uᵀCu 展開之後就是 「常數 + 常數 × cos 2θ + 常數 × sin 2θ」,所以它必定是週期 180° 的正弦波。 而正弦波只有一個最高點和一個最低點 —— 這就是「主軸只有一根、而次軸必定垂直於它」的原因。
特徵向量不是憑空定義出來的東西,它就是「投影後最散開」那個方向的答案; 特徵值就是那個最大的散開程度。
你轉滑桿在做的事,數學上寫成一行:找單位向量 u 讓 uTCu 最大。 而這個問題的解,恰好就是 C 的最大特徵值對應的特徵向量 —— 這不是巧合,這是特徵向量的另一個等價定義。
⑤ 兩根新軸各自代表什麼意思?(直球回答)
這是整關最該被回答的問題。答案很具體:新軸是舊欄位的加權組合,權重就是特徵向量的分量。 所以新軸永遠可以被讀出意義 —— 只要你去看那些權重。
載荷(loading)= 新軸是舊欄位的加權組合,那一組權重。就這樣,沒有別的意思。
先給最小的例子:假設某根新軸的載荷是 (0.70 身高, 0.71 體重), 意思就是「一個人在這根軸上的分數 = 0.70 × 他的身高偏差 + 0.71 × 他的體重偏差」 —— 跟你算加權平均成績時那組權重,是同一種東西。
而載荷在數值上就是特徵向量的分量:v1 的 x 分量就是身高的權重、 y 分量就是體重的權重。所以「讀載荷」和「讀特徵向量」是同一個動作,只是兩個圈子的叫法不同 —— 統計圈習慣叫載荷(loading),線代圈習慣叫特徵向量的分量。
而讀載荷只有兩條規則:權重同號(都正、或都負)→ 這根軸在講「一起變大」的共同因子; 權重一正一負 → 這根軸在講「此消彼長」的對比因子。這一整節就靠這兩條讀完。
你會看到什麼:左邊是同一團青點(已扣掉平均), 加上兩根穿過原點的虛線 —— 紫=主軸 v₁、桃=次軸 v₂。 右邊的表把每個人的原始身高/體重,換算成他在這兩根新軸上的座標: PC1(沿主軸的位置)與 PC2(沿次軸的位置)。
你可以動什麼:點表格任何一列。那個人會在左圖被綠圈圈起來, 並畫出他的兩個分量:紫箭頭=他的 PC1(先沿主軸走多遠),桃虛線=他的 PC2(再垂直偏出去多少)。
要看出什麼:PC1 與 PC2 這兩個數字完整取代原本的 (身高, 體重) —— 同一個人、同樣兩個數字,只是換一組軸來描述。而換過之後那兩個數字各有意思: PC1 是「整體多大隻」,PC2 是「同身高下偏壯還是偏瘦」。舊的兩欄做不到這件事,因為它們都混著大隻程度。
| 代號 | 身高 | 體重 | PC1 | PC2 | 怎麼讀 |
|---|
身高/體重是「主成分好解釋」的最佳案例,我故意挑它就是為了讓你一眼看懂新軸的意思。 真實資料集裡,主成分經常是一坨看不出所以然的加權組合 —— 這時候正確反應是「這個主成分我讀不出來」,不是硬掰一個故事。
⑥ 只留一根軸:降維與重建
既然主軸吃掉了絕大部分的散開程度,那第二根軸能不能丟?丟了會掉多少東西?按下去看。
你會看到什麼:青點=每個人真正的位置; 綠點=只用留下的軸把他「重建」回來的位置; 紅線=兩者的距離,也就是這次降維在他身上造成的誤差。 紫色虛線是主軸 v₁。
你可以動什麼:兩顆按鈕切換 k(=你決定留幾根軸)。 「只用 1 根軸」=每個人只剩一個數字 PC1;「用 2 根軸」=兩個數字都留。
要看出什麼:k = 1 時綠點全部落在紫色主軸上(只剩一維,就只能長成一條線), 而且每一條紅線都垂直於主軸 —— 所以被丟掉的東西一點都不神秘: 它就是「垂直於主軸的那一點差異」,在這份資料裡叫做胖瘦。 切到 k = 2,紅線全部消失、誤差歸零,因為兩根軸就把平面填滿了。
順便看一個看起來像巧合、其實是定理的事:k = 1 時 SSE = 92.96,而 λ₂ × (n − 1) = 8.4512 × 11 = 92.96,一模一樣。 換句話說 —— 你丟掉的誤差總量,正好就是你丟掉那根軸的變異數(再乘回自由度)。 這就是為什麼「解釋比例」可以直接拿 λ 來算,不必真的去量每一條紅線。
丟掉的不是雜訊,也不是「沒用的東西」 —— 丟掉的是垂直於主軸的那一點差異, 在這份資料裡就是「同身高下偏壯還是偏瘦」。它是真實存在的資訊,只是變異最小。
所以判斷「能不能降維」的問題不是「解釋比例夠不夠高」,而是 你接下來要回答的問題,會不會剛好落在你丟掉的那個方向上。 要比體型大小 → 丟得掉;要挑健身教練 → 你丟掉的正是你要的。
多維時 PCA 在幹嘛:4 科成績 → 2 根軸
兩維只能給你直覺,PCA 真正在用的地方是幾十、幾百維。這裡放 12 個學生的 4 科成績
(國文/英文/數學/物理,同樣是合成資料),做 4 → 2 的降維。
4×4 對稱矩陣的特徵分解 LAB.M 沒有,
所以這一節用檔案內自己寫的 Jacobi 旋轉法算(見 jacobiEig),並印出殘差自我驗證。
再提醒一次:λ 的單位就是「變異數」。這份資料是考試分數,所以 λ 的單位是「分數的平方」; λ 越大=那根軸上的分數被拉得越開。
| 成分 | λ | 解釋比例 | 累積 |
|---|
| 科目 | PC1 權重 | PC2 權重 |
|---|
| 學生 | 國 | 英 | 數 | 物 | PC1 | PC2 | 怎麼讀 |
|---|
⑦ 要不要先標準化?這題會決定你算出什麼
PCA 追的是變異數,而變異數有單位。下面三顆按鈕用的是完全同一批人, 只是記錄的單位不同、或先做了標準化。看主軸方向怎麼變。
你會看到什麼:同一批 12 個人的青點, 加一根紫色主軸(=該模式算出來的 v₁)。 三顆按鈕不是三批資料,是同一批人的三種記法:cm/kg、把身高改記成 mm、以及先做 z-score (z-score 模式下兩軸的單位變成 σ,也就是「幾個標準差」,沒有單位)。
你可以動什麼:按三顆按鈕切換模式;下面那張表永遠四種模式都列出來,方便直接對照。 畫面會自動框住當前資料,但兩軸永遠共用同一個比例尺(1 單位 = 1 單位), 所以你看到的形狀就是 PCA 看到的形狀。
要看出什麼:按到 mm / kg 的那一刻:資料一個數字都沒改, 這團點卻被拉成一條又長又扁的橫線,主軸角度從 45.24° 倒到 5.31° —— PCA 的答案被「你用什麼單位記錄」綁架了。第三顆按鈕 z-score 就是解藥。
| 模式 | 主軸角度 | 載荷(身高, 體重) | 主軸解釋比例 | 主軸在講什麼 |
|---|
你會發現 cm/kg(45.238°、96.05%)和 z-score(45.000°、96.05%) 解釋比例一模一樣,只有角度差一點。這是巧合,不是規律。 原因是這份資料兩欄的變異數剛好差不多大(身高 106.18、體重 107.82,只差 1.5%), z-score 幾乎等於沒縮放。
標準化會改解釋比例,而且經常改得很兇 —— 同一張表的 mm/kg 那一列就是反例: 解釋比例 99.85%,z-score 之後掉回 96.05%。差了快 4 個百分點, 而那 4% 正是「胖瘦」這件事被單位吃掉又還回來的量。
把身高從 cm 改記成 mm,資料一個數字都沒變(同樣是同一批人), 但身高那一欄的變異數乘了 100 倍,於是它直接把主軸搶走 —— 主軸幾乎變成「身高」本人。
所以:各欄單位不同(公分 vs 公斤 vs 元 vs 次數)時,先做 z-score 標準化。 標準化之後每欄變異數都是 1,共變異數矩陣就退化成 相關係數矩陣 —— 這時候 PCA 吃的其實是相關係數, 跟你用什麼單位記錄完全無關(上面兩種單位的 z-score 結果一模一樣,可以自己按來對照)。
⑧ 數學長怎樣
整個 PCA 裸寫出來就五行,而且每一行都是前面四關的東西:
const mean = LAB.M.centroid(data); // 1. 重心(02 關的平均)
const X = LAB.M.center(data); // 2. 去中心化:把 0 搬到重心
const C = LAB.M.covMatrix(X, 1); // 3. 共變異數矩陣(03 關,ddof=1)
const eg = LAB.M.eig2(C).pairs; // 4. 它的特徵向量 = 資料主軸(04 關)
const pc1 = LAB.M.scores(data, eg[0].vector, mean) // 5. 每個人在主軸上的座標(01 關的投影)
符號版。第一式是共變異數矩陣的定義:
XTX = 把「每一欄」兩兩做內積:對角線是同一欄跟自己的內積(=平方和), 非對角線是兩欄互相的內積。
n − 1 = 自由度。扣掉平均之後,n 個偏差裡只有 n−1 個是自由的 (最後一個被「總和必須為 0」綁死),所以除 n−1 才是對樣本變異數的無偏估計。 全站一律用這個版本(02 關講過)。
所以 C 的每一格都是一個內積 —— 這就是主線那句「變異數與共變異數其實都是內積」的收尾。
第二式是 04 關的老朋友,只是 A 換成了 C:
C v = 把這個方向餵進共變異數矩陣。若結果跟 v 同方向,v 就是特徵向量(04 關的定義)。
λ = 特徵值。在 C 是共變異數矩陣的場合,它有一個非常實在的意思: 資料投影到 v 之後的變異數。
vTCv = 二次型,讀成「往 v 這個方向看過去,這團資料有多散」。 你在 ④ 轉滑桿看到的大數字就是它。
λ1 / (λ1 + λ2) = 主軸的解釋變異比例。
兩式合起來就是這關的一句話:把資料做成 C,C 的特徵向量就是資料的主軸, 特徵值就是那根主軸上的變異數。
⑨ 工程師的「原來如此」
拿 500 檔股票的日報酬做一個 500×500 共變異數矩陣,然後做特徵分解。 第一主成分幾乎必然是大盤 —— 它的載荷全部同號,意思是「所有股票一起漲、一起跌」的那個共同因子, 而且它通常吃掉三到四成的總變異。第二、第三主成分才開始長出產業結構 (科技 vs 傳統、循環 vs 防禦,載荷一正一負)。
這就是風險模型的骨架:把「500 檔股票各自亂動」重寫成「幾個因子在動 + 一點個股殘差」。 要對沖掉大盤風險,你對沖的其實就是第一主成分; 要算風險值,你也不會去反轉那個 500×500 矩陣(它接近奇異),而是用前幾個主成分近似它。
一張 64×64 的灰階人臉是 4096 維向量。把幾千張臉的共變異數矩陣做特徵分解, 取前 50 個特徵向量(每一個本身就是一張「臉的模板」,這就是 eigenfaces 這名字的來源), 任何一張臉都能寫成這 50 張模板的加權組合 —— 4096 個數字壓成 50 個,還認得出是誰。
今天的版本換了外皮但是同一件事:1536 維的文字 embedding 進向量資料庫之前, 常先 PCA 降到 128~256 維再存。省下來的不只是硬碟,是每次相似度搜尋的內積次數。
16 顆加速度計貼在同一台機器上量振動。真正的訊號源可能只有兩三個(馬達轉頻、軸承、結構共振), 所以 16 條時序的變異幾乎全部集中在前幾個主成分,尾巴那十幾個特徵值小到接近量測底噪。
做法:投影到前 k 個主成分、把其餘的係數歸零、再重建回 16 條 —— 出來的訊號乾淨很多。 這跟你在 ⑥ 玩的「投影再重建」是同一段程式碼, 差別只在那裡我們把丟掉的部分當資訊,這裡把它當雜訊。
⑩ 拿去用之前 —— 五件教科書不講、但上線就會咬人的事
前面九節在回答「PCA 是什麼、為什麼成立」。這一節換一種問題: 你真的要把它接進系統裡,於是冒出五件數學課不會提的事。 每一件的格式都一樣 —— 問題 → 一句話答案 → 具體怎麼做。
1. 這套算法到幾維還跑得動?
成本拆開來看:建 C 是 O(n · d2) (d 欄兩兩做一次內積,每次掃 n 列),特徵分解是 O(d3)。 d 小的時候沒人在意,但 d = 1536(一個典型的文字 embedding)時, C 本身就是 15362 ≈ 236 萬個 float —— 用 float32 存也要 9 MB, 而它只是個中間產物,你要的其實只有前面幾根軸。
怎麼做:跳過 C,直接對去中心化後的資料矩陣 X 做 SVD。 X 的右奇異向量就是 C 的特徵向量,奇異值平方除以 n − 1 就是特徵值 —— 數學上完全等價,但你不必把 d×d 那張表造出來,數值上也穩得多 (組 C 的時候每個數字都被平方過一次,小的特徵值容易被浮點誤差吃掉)。 如果只要前 k 根軸,連完整 SVD 都不用做:randomized SVD 或 power iteration (就是 04 關那個「乘乘乘」)只算你要的那幾根。 這也是為什麼 sklearn 的 PCA 底層走 SVD 而不是 eig。接口整理在 全景 01 關那條「SVD 捷徑」。
2. 那我 30 欄到底該砍到剩幾欄?
⑥ 說的「看丟掉的方向跟你的問題有沒有關係」立場是對的,但它寫不成 code。 可操作的尺有四把,只有最後一把真的可靠。
拿本頁 ⑥b 那 4 科成績的四個 λ 當現場範例,畫成 scree 圖 (長條由高到低,這是選 k 最常看的一張圖):
- scree 肘點:找長條「從陡然變平」的那一折,折點前面全留。 上圖 PC2 → PC3 掉了快 15 倍,肘點就在那裡,所以取 2 根。 毛病:真實資料常常沒有肘點,是一條平滑的滑梯 —— 兩個人看會看出兩個答案。
- 累積 90% / 95%:從上往下加,超過門檻就停。上圖累積到 PC2 是 97.46%,門檻設 90% 也是取 2 根。 毛病:門檻是你自己拍的,跟下游任務沒有任何關係。d 很大時「95%」經常還是好幾百根。
- Kaiser 準則 λ > 1:留特徵值大於 1 的軸。 毛病:只有對相關係數矩陣(也就是先做過 z-score)才有意義 —— 那時候每欄變異數都是 1,「λ > 1」才讀得成「這根軸比單獨一欄更會解釋」。 直接套在上圖那四個 λ(單位是「分數平方」)上就是四根全留,等於沒篩。
- 下游任務的 cross-validation:把 k 當成超參數,k = 1, 2, 5, 10… 各跑一次你真正要跑的模型, 比驗證集分數。這是唯一真正可靠的一把,因為它問的正是你該問的那句話 —— 「砍到這裡,我要做的事變差了嗎」。 代價是要跑 k 次,而且前提是你已經做對了下面第 3 點。
3. 新資料進來怎麼辦?fit 和 transform 的區別
PCA 是 fit 出來的,有三組參數必須存下來:重心、每欄的標準差、特徵向量。 新資料只能拿舊參數 transform,不可以重新 fit。
為什麼:重新 fit 會算出不一樣的重心、不一樣的軸,於是兩批資料的 PC1 根本是 兩個不同的東西,分數放在一起比大小毫無意義 —— 今天算出來的 −17.67 和明天算出來的 −17.67 不是同一件事。 這是 PCA 上線最常見的一個 bug,而且它不會報錯,只會讓你的數字慢慢失真。
怎麼做:fit 只在訓練資料上跑一次,把 mean / sd / V 三組序列化存檔;
之後每一筆新資料都只做 (x − mean) / sd 再跟 V 做內積,就這樣,不再碰 fit。
順帶講一個同源的坑,叫資料洩漏(data leakage):在全部資料上先 z-score、 或先做完 PCA,然後才切 train / test。看起來很無害,但 test 那一半的平均數、標準差、主軸方向 都已經滲進參數裡了 —— 你的驗證分數會偏高,上線才發現沒那麼好。 順序永遠是「先切,再 fit」。
4. 主軸的正負號,明天重算會不會翻面?
會。正負號是任意的(坑 3 講過), 所以你得自己釘一個符號規範,並且把它跟參數一起存起來。
什麼時候會翻:換一套 library、升一次版本、資料多進一筆、甚至同一份程式跑在不同 CPU 上 —— 只要迭代法的起始向量不同,算出來的 v 就可能整根乘上 −1。 數學上完全等價(同一根軸),但你存下來的 PC 分數會整欄變號, 下游那條「PC2 > 0 就標成偏壯」的規則會全部反過來,而且不會有任何錯誤訊息。
怎麼做:fit 完立刻做一次符號規範化。例如強迫某個指定欄位的載荷為正 ——
本頁 ⑥b 的 jacobiEig 就有做這件事(讓絕對值最大的那個分量為正),
另一種常見規範是讓所有載荷的總和為正。選哪一種不重要,
重要的是它跟 mean / sd / V 一起被存下來,而且下次不准變。
5. PC1 = −17.67 的單位是什麼?能直接餵下游嗎?
PC 分數是「各欄的加權組合」,所以單位是混的(除非你先標準化過,那它就是無單位的 σ)。 要餵給吃距離的模型之前,通常還得再標準化一次。
看 ⑤ 那條式子就懂了: PC1 = +0.704 × (身高 − 167.00) + 0.710 × (體重 − 59.00) —— 0.704 個公分加 0.710 個公斤,加出來的東西沒有名字。 所以 PC1 = −17.67 只能跟同一批人的其他 PC1 比大小, 不能單獨解讀成「他矮了 17.67 公分」。
更會咬人的是尺度:PC1 和 PC2 的變異數差 24 倍 (λ₁ = 205.55、λ₂ = 8.45)。直接把這兩欄丟進 kNN、k-means 或任何吃歐氏距離的東西, PC1 會壓死 PC2 —— 這正是 02 關警告過的「大單位吃掉小單位」, 只是換了個座標系又犯一次。需要的話再把每根軸除以自己的 √λ (這個動作叫 whitening),讓每軸變異數都變成 1。 但記得:whitening 同時把「PC1 比 PC2 重要」這個資訊也抹掉了, 該不該做取決於下游模型吃不吃這件事。
這五件事都不是數學問題 —— 特徵向量的定義解決不了任何一件。 它們是「數學懂了之後才會遇到的問題」:懂了 PCA 你才有資格問「該砍幾軸」, 也才有機會踩到「符號翻面」這種坑。
⑪ 踩坑
忘了去中心化。直接拿沒扣平均的資料算 XTX 再做特徵分解, 你量到的會是「這團資料離原點多遠」,不是「這團資料長什麼形狀」。 這份身高體重資料的重心在 (167, 59),離原點 177 —— 而它的散開幅度只有 10 左右。 沒去中心化的話,第一主成分會直接指向 (167, 59) 那個方向, 解釋比例高到 99.9%,看起來超漂亮,但它講的是「這些人都在畫面右上角」這種廢話。 回去看 02 關為什麼要先扣平均。
忘了標準化。單位大的欄位會霸佔主軸,而且它不會報錯 —— 你會得到一個看起來很正常、實際上只是在講「哪一欄的數字比較大」的主成分。 判斷方法很簡單:如果兩欄單位不同(公分 vs 公斤、元 vs 次數、毫秒 vs 個), 先 z-score。細節在 ⑦。
主成分不一定可解釋,不要硬掰。PCA 的目標函數裡完全沒有「可解釋性」這一項, 它只管變異數最大。身高體重這種例子好解釋是運氣(兩欄剛好一個共同因子 + 一個對比因子)。 另外提醒:特徵向量的正負號是任意的,(0.71, −0.70) 和 (−0.71, 0.70) 是同一根軸。 所以「PC2 高分代表偏瘦還是偏壯」不能背,要現場去看載荷的符號。
PCA 只會找直線方向。下面這團點明顯有結構(一個環),但它沿著任何一個直線方向的散開程度都差不多, 所以 PCA 給你兩個幾乎一樣大的特徵值、兩根隨便挑的軸,等於什麼都沒說。 馬蹄形、螺旋、分群資料都是同一類失手。這種時候要換工具(kernel PCA、t-SNE、UMAP、autoencoder), 不是把 PCA 的參數調來調去。
⑫ 這關回答了什麼
找出資料的特徵向量之後,那到底代表什麼意思?
代表你拿到了一組新的座標軸,而且這組軸是資料自己選的:第一根指向資料最散開的方向, 第二根垂直於它、指向剩下最散開的方向。
拿到之後可以做三件很實際的事:(1) 讀意義 —— 看每根軸的權重(載荷)是怎麼由舊欄位組成的,就知道這根軸在講什麼事(⑤); (2) 降維 —— 把變異數很小的軸整根丟掉,資料維度直接砍下來(⑥); (3) 解糾纏 —— 換到新座標系之後,各欄之間的共變異數變成 0, 原本互相污染的欄位變成互不相關的獨立座標(③ 的 step 5)。
二維資料算出來的兩個新軸,各自代表什麼?
用這份身高體重資料直接回答,因為答案是從權重讀出來的,不是我掰的:
主軸的權重是 (+0.70 身高, +0.71 體重) —— 兩個都是正的、而且差不多大, 意思是「身高和體重一起增加」。這根軸就是這個人整體多大隻。 它吃掉 96% 的變異,也就是說這群人之間的差異,96% 其實只是體型大小。
次軸的權重是 (+0.71 身高, −0.70 體重) —— 一個正一個負, 意思是「身高加分、體重扣分」。這根軸就是同樣身高之下偏瘦還是偏壯(分數高=偏瘦)。 它只佔 4%,但它是唯一在講胖瘦的那根軸 —— 你要是把它丟了,就再也分不出 165/53 和 163/60 的差別。
通則:新軸 = 舊欄位的加權組合,權重就是特徵向量的分量。權重同號 → 這根軸在講「一起變大」的共同因子;權重一正一負 → 在講「此消彼長」的對比因子。
特徵向量是矩陣的還是資料集的?
只有矩陣才有特徵向量。「資料集的特徵向量」嚴格講是一句簡稱, 它真正的意思是「這份資料的共變異數矩陣的特徵向量」。
所以流程一定是:資料 →(去中心化)→ 做成共變異數矩陣 → 這個矩陣才有特徵向量。 少了中間那一步,「找資料的特徵向量」是沒有定義的操作。
順便說:同一份資料可以做成好幾種矩陣(共變異數矩陣、相關係數矩陣、圖的鄰接矩陣、Gram 矩陣), 每一種的特徵向量講的是不同的事。先問「是哪個矩陣」,再問「特徵向量是什麼意思」。 這個分野在 全景 01 關的「矩陣 vs 資料」有完整整理。
為什麼一定要先去中心化?
因為不扣平均的話,你量到的是位置,不是形狀。
XTX 這個式子算的是「每個點到原點的距離結構」。 原點是 (0, 0),可是這群人在 (167, 59) 附近 —— 他們離原點的距離(177) 比他們彼此之間的差異(10 左右)大了 17 倍。 於是第一主成分會被「大家都在右上角」這件事綁架,指向 (167, 59) 的方向。
扣掉平均之後,原點被搬到資料的重心,XTX 量的就變成「彼此之間怎麼散開」,也就是形狀。在 ③ 的 step 2 可以直接看到這一步在做什麼。
為什麼我們要 care 特徵向量?它到底解決了什麼問題?
它解決的是:你手上的座標軸是別人給的,而它們互相糾纏。
公分和公斤這兩根軸都同時混著「大隻程度」,所以你沒辦法乾淨地問「這群人差在哪」。 共變異數矩陣的非對角線 98.55 就是這個糾纏的量化值。 特徵向量給你一組新軸,讓非對角線變成 0 —— 糾纏被解開,每根軸各管一件事。
換句話說,特徵向量的用途是把一個「混在一起」的東西拆成「彼此獨立的幾個方向」。 這個能力在 04 關用來拆解「一個矩陣反覆作用會把向量帶去哪」(對角化、矩陣冪次), 在這關用來拆解「一份資料的變異是由哪幾個獨立方向組成的」。同一把刀,兩種用法。
降維之後丟掉的是什麼?什麼時候不該降?
丟掉的是垂直於保留軸的那些方向上的差異。在這份資料裡,只留主軸就是丟掉「胖瘦」 —— 每個人的體型大小完整保留,但同身高下誰壯誰瘦的資訊被抹平了(可以在 ⑥ 看到紅色殘差線段全都垂直於主軸)。
不該降的情況:(1) 你要回答的問題剛好落在小變異方向上 —— 異常偵測、瑕疵檢測、罕見事件通常就藏在最後幾個主成分裡,砍掉等於砍掉答案; (2) 資料的結構不是線性的(環狀、螺旋、多群),PCA 找不到,見坑 4; (3) 你需要可解釋的原始欄位 —— 主成分是加權組合, 跟法務解釋「為什麼拒貸」時你沒辦法說「因為他的 PC3 太低」。
判斷標準不是「解釋比例夠不夠高」,而是被丟掉的方向跟你的問題有沒有關係。
什麼時候要先做標準化?
各欄的單位不同(公分 vs 公斤 vs 元 vs 次數)時就要做。PCA 追的是變異數, 而變異數帶單位 —— 把身高從 cm 改記成 mm,資料一個數字都沒變, 主軸卻從 45.24° 倒到 5.31°,直接變成「身高」本人。
反過來:如果各欄本來就是同一種單位、同一個量級(四科成績、16 顆同型號感測器的讀數), 那不要標準化 —— 那時候「哪一欄變異比較大」是真實資訊,標準化會把它抹平。
三顆按鈕自己按一遍就有感覺:⑦ 要不要先標準化。 另外注意那一節的表格有個陷阱 —— cm 和 z-score 的解釋比例剛好一樣是巧合,不是規律。
內積 → 變異數其實是內積 → 共變異數也是內積 → 共變異數矩陣 C → C 的特徵向量就是資料主軸 → PCA。 線性代數 01 到 05 這五關串成的那條線,到這裡閉合。
接下來要往哪走,看你想解決哪個問題:
- 想知道 SVD 怎麼直接吃一張長方形的資料表(不必先組出 C 這張方形小表, 也就是 ⑩ 第 1 點那個「上到幾百維就不要組 C」的正解)→ 07 SVD:轉一下、拉一下、再轉一下。 如果想先把「正交矩陣」這個零件補齊再過去,順路先走 06 空間補完。
- 想把這一頁那顆 1σ 橢圓當成一把尺來用,回答「這個新來的人算不算離群」→ 機率統計 05 橢圓的真身:拿 C 當一把尺。 那一關會把 λ 和 v₁ 從「主軸」改讀成「量距離的單位」—— 同一顆橢圓,換一種用法。
想先確認自己真的懂了再往前,就去 全景 01 全景地圖與自我驗收 做一次費曼測試:用國中生聽得懂的話,把 PCA 講一遍。