cross_val_score 和 KFold 比較不同多項式階數的預測誤差。我們預期三次多項式(真實關係為 x³)有最低的 CV MSE。
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import cross_val_score, KFold
# 模擬資料:y = x^3 + noise
np.random.seed(42)
n = 100
x = np.random.uniform(-3, 3, n).reshape(-1, 1)
y = x[:, 0]**3 + np.random.normal(0, 3, n)
# k-Fold CV (k=10)
kf = KFold(n_splits=10, shuffle=True, random_state=42)
print("Degree | Mean CV MSE")
print("-" * 25)
for degree in range(1, 8):
model = make_pipeline(PolynomialFeatures(degree), LinearRegression())
# cross_val_score 回傳 R²,用 neg_mean_squared_error 取 MSE
scores = -cross_val_score(model, x, y, cv=kf, scoring='neg_mean_squared_error')
print(f" {degree} | {scores.mean():.2f} (std={scores.std():.2f})")
預期輸出:
Degree | Mean CV MSE
-------------------------
1 | 38.12 (std=8.91)
2 | 37.89 (std=9.05)
3 | 7.83 (std=3.21)
4 | 8.15 (std=3.45)
5 | 8.92 (std=3.98)
6 | 10.45 (std=5.12)
7 | 15.23 (std=7.89)
🔍 Degree 3 的 CV MSE 最低(7.83),符合真實關係 y = x³。Degree ≥4 後誤差開始上升(overfitting)。
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
np.random.seed(42)
n = 50
x = np.random.uniform(-3, 3, n).reshape(-1, 1)
y = x[:, 0]**3 + np.random.normal(0, 3, n)
# LOOCV:每次留一個樣本
for degree in range(1, 6):
errors = []
for i in range(n):
# 訓練集:除了第 i 筆
x_train = np.delete(x, i, axis=0)
y_train = np.delete(y, i)
# 測試集:第 i 筆
x_test = x[i].reshape(1, -1)
y_test = y[i]
poly = PolynomialFeatures(degree)
x_train_poly = poly.fit_transform(x_train)
x_test_poly = poly.transform(x_test)
model = LinearRegression().fit(x_train_poly, y_train)
y_pred = model.predict(x_test_poly)[0]
errors.append((y_test - y_pred) ** 2)
print(f"Degree {degree}: LOOCV MSE = {np.mean(errors):.2f}")
預期輸出:
Degree 1: LOOCV MSE = 39.21
Degree 2: LOOCV MSE = 38.74
Degree 3: LOOCV MSE = 8.15
Degree 4: LOOCV MSE = 8.92
Degree 5: LOOCV MSE = 10.67
建立預測模型時,我們常面對「簡單模型(欠擬合)vs 複雜模型(過擬合)」的兩難。交叉驗證讓我們用數據說話:跑 k=10 的 CV,選 MSE 最低的模型階數。
k-Fold CV 是 GridSearchCV 的核心機制。在選擇 Ridge 的 α、KNN 的 K、決策樹深度時,CV 提供客觀的比較基準。
GridSearchCV 內建 k-Fold CVValidation Set 的 MSE 變異大(取決於哪筆資料被分到驗證集);LOOCV 幾乎無偏但變異也大(n 個訓練集高度相關);k-Fold CV 在 bias 和 variance 間取得平衡。
| ✅ 優點 |
|---|
| 直接估計 test error,不需依賴調整後的 training error(如 AIC/BIC) |
| 適用於任何模型類型(線性、非線性、樹模型皆可) |
| k-Fold CV 在計算成本與準確性之間取得良好平衡 |
sklearn 一行 cross_val_score 即可完成,實作門檻低 |
| ⚠️ 缺點 |
|---|
| LOOCV 計算成本高:n 個觀測值需要訓練 n 次模型 |
| 時間序列資料不能直接用隨機 CV(會洩漏未來資訊) |
| k 的選擇無絕對標準(實務慣例 k=5 或 10) |
| 資料量極大時,CV 可能過於保守(可用 single validation set) |
| 方法 | 訓練次數 | Bias | Variance | 適合場景 |
|---|---|---|---|---|
| Validation Set | 1 次 | 高 | 高(分割隨機性) | 大數據集、快速原型 |
| LOOCV | n 次 | 極低 | 高(模型相關性) | 小數據集、需最低 bias |
| k-Fold CV (k=5) | 5 次 | 中低 | 中 | 一般實務(推薦) |
| k-Fold CV (k=10) | 10 次 | 低 | 中低 | 標準選擇,論文常用 |
交叉驗證對 Hermes 架構的啟發:就像 k-Fold CV 用不同的資料切分來評估模型穩健性,Hermes 的技能系統也應該用不同的任務場景來「交叉驗證」每個 skill 的有效性。一個 skill 不應該只通過一次測試就被信任——需要在多種輸入變化下反覆驗證。這和我們對子 agent 的表現追蹤(連續 2 次空回傳才汰換)是同一個統計思維:不要因單次失敗就下結論。