數據與方法

本次分析所用的數據可從DVRPC的數據集中獲取,數據格式為GeoJSON,GeoJSON是一種常見的地理數據結構編碼格式,可以輕松與Python中的GeoPandas等地理空間庫集成

使用該數據集預測空氣污染水平,具體為PM2.5濃度(pm25f_pfs),并基于多個環境和社會經濟特征作為預測變量,選擇的預測變量(自變量)包括:

在本次分析中,采用XGBoost機器學習模型,這是一種因其魯棒性和靈活性而被廣泛應用于回歸任務的算法,為了增強模型的可解釋性,我們使用了SHAP值,這是一種常用于解釋機器學習模型輸出的方法,當然這里作者不會過多去考慮模型精確度重點在于SHAP值地圖可視化解釋ML模型

代碼實現

數據讀取

import geopandas as gpd
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False
# 讀取 GeoJSON 文件
gdf = gpd.read_file("Climate_and_Economic_Justice_Screening_Tool_v1.0.geojson")

# 打印前幾行,查看字段信息
gdf.head()

讀取一個GeoJSON格式的地理空間數據文件,顯示其前幾行數據以查看字段信息

數據集分割

from sklearn.model_selection import train_test_split
# 選擇因變量和自變量
y = gdf['pm25f_pfs']
X = gdf[['ebf_pfs', 'hsef', 'wf_pfs', 'n_clt', 'n_trn', 'n_hsg', 'n_pln', 'sn_c']]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
random_state=42)

提取自變量(X)和因變量(y),然后使用8-2比例劃分數據集,確保隨機種子設置以便重現性

模型構建

import xgboost as xgb
from sklearn.model_selection import GridSearchCV

# XGBoost回歸模型參數
params_xgb = {
'learning_rate': 0.02, # 學習率,控制每一步的步長,用于防止過擬合。典型值范圍:0.01 - 0.1
'booster': 'gbtree', # 提升方法,這里使用梯度提升樹(Gradient Boosting Tree)
'objective': 'reg:squarederror', # 損失函數,這里使用平方誤差,適用于回歸任務
'max_leaves': 127, # 每棵樹的葉子節點數量,控制模型復雜度
'verbosity': 1, # 控制 XGBoost 輸出信息的詳細程度,0表示無輸出,1表示輸出進度信息
'seed': 42, # 隨機種子,用于重現模型的結果
'nthread': -1, # 并行運算的線程數量,-1表示使用所有可用的CPU核心
'colsample_bytree': 0.6, # 每棵樹隨機選擇的特征比例,用于增加模型的泛化能力
'subsample': 0.7, # 每次迭代時隨機選擇的樣本比例,用于增加模型的泛化能力
'eval_metric': 'rmse' # 評價指標,這里使用均方根誤差(rmse)
}

# 初始化XGBoost回歸模型
model_xgb = xgb.XGBRegressor(**params_xgb)

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

# 使用GridSearchCV進行網格搜索和k折交叉驗證
grid_search = GridSearchCV(
estimator=model_xgb,
param_grid=param_grid,
scoring='neg_mean_squared_error', # 評價指標為負均方誤差
cv=5, # 5折交叉驗證
n_jobs=-1, # 并行計算
verbose=1 # 輸出詳細進度信息
)

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

# 輸出最優參數
print("Best parameters found: ", grid_search.best_params_)
print("Best RMSE score: ", (-grid_search.best_score_) ** 0.5) # 還原RMSE

# 使用最優參數訓練模型
best_model_xgboost = grid_search.best_estimator_

配置XGBoost回歸器的超參數,并使用網格搜索和交叉驗證來識別最佳參數。使用最佳參數在訓練數據上重新訓練模型

SHAP值可視化

點圖(Dot Plot)

import shap
# 構建 shap解釋器
explainer = shap.TreeExplainer(best_model_xgboost)
# 計算shap值
shap_values = explainer.shap_values(X)

# 特征標簽
labels = X.columns
plt.figure(dpi=1200)
shap.summary_plot(shap_values, X, feature_names=labels, plot_type="dot", show=False)
plt.savefig("SHAP_1.pdf", format='pdf', bbox_inches='tight')

展示每個特征的SHAP值分布,清晰顯示了每個特征對預測PM2.5水平的正向或負向影響及其幅度

條形圖(Bar Plot)

plt.figure(figsize=(15, 5), dpi=1500)
shap.summary_plot(shap_values, X, plot_type="bar", show=False)
plt.savefig("SHAP_2.pdf", format='pdf', bbox_inches='tight')
plt.show()

根據SHAP值的平均絕對值對特征進行排序,突出顯示了模型中最具影響力的預測變量,其中wf_pfs(工作參與率)是對模型輸出影響最大的特征,其次是ebf_pfs(暴露于洪水的比例)和hsef(住房壓力因素)

使用GeoJSON繪制SHAP值地圖

數據整理

# 將 SHAP 值轉換為 DataFrame,并為列名添加 "shap_" 前綴,同時保留原始特征名
shap_df = pd.DataFrame(shap_values, columns=[f'shap_{col}' for col in X.columns])
# 將 SHAP 值和原始特征合并
gdf_with_shap = pd.concat([gdf, shap_df], axis=1)
gdf_with_shap

本次分析的一個重要方面是能夠在地理地圖上可視化SHAP值,這為區域內模型預測差異的洞察提供了幫助,通過將SHAP值與原始GeoJSON數據結合,創建一個包含詳細空間可視化SHAP值的地理空間數據集(gdf_with_shap)

ebf_pfs特征SHAP地圖

# 繪制基于 'shap_ebf_pfs' 字段的地圖
gdf_with_shap.plot(column='shap_ebf_pfs',
legend=True,
cmap=shap.plots.colors.red_white_blue, # 使用 SHAP 配色
figsize=(10, 10))
# 設置標題
plt.title("SHAP Value for ebf_pfs")
plt.savefig("SHAP_3.pdf", format='pdf', dpi=1200, bbox_inches='tight')
plt.show()

這里先單獨繪制一個特征的SHAP值地圖,以了解特征如何在不同地理區域影響PM2.5預測水平,ebf_pfs(暴露于洪水的人口百分比)的SHAP地圖顯示了這一因素在特定區域增加或減少預測PM2.5水平的影響

總結而言,這張圖展示了特征ebf_pfs在不同地理區域對模型預測結果的影響,為環境決策提供了更具針對性的區域洞察。需要注意的是,這里的重點在于如何繪制SHAP地圖,因此并未深入研究模型的精確度是否足夠應用于實際場景


全面的SHAP地圖可視化

# 提取所有以 'shap_' 開頭的列名
shap_columns = [col for col in gdf_with_shap.columns if col.startswith('shap_')]
# 創建一個畫布,設置子圖的網格布局
num_cols = len(shap_columns)
fig, axes = plt.subplots(nrows=(num_cols + 2) // 2, ncols=2, figsize=(18, 6 * ((num_cols + 2) // 2)))

# 展平 axes 數組以便于迭代
axes = axes.ravel()

# 遍歷每個 SHAP 列,繪制地圖
for i, shap_col in enumerate(shap_columns):
gdf_with_shap.plot(column=shap_col,
legend=True,
cmap=shap.plots.colors.red_white_blue,
ax=axes[i]) # 在對應子圖上繪制
axes[i].set_title(f"SHAP Value for {shap_col}", fontsize=12)

# 刪除多余的子圖(如果有的話)
for j in range(i + 1, len(axes)):
fig.delaxes(axes[j])

plt.tight_layout()
plt.savefig("SHAP_4.pdf", format='pdf', dpi=1200, bbox_inches='tight')
plt.show()

為了提供全面的視角,使用網格布局繪制了所有特征的SHAP地圖,為不同的社會經濟和環境因素如何影響各個區域的空氣質量提供了詳細的研究

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

上一篇:

深度學習二分類模型中的 SHAP 解釋:深入淺出的解讀與代碼實踐

下一篇:

SCI圖表復現:優化SHAP特征貢獻圖展示更多模型細節

我們有何不同?

API服務商零注冊

多API并行試用

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

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

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

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

#AI深度推理大模型API

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

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