You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SHAP包手动分组特征?实现RNN模型3D特征的整体SHAP值计算

问题:用SHAP计算RNN模型的整体特征重要性(按特征维度聚合)

我需要用SHAP计算RNN模型的特征重要性,模型输入是[N_instances × N_times × N_features]的3D特征矩阵,预测[N_instances × 1]的输出。比如化工反应器12小时内每小时的温度、压力时间序列(N_features=2),用来预测化学品总质量,现在只能得到每个时间点的温度/压力对应的SHAP值(共2×12个),想要获取每个特征的整体SHAP值(仅2个)。

目前我的代码实现如下(已将3D数据展平为2D适配SHAP):

# Imports
from keras.models import Sequential
from keras.layers import Dense, LSTM
import shap
import numpy as np

# Generate random 3-D X data and 1-D y data.
N_TIMES = 10
N_INSTANCES = 256
N_FEATURES = 3
X = np.random.random((N_INSTANCES, N_TIMES, N_FEATURES))
y = np.random.random((N_INSTANCES, 1))

# Write a simple model
model1 = Sequential()
model1.add(LSTM(8, input_shape=(N_TIMES, N_FEATURES), return_sequences = False, stateful=False, activation='relu'))
model1.add(Dense(1))

# Compile and train the model on data
model1.compile(loss='mean_squared_error',
              optimizer='adam',
              metrics=['MeanSquaredError'])
history = model1.fit(X,
                     y,
                     batch_size=16,
                     epochs=3,
                     verbose = 0
                    )

# Define function to take in a 2D feature array and return model predictions
def model_for_shap(X_flat):
    X = X_flat.reshape((X_flat.shape[0], N_TIMES, N_FEATURES))
    return model1.predict(X)

X_flat = X.reshape((N_INSTANCES, N_TIMES*N_FEATURES))

# Run SHAP 
background = X.reshape((X.shape[0], X.shape[1]*X.shape[2]))
e = shap.Explainer(model_for_shap, background)
shap_values = e.shap_values(X[:10].reshape((10, N_TIMES*N_FEATURES)))
print(f"Shape of shap_values: {shap_values.shape}")

输出为:

Shape of shap_values: (10, 30)

这符合预期,但我希望每次屏蔽整个特征的时间序列,得到对应N_FEATURES个特征的SHAP值(而非30个)。我认为Partition masker可能有用,但不清楚如何调整clustering参数实现目标。


解决方案:使用Partition Masker按特征维度分组

完全可以实现你的需求,核心是通过shap.PartitionMasker定义特征分组规则,把同一特征的所有时间点归为一组,这样SHAP会计算每组(即每个特征整体)的重要性。

步骤1:构建聚类分组矩阵

生成一个聚类数组,让同一特征的所有时间点对应同一个聚类ID。比如N_TIMES=10、N_FEATURES=3时,聚类数组为[0,0,...0, 1,1,...1, 2,2,...2](每个数字重复10次)。

代码实现:

# 生成聚类分组:同一特征的所有时间点属于同一组
clustering = np.repeat(np.arange(N_FEATURES), N_TIMES)

步骤2:初始化Partition Masker并适配SHAP Explainer

用上述聚类数组初始化PartitionMasker,并传入SHAP Explainer。修改后的SHAP部分代码如下:

# 生成聚类分组
clustering = np.repeat(np.arange(N_FEATURES), N_TIMES)

# 初始化Partition Masker:按分组屏蔽特征
masker = shap.PartitionMasker(
    masker=background,
    clustering=clustering
)

# 使用带masker的Explainer
e = shap.Explainer(model_for_shap, masker=masker, background=background)
shap_values = e.shap_values(X[:10].reshape((10, N_TIMES*N_FEATURES)))

# 查看结果形状:(10, 3),对应10个样本×3个特征的整体SHAP值
print(f"Shape of aggregated shap_values: {shap_values.shape}")

关键说明

  • clustering参数的作用是告知SHAP哪些特征属于同一组,同一组的特征会被同时屏蔽/暴露,从而计算该组的整体重要性。
  • 这里的分组逻辑是“同一特征的所有时间步为一组”,完美匹配你需要的“屏蔽整个特征时间序列”的需求。
  • 最终的shap_values形状为(N_samples, N_FEATURES),每个值对应一个特征的整体SHAP重要性。

验证结果

运行修改后的代码,输出会是:

Shape of aggregated shap_values: (10, 3)

这正是你需要的每个特征的整体SHAP值。


内容的提问来源于stack exchange,提问作者pckinnunen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 18:06:32