在機器學習中,超參數(Hyperparameters)是指在訓練過程中需要手動設定、而非通過模型學習獲得的參數,例如隨機森林(Random Forest)中的n_estimators
, max_depth
, min_samples_split
,支持向量機(SVM)中的C
, kernel
, gamma
,都是該模型中的超參數。這些參數通常會影響模型的訓練過程和最終性能,需要在模型訓練之前設置。
# 可使用目錄功能快速確認要閱覽的主題
網格搜索是一種窮舉搜尋方法,通過對給定參數空間中的每一個可能組合進行評估,找到表現最好的超參數組合。
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 載入數據集
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42)
# 定義模型
rf = RandomForestClassifier(random_state=42)
# 定義參數網格
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [None, 10, 20, 30],
'min_samples_split': [2, 5, 10]
}
# 使用GridSearchCV
grid_search = GridSearchCV(estimator=rf, param_grid=param_grid, cv=5, scoring='accuracy')
grid_search.fit(X_train, y_train)
# 最佳參數
print(f"Best Parameters: {grid_search.best_params_}")
# 最佳模型
best_rf = grid_search.best_estimator_
print(f"Best Model Score: {best_rf.score(X_test, y_test)}")
隨機搜索通過在參數空間中隨機採樣來找到優化的超參數組合。這種方法通常比網格搜索更快,尤其是在參數空間較大時。
from sklearn.model_selection import RandomizedSearchCV
from sklearn.ensemble import RandomForestClassifier
# 定義隨機搜索的參數分佈
param_dist = {
'n_estimators': [50, 100, 200],
'max_depth': [None, 10, 20, 30],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 4]
}
# 使用RandomizedSearchCV
random_search = RandomizedSearchCV(estimator=rf, param_distributions=param_dist, n_iter=10, cv=5, scoring='accuracy', random_state=42)
random_search.fit(X_train, y_train)
# 最佳參數
print(f"Best Parameters: {random_search.best_params_}")
# 最佳模型
best_rf = random_search.best_estimator_
print(f"Best Model Score: {best_rf.score(X_test, y_test)}")
貝葉斯優化是一種更加智能的超參數調整方法。它通過構建超參數與模型性能之間的概率模型(如高斯過程),根據這一模型進行探索和利用,從而更有效地找到最優的超參數組合。
使用hyperopt
庫進行貝葉斯優化:
from hyperopt import fmin, tpe, hp, Trials
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
# 定義目標函數
def objective(params):
clf = RandomForestClassifier(**params, random_state=42)
score = cross_val_score(clf, X_train, y_train, cv=5, scoring='accuracy').mean()
return -score
# 定義參數空間
space = {
'n_estimators': hp.choice('n_estimators', [50, 100, 200]),
'max_depth': hp.choice('max_depth', [None, 10, 20, 30]),
'min_samples_split': hp.uniform('min_samples_split', 2, 10),
'min_samples_leaf': hp.uniform('min_samples_leaf', 1, 4)
}
# 使用貝葉斯優化
trials = Trials()
best = fmin(fn=objective, space=space, algo=tpe.suggest, max_evals=50, trials=trials)
print(f"Best Parameters: {best}")
在進行超參數搜索的同時,可以使用交叉驗證來評估模型的泛化能力,避免過度擬合。
from sklearn.model_selection import cross_val_score
# 使用交叉驗證來評估模型性能
scores = cross_val_score(rf, X_train, y_train, cv=5, scoring='accuracy')
print(f"Cross-Validation Scores: {scores}")
print(f"Mean Accuracy: {scores.mean()}")
一些先進的搜尋算法如 Optuna
、BayesianOptimization
、Scikit-Optimize
等,可以在更高維度的參數空間中找到最優參數。這些工具通過探索和利用當前找到的最佳參數來進行自適應調整。
import optuna
from sklearn.ensemble import RandomForestClassifier
# 定義目標函數
def objective(trial):
n_estimators = trial.suggest_int('n_estimators', 50, 200)
max_depth = trial.suggest_int('max_depth', 10, 30)
min_samples_split = trial.suggest_uniform('min_samples_split', 2, 10)
clf = RandomForestClassifier(n_estimators=n_estimators, max_depth=max_depth, min_samples_split=min_samples_split, random_state=42)
return cross_val_score(clf, X_train, y_train, cv=5, scoring='accuracy').mean()
# 使用Optuna進行優化
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=50)
# 最佳參數
print(f"Best Parameters: {study.best_params}")
這種流程通過交叉驗證來選擇最佳模型,然後在獨立的測試集上進行最終檢驗,能夠最大程度地保證模型的穩定性和泛化能力,是機器學習建模的最佳實踐之一。
以下是使用交叉驗證找出最佳超參數,然後用獨立測試集來評估模型的範例。這裡將使用隨機森林模型作為例子。
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score
from sklearn.metrics import accuracy_score
# 假設你有一個 DataFrame 叫做 df_analysis,其中包含 Titanic 資料
將數據分成特徵(X)和目標(y),然後進行訓練集和測試集的分割。
df_train = df_analysis[0:891] # 取前 891 行作為訓練資料
train_valid_X = df_train.drop(columns=['Survived']) # 所有特徵
train_valid_y = df_train['Survived'] # 目標變數 'Survived'
test_X = df_analysis[891:].drop(columns=['Survived']) # 剩下的行作為測試資料
# 將訓練集再進行訓練/驗證集的分割
train_X, valid_X, train_y, valid_y = train_test_split(train_valid_X, train_valid_y, train_size=0.7, random_state=42)
# 設定隨機森林的超參數範圍
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [None, 10, 20, 30],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 4]
}
# 建立隨機森林模型
rf = RandomForestClassifier(random_state=42)
# 使用 GridSearchCV 來尋找最佳超參數組合
grid_search = GridSearchCV(estimator=rf, param_grid=param_grid, cv=5, scoring='accuracy', n_jobs=-1, verbose=2)
grid_search.fit(train_X, train_y)
# 輸出最佳的超參數
print("最佳超參數組合:", grid_search.best_params_)
# 使用最佳超參數訓練模型
best_rf = grid_search.best_estimator_
best_rf.fit(train_X, train_y)
# 在驗證集上評估模型
valid_accuracy = accuracy_score(valid_y, best_rf.predict(valid_X))
print(f"驗證集準確率: {valid_accuracy:.2f}")
# 在測試集上評估模型
test_predictions = best_rf.predict(test_X)
# 因為 Kaggle 的 Titanic 比賽中沒有測試集的 Survived 標籤,這裡假設測試集是有標籤的
# 如果測試集沒有標籤,只能保存預測結果然後提交到 Kaggle 平台進行評分
test_accuracy = accuracy_score(test_y, test_predictions)
print(f"測試集準確率: {test_accuracy:.2f}")
# 將預測結果保存到 CSV 文件
submission = pd.DataFrame({
"PassengerId": df_analysis[891:]['PassengerId'],
"Survived": test_predictions
})
submission.to_csv("titanic_submission.csv", index=False)
GridSearchCV
中使用 5 折交叉驗證來評估每個超參數組合的表現,從而找出最佳的超參數組合。這樣可以幫助你找到最好的模型設定,並確認它是否在未見過的數據上也有良好的表現,從而避免過擬合。