最大邊界核技巧

ISLP 第 9 章 — 對應講義 09
超平面|最大邊界|支持向量|軟邊界 C|Hinge loss|核技巧|多項式核|RBF 核
向下捲動開始互動
📌 本頁使用方式(ISLP Ch.9|講義 09)

照節次讀:每節先讀說明,動手玩互動元件——先預測結果,再按按鈕驗證。 ② 對照講義:每個 §徽章都標了 ISLP 節號與講義頁碼,細節與完整推導請回講義與課本。 ③ 每節做 quiz:答錯就回到該節重讀,不要往下跳;錯的選項也寫了「錯在哪」。 ④ 最後翻關鍵詞彙卡自測術語,並用 REF 總覽當速查表。

CONTENTS · 內容目錄
PROLOGUE · 開場

超平面:把分類問題變成幾何問題 ISLP §9.1講義 09 · p.2–7

前面幾章的分類器都先繞一圈:邏輯斯迴歸去估 $\Pr(Y \mid X)$,LDA 去估 $\Pr(X \mid Y)$ 再用貝氏定理翻回來,樹去切區塊。這一章換一條路—— 直接在特徵空間裡找一片把兩類分開的平面。不估機率、不假設分佈, 就是幾何。

講義第 3 頁把整章的劇本寫得很乾淨:先試著找一片分得開的平面; 如果找不到,往兩個方向想辦法——把「分開」的定義放鬆(軟邊界), 以及把特徵空間變大(核)。這兩招合起來就是支持向量機。

三層結構,一層一層加東西 1. 最大邊界分類器(maximal margin classifier): 資料完全分得開時,選離兩邊都最遠的那一刀。
2. 支持向量分類器(support vector classifier):允許少數點犯規, 用一個調整參數決定容忍度。也叫軟邊界分類器。
3. 支持向量機(support vector machine, SVM):把內積換成核, 邊界就彎起來了。
三者不是三種方法,是同一個方法的三個層次——最外面那層用線性核時 會原地退回最裡面那層。

起點是超平面(hyperplane)。p 維空間裡的超平面是一個 p − 1 維的 平坦仿射子空間;p = 2 就是一條線,p = 3 就是一個平面。它的方程式簡單到有點反高潮:

$$\beta_0 + \beta_1 X_1 + \beta_2 X_2 + \cdots + \beta_p X_p = 0$$

寫成 $f(X) = \beta_0 + \beta^{\top} X$。滿足 $f(X) = 0$ 的點在超平面上, $f(X) > 0$ 的點在一側、$f(X) < 0$ 的點在另一側。所以只要看 $f(X)$ 的正負號, 就知道一個點站在哪一邊——分類問題被壓成一次算術。

而且 $f(X)$ 的大小也有意思。向量 $\beta = (\beta_1,\dots,\beta_p)$ 是超平面的法向量(normal vector),指向與超平面垂直的方向; 點 $x$ 到超平面的垂直距離正好是

$$\text{距離} = \frac{|f(x)|}{\lVert \beta \rVert}, \qquad \lVert \beta \rVert = \sqrt{\beta_1^2 + \cdots + \beta_p^2}$$

所以 $|f(x)|$ 大就是離邊界遠、這個判斷有把握;$|f(x)|$ 接近 0 就是貼在邊界上、 隨時可能翻盤。這個「離邊界多遠 = 多有把握」的直覺,是整章的地基。

拖三個滑桿看超平面怎麼動,以及三個測試點的 f(x) 怎麼變。
β₀1.0
β₁2.0
β₂3.0
怎麼玩 圖 9.1
三個滑桿分別調 β₀、β₁、β₂。藍色區域是 f(x) > 0、紅色區域是 f(x) < 0,中間那條紅線就是超平面。綠色短箭頭是法向量 β 的方向——注意它永遠垂直於線。預設值 1、2、3 就是 ISLP 圖 9.1 畫的那條 1 + 2X₁ + 3X₂ = 0。
目前的超平面
方程式
‖β‖
A 點:f(x) | 距離
B 點:f(x) | 距離
C 點:f(x) | 距離
兩個容易忽略的細節
① 係數整組縮放不改變超平面。三個滑桿同時乘 3,線不動、f(x) 卻變三倍。
② β₁ 與 β₂ 同時是 0 就沒有超平面。把那兩個滑桿都推到 0 看看。

有了超平面,分類規則就寫完了:把 $y_i$ 編碼成 $\pm 1$, 分離超平面(separating hyperplane)就是滿足

$$y_i\left(\beta_0 + \beta_1 x_{i1} + \cdots + \beta_p x_{ip}\right) > 0 \qquad \text{對每一筆 } i = 1, \dots, n$$

的那些超平面(ISLP 式 9.8)。這一個式子把「藍色的要 $f > 0$、紫色的要 $f < 0$」 兩條規則合成一條,因為 $y_i$ 自己會把符號翻過來。這個 $y_i f(x_i)$ 之後會一直出現, 它就是「這一筆分對了嗎、有多篤定」的度量。

講義完整實作:造資料、配一個線性 SVC、取出係數

lab 09 · SVC(kernel='linear') 的第一次配適
rng = np.random.default_rng(1) X = rng.standard_normal((50, 2)) y = np.array([-1]*25+[1]*25) X[y==1] += 1 fig, ax = subplots(figsize=(8,8)) ax.scatter(X[:,0], X[:,1], c=y, cmap=cm.coolwarm); svm_linear = SVC(C=10, kernel='linear') svm_linear.fit(X, y) svm_linear.coef_
預期輸出(儲存格 29)
array([[1.17303943, 0.77348227]])

這 50 筆資料是本章前半的主角,本頁所有烘焙圖都是重播同一組default_rng(1) 抽樣算出來的。coef_ 就是 (β₁, β₂) = (1.173, 0.773),intercept_ 是 β₀。配適那一格的輸出只是 SVC(C=10, kernel='linear')——sklearn 印的是估計器本身,不是結果。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 14、16、29
QUIZ · 超平面

把某個超平面的係數 (β₀, β₁, β₂) 全部乘上 −2,會發生什麼事?

(A) 超平面本身完全不動,但每個點的 f(x) 變成 −2 倍,正負兩側因此互換
(B) 超平面會平移,但方向不變
(C) ‖β‖ 不變,所以距離不變,一切照舊
PART 01 · 最大邊界分類器

能分開的話,選離兩邊都最遠的那一刀 ISLP §9.1.3–9.1.4講義 09 · p.8–11

如果資料真的分得開,麻煩來了:分離超平面有無限多個。 隨便一條分得開的線,都可以稍微平移一點、旋轉一點,還是分得開(ISLP 圖 9.2 左畫了三條)。 無限多個候選,總得有個挑法。

挑法很自然:選離兩邊都最遠的那一條。先算每個訓練點到超平面的垂直距離, 其中最小的那個距離叫做邊界(margin,ISLP 記為 M); 邊界最大的那個分離超平面就是最大邊界超平面(maximal margin hyperplane, 也叫最佳分離超平面)。用它做分類就是最大邊界分類器

一句話的幾何直覺 最大邊界超平面就是能塞進兩類之間那塊最寬「板子」的中線。 板子有多寬由最擠的地方決定,所以答案只跟「最擠的那幾個點」有關——這件事等一下會變成 整章最重要的性質。

寫成最佳化問題(ISLP 式 9.9–9.11):

$$\begin{aligned} &\underset{\beta_0,\beta_1,\dots,\beta_p,\,M}{\text{maximize}} \quad M \\ &\text{subject to} \quad \sum_{j=1}^{p} \beta_j^2 = 1, \\ &\qquad\qquad\quad\; y_i\left(\beta_0 + \beta_1 x_{i1} + \cdots + \beta_p x_{ip}\right) \ge M \quad \forall\, i \end{aligned}$$

兩個限制式各有分工。$\sum \beta_j^2 = 1$ 不是對超平面的限制(前一節說過, 縮放係數不改變超平面),它的作用是把 $y_i f(x_i)$ 校準成真正的距離; 有了這個校準,第二條 $y_i f(x_i) \ge M$ 才真的在說「每一筆都在正確一側,而且至少離 M 遠」。 於是 M 就是邊界,而目標函數就是把它推到最大。

拖動任何一個點。加粗描邊的是支持向量,只有它們會改變答案。
怎麼玩
直接拖動任何一個點。元件會即時解出最大邊界超平面:紅實線是邊界、兩條虛線是 margin 的兩側、加粗描邊的點是支持向量
重點在這裡:拖動任何一個沒被描邊的點,只要不越過虛線,紅線一動也不動。拖到越過虛線,它就變成支持向量、線立刻跟著動。
即時解
margin 半寬 M
板子總寬 2M
支持向量個數
邊界(f = 0)
解是怎麼算出來的 LIVE
不是跑 QP,是用一個等價的幾何事實:最大邊界超平面就是兩類凸包最近點對連線的垂直平分線,M 是那段距離的一半(紫色線段)。點很少,把所有候選組合都算一遍就好,每次拖曳都重算。
凸包一旦重疊就不存在分離超平面——把兩堆點拖到交錯,元件會直接說解不出來。

那幾個剛好落在虛線上的點就是支持向量(support vector)。 名字的由來很直白:它們像柱子一樣「支撐」著那片超平面——移動它們,超平面跟著動; 移動別的點,超平面完全不理你(只要那個點沒有越過 margin)。ISLP 說得很重:

順便說一句:ISLP §9.7 第 3 題就是這個元件的手算版。它給你 7 個點, 答案是 $X_2 = X_1 - 0.5$,支持向量是第 2、3、5、6 筆,$M = 1/(2\sqrt{2}) \approx 0.354$; 第 (f) 小題問「第 7 筆稍微移動會不會影響超平面」——你在上面拖過就知道答案了。 本頁 EX 區的第 3 題會再問一次。

最大邊界超平面只依賴支持向量,不依賴其他觀測值 這是本章反覆出現的主題。 好處是對離邊界很遠的點極度穩健——LDA 的規則要用到每一類的平均與整體共變異, 換掉一個遠處的點就會動;最大邊界超平面不會。
壞處是對支持向量極度敏感。ISLP 圖 9.5 就是這個代價:右圖只多加一個藍點, 最大邊界超平面就大幅轉向,而且 margin 縮到極窄。只靠三個點決定的分類器, 聽起來就不太可靠——這正是下一節要修的問題。

講義完整實作:把兩類推開到剛好可分開,再用超大的 C 配適

lab 09 · 剛好線性可分開的情況(C = 10⁵)
X[y==1] += 1.9; fig, ax = subplots(figsize=(8,8)) ax.scatter(X[:,0], X[:,1], c=y, cmap=cm.coolwarm); svm_ = SVC(C=1e5, kernel='linear').fit(X, y) y_hat = svm_.predict(X) confusion_table(y_hat, y)
預期輸出(儲存格 43)
Truth      -1   1
Predicted        
-1         25   0
 1          0  25

X[y==1] += 1.9 把兩類再推開一點,剛好變成線性可分開。用 C=1e5(sklearn 的 C,見下一節)配出來的分類器沒有任何訓練誤差,而且只用了 3 個支持向量——這就是最大邊界超平面。lab 儲存格 47 換成 C=0.1,訓練誤差同樣是 0,但支持向量變成 12 個、margin 寬得多。ISLP §9.6.1 的評語是:後者「因為點更多所以更穩定」,在測試資料上可能更好。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 41、43
觀念釐清
Q:為什麼叫「支持向量」?為什麼只有它們影響解?

先說「向量」:在 p 維空間裡,一筆觀測值 $x_i$ 就是一個 p 維向量,所以這些點本來就是向量。「支持」則是力學的比喻——它們頂在 margin 的兩側,撐著那塊板子。抽掉一根柱子,板子就塌下來換位置。

從最佳化的角度看:最大邊界問題的限制式是 $y_i f(x_i) \ge M$。在最佳解上,只有取等號的那些限制式是「緊的」(active);取嚴格大於的限制式等於根本沒在限制什麼,把它整條刪掉,解一模一樣。KKT 條件把這件事寫成 $\hat\alpha_i \left(y_i f(x_i) - M\right) = 0$:限制式不緊時 $\hat\alpha_i = 0$,而解只由 $\hat\alpha_i > 0$ 的那些點組成(講義第 18 頁:$\hat\beta = \sum_i \hat\alpha_i y_i x_i$)。

從損失函數的角度看:本頁 PART 03 會證明支持向量分類器等價於最小化hinge loss 加上 ridge 懲罰,而 hinge loss 在 $y_i f(x_i) \ge 1$ 時剛好等於 0。一個對目標函數貢獻恰好為 0 的點,當然不可能影響最佳解。兩個角度說的是同一件事。

Q:margin 大在測試資料上真的比較好嗎?

直覺上合理:margin 大表示兩類之間有一塊很寬的無人區,新資料落進來也大概不會踩線。ISLP 就是這樣說服讀者的——「我們希望訓練資料上 margin 大的分類器在測試資料上 margin 也大」。

但它明確加了一句警告:p 很大的時候最大邊界分類器會過度配適。維度愈高,愈容易找到一片「剛好」把訓練資料切開的超平面——那片超平面的位置可能完全由雜訊決定。lab 的 Khan 資料就是極端例子:n = 63 而 p = 2308,訓練誤差輕鬆變成 0,「這並不令人驚訝」。

所以實務上幾乎沒有人用純粹的最大邊界分類器。真正在用的是加了正則化的軟邊界版本,而且那個調整參數要靠交叉驗證選。

QUIZ · 最大邊界

在最大邊界分類器裡,把一個支持向量的點往遠離邊界的方向移動一小段,解會怎麼變?

(A) 完全不變。它對應的限制式本來就是鬆的,移動之後更鬆,一樣不影響最佳解
(B) 會稍微改變,因為目標函數是所有點的距離總和
(C) 邊界方向不變,但 β₀ 會微調,因為資料的重心動了
PART 02 · 軟邊界與 C

不能完全分開時:允許犯錯,用 C 決定容忍度 ISLP §9.2講義 09 · p.12–23

上一節結尾的兩個問題要一起解決。第一個是資料常常根本分不開 (講義第 10 頁:除非 n < p,通常都分不開),這時 M > 0 的解不存在, 整個最佳化問題沒有答案。第二個是就算分得開,硬要分開也可能是壞主意 ——ISLP 圖 9.5 只加一個點就讓超平面大幅轉向,margin 縮到極窄。

解法是把「分開」的定義放鬆:允許少數點跑到 margin 錯的一側, 甚至跑到超平面錯的一側。換來的是兩件 ISLP 明列的好處—— 對單一觀測值更穩健,以及大多數點分得更好。 這個分類器叫支持向量分類器,也叫軟邊界分類器 (margin 之所以「軟」,就是因為它可以被違反)。

$$\begin{aligned} &\underset{\beta_0,\dots,\beta_p,\,\epsilon_1,\dots,\epsilon_n,\,M}{\text{maximize}} \quad M \\ &\text{subject to} \quad \sum_{j=1}^{p} \beta_j^2 = 1, \\ &\qquad\qquad\quad\; y_i\left(\beta_0 + \beta_1 x_{i1} + \cdots + \beta_p x_{ip}\right) \ge M\left(1 - \epsilon_i\right), \\ &\qquad\qquad\quad\; \epsilon_i \ge 0, \quad \sum_{i=1}^{n} \epsilon_i \le C \end{aligned}$$

新東西是鬆弛變數(slack variable)$\epsilon_i$:它記錄第 i 筆 相對於 margin 與超平面的位置。三種狀態要分清楚:

εᵢ 的值這一筆在哪裡是支持向量嗎分類正確嗎
εᵢ = 0在 margin 正確的一側(或剛好在 margin 上)只有「剛好在 margin 上」的算
0 < εᵢ ≤ 1違反了 margin,但還在超平面正確的一側
εᵢ > 1跑到超平面錯的一側

然後是 $\sum_i \epsilon_i \le C$ 這一條。ISLP 把 C 說成 「margin 可以被違反多少的預算」:C = 0 時沒有預算, 所有 $\epsilon_i$ 必須是 0,整個問題退回最大邊界超平面; C 愈大,愈容忍違反,margin 就愈寬。這裡有一個大坑,先講清楚:

ISLP 的 C 與 scikit-learn 的 C 方向完全相反 ISLP 式 9.15 的 C 是「預算」 ——違反量的總和上限。C 大 → 容忍多 → margin 寬 → 支持向量多 → 偏差大變異小。
scikit-learn 的 SVC(C=…) 是「懲罰」 ——目標函數是 ½‖β‖² + C·Σεᵢ,C 是對違反的罰款。C 大 → 罰得重 → 容忍少 → margin 窄 → 支持向量少 → 偏差小變異大。
講義第 18 頁把這件事寫成一行:「C 與 const 成反比」 (const 就是 ISLP 的預算 C)。
所以看到 C 一定要先問是哪一種。下面的元件與 lab 用的都是 sklearn 的 C, 滑桿往右推是「罰得更重、margin 更窄」。
圖表需要連網載入 Chart.js。此圖的重點:sklearn 的 C 從 0.001 加到 100,支持向量個數從 50(全部)一路掉到 27 左右——C 愈大容忍愈少,參與決定邊界的點就愈少。
選資料集、推 C 的滑桿,看邊界、margin 帶與支持向量怎麼變。
sklearn 的 C1
怎麼看 圖 9.7
上圖:是兩類,紅實線是邊界、虛線是 margin 的兩側、淡藍色帶子是 margin 區域。加粗描邊的是支持向量,方框標記的是被錯誤分類(εᵢ > 1)的點。
下圖:同一組資料掃過六個 C,支持向量個數與違反 margin 的點數。
這一格的配適
sklearn 的 C
ISLP 的預算 C 相當於
margin 半寬 1/‖β‖
支持向量個數
違反 margin 的點
被錯誤分類的點
兩組資料在對什麼 BAKED
「不可分開」就是 lab 儲存格 14 那 50 筆。C = 10 時支持向量 29 個(lab 儲存格 22、23),C = 0.1 時 36 個(儲存格 27 的 [18 18])——元件上的數字就是那些數字。
「剛好可分開」是儲存格 41 把兩類推開 1.9 之後的版本。C = 10⁵ 只用 3 個支持向量、C = 0.1 用 12 個,正是 ISLP §9.6.1 講的 three 與 twelve。

偏差與變異在這張圖上看得很清楚。C 小(滑桿左端):margin 寬、支持向量多, 決定邊界的點多,所以變異小、偏差大,配得比較鬆。 C 大(滑桿右端):margin 窄、支持向量少,邊界由少數點決定, 所以偏差小、變異大,配得很緊。C 就是這一章的調整參數, 跟 ridge 的 $\lambda$、樹的 $\alpha$ 是同一種東西,一律靠交叉驗證選。

最重要的性質原封不動地繼承下來,而且更強:只有落在 margin 上、 或違反 margin 的觀測值會影響超平面。嚴格待在正確一側的點, 你把它拖到再遠的地方,分類器完全不變。這些會影響答案的點就是支持向量。

講義完整實作:支持向量是哪幾筆

lab 09 · 取出支持向量(C = 10)
# get indices of support vectors svm_linear.support_ # get number of support vectors for each class svm_linear.n_support_
預期輸出(儲存格 23)
array([15, 14], dtype=int32)

support_ 是支持向量在原始資料裡的索引(儲存格 22 印出 29 個),n_support_ 是每一類各幾個:[15, 14],合起來 29。儲存格 21 用 support_vectors_ 把座標印成表格。50 筆資料裡有 29 筆是支持向量——這份資料重疊得很厲害。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 21、22、23
lab 09 · 換成小的 C:支持向量變多
svm_linear_small = SVC(C=0.1, kernel='linear') svm_linear_small.fit(X, y) fig, ax = subplots(figsize=(8,8)) plot_svm(X, y, svm_linear_small, ax=ax) # get number of support vectors for each class svm_linear_small.n_support_
預期輸出(儲存格 27)
array([18, 18], dtype=int32)

C=0.1 的支持向量變成 [18, 18] = 36 個。lab 的說法是「使用較小的成本參數值,我們獲得更多的支援向量,因為邊界現在更寬」——sklearn 的 C 小 = 罰得輕 = margin 寬,跟 ISLP 的預算 C 剛好相反。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 25、27

講義完整實作:用交叉驗證選 C

lab 09 · GridSearchCV 掃七個 C
kfold = skm.KFold(5, random_state=0, shuffle=True) grid = skm.GridSearchCV(svm_linear, {'C':[0.001,0.01,0.1,1,5,10,100]}, refit=True, cv=kfold, scoring='accuracy') grid.fit(X, y) grid.best_params_ grid.cv_results_[('mean_test_score')]
預期輸出(儲存格 33)
array([0.46, 0.46, 0.72, 0.74, 0.74, 0.74, 0.74])

七個 C 的 5 折交叉驗證準確率是 [0.46, 0.46, 0.72, 0.74, 0.74, 0.74, 0.74]。最佳是 C = 1(儲存格 31 的輸出),但後面四個 C 的準確率完全一樣——這種平台很常見,就挑最簡單(最正則化)的那個,不要假裝 0.74 跟 0.74 有差別。注意 C = 0.001 與 0.01 的準確率只有 0.46,比亂猜還差:罰得太輕,β 被壓到幾乎是 0,分類器整組崩掉。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 31、33
lab 09 · 用選出來的 C 預測測試資料
best_ = grid.best_estimator_ y_test_hat = best_.predict(X_test) confusion_table(y_test_hat, y_test)
預期輸出(儲存格 37)
Truth      -1   1
Predicted        
-1          8   4
 1          2   6

混淆矩陣的對角線是 8 + 6 = 14,20 筆裡對了 14 筆 → 70%。lab 儲存格 39 換成 C=0.001,正確率掉到 60%(幾乎把所有點都判成 +1)。這一頁的每一個混淆矩陣都是 confusion_table(預測, 真實)列是預測、欄是真實,順序跟 sklearn 的 confusion_matrix 相反,看的時候要注意。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 35、37
觀念釐清
Q:C 到底是「容忍度」還是「懲罰」?我每次都搞反。

兩個都對,因為那是兩個不同的 C。記一個口訣:ISLP 的 C 在限制式裡,sklearn 的 C 在目標函數裡。

ISLP(式 9.15):$\sum_i \epsilon_i \le C$。C 站在不等式的右邊,是「你最多可以犯多少規」的預算。預算多 → 犯規多 → margin 寬。C = 0 就是一毛錢都不准犯規,退回最大邊界分類器。

sklearn(等價的 primal 式,講義第 18 頁):$\min \frac12\lVert\beta\rVert^2 + C\sum_i \epsilon_i$。C 站在目標函數裡乘著犯規總量,是罰款單價。單價高 → 沒人敢犯規 → margin 窄。$C \to \infty$ 就是硬邊界。

所以講義寫「C 與 const 成反比」。實務上你摸到的幾乎都是 sklearn 那個,記住「C 大 = 配得緊 = 容易過度配適」就好,跟 ridge 的 λ 剛好反向(λ 大 = 配得鬆)。順便一提,$\lambda$ 在式 9.25 裡的方向與 ISLP 的預算 C 同向。

Q:SVM 需要標準化嗎?

需要,而且比大多數方法更需要。講義第 33 頁講得很直接:「SVM 的演算法不具尺度不變性,所以強烈建議先縮放你的資料」

理由就在這一章的第一句話:SVM 從頭到尾都在算距離內積。一個以「元」為單位的收入變數(範圍幾十萬)和一個以「年」為單位的年齡變數(範圍幾十),在 ‖β‖ 與 margin 裡的權重會差好幾個數量級——收入那一維會完全主導邊界的方向,年齡等於被忽略。RBF 核更嚴重,因為 $\exp(-\gamma \sum_j (x_{ij}-x_{i'j})^2)$ 裡的平方距離會被大尺度的那一維吃光。

做法跟第 5 章一樣:把 StandardScaler 包進 Pipeline,再交給 GridSearchCV,這樣每一折都會用該折的訓練部分重新算平均與標準差,不會洩漏。順帶一提,這也是為什麼 lab 的 Khan 例子用線性核就好——基因表現量本來就在同一個尺度上。

QUIZ · 軟邊界與 C

scikit-learn 裡把 SVC(kernel='linear') 的 C 從 0.1 加到 100,預期會看到什麼?

(A) margin 變窄、支持向量變少、訓練誤差變小,但過度配適的風險上升
(B) margin 變寬、支持向量變多,因為 C 是違反量的預算
(C) margin 不變,只有被判錯的點數會變,因為 margin 由資料的幾何決定
PART 03 · Hinge loss

為什麼只有支持向量會影響答案 ISLP §9.5ESL §12.3.2 · 進階

📑 這一節是延伸:它解釋「為什麼只有支持向量影響答案」背後的損失函數, 是 ISLP §9.5 與 ESL §12.3.2 的內容。第一輪讀可以先跳過,直接去 PART 04 的核技巧; 但如果你想真正弄懂 SVM 跟邏輯斯迴歸的關係,回頭一定要讀這一節。

前面把支持向量分類器寫成一個帶限制式的最佳化問題。ISLP §9.5 給了一個 完全等價、但看起來完全不同的寫法(式 9.25):

$$\underset{\beta_0,\beta_1,\dots,\beta_p}{\text{minimize}} \left\{ \sum_{i=1}^{n} \max\left[0,\; 1 - y_i f(x_i)\right] \; + \; \lambda \sum_{j=1}^{p} \beta_j^2 \right\}$$

這就是全書一直在用的「損失 + 懲罰」格式(式 9.26)。 後面那一項你認得——它就是第 6 章的 ridge 懲罰。前面那一項叫 hinge loss(合頁損失,因為它的圖長得像門的合頁):

$$L\left(X, y, \beta\right) = \sum_{i=1}^{n} \max\left[0,\; 1 - y_i\left(\beta_0 + \beta_1 x_{i1} + \cdots + \beta_p x_{ip}\right)\right]$$
λ 與 C 的對應關係 式 9.25 的 λ 大 → β 被壓得小 → margin 寬 → 容忍更多違反, 所以 λ 大對應 ISLP 的預算 C 大(也就是 sklearn 的 C 小)。 ISLP 原文:「a small value of λ in (9.25) amounts to a small value of C in (9.15)」。
注意腳註裡的一句話:在這個 hinge + 懲罰的寫法下,margin 固定對應到數值 1, 而 margin 的實際寬度由 √Σβⱼ² 決定。所以「調 λ」跟「調 margin 寬度」是同一件事。

現在看那條曲線。橫軸是 $y_i f(x_i)$——分對了是正的,愈大愈篤定;分錯了是負的。

圖表需要連網載入 Chart.js。此圖的重點:hinge loss 在 y·f(x) ≥ 1 之後完全等於 0,邏輯斯損失則永遠大於 0(只是很小)。這個「完全等於 0」就是支持向量稀疏性的來源。
綠線是 hinge、紅線是邏輯斯。注意綠線在右邊完全貼著 0。
怎麼看這張圖 圖 9.12
綠線是 hinge max(0, 1 − y·f),紅線是邏輯斯損失 log(1 + e^(−y·f))。灰色區帶是 y·f ≥ 1——綠線在那裡貼在 0 上,紅線只是變小但永遠不是 0。其他地方兩條幾乎平行,這就是 ISLP 說「行為相當相似」的意思。
幾個位置的損失
y·f = 2(篤定分對)
y·f = 1(剛好在 margin 上)
y·f = 0(剛好在邊界上)
y·f = −2(篤定分錯)

那個「剛好是 0」是本節的全部重點。一個損失恰好為 0 的點,對目標函數的貢獻是 0, 對它求梯度也是 0——把它從資料裡整筆刪掉,最佳解一模一樣。 所以最佳解只由 $y_i f(x_i) < 1$ 的那些點決定,而那些點正好就是 「落在 margin 上或違反 margin」的觀測值,也就是支持向量。 對照之下,邏輯斯迴歸的損失永遠大於 0,每一筆資料都在(微弱地)拉扯答案, 所以它沒有稀疏性、也沒有支持向量的概念。

按「顯示 0–1 損失」會疊上我們真正想最小化的東西:分錯是 1、分對是 0 的 階梯函數。它既不連續也不凸,沒辦法直接最佳化——所以大家改去最小化它的 凸上界。hinge 與邏輯斯都是這樣的上界,這種替身叫做 代理損失(surrogate loss)。你在圖上會看到兩條曲線都完整地蓋在階梯之上。

講義完整實作:直接對 hinge loss 做隨機梯度下降

lab 09 · SGDClassifier(loss="hinge")
# we create 50 separable points X, Y = make_blobs(n_samples=50, centers=2, random_state=0, cluster_std=0.60) # fit the model clf = SGDClassifier(loss="hinge", alpha=0.01, max_iter=200) clf.fit(X, Y) # plot the line, the points, and the nearest vectors to the plane xx = np.linspace(-1, 5, 10) yy = np.linspace(-1, 5, 10) X1, X2 = np.meshgrid(xx, yy) Z = np.empty(X1.shape) for (i, j), val in np.ndenumerate(X1): x1 = val x2 = X2[i, j] p = clf.decision_function([[x1, x2]]) Z[i, j] = p[0] levels = [-1.0, 0.0, 1.0] linestyles = ["dashed", "solid", "dashed"] colors = "k" plt.contour(X1, X2, Z, levels, colors=colors, linestyles=linestyles) plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Paired, edgecolor="black", s=20) plt.axis("tight") plt.show()

講義第 32 頁的重點:SGDClassifier(loss="hinge") 就是用隨機梯度下降去最小化式 9.25alpha 就是 λ。它不解 QP,所以資料量很大時比 SVC 快得多,代價是解得比較粗。這一格畫的三條等高線 [-1, 0, 1] 就是 margin 的兩側與邊界本身——跟 plot_svm() 畫的是同一件事。順帶一提,講義也提醒 SGD 對特徵尺度很敏感,用它之前更要標準化。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 95
QUIZ · Hinge loss

某一筆觀測值的 y·f(x) = 3。它對式 9.25 那個目標函數的貢獻是多少?把它從訓練資料裡刪掉會發生什麼事?

(A) 貢獻是 0;刪掉它最佳解完全不變(除非刪掉之後別的點的位置關係改變了 margin)
(B) 貢獻是 −2,因為 1 − y·f(x) = −2
(C) 貢獻很小但不是 0,所以刪掉它解會微微改變
PART 04 · 核技巧

不用真的升維也能畫出彎的邊界 ISLP §9.3講義 09 · p.24–33

軟邊界解決了「分不開」,但沒有解決「邊界根本不是直的」。 講義第 19 頁那張圖就是這種情形:一團在中間、一圈在外面, 無論 C 調成多少,一條直線都沒救。

第 7 章遇過一模一樣的問題,答案是特徵擴張(feature expansion): 把 $X_1^2, X_2^2, X_1X_2, X_1^3, \dots$ 加進特徵裡,在放大的空間配線性分類器, 映射回原空間就變成彎的邊界。用二次項的話(ISLP 式 9.16):

$$\beta_0 + \beta_1 X_1 + \beta_2 X_2 + \beta_3 X_1^2 + \beta_4 X_2^2 + \beta_5 X_1 X_2 = 0$$

這在放大的空間裡是線性的,在原空間裡是二次曲線(圓、橢圓、雙曲線)。 問題是維度爆炸得很快:講義第 21 頁做到三次多項式,兩個變數就變成九維; p 個變數做到 d 次是 $\binom{p+d}{d} - 1$ 維。p = 100、d = 3 就已經 17 萬多維, 算不動。

關鍵事實:解與預測只用得到內積 ISLP §9.3.2 揭露一件很漂亮的事: 支持向量分類器的解與預測只需要觀測值之間的內積,用不到觀測值本身。
$$f(x) = \beta_0 + \sum_{i \in S} \alpha_i \langle x, x_i \rangle, \qquad \langle x_i, x_{i'} \rangle = \sum_{j=1}^{p} x_{ij} x_{i'j}$$ 要估 $\alpha_1,\dots,\alpha_n$ 與 $\beta_0$,只要算出所有 $\binom{n}{2}$ 對 訓練觀測值之間的內積就夠了(講義第 23 頁)。
而且 $\alpha_i$ 只有支持向量是非零的,所以那個和式的項數通常遠少於 n。

既然演算法只透過內積接觸資料,那就把每一處內積換成別的東西

$$\langle x_i, x_{i'} \rangle \;\longrightarrow\; K(x_i, x_{i'})$$

$K$ 叫做(kernel),是一個衡量兩筆觀測值有多像的函數。 這就是核技巧(kernel trick):講義第 22 頁一句話說完—— 「我們不需要真的知道 Φ(x),只要在原空間用核函數計算就好」

講義第 24 頁的例子把這件事說得最清楚。取二次映射 $\Phi(x) = (\sqrt{2}\,x_1 x_2,\; x_1^2,\; x_2^2)$,那麼

$$\Phi(a)^{\top} \Phi(b) = 2a_1a_2b_1b_2 + a_1^2b_1^2 + a_2^2b_2^2 = \left(a_1b_1 + a_2b_2\right)^2 = \left(a^{\top} b\right)^2$$

左邊要先算兩個三維向量再做內積;右邊只要在原本的二維空間做一次內積再平方。 兩者完全相等。維度愈高這個省法愈划算;RBF 核對應的特徵空間是無限維的, 本來就不可能真的走進去算。

選模式後按「開始」。一維的點會被抬到二維,然後一條直線就分開了。
怎麼玩 LIVE + BAKED
「一維 → 二維」:按 ▶ 看點被抬到 (x, x²)。一維上紅色被藍色夾住、一個門檻切不開;抬到二維後一條水平線就分開了;映射回一維就變成兩個門檻。
「同心圓 → 二次核」:lab 儲存格 52 的真實資料,填色是二次核 SVM 的決策區域。
核技巧的三步 CODE
原空間分不開 映射 φ:x → (x, x²) 在新空間配線性超平面 映射回去 → 彎的邊界 核技巧:跳過第 2、3 步, 直接算 K(x, x′) 就好
狀態
目前的空間
需要幾維
線性分得開嗎
支持向量個數
內圈的 x₁²+x₂² 最大
外圈的 x₁²+x₂² 最小

講義完整實作:手寫一個二次核,跟「先映射再配線性」比對

lab 09 · 特徵映射 vs 自訂核(同心圓資料)
def feature_map_1(X): return np.asarray((np.sqrt(2)*X[:,0]*X[:,1], X[:,0]**2, X[:,1]**2)).T def my_kernel_1(X,Y): return np.dot(feature_map_1(X),feature_map_1(Y).T ) ## Reference https://xavierbourretsicotte.github.io/Kernel_特徵_map.html X, y = make_circles(100, factor=.1, noise=.1, random_state = 0) Z = feature_map_1(X) #2D scatter plot fig = plt.figure(figsize = (16,8)) ax = fig.add_subplot(1, 2, 1) ax.scatter(X[:,0], X[:,1], c = y, cmap = 'viridis') ax.set_xlabel('$x_1$') ax.set_ylabel('$x_2$') ax.set_title('Original data') #3D scatter plot ax = fig.add_subplot(1, 2, 2, projection='3d') ax.scatter3D(Z[:,0],Z[:,1], Z[:,2],c = y, cmap = 'viridis' ) #,rstride = 5, cstride = 5, cmap = 'jet', alpha = .4, edgecolor = 'none' ) ax.set_xlabel('$z_1$') ax.set_ylabel('$z_2$') ax.set_zlabel('$z_3$') ax.set_title('Transformed data: ') #SVM using linear kernel with 特徵 map 1 clf = SVC(C = 1, kernel = 'linear') clf.fit(Z, y) w = clf.coef_.flatten() b = clf.intercept_.flatten() print('w=',w,'b=',b) # create x,y xx, yy = np.meshgrid(np.linspace(-1,1), np.linspace(0,1)) # calculate corresponding z # The equation of the separating plane is given by all x in R^3 such that: # np.dot(w, x) + b = 0. We should solve for the last coordinate boundary = (-w[0] * xx - w[1] * yy - b) * 1. /w[2] # plot the surface ax.plot_surface(xx, yy, boundary, alpha = .3) ax.set_ylim(.2,1.2) ax.set_zlim(-.9,1.1) #ax.view_init(0, 260) plt.show()
預期輸出(儲存格 52)
w= [-0.05481854 -2.53191791 -2.52028513] b= [1.14976292]
<Figure size 1600x800 with 2 Axes><figure omitted>

feature_map_1 把二維點送到三維 (√2·x₁x₂, x₁², x₂²),my_kernel_1 則是那個映射的內積——也就是它的核。在三維空間配出來的線性超平面是 w = [-0.0548, -2.5319, -2.5203]b = 1.1498:第一個係數幾乎是 0(交互項沒用),後兩個幾乎相等且為負——它學到的其實就是「x₁² + x₂² 小的是內圈」

來源:Ch09-svm-lab-zh.ipynb · 儲存格 51、52
lab 09 · 兩條路的答案一模一樣
#SVM using kernel 1 - 特徵 map 1 clf2 = SVC(kernel=my_kernel_1) clf2.fit(X, y) # predict on training examples - print accuracy score print('Accuracy score using feature map ',accuracy_score(y, clf2.predict(X))) print('Accuracy score using feature map ',accuracy_score(y, clf.predict(Z)))
預期輸出(儲存格 53)
Accuracy score using feature map  1.0
Accuracy score using feature map  1.0

SVC(kernel=my_kernel_1)(只用核、留在二維)與 SVC(kernel='linear').fit(Z, y)(真的升到三維)訓練準確率都是 1.0這就是核技巧的全部意思:兩條路數學上等價,但右邊那條不需要把 Φ(x) 算出來。儲存格 54 把決策區域畫出來,在原空間看是一個圓。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 53、54

常用的核有三個(講義第 40 頁列了各自的優缺點)。線性核就是普通內積, 等於什麼都不做:

$$K(x_i, x_{i'}) = \sum_{j=1}^{p} x_{ij} x_{i'j}$$

d 次多項式核(式 9.22)等於在 d 次多項式的空間裡配線性分類器:

$$K(x_i, x_{i'}) = \left(1 + \sum_{j=1}^{p} x_{ij} x_{i'j}\right)^{d}$$

徑向基核(radial basis kernel,RBF;式 9.24)用距離而不是內積:

$$K(x_i, x_{i'}) = \exp\left(-\gamma \sum_{j=1}^{p} \left(x_{ij} - x_{i'j}\right)^2\right), \qquad \gamma > 0$$

RBF 的行為非常局部:如果測試點 $x^*$ 離訓練點 $x_i$ 很遠, 那個平方距離很大、指數很小、$K(x^*, x_i)$ 幾乎是 0,於是 $x_i$ 在 $f(x^*) = \beta_0 + \sum_{i \in S} \alpha_i K(x^*, x_i)$ 裡幾乎沒有發言權。 只有附近的訓練點會影響一個測試點的預測。γ 就是「附近」有多近。

圖表需要連網載入 Chart.js。此圖的重點:γ 從 0.25 加到 50,訓練錯誤率一路掉到 0,但測試錯誤率先降後升——γ = 50 時訓練幾乎完美而測試最差,這就是過度配適。
推滑桿掃過四組 (C, γ),看決策區域從平滑變成一堆小島。
組合γ = 0.5, C = 1
怎麼看 圖 9.9
上圖:填色是 RBF 核 SVM 的決策區域(烘焙的 40×40 格點),點是訓練資料。推滑桿掃過四組 (C, γ)。看 γ = 50 那一格:邊界縮成一個個包住單點的小島,訓練錯誤率是 0——那不是學到了結構,那是把每個點各自圈起來。
下圖:C = 1 固定,γ 從 0.25 掃到 50 的訓練與測試錯誤率。
這一格的配適
γ
sklearn 的 C
支持向量個數
訓練錯誤率
測試錯誤率
這一組的出處
交叉驗證選出來的是哪一組 BAKED
lab 儲存格 67 用 5 折交叉驗證掃 C ∈ {0.1, 1, 10, 100, 1000} × γ ∈ {0.5, 1, 2, 3, 4},選出 C = 1、γ = 0.5,測試錯誤率 12%(儲存格 69 的混淆矩陣 69/6/6/19)。滑桿最左邊那一格就是它。
γ 也是一個正則化參數
講義第 26 頁:「γ 也是一個正則化參數,過度配適時應該把它調小」。γ 小 → 每個支持向量的影響範圍大 → 邊界平滑 → 偏差大變異小;γ 大 → 影響範圍小 → 邊界破碎 → 偏差小變異大。它跟 C 要一起用網格搜尋調,因為兩者都在控制彈性。

講義完整實作:RBF 核 SVM

lab 09 · 非線性邊界的資料 + RBF 核
X = rng.standard_normal((200, 2)) X[:100] += 2 X[100:150] -= 2 y = np.array([1]*150+[2]*50) (X_train, X_test, y_train, y_test) = skm.train_test_split(X, y, test_size=0.5, random_state=0) svm_rbf = SVC(kernel="rbf", gamma=1, C=1) svm_rbf.fit(X_train, y_train)
預期輸出(儲存格 61)
SVC(C=1, gamma=1)

200 筆資料分成三塊:前 100 筆整體 +2、第 101–150 筆整體 −2、剩下 50 筆留在原地,標籤是 [1]*150 + [2]*50——所以第 2 類被第 1 類從兩邊夾住,邊界必然是非線性的。上面那張圖用的就是這 100 筆訓練資料(test_size=0.5)。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 57、61
lab 09 · 同時調 C 與 γ
kfold = skm.KFold(5, random_state=0, shuffle=True) grid = skm.GridSearchCV(svm_rbf, {'C':[0.1,1,10,100,1000], 'gamma':[0.5,1,2,3,4]}, refit=True, cv=kfold, scoring='accuracy'); grid.fit(X_train, y_train) grid.best_params_
預期輸出(儲存格 67)
{'C': 1, 'gamma': 0.5}

25 組組合裡最好的是 C = 1、γ = 0.5。lab 的補充很重要:「儘管其他幾個值也達到相同的值」——網格搜尋常常有一片平原,別把 best_params_ 當成唯一正確答案。接著儲存格 69 用它預測測試集,混淆矩陣是 69/6/6/19,錯誤率 12%。順帶一提,ISLP 書上印的 Out[24]{'C': 100, 'gamma': 1},跟 lab 實跑不同——這正是「平原上任選一點」的具體證據。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 67、69
觀念釐清
Q:核技巧「不用真的升維」到底是什麼意思?它省掉了什麼?

省掉的是把 Φ(x) 算出來、存起來、在高維空間裡做運算這三件事。

具體看講義第 24 頁那個例子。要做二次擴張,笨方法是:對每一筆資料算出三維向量 $\Phi(x) = (\sqrt2 x_1x_2, x_1^2, x_2^2)$,存成一個 n × 3 的矩陣,再在三維空間裡配 SVC。核方法是:完全不動原始的 n × 2 資料,需要內積的時候就算 $(x_i^\top x_{i'})^2$。兩者的答案數學上完全相同(lab 儲存格 53 實測都是 1.0),但後者永遠留在二維。

二維變三維省不了多少。但 p = 100 做到 d = 3 是 17 萬多維,而 RBF 核對應的特徵空間是無限維的(講義第 26 頁:由 Mercer 定理,確切的 Φ 無法明確寫出)。ISLP 說得很白:那個空間大到「我們本來也不可能在那裡做計算」。核方法讓你使用那個空間,卻永遠不必進去。

要付的代價是:你拿不到 β 了。線性核可以印 coef_ 看哪個變數重要,RBF 核只有 $\alpha_i$ 與支持向量——講義第 40 頁把這列成高斯核的缺點:「神祕(沒有 w)」。可解讀性換來了彈性。

QUIZ · 核技巧

用 RBF 核的 SVM 時,把 γ 從 0.5 調到 50,決策邊界會怎麼變?

(A) 邊界從平滑的曲線變成一個個包住訓練點的小島,訓練誤差趨近 0 但測試誤差變差
(B) 邊界會變得更平滑,因為 γ 是核的平滑參數
(C) 邊界不變,只有支持向量的個數會變,因為 γ 只影響核值的大小
PART 05 · 多類別

OVO 與 OVA:兩類的方法怎麼推廣 ISLP §9.4講義 09 · p.34–36

到這裡整章都在講兩類。K > 2 怎麼辦?ISLP §9.4 的答案有點掃興: 分離超平面這個概念本身沒辦法自然地推廣到多類別。 很多人提過各種做法,但實務上活下來的只有兩個,而且都是「把多類別問題拆成一堆兩類問題」。

一對一(one-versus-one,OVO,也叫 all-pairs):配 $\binom{K}{2} = K(K-1)/2$ 個分類器,每個只比較兩個類別 (第 k 類編成 +1、第 k′ 類編成 −1,其餘資料完全不用)。 測試點交給每一個分類器投一票,得票最多的類別勝出

一對其餘(one-versus-all,OVA,也叫 one-versus-rest):配 K 個分類器, 第 k 個把第 k 類編成 +1、其餘 K − 1 類全部編成 −1。 測試點指派給 $f_k(x^*) = \beta_{0k} + \beta_{1k}x_1^* + \cdots + \beta_{pk}x_p^*$ 最大的那一類——因為那代表最有信心。

兩個關鍵差別 ① 分類器的個數:OVO 是 K(K−1)/2,OVA 是 K。 K = 3 時兩者都是 3(所以下面的元件看不到個數差別);K = 10 時是 45 對 10
② 每個分類器看到什麼:OVO 的每個分類器只吃兩類的資料, 問題小、類別平衡、通常分得開。OVA 的每個分類器要面對一個把好幾類混在一起的 「其餘」——樣本不平衡,而且那一團的形狀可能根本不是一片超平面切得開的。
ISLP 的建議:K 不太大就用 OVO(講義第 29 頁同樣的結論)。
按按鈕切換 OVO 與 OVA,看兩種規則把平面切成什麼形狀。
怎麼玩
三類資料,按前兩個按鈕切換 OVO 與 OVA:填色是決策區域,三條虛線是那三個分類器的邊界。K = 3 時兩邊都是 3 個分類器,所以要看的不是個數,是它們把平面切成什麼形狀
「疊上不一致」會用橘色蓋住兩種規則答案不同的格子——那些地方一個測試點的預測類別會因為你選 OVO 還是 OVA 而改變。
目前的設定
方法
要訓練幾個分類器
每個分類器用多少資料
決策規則
兩種規則不一致的格子
OVO 三票平手的格子
K 變大以後要訓練幾個 HYBRID
KOVOOVA
333
464
104510
1004950100
OVO 是 K 的平方級。但 OVO 的每個問題都小得多,總計算量常常還是它划算。

兩件事值得看清楚。第一,兩種規則真的會給出不同答案: 在這組資料上,格點裡大約 7% 的位置,一個測試點的預測類別會因為你選 OVO 還是 OVA 而改變。 差異來自 OVA 的每個分類器都被迫把「其餘兩類」當成一團來切,而 OVO 的每個分類器只處理兩類。

第二,OVO 的投票在理論上可能平手——三個分類器各投一票給不同的類別, 誰都沒過半,投票規則本身給不出答案。但你在這組資料上看到的平手格子是 0 格:三團分得很開時,三條成對邊界幾乎就是三個間隙的垂直平分線, 而三角形三邊的垂直平分線會交於同一點(外心),所以平手區幾乎退化成一個點。 平手要變成真問題,得等到類別重疊或 K 變大的時候。 實作上 libsvm 用 decision_function 的加總去打破平手, 但那是實作細節,不是投票規則給的答案。

關於 decision_function_shape 的一個常見誤解 SVCdecision_function_shape 只改變 decision_function() 輸出的形狀,不改變底層的訓練方式libsvm 一律用 OVO 訓練 K(K−1)/2 個分類器;設成 'ovr' 時 sklearn 是把 OVO 的結果換算成 K 個分數。 真的想要「訓練 K 個一對其餘分類器」,要用 OneVsRestClassifier(SVC(...)) 包起來—— 上面元件的 OVA 那三條線就是這樣配出來的。

元件裡的三條線都是真的 SVC(kernel='linear', C=1) 配適結果 (OVO 的三個只吃兩類的資料、OVA 的三個吃全部資料),係數烘焙進頁面; 投票與取最大則由前端在格點上即時算,所以切換是瞬間的。 資料是另外造的三團 blob,沒有沿用 lab 儲存格 82 那一組——那組是環狀的非線性結構, 線性的成對配適在上面沒有意義(lab 自己用的也是 RBF 核)。

一對一(OVO)一對其餘(OVA)
分類器個數K(K−1)/2K
每個分類器的訓練資料只用相關的兩類全部 n 筆
類別平衡好(兩類各自的量)差(1 對 K−1)
決策規則投票,最多票者勝取 f_k(x*) 最大者
模糊情形可能平手(票數相同)可能兩個 f 都很小
sklearn 的設定decision_function_shape='ovo'decision_function_shape='ovr'
ISLP 的建議K 不太大就用這個K 很大時考慮

講義完整實作:四類的基因表現資料

lab 09 · Khan 資料(4 類、p = 2308、n = 63)
Khan = load_data('Khan') Khan['xtrain'].shape, Khan['xtest'].shape khan_linear = SVC(kernel='linear', C=10) khan_linear.fit(Khan['xtrain'], Khan['ytrain']) confusion_table(khan_linear.predict(Khan['xtrain']), Khan['ytrain']) confusion_table(khan_linear.predict(Khan['xtest']), Khan['ytest'])
預期輸出(儲存格 92)
Truth      1  2  3  4
Predicted            
1          3  0  0  0
2          0  6  2  0
3          0  0  4  0
4          0  0  0  5

p = 2308 遠大於 n = 63,所以 lab 直接說「這表示我們應該使用線性核,因為多項式或徑向基核產生的額外靈活性是不必要的」——維度已經夠高了,隨便都找得到分得開的超平面。訓練混淆矩陣(儲存格 90)完全對角、零訓練誤差,「這並不令人驚訝」;測試集 20 筆只錯 2 筆。這一格用的是 SVC 的預設多類別機制,也就是 OVO。lab 儲存格 84 則用 decision_function_shape='ovo' 明確指定,在三類的二維資料上把決策區域畫出來。

來源:Ch09-svm-lab-zh.ipynb · 儲存格 88、90、92
QUIZ · 多類別

K = 10 個類別。OVO 與 OVA 各要訓練幾個二元分類器?

(A) OVO 要 45 個(10×9/2),OVA 要 10 個
(B) 兩者都要 10 個,只是決策規則不同(投票 vs 取最大)
(C) OVO 要 10 個,OVA 要 45 個
PART 06 · 與邏輯斯迴歸的關係

兩個損失函數其實很像,差別在哪 ISLP §9.5講義 09 · p.37–39

SVM 在 1990 年代中期出場時很轟動:找一片盡量分開資料的超平面、允許少數違反、 用核擴張特徵空間——這套說法看起來跟邏輯斯迴歸、LDA 完全是兩個世界的東西。 ISLP §9.5 的任務就是把這個神祕感拆掉。

拆解的關鍵就是 PART 03 那個式子。支持向量分類器等價於

$$\underset{\beta}{\text{minimize}} \left\{ \underbrace{\sum_{i=1}^{n} \max\left[0, 1 - y_i f(x_i)\right]}_{\text{hinge loss}} + \lambda \underbrace{\sum_{j=1}^{p} \beta_j^2}_{\text{ridge 懲罰}} \right\}$$

而加了 ridge 懲罰的邏輯斯迴歸是

$$\underset{\beta}{\text{minimize}} \left\{ \sum_{i=1}^{n} \log\left(1 + e^{-y_i f(x_i)}\right) + \lambda \sum_{j=1}^{p} \beta_j^2 \right\}$$

只有損失函數換了一項,其他一模一樣。而 PART 03 的圖顯示這兩個損失 除了「hinge 在右邊剛好是 0」之外幾乎平行。所以 ISLP 的結論不意外: 「邏輯斯迴歸與支持向量分類器常常給出非常相似的結果」

支持向量分類器 / SVM邏輯斯迴歸LDA
損失函數hinge:max(0, 1 − y·f)log(1 + e^(−y·f))(不是損失,是概似)
在 y·f ≥ 1 時的損失恰好 0很小但 > 0
解由誰決定只有支持向量全部資料(遠處權重極小)各類的平均與共變異
機率輸出沒有(要另外校準)天生就有
類別分得很開時表現較好係數會發散、不穩定表現較好
類別重疊很多時還可以通常較好還可以
非線性邊界核,很成熟可以用核,但少見且較貴同左
p ≫ n線性核 + 正則化,很強要正則化會退化
怎麼選?講義第 31 頁的四句話 ① 類別(幾乎)可分開時,SVC 比邏輯斯迴歸好,LDA 也好。 邏輯斯迴歸在完全可分的資料上會讓係數跑到無限大(最大概似不存在),必須靠懲罰救。
② 類別重疊很多時,加了 ridge 懲罰的邏輯斯迴歸與 SVC 非常相似。 這時選哪個多半只是習慣問題。
③ 想要機率就用邏輯斯迴歸。SVM 只吐 f(x) 的符號; 想要機率得再套 Platt scaling(SVC(probability=True)), 那是額外做一次交叉驗證去配一個 sigmoid,慢而且不見得校準得好。
④ 非線性邊界時,核 SVM 是最普及的選擇。 但要記得:核不是 SVM 的專利,邏輯斯迴歸與 LDA 也能用核,只是計算比較貴、歷史上比較少人做。

ISLP 這一節結尾還提了一個延伸:支持向量迴歸 (support vector regression)。最小平方法讓每一筆殘差都計入損失; 支持向量迴歸只讓絕對值超過某個正常數的殘差計入—— 等於把 margin 的概念搬到迴歸,落在「管子」裡的點對解沒有貢獻, 稀疏性因此保留下來。sklearn.svm.SVR 就是它。

講義完整實作:用核近似 + SGD 逼近核 SVM

lab 09 · RBFSampler + SGDClassifier
np.random.seed(1) X = np.random.normal(size=400).reshape(200, 2) X[0:100, :] += 2 X[100:150, :] -= 2 y = np.concatenate((np.full(150, 1, dtype=np.int64), np.full(50, 2, dtype=np.int64))) X = np.concatenate((X, np.random.normal(size=100).reshape(50, 2))) y = np.concatenate((y, np.full(50, 0, dtype=np.int64))) X[y == 0, 1] += 2 plt.scatter(X[:, 0], X[:, 1], c=y+1, cmap='Spectral'); rbf_feature = RBFSampler(gamma=1, random_state=1) X_features = rbf_feature.fit_transform(X) clf = SGDClassifier(loss="hinge", alpha=0.01, max_iter=200) clf.fit(X_features, y) clf.score(X_features, y)
預期輸出(儲存格 97)
0.84

RBFSampler 用隨機傅立葉特徵近似 RBF 核:它真的把資料映射到一個有限維的空間,讓內積近似 K(x, x′),然後就可以用便宜的線性方法(這裡是 hinge loss 的 SGD)。訓練準確率 0.84 比不上真正的 SVC(kernel='rbf'),但它是 O(n) 的,資料上百萬筆時 SVC 根本跑不動。講義第 32 頁:「大規模問題就用 SGDClassifier 配 hinge loss」

來源:Ch09-svm-lab-zh.ipynb · 儲存格 96、97
觀念釐清
Q:SVM 與邏輯斯迴歸該選哪一個?

先問一句話:你要不要機率?要就選邏輯斯迴歸,討論結束。風險分數、期望成本決策、要調閾值、要跟別的模型做集成——全部需要校準過的機率,SVM 給不了(probability=True 是事後貼上去的,還會慢好幾倍)。

不要機率的話,看類別分得多開。分得很開 → SVM:邏輯斯迴歸在完全可分的資料上係數會發散,而 SVM 的 margin 概念天生就處理這種情形。重疊很多 → 邏輯斯迴歸:這時 hinge 的稀疏性沒什麼好處,而邏輯斯迴歸的機率輸出與可解讀性是白拿的。重疊的中間地帶兩者結果會很像,因為損失函數很像。

另外兩個實務考量。n 很大SVC 是 O(n²)~O(n³) 的,幾萬筆以上就開始痛,這時用 LinearSVCSGDClassifier 或邏輯斯迴歸。要看變數重要度:線性核的 coef_ 可以看,RBF 核沒有 β 可看(講義第 40 頁列為高斯核的缺點:「神祕」)。

Q:既然核不是 SVM 的專利,為什麼「核」幾乎都跟 SVM 一起出現?

ISLP 明確回答了:「歷史原因」。任何只透過內積接觸資料的方法都能核化(核邏輯斯迴歸、核 PCA、核嶺迴歸都存在),但核在 SVM 的脈絡裡遠比在其他地方普及。

不過也有技術上的理由。SVM 的解是稀疏的——只有支持向量的 $\alpha_i$ 非零,所以預測時只要算 |S| 個核值。核邏輯斯迴歸沒有這個性質:每一筆訓練資料的權重都非零,預測一個點要算 n 個核值,訓練還要處理一個 n × n 的核矩陣。n 稍微大一點就吃不消。hinge loss 那段「剛好等於 0」,換來的正是核方法在計算上的可行性。

QUIZ · SVM vs 邏輯斯迴歸

一份資料的兩個類別重疊得相當厲害,而且你需要輸出每一筆的違約機率。該選哪個?

(A) 邏輯斯迴歸(加 ridge 懲罰):重疊時兩者表現相近,而機率輸出是它天生就有的
(B) SVM 配 RBF 核:它比較有彈性,機率可以用 SVC(probability=True) 拿到
(C) SVM 配線性核:類別重疊正是 hinge loss 的強項,因為它會忽略遠處的點
EXERCISES · 練習

動手驗證:ISLP 第 9 章精選題 ISLP §9.7 習題

下面幾題取自 ISLP §9.7 的課後習題,題號都對得回課本。先自己想過再點選項; 每個選項——包含錯的——都寫了為什麼。想看完整解答再對照下面3個站。

EXERCISE 1 · ISLP 9.7 第 1 題(a)

課本第 1 題要你畫出超平面 $1 + 3X_1 - X_2 = 0$,並標出兩側。點 $(0, 0)$ 落在哪一側?

(A) 落在 1 + 3X₁ − X₂ > 0 的那一側,因為代進去得到 1
(B) 落在線上,因為原點滿足任何過原點的超平面方程式
(C) 落在 < 0 的那一側,因為 −X₂ 這一項是負的
EXERCISE 2 · ISLP 9.7 第 2 題(c)(d)

課本第 2 題的分類器規則是:$(1+X_1)^2 + (2-X_2)^2 > 4$ 判成藍色,否則紅色。四個點 $(0,0)$、$(-1,1)$、$(2,2)$、$(3,8)$ 分別是什麼顏色?而 (d) 小題問這個邊界算不算線性——答案是什麼?

(A) 藍、紅、藍、藍;(d) 對 X₁、X₂ 不是線性,但對 X₁、X₁²、X₂、X₂² 是線性的
(B) 藍、紅、藍、藍;(d) 不是線性,因為出現了平方項,所以怎麼看都是非線性的
(C) 紅、紅、藍、藍;(d) 對 X₁、X₁²、X₂、X₂² 是線性的
EXERCISE 3 · ISLP 9.7 第 3 題(e)(f)

課本第 3 題的 7 個點:紅色是 (3,4)、(2,2)、(4,4)、(1,4),藍色是 (2,1)、(4,3)、(4,1)。最佳分離超平面是 $X_2 = X_1 - 0.5$。哪幾筆是支持向量?(f) 小題問「第 7 筆 (4,1) 稍微移動會不會影響超平面」——為什麼?

(A) 支持向量是第 2、3、5、6 筆;第 7 筆不是支持向量,離 margin 很遠,稍微移動不影響
(B) 支持向量是全部 7 筆,因為最大邊界問題的每一條限制式都要滿足
(C) 支持向量是第 1、4、7 筆(離邊界最遠的那些),第 7 筆移動會影響超平面
EXERCISE 4 · ISLP 9.7 第 6 題

課本第 6 題要你造一組「剛好可以線性分開」的資料,然後比較大 C 與小 C。課本的主張是什麼,理由是什麼?(這裡的 C 是 sklearn 的 C)

(A) 小 C(會錯分幾筆訓練資料)在測試資料上可能贏過大 C,因為大 C 的邊界只由極少數點決定、變異大
(B) 大 C 一定更好,因為它的訓練誤差是 0,而訓練誤差 0 表示模型完全學會了資料
(C) 兩者測試誤差會一樣,因為資料可以線性分開,最佳超平面唯一
REFERENCE · 總覽

支持向量機速查表 ISLP Ch.9

考前把這一頁掃過去就好。

三個層次:一次看清楚它們的差別

最大邊界分類器支持向量分類器支持向量機(SVM)
ISLP 節次§9.1.3–9.1.4§9.2§9.3
資料要可分開嗎,不可分就沒有解不用不用
邊界形狀直的直的可以彎
允許違反 margin不允許允許(用 C 控制)允許
調整參數沒有CC + 核的參數(d 或 γ)
解由誰決定支持向量支持向量支持向量
sklearnSVC(kernel='linear', C=1e5)SVC(kernel='linear', C=…)SVC(kernel='rbf'/'poly', …)

三種核

式子調的參數優點缺點
線性Σⱼ xᵢⱼxᵢ′ⱼ只有 C快、可以看 coef_、不易過度配適;p ≫ n 的首選邊界只能是直的
d 次多項式(1 + Σⱼ xᵢⱼxᵢ′ⱼ)^dC、d比線性有彈性,d 的意義很具體d 大時數值不穩;實務只用小 d
徑向基(RBF)exp(−γ Σⱼ (xᵢⱼ−xᵢ′ⱼ)²)C、γ最有彈性、有界(數值穩)、只有一個核參數沒有 β 可解讀、比線性慢、容易過度配適

lab 上的實測數字(全部逐字取自 Ch09-svm-lab-zh.ipynb

情境設定支持向量結果出處
50 筆·不可分開C = 1029(15 + 14)coef_ = [1.173, 0.773]儲存格 22、23、29
50 筆·不可分開C = 0.136(18 + 18)margin 更寬儲存格 27
50 筆·不可分開CV 選 Cbest C = 1,準確率 0.74儲存格 31、33
50 筆·不可分開C = 1(測試)70% 正確(8 + 6 / 20)儲存格 37
50 筆·不可分開C = 0.001(測試)60% 正確儲存格 39
50 筆·可分開C = 10⁵3訓練誤差 0,margin 極窄儲存格 43–46
50 筆·可分開C = 0.112訓練誤差 0,margin 寬得多儲存格 47、48
同心圓 100 筆二次核訓練準確率 1.0儲存格 52、53
200 筆·非線性RBF, CV 選 C 與 γbest C = 1、γ = 0.5,測試錯誤 12%儲存格 67、69
Khan(4 類)線性核, C = 10訓練誤差 0;測試 20 筆錯 2 筆儲存格 88、90、92
200 筆·核近似RBFSampler + SGD訓練準確率 0.84儲存格 97

公式速查

名稱式子備註
超平面$\beta_0 + \beta^{\top}X = 0$式 9.1–9.2
點到超平面的距離$|f(x)| / \lVert\beta\rVert$講義第 6 頁
分離超平面的條件$y_i f(x_i) > 0 \;\forall i$式 9.8
最大邊界max M s.t. $\sum\beta_j^2=1$, $y_i f(x_i) \ge M$式 9.9–9.11
軟邊界多了 $y_i f(x_i) \ge M(1-\epsilon_i)$, $\sum\epsilon_i \le C$式 9.12–9.15
對偶問題max $\sum_i\alpha_i - \frac12\sum_i\sum_{i'}\alpha_i\alpha_{i'}y_iy_{i'}\langle x_i,x_{i'}\rangle$講義第 17–18 頁;只出現內積
線性核的解$f(x) = \beta_0 + \sum_{i \in S}\alpha_i\langle x,x_i\rangle$式 9.19;S 是支持向量的索引集
核化的解$f(x) = \beta_0 + \sum_{i \in S}\alpha_i K(x,x_i)$式 9.23
多項式核$\left(1+\sum_j x_{ij}x_{i'j}\right)^{d}$式 9.22
徑向基核$\exp\left(-\gamma\sum_j (x_{ij}-x_{i'j})^2\right)$式 9.24
損失 + 懲罰min $\sum_i \max[0, 1-y_if(x_i)] + \lambda\sum_j\beta_j^2$式 9.25–9.26;λ 大 ↔ 預算 C 大
三個一定要記住的觀念 1. 解只依賴支持向量。 嚴格待在 margin 正確一側的點對答案毫無貢獻——因為 hinge loss 在那裡恰好是 0。 這給了 SVM 對遠處離群值的穩健性,也給了核方法計算上的可行性。
2. ISLP 的 C 與 scikit-learn 的 C 方向相反。 ISLP 的 C 是違反量的預算(C 大 → margin 寬); sklearn 的 C 是違反的懲罰(C 大 → margin 窄)。 講義第 18 頁:兩者成反比。
3. 核技巧不是「升維」,是「跳過升維」。 演算法只透過內積接觸資料,所以把內積換成 K(x, x′) 就換掉了整個特徵空間, 而 Φ(x) 從頭到尾不必算出來。RBF 核的特徵空間是無限維的,本來也算不出來。
順手提醒 SVM 一定要先標準化(講義第 33 頁:演算法不具尺度不變性), 而且要包進 Pipeline 才不會洩漏。C 與核參數要一起用網格搜尋調, 兩者都在控制彈性。SVM 不吐機率,需要機率就用邏輯斯迴歸, 或接受 probability=True 的額外成本。

本頁「預期輸出」逐字取自課程 lab notebook(老師在課程環境實跑);圖表用的烘焙資料由 tools/frames/ 在固定種子下產生,環境為 numpy 1.24.4 · pandas 2.3.2 · scikit-learn 1.6.1 · scipy 1.13.1 · statsmodels 0.14.2 · ISLP 0.4.0 · pygam 0.10.1。每張卡下方的「來源」標了 lab 的儲存格編號,可以直接回去對。

CARDS · 關鍵詞彙卡

關鍵詞彙卡:點卡片翻面 課程題庫 · 26 張

詞彙卡取自本章講義與 ISLP 第 9 章,正面是中文術語(附英文原名)。 先看正面、心裡默想定義,再翻面對答案;洗牌後再過一輪,直到每張都能不看答案講出來。