import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")

plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False
df = pd.read_excel('2024-11-10-公眾號Python機器學習AI.xlsx')
from sklearn.model_selection import train_test_split

X = df.drop(['待預測變量Y'],axis=1)
y = df['待預測變量Y']

# 劃分訓練集和測試集
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 然后將訓練集進一步劃分為訓練集和驗證集
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.125, random_state=42) # 0.125 x 0.8 = 0.1

import optuna # 導入Optuna庫,用于超參數優化
from xgboost import XGBRegressor
from sklearn.metrics import mean_squared_error
from optuna.visualization import plot_optimization_history, plot_contour, plot_param_importances, plot_parallel_coordinate, plot_edf # 導入Optuna的可視化工具,用于繪制優化歷史、參數重要性等

# 定義目標函數,用于Optuna的優化
def objective(trial):
# 定義模型的超參數搜索空間,Optuna會在此范圍內進行參數采樣
params = {
# 'n_estimators':模型中要構建的決策樹的數量
# 值越高,模型擬合越充分,但計算開銷也更大。一般較低的值適合快速迭代和避免過擬合
'n_estimators': trial.suggest_categorical('n_estimators', [50, 100, 200, 300]), #離散的類別選擇范圍

# 'max_depth':控制每棵樹的深度,以防止過擬合。較高的深度會增加模型復雜性
'max_depth': trial.suggest_int('max_depth', 3, 15, step=1), #整數范圍

# 'learning_rate':學習率決定每棵樹對最終預測的貢獻。較小的學習率通常需要更大的'n_estimators'來充分學習
'learning_rate': trial.suggest_loguniform('learning_rate', 0.01, 0.3), # 對數均勻分布的連續浮點數范圍

# 'subsample':表示每棵樹隨機選擇的樣本比例,通常用于減少過擬合
'subsample': trial.suggest_uniform('subsample', 0.5, 1.0), # 線性均勻分布的連續浮點數范圍

# 'colsample_bytree':控制每棵樹使用的特征比例,以增強模型的魯棒性
'colsample_bytree': trial.suggest_uniform('colsample_bytree', 0.5, 1.0),

# 'gamma':控制是否允許分裂,越高的值會使算法更保守,幫助避免過擬合
'gamma': trial.suggest_uniform('gamma', 0, 5)
}

# 使用采樣的參數創建XGBRegressor模型
model = XGBRegressor(**params, random_state=42)

# 使用訓練數據擬合模型
model.fit(X_train, y_train)
# 使用驗證集進行預測
y_pred = model.predict(X_val)
# 計算并返回均方誤差(MSE),作為優化的目標
return mean_squared_error(y_val, y_pred)

# 創建Optuna的Study對象,并設置優化方向為“minimize”表示最小化均方誤差
# 默認情況下,Optuna使用的優化算法是 TPE (Tree-structured Parzen Estimator),
# 這是一種貝葉斯優化方法,適合高效地探索超參數空間
study = optuna.create_study(direction="minimize")
# 運行優化,進行100次試驗
study.optimize(objective, n_trials=100)
print("Best parameters:", study.best_params)
# 使用最佳參數重新訓練模型
best_model = XGBRegressor(**study.best_params, random_state=42)
best_model.fit(X_train, y_train)

使用Optuna庫對XGBoost回歸模型進行自動化超參數優化。首先,代碼將數據集劃分為訓練集、驗證集和測試集,然后定義目標函數(objective)來指定要優化的超參數范圍,包括n_estimators、max_depth、learning_rate、subsample、colsample_bytree和gamma。Optuna在此范圍內自動采樣超參數組合,通過最小化均方誤差(MSE)來找到最優參數,運行100次試驗后,代碼輸出最優參數并用其重新訓練XGBoost模型,從而提高模型性能

記錄與可視化調參優化歷史

# 獲取優化歷史中的數據,每列的含義如下:
# 'trial_number': 每次試驗的編號,用于區分不同的試驗
# 'value': 每次試驗的目標值(優化過程中的結果),通常是需要最小化或最大化的目標值
# 'datetime_start': 每次試驗的開始時間,用于記錄試驗的開始時間點
# 'datetime_complete': 每次試驗的完成時間,用于記錄試驗的結束時間點

optimization_history = {
'trial_number': [], # 試驗編號
'value': [], # 目標值
'datetime_start': [], # 試驗開始時間
'datetime_complete': [] # 試驗完成時間
}

for trial in study.trials:
optimization_history['trial_number'].append(trial.number)
optimization_history['value'].append(trial.value)
optimization_history['datetime_start'].append(trial.datetime_start)
optimization_history['datetime_complete'].append(trial.datetime_complete)

# 將數據轉換為 DataFrame
optimization_history = pd.DataFrame(optimization_history)
optimization_history

從Optuna的study對象中提取每次試驗的編號、目標值、開始和結束時間,存入字典并轉換為DataFrame,以便查看和分析優化歷史

# 找到最優試驗
best_trial_idx = optimization_history['value'].idxmin()
best_trial_number = optimization_history['trial_number'][best_trial_idx]
best_value = optimization_history['value'][best_trial_idx]
plt.figure(figsize=(10, 6), dpi=1200)
# 繪制非最佳點
plt.plot(
optimization_history['trial_number'],
optimization_history['value'],
marker='o',
linestyle='-',
color='skyblue',
alpha=0.4,
label='All Trials'
)
# 繪制最佳點
plt.plot(
best_trial_number,
best_value,
marker='*',
color='darkblue',
markersize=15,
label=f'Best Trial (#{best_trial_number})'
)
plt.title("Optimization History")
plt.xlabel("Trial Number")
plt.ylabel("MSE")
plt.grid(True)
plt.legend(loc='upper right', bbox_to_anchor=(1, 1), frameon=True)
plt.savefig('1.pdf', format='pdf', bbox_inches='tight')
plt.show()

從優化歷史中找到具有最低目標值(MSE)的最佳試驗,并提取其編號和對應的MSE值。然后,繪制優化歷史折線圖,其中所有試驗結果以點的形式呈現,最佳試驗點以星號標出,使得用戶能夠清晰地看到整個調參過程中的性能變化

超參數重要性分析與可視化

from optuna.importance import get_param_importances
# 獲取超參數的重要性數據
param_importances = get_param_importances(study)
# 將數據轉換為 DataFrame
Hyperparameter_Importances = pd.DataFrame(list(param_importances.items()), columns=['Parameter', 'Importance'])
Hyperparameter_Importances

使用Optuna的get_param_importances函數來計算超參數對優化目標的重要性,并將其結果轉換為DataFrame便于查看和分析。

# 對參數按重要性進行排序,便于圖表的展示
Hyperparameter_Importances = Hyperparameter_Importances.sort_values(by='Importance', ascending=False)
# 繪制超參數重要性條形圖
plt.figure(figsize=(10, 6), dpi=1200)
bars = plt.barh(Hyperparameter_Importances['Parameter'], Hyperparameter_Importances['Importance'], color='skyblue')
plt.gca().invert_yaxis() # 反轉Y軸,使重要性最高的參數在頂部
# 為每個條形圖顯示數值
for bar, importance in zip(bars, Hyperparameter_Importances['Importance']):
plt.text(bar.get_width() + 0.01, bar.get_y() + bar.get_height() / 2,
f'{importance:.3f}', va='center')
plt.title("Hyperparameter Importances")
plt.xlabel("Importance")
plt.ylabel("Parameter")
# 設置x軸范圍
plt.xlim(0, max(Hyperparameter_Importances['Importance']) * 1.1)
plt.savefig('2.pdf', format='pdf', bbox_inches='tight')
plt.show()

對超參數的重要性數據進行排序,然后使用水平條形圖展示每個超參數對模型性能的重要性,確保最重要的參數位于頂部。代碼還在每個條形上標出數值,提供了各參數對結果影響的精確度量,結果圖顯示了gamma和learning_rate是對模型性能影響最大的兩個超參數,而max_depth和subsample的影響較小。通過這種可視化,用戶可以更好地理解哪些超參數最值得關注和優化

多維參數組合與目標值的可視化分析

# 提取每次試驗的參數組合和目標值
data = {
'trial_number': [],
'value': []
}

# 提取所有參數名并初始化列
for param_name in study.trials[0].params.keys():
data[param_name] = []

# 遍歷所有試驗,提取參數和目標值
for trial in study.trials:
data['trial_number'].append(trial.number)
data['value'].append(trial.value)

# 填充每個參數的值,如果該試驗沒有設置某個參數,則填充為 None
for param_name in data.keys():
if param_name not in ['trial_number', 'value']:
data[param_name].append(trial.params.get(param_name, None))

# 將數據轉換為 DataFrame
Parameter_Combinations = pd.DataFrame(data)
Parameter_Combinations

從每次試驗中提取超參數組合和目標值,將其整理成DataFrame,以便后續分析不同參數組合對目標值的影響

gamma和learning_rate對目標值的2D可視化分析

from mpl_toolkits.mplot3d import Axes3D
Parameter_Combinations['gamma'] = Parameter_Combinations['gamma'].astype(float)
Parameter_Combinations['learning_rate'] = Parameter_Combinations['learning_rate'].astype(float)

plt.figure(figsize=(10, 8))

# 繪制散點圖,使用 'value' 進行顏色編碼
sc = plt.scatter(
Parameter_Combinations['gamma'],
Parameter_Combinations['learning_rate'],
c=Parameter_Combinations['value'],
cmap='viridis',
s=50, # 設置散點大小
alpha=0.7 # 設置透明度
)

cbar = plt.colorbar(sc, format='%.3f')
cbar.set_label('Objective Value')
plt.xlabel("gamma")
plt.ylabel("learning_rate")
plt.title("2D Plot of gamma and learning_rate vs Objective Value")
plt.savefig('3.pdf', format='pdf', bbox_inches='tight')
plt.show()

繪制gamma和learning_rate兩個超參數對目標值(Objective Value)的影響【排名影響前二參數】,通過散點圖展示每組參數組合的效果,并使用顏色編碼表示目標值大小。結果顯示了不同參數組合下的目標值分布,顏色越淺表示目標值越低,從而幫助識別表現較優的參數區域

colsample_bytree、gamma和learning_rate對目標值的3D可視化分析

繪制colsample_bytree、gamma和learning_rate三個超參數組合對目標值(Objective MSE)的三維散點圖【排名影響前三參數】,使用顏色編碼目標值大小。結果圖展示了不同參數組合的目標值分布,顏色越淺表示目標值越低,便于識別在多維參數空間中表現最佳的區域

文章轉自微信公眾號@Python機器學習AI

上一篇:

實用機器學習技巧:帶有95%置信區間的ROC曲線繪制

下一篇:

貝葉斯優化在XGBoost中的應用:從參數調優到性能提升
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費