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

使用LIME解释带Sigmoid输出的二分类DNN模型时的问题

解决Keras二分类DNN结合LIME解释的概率输出问题

问题背景

要给输出层为单神经元+Sigmoid激活的二分类DNN模型用LIME做结果解释,遇到两个核心问题:

  1. Keras Sequential模型没有predict_proba方法,自带的predict方法被误以为只输出0/1(实际是正类概率)
  2. 自定义的概率转换函数返回3D数组,导致LIME的explain_instance报错

错误原因分析

  1. 关于predict方法的误解:Keras中Sigmoid输出的二分类模型,predict方法返回的是每个样本属于正类的概率(形状为(n_samples, 1)的2D数组),并非直接输出0/1的硬分类结果,除非手动添加了阈值判断(比如predict(data) > 0.5)。
  2. 3D数组的由来:之前写的prob函数中,model.predict(data)返回(n_samples,1)的数组,用zip(1-model.predict(data), model.predict(data))会生成每个元素为两个长度为1的数组的迭代器,转成np.array后就变成了(n_samples, 2, 1)的3D数组,而LIME要求输入的概率是(n_samples, 2)的2D数组(每个样本对应两个类别的概率)。

解决方案

1. 修正概率转换函数

将predict返回的2D数组压平为1D,再与1-概率拼接成符合LIME要求的2D数组:

def custom_predict_proba(data):
    # 获取正类概率,从(n_samples,1)压平为(n_samples,)
    pos_probs = DNN.predict(data).flatten()
    # 拼接负类概率和正类概率,得到(n_samples,2)的数组
    return np.column_stack((1 - pos_probs, pos_probs))

2. 修正LIME Explainer初始化

LIME的LimeTabularExplainer应该使用训练数据初始化,保证解释时的数据分布与模型训练一致,避免用测试数据初始化:

explainer = lime_tabular.LimeTabularExplainer(
    training_data=np.array(nsl_kdd_train_X2),
    feature_names=nsl_kdd_data_X2.columns,
    class_names=['normal', 'anomaly'],
    mode="classification",
    verbose=True
)

完整修正代码

import tensorflow as tf
import numpy as np
from lime import lime_tabular

# 构建并训练DNN模型
DNN = tf.keras.models.Sequential([
    tf.keras.layers.Input(121),
    tf.keras.layers.Dense(182, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(182, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

DNN.compile(optimizer='adam',
            loss="binary_crossentropy",
            metrics=['accuracy'])

DNN_trained = DNN.fit(nsl_kdd_train_X2, nsl_kdd_train_Y2, epochs=5)

# 自定义符合LIME要求的概率预测函数
def custom_predict_proba(data):
    pos_probs = DNN.predict(data).flatten()
    return np.column_stack((1 - pos_probs, pos_probs))

# 初始化LIME解释器
explainer = lime_tabular.LimeTabularExplainer(
    training_data=np.array(nsl_kdd_train_X2),
    feature_names=nsl_kdd_data_X2.columns,
    class_names=['normal', 'anomaly'],
    mode="classification",
    verbose=True
)

# 对测试集中的样本进行解释
explanation = explainer.explain_instance(
    nsl_kdd_test_X2.iloc[1],  # 注意:如果是DataFrame需要用iloc取行,避免索引问题
    custom_predict_proba,
    num_features=len(nsl_kdd_data_X2.columns)
)

# 可视化解释结果
explanation.show_in_notebook()
# 或者保存为HTML文件
explanation.save_to_file('explanation.html')

额外注意

如果nsl_kdd_test_X2是Pandas DataFrame,取单个样本时要用iloc[1]而不是[1],否则会返回列而不是行,导致输入形状不匹配模型要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 14:04:53