空間補完:span、秩、正交矩陣
玩完這關,你會量出一堆欄位裡真正有幾個方向、看出哪個矩陣把平面壓扁了回不來、 並且知道為什麼工程師寧可繞一大圈也要用正交矩陣。
① 你手上的問題:30 個欄位,卻沒有 30 個方向
你手上一張表,30 個欄位。你把它整包丟進去跑迴歸,結果程式沒爆但答案很怪:
係數大得莫名其妙、正負號跟常識相反、你重新抽一次樣本,係數整組換一批人。
更糟的版本是它真的爆了 —— Singular matrix、matrix is not invertible。
你翻回原始表格找兇手,發現裡面躺著這三欄:
| 學生 | 期中 | 期末 | 總分 |
|---|---|---|---|
| 小林 | 70 | 80 | 150 |
| 阿凱 | 85 | 75 | 160 |
| Wen | 60 | 65 | 125 |
| 老周 | 90 | 95 | 185 |
「總分」不是一個新欄位,它是期中+期末,一個字都沒多講。
你以為餵了 3 個線索進去,其實只有 2 個;第 3 個是前兩個的複製品,
而程式解方程式的時候被這件事整到 —— 它要找「唯一的一組係數」,但因為
期中係數 +1、期末係數 +1、總分係數 0 跟
期中 0、期末 0、總分 +1 給出完全一樣的預測,唯一解根本不存在。
問題不是數字錯,也不是模型爛。問題是:你沒有一把尺去量「這堆欄位真正有幾個方向」。 30 欄可能只有 2 個方向,也可能有 29.7 個方向(更陰險的那種)。
span —— 幾根箭頭能走到的所有地方,也就是「這堆線索的活動範圍」。
rank(秩) —— 那個活動範圍有幾維,也就是「真正有幾個方向」。
正交矩陣 Q —— 一種絕對不會把空間壓扁、絕對回得去的變換,工程上的救命符。
② span:兩根箭頭能走到哪
先給最小的例子:只有一根箭頭
你站在原點,手上只有一個動作可以重複做:沿著箭頭 a = (2, 1) 走。你可以走 3 次(走到 (6, 3))、 走 0.5 次(走到 (1, 0.5))、也可以倒退走 −2 次(走到 (−4, −2))。
把「走 s 次」的所有結果 s·a 全部畫出來,你會得到什麼?一條穿過原點的直線。 不管你多努力調 s,你永遠碰不到 (0, 1) —— 它不在那條線上,而你只有這一個方向可以走。
這條「你能走到的所有地方」有個名字:span(生成空間)。 span{a} 讀作「a 生成的空間」,這個例子裡它是一條直線。 s —— 你走了幾次,是任意實數(可以是負的、可以是小數)。
加第二根箭頭:多一條巷子可以走
現在給你第二個動作:沿 b 走 t 次。你可以先沿 a 走 s 次、再沿 b 走 t 次, 最後落在 s·a + t·b。
這個式子有個名字:線性組合(linear combination)。 白話就是「兩個動作各做幾份,加起來」—— 跟調飲料一樣, a 是黑糖、b 是鮮奶,(s, t) 是配方,span 就是你這兩罐原料能調出的所有飲料。
你會看到什麼:藍箭頭 a 與 橘箭頭 b 是你的兩個動作(兩條同色虛線是它們各自能走的「巷子」); 綠箭頭是這次的落點 s·a + t·b, 兩條淡虛線畫出「先走 s·a、再走 t·b」的接龍路徑。
你可以動什麼:藍點與橘點可以直接拖(改變兩個動作的方向與長度); 兩根滑桿是配方 s、t; 按「掃一遍」會把 289 種 (s, t) 組合的落點全部撒成綠點。
要看出什麼:一般情況綠點撒滿一整片(span = 平面,2 維); 按下「把 b 轉到跟 a 同方向」,同樣 289 個組合瞬間塌成一條線(span = 直線,1 維)—— 第二根箭頭沒帶來新方向,白給的。
綠點是「掃一遍」撒出來的落點。這裡只掃 s、t ∈ [−2, +2], 所以你看到的是一塊平行四邊形的斑點區;把 s、t 開到無限大,它會真的填滿整個平面。
det[a b] —— 把 a、b 當成矩陣的兩個欄排好,取它的行列式;
幾何上就是 a、b 撐出的平行四邊形面積(帶正負號,負號只代表 b 在 a 的順時針側)。
面積 = 0 ⟺ 兩根壓在同一條線上。這跟 04 關的 det = 面積倍率 是同一個 det。
|cos(a, b)| —— 01 關的餘弦相似度取絕對值:
0 = 完全垂直(方向最不重複),1 = 完全同向或完全反向(方向 100% 重複)。
所以這一段的結論是:span 就是「你這幾個動作能到的所有地方」。 它的大小不看你有幾根箭頭,只看那些箭頭指向幾個真正不同的方向。
③ 線性獨立:第二根箭頭有沒有帶來新東西
剛剛那個「b 轉到跟 a 同方向」的瞬間,塌下去的不只是圖,是資訊量。 這件事的正式名字是:
反過來,找不到這種 k ⟹ 兩根線性獨立(linearly independent),各自帶來一個新方向。
接回你那張表:「總分」就是這種箭頭
把 ① 那張表的每一欄看成一根箭頭(4 個學生 ⟹ 4 維空間裡的箭頭):
總分 = (150, 160, 125, 185) = 1·期中 + 1·期末 「總分」完全躺在 span{期中, 期末} 裡面 —— 它不是第三個方向,是前兩個的線性組合。 所以這 3 欄的 rank 是 2,不是 3。程式找不到唯一解,不是 bug,是你真的只給了 2 個方向。
注意這裡的 k 不必是整數、也不必只有兩欄。總價 = 單價 × 數量 是乘法、不算線性相依,
但 log(總價) = log(單價) + log(數量) 就是了 —— 取完 log 丟進線性模型的人常常自己踩到。
(為什麼取完 log 就從乘變成加:基礎 01 關 ④ 節。)
致命的是「幾乎共線」,不是「完全共線」
共線這件事是連續的,不是 yes/no。回去那張圖把 b 慢慢轉向 a,你會看到 det[a b] 從 4.89 一路縮到 0.3、0.05 —— 它不會突然變 0,是慢慢乾掉的。 這個「快共線但還沒共線」的狀態有個名字:多重共線性(multicollinearity), 而它比完全共線更難搞,因為程式不會報錯。
看一個小到可以手算的例子。a = (1, 0)、 b = (1, 0.02),det = 0.02,幾乎共線但沒有完全共線。 現在請它們湊出某個目標 y:
| 目標 y | 要的配方 s(a 幾份) | 要的配方 t(b 幾份) |
|---|---|---|
| (1.00, 0.000) | +1.00 | 0.00 |
| (1.00, 0.010) | +0.50 | +0.50 |
| (1.00, 0.020) | 0.00 | +1.00 |
目標只動了 0.02,配方卻從 (1, 0) 一路翻到 (0, 1) —— 放大 50 倍(50 = 1 / det)。 在迴歸裡「配方」就是你的係數,於是你會看到:資料抖一下、係數整組換臉、正負號翻過來, 而 R² 看起來還很漂亮。這就是多重共線性的真面目:不是算不出來,是算出來的東西沒有意義。
「線性獨立」講的是欄位之間,不是資料點之間。 兩根箭頭獨立 ≠ 兩個人的資料不像。這一節從頭到尾把一欄當一根箭頭看, 跟 03 關把一列當一個資料點看,是兩種不同的看法 —— 全景 01 關的地圖專門在講這件事。
所以這一段的結論是:線性相依=有欄位在重複別人講過的話; 而「幾乎重複」比「完全重複」更危險,因為它不報錯,只是安靜地把你的答案放大成噪音。
④ 秩(rank):真正撒得出來的維度數
換個角度看同一件事:矩陣 A 是一個動作, 它把整個平面上的每個點搬到新位置。rank 就是在問: 搬完之後,剩下的東西還是一整片平面,還是被壓成一條線了? 最乾淨的看法是拿一個圓去測 —— 圓上的點朝每個方向都有,A 對每個方向做了什麼,一眼就看得到。
你會看到什麼:藍色虛線圓是輸入(半徑 1 的單位圓,上面均勻取 28 個 藍點);綠色形狀是那 28 個點被 A 搬過去之後的落點; det 掉到 0 時會多出一條紅色虛線,那是被壓掉的方向。
你可以動什麼:四根滑桿就是矩陣 A 的四個數字 a、b、c、d(位置對應右上角那個 2×2 方框); 也可以按預設鈕直接跳到「旋轉」「剪切」「壓扁」。
要看出什麼:rank = 2 時圓 → 橢圓,面積變成原來的 |det| 倍,A 可逆; 按下「壓扁」讓 det = 0,圓 → 一條線段,紅線那個方向的資訊永久消失、回不去了。
圓上的點被搬到哪,是靠 28 個取樣點畫出來的,所以綠色邊界是折線而不是真曲線 —— 這是取樣,不是計算誤差。
程式判斷 rank 時我用的門檻是 |det A| < 0.001 就當成 0。
為什麼要門檻?因為滑桿是小數,浮點數幾乎永遠不會給你剛好的 0
(0.85 × 1.2 − 0.51 × 2.0 算出來可能是 -2.2e-16)。
真實世界的 numpy.linalg.matrix_rank 也是這樣做的,只是門檻挑得更講究。
「回不去了」到底是什麼意思
rank 掉下去的那一刻,發生的事情是:一整條直線上的無數個點,被搬到同一個落點上。 紅虛線就是那條線的方向(正式名字叫核,kernel/null space)—— 沿著它走多遠都不影響輸出,所以輸出根本不知道你原本走了多遠。
這就是「不可逆」的真正意思:不是算式解不出來,是答案本來就不唯一。
給你一個落點,我沒辦法告訴你它從哪來,因為有無限多個來源都長成這樣。
04 關說 det 是面積倍率 —— 面積倍率 0 就是「把二維壓成一維」,
壓扁這件事沒有還原鍵。這也是 ① 那張表跑出
Singular matrix 的同一件事,只是換成 30 欄的版本。
rank 滿(2×2 的 rank = 2)⟺ det ≠ 0 ⟺ 可逆 ⟺ 欄向量線性獨立。 這四句話在 2×2 是完全等價的四種說法,看到哪一個都可以翻成其他三個。
所以這一段的結論是:rank 是「動作做完還剩幾維」的計數器。 rank 掉 ⟹ 有方向被壓成 0 ⟹ 資訊永久消失 ⟹ 回不去(不可逆)。
⑤ 正交矩陣 Q:唯一保證不弄壞形狀的變換
01 關講過「兩根垂直、長度 1 的軸」: q1、q2, 互相垂直(內積 0)、各自長度 1。現在做一件很機械的事 —— 把它們一根當第一欄、一根當第二欄,排成一個矩陣:
名字有點誤導:它叫「正交」矩陣,但要求不只正交,還要長度都是 1 (嚴格講是 orthonormal,正交+單位長)。
這種矩陣做出來的動作只有兩種:轉一下,或者轉一下再照鏡子。 它不能拉、不能壓、不能歪 —— 物理上就是剛體運動:拿起一個實心零件搬到別的地方, 零件本身一點都沒變形。
你會看到什麼:兩張圖,藍色虛線的 L 形都是同一個原圖; 左圖綠色是套上正交矩陣 Q 的結果,右圖桃色是套上一般矩陣 A 的結果。 直角那個角落有一段弧線,上面寫著當下實測的角度。
你可以動什麼:Q 只有一個角度滑桿 θ 加一個「照鏡子」開關(因為它只能做這兩件事); A 有兩根滑桿(橫向拉伸 k、剪切量 h)。 兩張圖上的藍點都可以拖,拖它是搬動原圖的位置。
要看出什麼:下面那張表裡,Q 那一欄的邊長、夾角、面積永遠等於原圖(差值 0.00); A 那一欄只要你動任何一根滑桿,三個數字全部走鐘。
實測三個指標:誰把形狀弄壞了
| 指標 | 原圖 | 套 Q 之後 | 差 | 套 A 之後 | 差 |
|---|---|---|---|---|---|
| 底邊長 | 2.60 | 2.60 | 0.00 | 3.90 | +1.30 |
| 側邊長 | 3.20 | 3.20 | 0.00 | 3.80 | +0.60 |
| 直角那一角(度) | 90.0 | 90.0 | 0.00 | 62.0 | -28.0 |
| 面積 | 4.41 | 4.41 | 0.00 | 6.62 | +2.21 |
Q 的三個等價性質 —— 現場驗算給你看
教科書會丟三條式子給你。它們講的其實是同一件事,而且下面的數字是用你現在滑桿上的 Q 即時算的, 不是印死的:
性質一:QTQ = I
QT(Q transpose,轉置)= 把 Q 沿對角線翻過來,行變欄、欄變行。
I(identity,單位矩陣)= 對角線 1、其他 0,代表「什麼都不做」的動作。
為什麼會等於 I:QTQ 的第 (i, j) 格,剛好就是
qi · qj(內積)。
自己跟自己內積 = 長度平方 = 1(對角線);不同兩根內積 = 0(垂直,其他格)。
所以這條式子只是把「兩根垂直、長度 1」寫成矩陣。
性質二:Q−1 = QT
Q−1 = 反動作(做完 Q 再做 Q−1 會回到原點)。 一般矩陣求反動作要算行列式、除來除去、還可能失敗; Q 的反動作只要把它翻過來就好 —— 這是工程上最爽的一件事:零成本、零誤差、絕不失敗。
性質三:|det Q| = 1
det 是面積倍率(④)。面積倍率 1 = 不脹不縮。 正負號只差在有沒有照鏡子:det = +1 是純旋轉,det = −1 是旋轉+鏡射 (鏡射會把「逆時針」變成「順時針」,所以帶負號)。
幾何上:正交(且非零)⟹ 一定線性獨立;但獨立不一定正交
(a = (1,0)、b = (1, 0.02) 獨立得很,卻幾乎共線)。正交是獨立的高級版,
不只是「不重複」,而是「一點都不重疊」。
統計上更要小心:兩欄共變異數 0(去中心化之後互相正交)
不等於機率上獨立 —— 前者只保證「沒有線性關係」,
y = x² 這種資料共變異數可以是 0,但 y 完全由 x 決定。同一個詞在兩門課裡意思不一樣,這是真的坑。
所以這一段的結論是:Q 就是「兩根垂直單位軸排成的矩陣」, 它做的事是剛體運動(邊長、夾角、面積全保住),而它的反動作就是轉置 —— 免費、精確、永不失敗。
⑥ 複合變換:矩陣乘法就是動作接龍
到目前為止每張圖都只套一個矩陣。真實的東西是接龍的: 先剪切、再旋轉;或者先縮放、再鏡射。問題是 —— 接龍的順序有差嗎?
你會看到什麼:兩排各三格。上排是先 B 再 A(原圖 → 套 B → 再套 A), 下排是先 A 再 B。藍虛線永遠是原圖當參考, 綠色是上排的最終結果,桃色是下排的最終結果; 下排最後一格會把上排的綠色結果疊上去虛線,方便你直接對照。
你可以動什麼:兩個下拉選單,分別挑 A 與 B 是什麼動作(旋轉/縮放/剪切/鏡射)。
要看出什麼:除了少數巧合(例如兩個都是旋轉), 綠色和桃色不會重疊 —— 同樣兩個動作,換個順序就是不同的結果。 對應到矩陣:AB ≠ BA。
為什麼 A(Bx) 要從右往左讀
因為括號。x 是原圖上的一個點,
Bx 是「B 先動它」的結果,然後 A 才拿這個結果去動。
所以離 x 最近的矩陣最先做 —— 這跟函式呼叫
a(b(x)) 一模一樣,你每天都在從裡往外讀,只是換了個寫法。
而矩陣乘法的定義就是為了讓這件事成立:(AB)x = A(Bx)。 也就是說 AB 這個「合成動作」= 先做 B 再做 A。 所以「矩陣乘法為什麼要這樣定義?」的答案是: 它不是規定,是為了讓「把兩個動作接成一個動作」剛好對得上。
矩陣乘法就是「動作接龍」,而接龍有先後順序,所以 AB ≠ BA。
先穿襪子再穿鞋,跟先穿鞋再穿襪子,結果差很多 —— 而數字乘法沒有這個問題
(3 × 5 = 5 × 3),因為數字只是縮放,縮放彼此不打架。
矩陣一旦帶了「方向」,順序就有意義了。
所以這一段的結論是:矩陣相乘 = 動作接龍,寫法從右往左讀, 而順序換掉就是另一個動作。這也是為什麼 下一關的 Q1 Σ Q2T 要照那個順序讀。
⑦ 平移擠不進 2×2:所以才有齊次座標
先實測一件事:2×2 一定把原點釘在原點
拿任何一個 2×2 矩陣去乘零向量:
所以「把整張圖往右移 3 格」這個動作,2×2 矩陣寫不出來: 它會要求原點跑到 (3, 0),而我們剛剛證明原點動不了。 這不是找不到解法,是這個工具箱裡真的沒有這個工具。 也難怪你在 ⑥ 看到的每一格圖都是「以原點為軸」在轉在歪。
把二維的點 (x, y) 寫成三個數 (x, y, 1),矩陣升級成 3×3 —— 那個永遠是 1 的第三個座標,會把矩陣第三欄的數字原封不動加到結果上, 平移就這樣被夾帶進來了。這套寫法叫齊次座標(homogeneous coordinates)。
右上角 tx、ty = 平移量, 直接加在結果上(這就是那個 1 的功勞)。
最下面那排 (0, 0, 1) = 樣板,不是資料。 它的唯一任務是讓輸出的第三個數字還是 1,這樣下一個 3×3 才能繼續接龍。
整包這種「線性 + 平移」的變換有個名字:仿射變換(affine transformation)。
你會看到什麼:藍虛線是原圖; 灰虛線是只套左上角 2×2(沒有平移)的結果 —— 注意它的角落還黏在原點; 綠實線是完整 3×3(含平移)的結果; 橘箭頭就是平移量 t。
你可以動什麼:橘點可以拖,拖它就是改 tx、ty; 下拉選單換左上角那個 2×2 要做什麼線性動作。
要看出什麼:拖橘點的時候,灰虛線完全不動(2×2 部分跟平移無關), 只有綠色跟著跑 —— 平移是被那個「1」偷偷加上去的,不是矩陣本體算出來的。
綠色形狀 = 灰色形狀整體平移 橘箭頭那麼多。形狀完全一樣,只是搬了位置。
02 關的去中心化(每個點減掉平均)本質上就是一次平移。 它為什麼要放在 PCA 之前?因為 共變異數矩陣 C 跟 PCA 都是純線性的工具(2×2 世界), 而純線性的世界裡原點動不了。所以我們手動把資料搬到原點、把平移這件事處理掉, 剩下的「散開的形狀」就是純線性部分,2×2 才夠用。 電腦圖學選擇多加一維把平移吞進矩陣;統計選擇先減掉平均把平移丟掉。 同一個問題的兩種解法。
所以這一段的結論是:2×2 一定把原點釘死,所以平移得另外處理 —— 要嘛升到 3×3 用齊次座標把它吞進來,要嘛先去中心化把它消掉。
⑧ 數學長怎樣:先給程式,再給符號
本關四個概念,寫成程式各只有幾行。先讀程式,符號版在後面。
// ---- span:兩根箭頭能走到哪 ----
// span{a, b} 就是「所有 s·a + t·b 的集合」,s、t 掃過所有實數。
function combine(a, b, s, t) {
return { x: s * a.x + t * b.x, y: s * a.y + t * b.y };
}
// ---- rank:真正剩幾個方向 ----
function rank2(a, b) { // a、b 是矩陣的兩個「欄」
const TOL = 1e-9;
const na = Math.hypot(a.x, a.y), nb = Math.hypot(b.x, b.y);
if (na < TOL && nb < TOL) return 0; // 兩根都是零向量 → 只剩原點
const det = a.x * b.y - a.y * b.x; // = 兩根撐出的平行四邊形面積
return Math.abs(det) < TOL ? 1 : 2; // 面積 0 → 共線 → 只撐出一條線
}
// ---- 正交矩陣:檢查 QᵀQ 是不是單位矩陣 ----
function isOrthogonal(Q) {
const G = LAB.M.matMul(LAB.M.transpose(Q), Q); // G[i][j] = 第 i 欄 · 第 j 欄
return Math.abs(G[0][0] - 1) < 1e-9 && Math.abs(G[1][1] - 1) < 1e-9
&& Math.abs(G[0][1]) < 1e-9; // 對角線 = 長度² = 1,其他 = 內積 = 0
}
// ---- 齊次座標:把 2×2 + 平移 塞進一個 3×3 ----
function affine(A, t, p) { // A 是 2×2、t 是平移、p 是點
const q = LAB.M.matVec(A, p); // 線性部分(原點不動)
return { x: q.x + t.x, y: q.y + t.y }; // 那個「1」的功勞:把 t 加上去
}
ℝ = 全體實數。s, t ∈ ℝ = s 和 t 可以是任何實數(含負數與小數)。
整句讀作:「所有 s 倍的 a 加 t 倍的 b,s、t 隨便挑」——也就是這兩個動作能到的所有地方。
2×2 的情況只有三種答案:2(滿秩,可逆)、1(壓成線)、0(壓成點,A 全是 0)。
前兩條完全等價(把第一條左乘 Q−1 就得到第二條)。 第三條是單向的:|det| = 1 只保證面積不變,不保證形狀不變 —— [[2, 0], [0, 0.5]] 的 det 是 1,但它把圖拉長了兩倍,不是正交矩陣。
兩個仿射變換接龍時,這種 3×3 直接相乘就好 —— 這是它真正的價值: 把「先轉再移,然後再轉再移…」壓成一次矩陣連乘。
⑨ 本頁符號速查(畫面上出現過的每一個)
| 符號 | 它是什麼 | 哪裡講的 |
|---|---|---|
| a | 第一根箭頭 / 第一個動作 / 矩陣的第一欄 | ② span |
| b | 第二根箭頭 / 第二個動作 / 矩陣的第二欄 | ② span |
| s、t | 配方:a 做幾份、b 做幾份(任意實數) | ② span |
| span{a, b} | a、b 能走到的所有地方 | ② span |
| det[a b] | a、b 撐出的平行四邊形面積(帶號);0 = 共線 | ② 讀數盤說明 |
| |cos(a, b)| | 共線度:0 垂直、1 完全重複方向 | ② 讀數盤說明 |
| k(在 b = k·a) | 倍率:b 是 a 的幾倍 ⟹ 線性相依 | ③ 線性獨立 |
| A | 一般 2×2 矩陣=一個「動作」;四個數字 a、b、c、d | ④ rank |
| det A | A 的面積倍率;0 = 壓扁了 | ④ rank |
| rank A | 做完 A 還剩幾維(2 / 1 / 0) | ④ 定義框 |
| 核 / null space | 被壓成 0 的那個方向(圖上紅虛線) | ④ 回不去了 |
| Q | 正交矩陣:欄是互相垂直的單位向量 | ⑤ 定義框 |
| q1、q2 | Q 的兩個欄,也就是那兩根垂直單位軸 | ⑤ 定義框 |
| θ | Q 轉的角度(度,逆時針) | ⑤ 滑桿 |
| QT(也寫 Aᵀ) | 轉置:沿對角線翻過來,行變欄 | ⑤ 性質一 |
| I | 單位矩陣:對角線 1、其他 0=「什麼都不做」 | ⑤ 性質一 |
| Q−1 | 反矩陣=反動作;Q 的反動作就是 QT | ⑤ 性質二 |
| k、h(在 A 那側) | k 橫向拉伸倍率、h 剪切量(x ← x + h·y) | ⑤ 滑桿 |
| AB、BA | 動作接龍:AB = 先 B 再 A;BA = 先 A 再 B | ⑥ 複合變換 |
| A(Bx) | 同一件事的括號寫法,從右往左讀 | ⑥ 從右往左讀 |
| x(在 Ax) | 被搬動的那個點(原圖上任一點) | ⑥ 從右往左讀 |
| t(在 Ax + t) | 平移向量 (tx, ty);圖上橘箭頭 | ⑦ 齊次座標 |
| M | 那個 3×3 齊次矩陣(左上 2×2 + 右上平移 + 底排樣板) | ⑦ 齊次座標 |
| 那個 1 | 齊次座標補的第三個數;樣板,不是資料 | ⑦ 公式註解 |
| ℝ、∈、dim、↦ | 全體實數/屬於/維度/送到 | ⑧ 符號版 |
⑩ 工程師的「原來如此」
你跑一個房價模型,放了「室內坪數」「權狀坪數」「公設比」。前兩者相關係數 0.97, 於是 det 幾乎是 0 ——③ 那個「放大 50 倍」的效應開始作用: 模型可以用「室內 +8000、權狀 −5000」,也可以用「室內 +1000、權狀 +2000」, 預測值幾乎一樣,係數天差地遠。於是你得到一個預測還行、但每個係數的正負號都在說謊的模型。
產業界量這件事的指標叫 VIF(variance inflation factor): 拿第 j 欄去被其他所有欄迴歸,VIFj = 1 / (1 − R2j)。 R² 越接近 1(越能被別人湊出來)VIF 就衝上去,超過 10 大家就開始砍欄位。 那個 1 − R² 就是「這一欄裡有多少是別人湊不出來的」,跟這一頁的 det 快歸零是同一件事的兩種寫法。
真正的修法有三條,全部都在這一頁的語言裡:砍掉重複的欄(降欄數到 rank)、 換成正交的欄(PCA 給你的主成分互相正交,det 不會爛)、 或者 ridge 迴歸(在對角線上加一點東西,硬把那個快歸零的 det 撐開,代價是答案偏一點)。
你在遊戲引擎裡看到的 MVP matrix(Model × View × Projection)全部是 4×4,
不是 3×3。原因就是 ⑦:3D 的旋轉/縮放只要 3×3,
但「把角色放到世界座標 (120, 0, 45) 的位置」是平移,3×3 塞不進去。
補一維變 4×4 之後,整條變換鏈可以事先乘成一個矩陣,
然後每一個頂點只要做一次 4×4 乘法 —— 幾十萬個頂點的差別就在這裡。
機器人手臂更是靠這個吃飯:每個關節的「轉多少度 + 往前伸多長」被寫成一個 4×4 (這叫 DH 參數),六個關節就是六個矩陣連乘,末端夾爪的位置與姿態一次算出來。 如果平移不能寫成矩陣,這條連乘就斷了,你得手工在每一步之間插入加法, 程式碼會變成無法維護的地獄。
⑪ 踩坑
df.shape[1] == 30 只告訴你「有 30 欄」,不告訴你「有幾個方向」。
① 那張表 3 欄但 rank 2。要量方向數請用
numpy.linalg.matrix_rank(X),不要數欄位。
另外一個常被忽略的上限:rank ≤ min(列數, 欄數)。
你有 500 欄但只有 80 列資料 ⟹ rank 最多 80,剩下 420 個方向從一開始就是假的。
這就是「p ≫ n」問題,跟你有沒有寫錯 code 無關。
完全共線 ⟹ numpy 直接丟 Singular matrix,你當場知道要修。
幾乎共線 ⟹ 它給你一個答案,而且不吭一聲,然後你拿那組被放大 50 倍的係數去做決策。
沒有報錯不代表沒事。習慣性檢查:算條件數(numpy.linalg.cond),
超過 103 就該皺眉,
1010 就是在騙自己。
幾何:正交(非零)⟹ 線性獨立,反之不成立。
統計:相關係數 0(幾何上正交)不等於機率獨立 ——
它只排除線性關係。y = x² 這種資料相關係數可以是 0,但 y 完全被 x 決定。
看到「independent」先問是哪一門課的 independent。
⑫ 這關回答了什麼
span 是什麼?
幾根箭頭能走到的所有地方。正式一點:所有線性組合 s·a + t·b 的集合,s、t 掃過全體實數。
用調飲料想:a 是黑糖、b 是鮮奶,span 就是這兩罐能調出的全部飲料。 兩罐口味不同 ⟹ 你能調出一整片組合(span = 平面); 兩罐其實是同一罐貼不同標籤 ⟹ 你只能調出一條線上的東西(span = 直線)。 去 ② 按「掃一遍」就會看到那 289 個落點怎麼塌。
線性獨立為什麼重要?
因為相依的欄位讓「唯一解」不存在。 ① 那張表裡,「期中 +1、期末 +1、總分 0」跟「期中 0、期末 0、總分 +1」 給出一模一樣的預測 —— 程式要挑一組出來,但沒有理由挑哪一組,於是它爆掉(或亂挑一組給你)。
更實務的版本:獨立性差 ⟹ det 快歸零 ⟹ 解方程式時除以一個很小的數 ⟹ 輸入抖一點、答案抖很多。你的係數就從「可以拿去講故事的東西」變成「噪音的放大版」。 細節在 ③,工程現場版在 ⑩ 的 VIF。
rank 跟欄數差在哪?
欄數是你「宣稱」有幾個線索,rank 是你「真的」有幾個。 欄數用眼睛數就有;rank 要算,因為它會扣掉互相重複的部分。
三個常見狀況:
① 有欄位是別人加出來的(總分 = 期中 + 期末)⟹ rank < 欄數。
② 資料列數比欄數少(80 列 500 欄)⟹ rank ≤ 80,剩下的方向根本不存在。
③ 沒有完全重複但高度相關 ⟹ rank 數字上還是滿的,但實際上快掉了
(這叫「數值 rank」,看條件數才抓得到)。詳見 ⑪ 坑一、坑二。
為什麼工程上超愛正交矩陣?
三個理由,一個比一個現實:
① 反動作免費。Q−1 = QT ——
翻一下就好,不解方程式、不會失敗。
② 誤差不放大。它保持長度(⑤ 表格實測差值都是 0.00),
所以誤差進去多大出來就多大,不會像 det 快歸零的矩陣那樣把 10⁻⁸ 放大成 10⁻²。
③ 絕不壓扁。|det Q| = 1 ⟹ 永遠滿秩 ⟹ 資訊不會消失。
所以正經的函式庫都先把矩陣拆成「正交的部分 × 好處理的部分」:QR、Householder、 以及 下一關的 SVD。細節在 ⑩ 第三塊。
AB 跟 BA 為什麼不一樣?
因為矩陣是動作,而動作有順序。AB 的意思是 先做 B 再做 A(從右往左讀,因為 A(Bx) 的括號在裡面先算)。 先剪切再旋轉,跟先旋轉再剪切,剪的方向整個不一樣 —— 去 ⑥ 看綠色跟桃色差多遠。
數字乘法沒這問題(3 × 5 = 5 × 3),是因為數字只會縮放,縮放彼此不打架。 矩陣一旦帶方向,順序就有意義了。特例存在:兩個旋轉可以交換、 任何矩陣跟 I 可以交換、對角矩陣彼此可以交換 —— 但那是巧合,不是通則,寫程式時不要賭。
平移為什麼要另外處理?
因為任何 2×2 矩陣一定把原點送回原點(A·0 = 0, 每一項都乘到 0)。而「往右移 3 格」要求原點跑到 (3, 0),2×2 做不到 —— 不是難,是結構上不可能。
兩條解法,各行各業選不同的:
電腦圖學/機器人:加一維變 3×3(3D 是 4×4),
用齊次座標把平移吞進矩陣,好處是整條變換鏈可以連乘。
統計/機器學習:先去中心化把平移消掉,
之後只剩純線性部分,2×2 就夠用了 —— 這就是 PCA 為什麼一定先減平均。
「rank 掉了」跟「不可逆」跟「det = 0」是三件事還是一件事?
一件事,三種說法。再加第四種:「欄向量線性相依」。在 2×2 裡這四句完全等價:
det = 0 ⟺ 兩欄撐出的面積是 0 ⟺ 兩欄共線(相依)⟺ 整個平面被壓到一條線上(rank 1) ⟺ 有一整條直線的點被壓到同一個落點 ⟺ 給你結果也還不回去(不可逆)。
去 ④ 按「把 det 拉到 0」,四件事會同時發生在同一個畫面上。
現在你手上有兩樣東西:Q(只轉不變形,絕對回得去)跟 對角矩陣(只沿座標軸拉伸,超好懂)。而 ⑥ 告訴你矩陣可以接龍。
那麼問一個貪心的問題:隨便給我一個矩陣,我能不能把它拆成「轉一下 → 沿軸拉一下 → 再轉一下」? 如果可以,那所有矩陣的行為就只有這三種零件,再歪的動作都能拆解、都能看懂、都能截斷成低秩近似。
答案是可以,而且對任何矩陣都成立(連不是方陣的都行)。 這就是 07 關:SVD —— 轉一下、拉一下、再轉一下。