想像你是武俠小說中的大俠,面對不同的對手,你會選擇不同的武器:長劍(直線攻擊)、雙節棍(非線性)、暗器(簡單快速)……這正是本章的核心問題:在分類問題中,LDA、QDA、Naive Bayes、邏輯迴歸和 KNN,這五種方法各有什麼長短?
本節是第四章的「大結局」——把前面所有方法攤在陽光下,從數學本質和實驗數據兩個角度,看看誰在什麼情境下勝出。這就像武林大會:不是比誰的招式花俏,而是比誰在實戰中最管用。
所有分類方法的核心決策邏輯可以統一寫成:把觀察值分配給使 log-odds 最大的類別。對於 \(K\) 個類別,以類別 \(K\) 為基準,計算:
這個式子的巧妙之處在於:不同方法只是用不同方式去逼近同一個目標。就像大家都想去台北,有人搭高鐵(參數法)、有人騎單車(非參數法),路線不同,目的地相同。
LDA 假設每個類別內的 \(X\) 服從多變量常態分布,且所有類別共享同一個共變異數矩陣 \(\Sigma\)。代入貝氏定理後:
QDA 放寬了「相同共變異數」的假設,每個類別有自己的 \(\Sigma_k\)。這讓 log-odds 中出現了 \(x_j x_l\) 的交互項:
LDA 是 QDA 在 \(c_{kjl}=0\) 時的特例——這正是「所有類別共用 \(\Sigma\)」的數學表現。
Naive Bayes 假設各特徵條件獨立:\(f_k(x) = \prod_j f_{kj}(x_j)\)。代入後得到:
其中 \(g_{kj}(x_j)\) 可以是任何函數——不一定要線性!這讓 Naive Bayes 極度靈活,但代價是:只能加法、不能乘法(無交互項)。
| 關係 | 說明 |
|---|---|
| LDA ⊂ QDA | LDA 是 QDA 在 \(c_{kjl}=0\) 時的特例(共變異數矩陣相等) |
| LDA ⊂ Naive Bayes | 若 Naive Bayes 的 \(g_{kj}(x_j)\) 取線性形式,就是 LDA(這點非常不直覺!) |
| Naive Bayes = LDA(特例) | 當 \(f_{kj}(x_j)\) 是單變量高斯 \(\mathcal{N}(\mu_{kj}, \sigma_j^2)\),Naive Bayes 等價於對角 \(\Sigma\) 的 LDA |
| QDA ⟂ Naive Bayes | 兩者互不包含:QDA 有交互項但形式受限;Naive Bayes 無交互項但函數自由 |
多類別邏輯迴歸的形式是:
這和 LDA 的 (4.32) 形式完全一樣!差別在於 參數估計方式:
KNN 不寫公式、不做假設——它只問:「離我最近的 K 個鄰居投誰?」這是純非參數方法:
這一段「形式相同、估計方式不同」的洞察,直接對應到 AI agent 的模型選擇策略:LDA vs 邏輯迴歸的取捨,本質上就是「模型假設強 → 資料少也好用」vs「模型假設弱 → 需要更多資料」。在 Hermes 的子 agent 調度中,當任務的特徵分布已知(近似常態),可以走 LDA 式的預設路徑;當任務分布未知,應走邏輯迴歸式的資料驅動路徑。這正是 subagent-performance-management skill 中「根據任務類型動態選擇模型」的統計學基礎。
理論歸理論,戰場見真章。ISLP 作者設計了六個模擬場景,每種場景生成 100 組訓練資料,計算測試錯誤率。關鍵問題:在什麼條件下,哪種方法表現最好?
所有場景都是 二元分類、\(p=2\) 個連續預測變數。三種線性邊界場景 + 三種非線性邊界場景。KNN 用兩種設定:\(K=1\) 和交叉驗證選 \(K\)。
| 場景 | 設定 | 🏆 優勝者 | 💀 落敗者 | 關鍵教訓 |
|---|---|---|---|---|
| 場景 1 | 每類 \(n=20\),不相關常態,不同均值 | LDA、邏輯迴歸 | KNN(變異數代價)、QDA(過度靈活) | 當 LDA 假設完全成立時,簡單即是最佳 |
| 場景 2 | 同場景 1,但兩變數相關 \(\rho=-0.5\) | LDA、邏輯迴歸 | Naive Bayes(獨立性假設被打破!) | Naive Bayes 的「Naive」不是說說而已——相關性一出現就崩 |
| 場景 3 | 每類 \(n=50\),t 分布(厚尾),相關 | 邏輯迴歸 | LDA(非常態)、QDA(非常態+過度靈活) | 當常態假設被打破,邏輯迴歸比 LDA 更穩健 |
| 場景 | 設定 | 🏆 優勝者 | 💀 落敗者 | 關鍵教訓 |
|---|---|---|---|---|
| 場景 4 | 常態,類 1 相關 \(\rho=0.5\),類 2 相關 \(\rho=-0.5\) (QDA 假設成立) |
QDA | Naive Bayes(獨立性被打破) | 當 QDA 的假設成立時,它就是王者 |
| 場景 5 | 不相關常態,但 Y 來自複雜非線性函數 | KNN-CV | KNN-1(未調參數的 KNN 最差!) | 非參數方法需要正確的平滑度;\(K=1\) 過擬合,變異數爆炸 |
| 場景 6 | 對角共變異數(獨立),每類僅 \(n=6\) | Naive Bayes | LDA、邏輯迴歸(邊界非線性)、QDA(小樣本估計不穩)、KNN(樣本太小) | 小樣本 + 獨立特徵 = Naive Bayes 的甜蜜點 |
| 方法 | 決策邊界 | 核心假設 | 參數數量 | 最佳情境 | 脆弱點 |
|---|---|---|---|---|---|
| 邏輯迴歸 | 線性 | 無 X 分布假設 | 少 | 邊界線性 + 不確定常態假設 | 邊界高度非線性 |
| LDA | 線性 | 常態 + 共同 Σ | 少 | 假設完全成立時(效率最高) | 非常態、異質共變異數 |
| QDA | 二次 | 常態 + 各類自有 Σ | 中 | 邊界中度非線性 | 非常態、高維度(參數爆炸) |
| Naive Bayes | 靈活(加法) | 條件獨立 | 中 | 小樣本 + 獨立特徵 | 特徵高度相關 |
| KNN | 任意 | 無(純非參數) | 無(但 K 需調) | \(n \gg p\) + 複雜邊界 | 高維度(維度詛咒)、不解釋 |
以下程式碼重現 ISLP §4.5.2 的核心比較邏輯(簡化版,使用 sklearn):
# ============================================
# §4.5 分類方法比較 — ISLP 六大場景摘要
# 基於 ISLP pp.164-166, Figures 4.11-4.12
# ============================================
try:
from google.colab import drive
drive.mount('/content/drive')
DATA_PATH = '/content/drive/MyDrive/ISLP_data/'
except ImportError:
DATA_PATH = '/tmp/'
import numpy as np
import pandas as pd
# ========== ISLP 課本圖 4.11-4.12 的近似錯誤率(從 boxplot 讀取中位數) ==========
# 這些數值反映課本實證研究的结果,供參考比較
data = {
'場景': [
'場景1 (線性,不相關,常態,n=20)',
'場景2 (線性,相關,常態,n=20)',
'場景3 (線性,相關,t分布,n=50)',
'場景4 (非線性,QDA假設,n=50)',
'場景5 (非線性,複雜邏輯,n=50)',
'場景6 (非線性,小樣本,n=6)',
],
'Logistic': [0.30, 0.19, 0.25, 0.35, 0.25, 0.35],
'LDA': [0.30, 0.19, 0.28, 0.36, 0.27, 0.35],
'QDA': [0.35, 0.20, 0.43, 0.30, 0.24, 0.30],
'Naive Bayes': [0.33, 0.27, 0.45, 0.35, 0.24, 0.25],
'KNN-1': [0.42, 0.27, 0.48, 0.37, 0.32, 0.42],
'KNN-CV': [0.37, 0.22, 0.35, 0.34, 0.20, 0.35],
}
df = pd.DataFrame(data).set_index('場景')
print("=" * 60)
print("📊 ISLP §4.5 六大場景分類方法比較")
print(" 數值為近似測試錯誤率(越低越好)")
print("=" * 60)
print(df.round(3))
print("\n🏆 各場景最佳方法:")
for idx, row in df.iterrows():
best_method = row.idxmin()
best_val = row.min()
star = "⭐⭐" if best_val == row.min() else ""
print(f" {idx}: {best_method} ({best_val:.3f})")
print("\n📌 線性邊界場景(1-3):Logistic/LDA 勝出")
print("📌 非線性邊界場景(4-6):QDA / KNN-CV / Naive Bayes 各有所長")
# ========== 快速繪圖:二維決策邊界示意 ==========
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from sklearn.discriminant_analysis import (
LinearDiscriminantAnalysis, QuadraticDiscriminantAnalysis
)
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from sklearn.neighbors import KNeighborsClassifier
def plot_decision_boundary(ax, clf, X, y, title):
"""繪製二元分類決策邊界"""
h = 0.05
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
ax.contourf(xx, yy, Z, alpha=0.3, cmap='coolwarm')
ax.scatter(X[y==0, 0], X[y==0, 1], c='blue', s=20, label='Class 0', alpha=0.7)
ax.scatter(X[y==1, 0], X[y==1, 1], c='red', s=20, label='Class 1', alpha=0.7)
ax.set_title(title, fontsize=10)
ax.set_xlabel('X1'); ax.set_ylabel('X2')
# 生成 QDA 場景資料(非線性邊界)
np.random.seed(42)
n = 80
cov0 = np.array([[1, 0.5], [0.5, 1]])
cov1 = np.array([[1, -0.5], [-0.5, 1]])
X0 = np.random.multivariate_normal([0, 0], cov0, n)
X1 = np.random.multivariate_normal([0, 0], cov1, n)
X = np.vstack([X0, X1])
y = np.hstack([np.zeros(n), np.ones(n)])
classifiers = [
('Logistic', LogisticRegression(max_iter=5000)),
('LDA', LinearDiscriminantAnalysis()),
('QDA', QuadraticDiscriminantAnalysis()),
('Naive Bayes', GaussianNB()),
('KNN (K=5)', KNeighborsClassifier(n_neighbors=5)),
]
fig, axes = plt.subplots(1, 5, figsize=(18, 3.5))
for ax, (name, clf) in zip(axes, classifiers):
clf.fit(X, y)
acc = clf.score(X, y)
plot_decision_boundary(ax, clf, X, y, f'{name}\n(準確率: {acc:.2%})')
plt.suptitle('§4.5 五大分類器決策邊界比較(QDA 場景)',
fontsize=13, fontweight='bold')
plt.tight_layout()
plt.savefig(DATA_PATH + 'islp_ch4_5_boundaries.png', dpi=120, bbox_inches='tight')
plt.show()
print("\n✅ 決策邊界圖已儲存至:", DATA_PATH + "islp_ch4_5_boundaries.png")
詐欺交易比例極低(類別不平衡)、特徵維度高、決策邊界複雜。
推薦:邏輯迴歸(可解釋性:監管需求)或 Naive Bayes(處理高維稀疏特徵,且獨立性假設在文本特徵上合理)。KNN 在此情境維度詛咒嚴重。
樣本少(\(n=20\) 患者)、特徵數中等(\(p=5\) 生物標記)、需要估計機率(非純分類)。
推薦:Naive Bayes(場景 6 的啟示:極小樣本+獨立特徵是最佳情境)或 LDA(若常態假設合理)。深度學習在此情境只會過擬合。
樣本量大(\(n=10^6\))、邊界未知、需要解釋哪些特徵驅動轉換。
推薦:邏輯迴歸(大樣本下效率可接受,且提供清楚的係數解釋——「年齡每增加一歲,購買機率上升 X%」)。若邊界明顯非線性,考慮 QDA。
所有比較的底層邏輯只有一個:偏差與變異數的取捨。
| 方法 | 偏差 | 變異數 | 適用 |
|---|---|---|---|
| LDA / 邏輯迴歸 | 高(線性限制) | 低(參數少) | 邊界線性或樣本少 |
| QDA | 中 | 中 | 中度非線性 |
| Naive Bayes | 中(加法限制) | 低(獨立性降維) | 高維、小樣本、獨立特徵 |
| KNN (K=1) | 極低 | 極高 | 僅 \(n \to \infty\) 時有效 |
| KNN (K 大) | 中 | 中 | \(n \gg p\) |
這張表的結構可以直接對應到 Hermes 的任務路由決策:
這正是 subagent-driven-development 中「根據任務複雜度動態分流」的理論基礎。統計學習的分類方法比較,本質上就是一張 agent 任務路由決策表。