import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
df = pd.read_csv('Chabuhou.csv')

# 劃分特征和目標(biāo)變量
X = df.drop(['Electrical_cardioversion'], axis=1)
y = df['Electrical_cardioversion']
# 劃分訓(xùn)練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
random_state=42, stratify=df['Electrical_cardioversion'])

使用一個(gè)心臟電復(fù)律的數(shù)據(jù)集,目標(biāo)是預(yù)測特定條件下患者是否需要電復(fù)律,特征變量(如年齡、心率、血壓等)經(jīng)過清洗和預(yù)處理后,分為訓(xùn)練集和測試集。

模型選擇與參數(shù)優(yōu)化

import xgboost as xgb
from sklearn.model_selection import GridSearchCV

# XGBoost模型參數(shù)
params_xgb = {
'learning_rate': 0.02, # 學(xué)習(xí)率,控制每一步的步長,用于防止過擬合。典型值范圍:0.01 - 0.1
'booster': 'gbtree', # 提升方法,這里使用梯度提升樹(Gradient Boosting Tree)
'objective': 'binary:logistic', # 損失函數(shù),這里使用邏輯回歸,用于二分類任務(wù)
'max_leaves': 127, # 每棵樹的葉子節(jié)點(diǎn)數(shù)量,控制模型復(fù)雜度。較大值可以提高模型復(fù)雜度但可能導(dǎo)致過擬合
'verbosity': 1, # 控制 XGBoost 輸出信息的詳細(xì)程度,0表示無輸出,1表示輸出進(jìn)度信息
'seed': 42, # 隨機(jī)種子,用于重現(xiàn)模型的結(jié)果
'nthread': -1, # 并行運(yùn)算的線程數(shù)量,-1表示使用所有可用的CPU核心
'colsample_bytree': 0.6, # 每棵樹隨機(jī)選擇的特征比例,用于增加模型的泛化能力
'subsample': 0.7, # 每次迭代時(shí)隨機(jī)選擇的樣本比例,用于增加模型的泛化能力
'eval_metric': 'logloss' # 評價(jià)指標(biāo),這里使用對數(shù)損失(logloss)
}

# 初始化XGBoost分類模型
model_xgb = xgb.XGBClassifier(**params_xgb)

# 定義參數(shù)網(wǎng)格,用于網(wǎng)格搜索
param_grid = {
'n_estimators': [100, 200, 300, 400, 500], # 樹的數(shù)量
'max_depth': [3, 4, 5, 6, 7], # 樹的深度
'learning_rate': [0.01, 0.02, 0.05, 0.1], # 學(xué)習(xí)率
}

# 使用GridSearchCV進(jìn)行網(wǎng)格搜索和k折交叉驗(yàn)證
grid_search = GridSearchCV(
estimator=model_xgb,
param_grid=param_grid,
scoring='neg_log_loss', # 評價(jià)指標(biāo)為負(fù)對數(shù)損失
cv=5, # 5折交叉驗(yàn)證
n_jobs=-1, # 并行計(jì)算
verbose=1 # 輸出詳細(xì)進(jìn)度信息
)

# 訓(xùn)練模型
grid_search.fit(X_train, y_train)

# 輸出最優(yōu)參數(shù)
print("Best parameters found: ", grid_search.best_params_)
print("Best Log Loss score: ", -grid_search.best_score_)

# 使用最優(yōu)參數(shù)訓(xùn)練模型
best_model = grid_search.best_estimator_

from sklearn.metrics import classification_report
pred = best_model.predict(X_test) # 預(yù)測測試集
print(classification_report(y_test, pred)) # 輸出模型完整評價(jià)指標(biāo)

選用XGBoost分類模型,模型參數(shù)通過網(wǎng)格搜索優(yōu)化,以找到最佳的學(xué)習(xí)率、樹的深度等參數(shù),最后輸出此情況下的最優(yōu)模型的詳細(xì)評價(jià)指標(biāo)。

SHAP值分析特征貢獻(xiàn)度

測試集特征貢獻(xiàn)度排名可視化

import shap
# 構(gòu)建 shap解釋器
explainer = shap.TreeExplainer(best_model)
# 計(jì)算測試集的shap值
shap_values = explainer.shap_values(X_test)
# 特征標(biāo)簽
labels = X_train.columns
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = 'Times new Roman'
plt.rcParams['font.size'] = 13

plt.figure(figsize=(15, 5))
shap.summary_plot(shap_values, X_test, plot_type="bar", show=False)
plt.title("X_test")
plt.xlabel('')
plt.tight_layout()
plt.show()

SHAP值是一種解釋模型預(yù)測的方法,通過計(jì)算每個(gè)特征對預(yù)測結(jié)果的貢獻(xiàn)度,我們可以了解哪些特征對模型的影響最大,并依據(jù)這些貢獻(xiàn)度來排序特征,從而篩選出重要特征。

特征排序

# 計(jì)算每個(gè)特征的平均絕對SHAP值
mean_shap_values = np.abs(shap_values).mean(axis=0)

# 獲取特征標(biāo)簽
labels = X_train.columns

# 根據(jù)平均絕對SHAP值對特征進(jìn)行排序
sorted_indices = np.argsort(mean_shap_values)[::-1] # 從大到小排序
sorted_labels = labels[sorted_indices]
sorted_shap_values = mean_shap_values[sorted_indices]

# 對特征變量按照模型特征貢獻(xiàn)度排序
X = df.drop(['Electrical_cardioversion'], axis=1).iloc[:, sorted_indices]

使用sorted_indices重新排列數(shù)據(jù)集的特征,使得最重要的特征排在前面,這樣排列后的數(shù)據(jù)集便于后續(xù)在不同特征組合下評估模型性能,特別是在進(jìn)行逐步特征添加和蒙特卡洛模擬時(shí),可以優(yōu)先考慮貢獻(xiàn)度大的特征。

蒙特卡洛模擬與特征組合

from sklearn.model_selection import cross_val_score

# 劃分特征和目標(biāo)變量
X = df.drop(['Electrical_cardioversion'], axis=1).iloc[:, sorted_indices]
y = df['Electrical_cardioversion']

# 設(shè)置隨機(jī)種子
np.random.seed(42)
n_features = X.shape[1]
mc_no = 20 # 蒙特卡洛模擬的次數(shù)
cv_scores = np.zeros(n_features) # 記錄交叉驗(yàn)證分?jǐn)?shù)

# 獲取最佳模型的所有參數(shù)
best_params = best_model.get_params()

# 過濾出你感興趣的參數(shù),結(jié)合默認(rèn)參數(shù)和網(wǎng)格搜索的最佳參數(shù)
params_xgb = {
'learning_rate': best_params['learning_rate'],
'booster': best_params['booster'],
'objective': best_params['objective'],
'max_leaves': best_params['max_leaves'],
'verbosity': best_params['verbosity'],
'seed': best_params['seed'],
'nthread': best_params['nthread'],
'colsample_bytree': best_params['colsample_bytree'],
'subsample': best_params['subsample'],
'eval_metric': best_params['eval_metric'],
'n_estimators': best_params['n_estimators'],
'max_depth': best_params['max_depth'],
}

model = xgb.XGBClassifier(**params_xgb)

# 蒙特卡洛模擬
for j in np.arange(mc_no):
# 每次模擬都重新劃分?jǐn)?shù)據(jù)集
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, train_size=0.8, random_state=j)

# 逐步增加特征數(shù)量并進(jìn)行交叉驗(yàn)證
for i in range(1, n_features + 1):
X_train_subset = X_train.iloc[:, :i]
scores = cross_val_score(model, X_train_subset, y_train, cv=5, scoring='accuracy', n_jobs=-1)
cv_scores[i - 1] += scores.mean()

# 計(jì)算平均交叉驗(yàn)證分?jǐn)?shù)
cv_scores /= mc_no

# 繪圖
plt.figure(figsize=(10, 6))
plt.plot(np.arange(1, n_features + 1), cv_scores)
plt.xlabel('Number of features selected')
plt.ylabel('Cross validation score (correct classifications)')
plt.title('Feature Selection Impact on Model Performance (with Cross Validation)')
plt.grid(True)
plt.tight_layout()
plt.show()

在確定了特征的貢獻(xiàn)度之后,我們利用蒙特卡洛模擬,逐步增加特征數(shù)量,觀察不同特征組合下模型的交叉驗(yàn)證分?jǐn)?shù),通過繪制不同特征組合下模型的交叉驗(yàn)證分?jǐn)?shù),可以直觀地看到增加特征數(shù)量對模型性能的影響,可以發(fā)現(xiàn)特征并不是越多越好而是會(huì)存在一個(gè)峰值讓模型精確度達(dá)到最高。

這里使用蒙特卡洛模擬的原因是它能夠通過隨機(jī)采樣和重復(fù)實(shí)驗(yàn),有效地應(yīng)對數(shù)據(jù)中的不確定性,提供對模型在不同特征組合下性能的穩(wěn)健估計(jì),從而幫助優(yōu)化特征選擇和提升模型的整體表現(xiàn)。

# 找到最優(yōu)的特征數(shù)
optimal_feature_count = np.argmax(cv_scores) + 1 # 獲取最佳特征數(shù)(加1是因?yàn)樗饕龔?開始)
optimal_features = X.columns[:optimal_feature_count] # 獲取最佳特征對應(yīng)的列名

# 輸出最優(yōu)的特征數(shù)和特征名稱
print("Optimal number of features:", optimal_feature_count)
print("Optimal features:", optimal_features.tolist()) # 輸出最佳特征的名稱列表
print("Best CV score:", cv_scores[optimal_feature_count - 1]) # 輸出最佳交叉驗(yàn)證分?jǐn)?shù)

輸出具體哪幾個(gè)特征組合在蒙特卡洛模擬中表現(xiàn)最佳,后續(xù)讀者就可以根據(jù)賽選出來的特征確定最后的模型,通過這樣做不僅能夠提升精確度,還能減少計(jì)算開銷,提升模型的訓(xùn)練速度和魯棒性。

文章轉(zhuǎn)自微信公眾號@Python機(jī)器學(xué)習(xí)AI

上一篇:

精確度與參數(shù)的完美融合:用可視化解讀模型優(yōu)化過程

下一篇:

Python實(shí)現(xiàn)數(shù)據(jù)預(yù)處理:常見異常值檢驗(yàn)方法解析

我們有何不同?

API服務(wù)商零注冊

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門場景實(shí)測,選對API

#AI文本生成大模型API

對比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

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

10個(gè)渠道
一鍵對比試用API 限時(shí)免費(fèi)