import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False
import warnings
warnings.filterwarnings("ignore")
df = pd.read_excel('2024-10-30-公眾號(hào)Python機(jī)器學(xué)習(xí)AI.xlsx')
from sklearn.model_selection import train_test_split
# 分割數(shù)據(jù)集
X = df.drop(['Type'], axis = 1)
y = df['Type']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3,
stratify=df['Type']) #分離訓(xùn)練集和測(cè)試集

加載數(shù)據(jù),并將數(shù)據(jù)集中特征與標(biāo)簽分離后,將其按7:3比例分為訓(xùn)練集和測(cè)試集,確保測(cè)試集按標(biāo)簽類別進(jìn)行分層抽樣

模型構(gòu)建

from sklearn.ensemble import RandomForestClassifier
# 創(chuàng)建隨機(jī)森林分類器實(shí)例,并設(shè)置參數(shù)
rf = RandomForestClassifier(
n_estimators=100, # 森林中樹(shù)的數(shù)量。默認(rèn)是100。
criterion='gini', # 指定用于拆分的質(zhì)量指標(biāo)。可選'gini'或'entropy'。
max_depth=None, # 每棵樹(shù)的最大深度。'None'表示不限制。
min_samples_split=2, # 節(jié)點(diǎn)分裂所需的最小樣本數(shù)。默認(rèn)是2。
min_samples_leaf=1, # 葉子節(jié)點(diǎn)所需的最小樣本數(shù)。默認(rèn)是1。
min_weight_fraction_leaf=0.0, # 類似'min_samples_leaf',但基于樣本權(quán)重。默認(rèn)0.0。
random_state=42, # 控制隨機(jī)數(shù)生成,以便結(jié)果可復(fù)現(xiàn)。
max_leaf_nodes=None, # 限制每棵樹(shù)的最大葉子節(jié)點(diǎn)數(shù)。'None'表示不限制。
min_impurity_decrease=0.0 # 節(jié)點(diǎn)分裂時(shí)要求的最小不純度減少量。默認(rèn)0.0。
)
# 訓(xùn)練分類器
rf.fit(X_train, y_train)

創(chuàng)建并配置了一個(gè)多分類隨機(jī)森林分類器,并使用訓(xùn)練數(shù)據(jù)對(duì)其進(jìn)行模型訓(xùn)練

shap值計(jì)算整理

import shap
explainer = shap.TreeExplainer(rf)
# 計(jì)算shap值為numpy.array數(shù)組
shap_values = explainer.shap_values(X_test)
# 提取每個(gè)類別的 SHAP 值
shap_values_class_0 = shap_values[:, :, 0]
shap_values_class_1 = shap_values[:, :, 1]
shap_values_class_2 = shap_values[:, :, 2]
shap_values_class_3 = shap_values[:, :, 3]
shap_values_class_4 = shap_values[:, :, 4]
# 計(jì)算每個(gè)類別的特征貢獻(xiàn)度
importance_class_0 = np.abs(shap_values_class_0).mean(axis=0)
importance_class_1 = np.abs(shap_values_class_1).mean(axis=0)
importance_class_2 = np.abs(shap_values_class_2).mean(axis=0)
importance_class_3 = np.abs(shap_values_class_3).mean(axis=0)
importance_class_4 = np.abs(shap_values_class_4).mean(axis=0)
importance_df = pd.DataFrame({
'Class_0': importance_class_0,
'Class_1': importance_class_1,
'Class_2': importance_class_2,
'Class_3': importance_class_3,
'Class_4': importance_class_4
}, index=X_train.columns)
type_mapping = {
0: 'Type_A',
1: 'Type_B',
2: 'Type_C',
3: 'Type_D',
4: 'Type_E'
}
importance_df.columns = [type_mapping[int(col.split('_')[1])] for col in importance_df.columns]
importance_df

使用SHAP計(jì)算訓(xùn)練好的多分類隨機(jī)森林模型對(duì)測(cè)試數(shù)據(jù)的特征貢獻(xiàn)度,首先,TreeExplainer 用于解釋模型,并生成每個(gè)類別的 SHAP 值,接著,提取每個(gè)類別(Class_0 到 Class_4)的 SHAP值,并計(jì)算了各類別下每個(gè)特征的平均貢獻(xiàn)度(取 SHAP 值絕對(duì)值的均值),最終,這些貢獻(xiàn)度被存儲(chǔ)在一個(gè) DataFrame 中,并將類別索引映射為具體的類別名稱(Type_A 到 Type_E),為后續(xù)分析提供可解釋的特征重要性表

不同類別下特征重要性的堆疊柱狀圖展示

import seaborn as sns
importance_df['row_sum'] = importance_df.sum(axis=1)
sorted_importance_df = importance_df.sort_values(by='row_sum', ascending=True)
sorted_importance_df = sorted_importance_df.drop(columns=['row_sum'])
elements = sorted_importance_df.index
colors = sns.color_palette("Set2", n_colors=len(sorted_importance_df.columns))
fig, ax = plt.subplots(figsize=(12, 6), dpi=1200)
bottom = np.zeros(len(elements))
for i, column in enumerate(sorted_importance_df.columns):
ax.barh(
sorted_importance_df.index,
sorted_importance_df[column],
left=bottom,
color=colors[i],
label=column
)
bottom += sorted_importance_df[column]
ax.set_xlabel('mean(|SHAP value|) (average impact on model output magnitude)', fontsize=12)
ax.set_ylabel('Features', fontsize=12)
ax.set_title('Feature Importance by Class', fontsize=15)
ax.set_yticks(np.arange(len(elements)))
ax.set_yticklabels(elements, fontsize=10)
for i, el in enumerate(elements):
ax.text(bottom[i], i, ' ' + str(el), va='center', fontsize=9)
ax.legend(title='Class', fontsize=10, title_fontsize=12)
ax.set_yticks([])
ax.set_yticklabels([])
ax.set_ylabel('')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.savefig('1.pdf', format='pdf', bbox_inches='tight')
plt.show()

使用 Seaborn 和 Matplotlib 繪制一個(gè) 堆疊水平柱狀圖,展示多分類模型中各特征在不同類別下的平均 SHAP 值的重要性,首先,將每個(gè)特征在所有類別中的 SHAP 值求和排序,以確定特征的重要性順序,接著,依次為每個(gè)類別繪制水平條形,并通過(guò)堆疊方式展示每個(gè)類別對(duì)特征的重要性貢獻(xiàn),圖例用于標(biāo)明不同類別的顏色對(duì)應(yīng)關(guān)系,最終圖形美化去除了多余的坐標(biāo)軸刻度,下面為一個(gè)二分類模型的shap特征貢獻(xiàn)圖

通過(guò)這兩張圖的直觀對(duì)比,我們可以發(fā)現(xiàn):二分類模型的 SHAP 特征貢獻(xiàn)圖(第一張圖)展示的是特征對(duì)整體目標(biāo)類預(yù)測(cè)的影響,而多分類模型的 SHAP 特征貢獻(xiàn)圖(第二張圖)將每個(gè)特征在不同類別中的貢獻(xiàn)分開(kāi)顯示,更詳細(xì)地揭示了特征在各類別間的差異性,也就是前面所說(shuō)的由于任務(wù)不同導(dǎo)致其可視化也存在差異多分類

模型特征貢獻(xiàn)圖其它繪制方法

與之前的堆疊柱狀圖相比,采用3D 柱狀圖來(lái)展示特征在不同類別中的貢獻(xiàn)度,提供更立體的視覺(jué)效果,使我們能夠從不同視角分析特征在各類別中的影響,相比之下,3D 圖更直觀,但在特征和類別較多時(shí)可能增加視覺(jué)復(fù)雜度,而堆疊柱狀圖更適合快速比較各類別的相對(duì)貢獻(xiàn)

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

上一篇:

理解 SHAP 值:如何根據(jù)模型性質(zhì)正確解釋 XGBoost 與隨機(jī)森林的結(jié)果

下一篇:

SCI圖表:基于相關(guān)性和標(biāo)準(zhǔn)差的多模型評(píng)價(jià)——泰勒?qǐng)D解析

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

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

查看全部API→
??

熱門(mén)場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

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

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

#AI深度推理大模型API

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

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