超參數調優

Vibe Prompt

「用遺傳演算法最佳化 Random Forest 的超參數:n_estimators(10-200)、max_depth(3-20)、min_samples_split(2-10),目標最大化交叉驗證準確率。」

import random
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_digits
from sklearn.model_selection import cross_val_score

data = load_digits()
X, y = data.data, data.target

def evaluate(params):
    n_est, depth, min_split = params
    rf = RandomForestClassifier(
        n_estimators=int(n_est),
        max_depth=int(depth),
        min_samples_split=int(min_split),
        random_state=42, n_jobs=-1
    )
    scores = cross_val_score(rf, X, y, cv=3, scoring='accuracy')
    return scores.mean()

# 簡單遺傳演算法調參
bounds = [(10, 200), (3, 20), (2, 10)]
pop = [[random.uniform(b[0], b[1]) for b in bounds] for _ in range(20)]

for gen in range(20):
    scored = [(evaluate(p), p) for p in pop]
    scored.sort(reverse=True)
    pop = [p for _, p in scored]
    print(f"第 {gen+1} 代最佳: {scored[0][0]:.4f} (n_est={int(scored[0][1][0])}, depth={int(scored[0][1][1])})")
    
    next_pop = pop[:2]
    while len(next_pop) < 20:
        p1, p2 = random.choices(pop[:10], k=2)
        child = [random.choice([p1[i], p2[i]]) for i in range(3)]
        child = [c + random.uniform(-5, 5) for c in child]
        child = [max(b[0], min(b[1], child[i])) for i, b in enumerate(bounds)]
        next_pop.append(child)
    pop = next_pop

print(f"\n最佳參數: n_est={int(pop[0][0])}, depth={int(pop[0][1])}, min_split={int(pop[0][2])}")

深入理解:超參數調優策略

Grid Search(網格搜尋)

from sklearn.model_selection import GridSearchCV

param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [5, 10, 20],
    'min_samples_split': [2, 5, 10]
}

grid = GridSearchCV(RandomForestClassifier(), param_grid, cv=5, scoring='accuracy')
grid.fit(X_train, y_train)
print(f"GridSearch 最佳參數: {grid.best_params_}")
print(f"GridSearch 最佳分數: {grid.best_score_:.4f}")
print(f"GridSearch 花費時間: 若每個組合需 30 秒,共需 {3*3*3*5*30} 秒")

| 方法 | 搜尋空間 | 優點 | 缺點 | |------|:--------:|------|------| | Grid Search | 全部組合 | 保證找到網格內最佳 | 維度災難(組合爆炸) | | Random Search | 隨機採樣 | 高維度更有效率 | 可能漏掉最佳 | | Bayesian Opt. | 機率模型引導 | 採樣效率最高 | 實作較複雜 | | 遺傳演算法 | 演化搜尋 | 平行化容易 | 需調 GA 參數 |

Random Search vs Grid Search

from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint, uniform

param_dist = {
    'n_estimators': randint(10, 300),
    'max_depth': randint(3, 30),
    'min_samples_split': randint(2, 15)
}

random = RandomizedSearchCV(
    RandomForestClassifier(), param_dist, 
    n_iter=30, cv=5, scoring='accuracy', random_state=42
)
random.fit(X_train, y_train)
print(f"RandomSearch 最佳參數: {random.best_params_}")
print(f"RandomSearch 最佳分數: {random.best_score_:.4f}")

關鍵要點

  • ✅ Grid Search 適合低維度(≤3),超過即組合爆炸
  • ✅ Random Search 在高維度下比 Grid Search 更有效率
  • ✅ Bayesian Optimization(如 Optuna)是目前最先進的調參方法
  • ✅ 遺傳演算法適合超大搜尋空間或不可微的目標
  • Nested Cross-Validation 是避免調參時 overfit 的正確做法


超參數最佳化:讓演算法自己調參數

機器學習模型的效能跟你選的超參數高度相關——learning rate、樹的深度、正則化強度。手動嘗試既慢又不系統。

三種超參數最佳化方法

| 方法 | 做法 | 效果 | 成本 | |:----|:----|:----|:----| | Grid Search | 窮舉所有組合 | 保證找到最佳 | 暴力,維度詛咒 | | Random Search | 隨機抽樣 | 通常夠好 | 比 Grid 有效率 | | Bayesian Optimization | 建立代理模型,聰明地選擇下一組參數 | 最佳 | 需要較多實作 |

為什麼 Bayesian Optimization 最好?

Grid Search 和 Random Search 都忽略了「過去的評估結果」。Bayesian Optimization 建立一個代理模型(通常是 Gaussian Process),用過去結果預測哪些參數組合最有可能提升效能——這可以節省 50-70% 的評估次數。

下一章預告:最佳化 API 實戰

學會了 GA、PSO、超參數最佳化之後,下一章把它們包裝成一個 FastAPI 服務——讓其他程式可以透過 API 呼叫最佳化演算法。

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!