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

使用GradientExplainer(shap)分析TensorFlow多输入多输出模型时出现KeyError

解决多输入模型的SHAP KeyError问题

你的KeyError源于多输入模型与SHAP交互时的数据格式不匹配,以下是具体修复方案:

问题根源

模型接收两个输入分支(数值特征、分类特征),但调用explainer()时混合使用了DataFrame和numpy数组,导致SHAP无法正确匹配模型的输入层结构。多输入场景下,SHAP要求背景数据和待解释数据的结构、类型完全一致。

修复步骤

1. 统一输入数据类型

将所有输入数据转为numpy数组,避免DataFrame与数组混合使用,确保训练和解释阶段的数据格式一致:

# 转换训练数据为numpy数组
X_train_num_arr = X_train_num.values
X_train_emb_arr = X_train_emb.values
y_train_arr = y_train.values

# 用数组训练模型(与解释阶段保持格式统一)
history = model.fit([X_train_num_arr, X_train_emb_arr], y_train_arr, verbose=1, 
                    epochs=10, batch_size=50)

2. 正确初始化并调用GradientExplainer

背景数据和待解释数据都使用numpy数组列表,严格匹配模型的输入结构:

# 用numpy数组初始化Explainer
explainer = shap.GradientExplainer(model, [X_train_num_arr, X_train_emb_arr])

# 解释时传入同结构的数组列表
shap_values = explainer([X_train_num_arr, X_train_emb_arr])

3. 处理SHAP输出结果

多输入模型的SHAP结果是一个列表,每个元素对应一个输入分支的SHAP值:

  • shap_values[0]:数值特征的SHAP值,形状为(样本数, 数值特征数, 目标数)
  • shap_values[1]:分类特征嵌入后的SHAP值,形状为(样本数, 嵌入维度, 目标数)

若需要查看原始分类特征的贡献,可将嵌入层的SHAP值与嵌入层权重做加权和,映射回原分类特征维度。

完整修正代码

import shap
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.initializers import glorot_uniform
import pandas as pd
import numpy as np

# 生成测试数据
X_train_num = pd.DataFrame(np.random.randint(0,100,size=(1000, 33)))
X_train_emb = pd.DataFrame(np.random.randint(0,19,size=(1000, 1)))
y_train = pd.DataFrame(np.random.randint(0,100,size=(1000, 5)))

final_features = X_train_num.columns
targets = y_train.columns

# 定义优化器
optimizer = Adam(
    learning_rate=0.0002,
    beta_1=0.9,
    beta_2=0.999,
    epsilon=1e-07,
    amsgrad=False
)

# 构建多输入模型
def get_model(final_features, targets):   
    no_of_unique_cat = 20 
    embedding_size = 10

    layer_numerical = Input(shape=(len(final_features),)) 
    cat_input = Input(shape=(1,))
    embed_layer = Embedding(input_dim=no_of_unique_cat, output_dim=embedding_size)(cat_input)
    embed_layer = Flatten()(embed_layer)
    merged_layer = concatenate([layer_numerical, embed_layer])

    output = Dropout(0.1)(merged_layer)
    output = Dense(360, kernel_initializer=glorot_uniform(), activation='relu')(output)
    output = Dropout(0.3)(output)
    output = Dense(20, kernel_initializer=glorot_uniform(), activation='relu')(output)
    output = Dense(len(targets))(output)
    
    model = models.Model(inputs=[layer_numerical, cat_input], outputs=output)
    model.compile(loss='mae', optimizer=optimizer)
    return model

model = get_model(final_features, targets)

# 统一转换为numpy数组
X_train_num_arr = X_train_num.values
X_train_emb_arr = X_train_emb.values
y_train_arr = y_train.values

# 训练模型
history = model.fit([X_train_num_arr, X_train_emb_arr], y_train_arr, verbose=1, 
                    epochs=10, batch_size=50)

# SHAP模型解释
explainer = shap.GradientExplainer(model, [X_train_num_arr, X_train_emb_arr])
shap_values = explainer([X_train_num_arr, X_train_emb_arr])

# 打印结果结构验证
print(f"数值特征SHAP形状: {shap_values[0].shape}")
print(f"分类特征SHAP形状: {shap_values[1].shape}")

内容的提问来源于stack exchange,提问作者Jaime Hernandez-Sanchez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:10:24