超參數調優
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 呼叫最佳化演算法。