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

线性模型SHAP值手动计算与SHAP库结果差异原因问询

线性模型手动计算SHAP值与SHAP库结果不一致的原因

我训练了一个预测房价的线性模型,对比手动计算的Shapley值和SHAP库返回值时发现存在细微差异。我理解线性模型的Shapley值计算公式应该是:
coeff * features for obs - coeffs * mean(features in training set)
或SHAP文档所述的coef[i] * (x[i] - X.mean(0)[i])(i代表单个特征),想知道为什么两者结果不同。

相关代码

import pandas as pd
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import shap

X, y = fetch_california_housing(return_X_y=True, as_frame=True)
X = X.drop(columns = ["Latitude", "Longitude", "AveBedrms"])

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=0,
)

scaler = MinMaxScaler().set_output(transform="pandas").fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

linreg = LinearRegression().fit(X_train, y_train)
coeffs = pd.Series(linreg.coef_, index=linreg.feature_names_in_)

X_test.reset_index(inplace=True, drop=True)
obs = 6188

# 手动计算Shapley值
effect = coeffs * X_test.loc[obs]
manual_shap = effect - coeffs * X_train.mean()

手动计算结果

MedInc        0.123210
HouseAge     -0.459784
AveRooms     -0.128162
Population    0.032673
AveOccup     -0.001993
dtype: float64

SHAP库计算代码与结果

explainer = shap.LinearExplainer(linreg, X_train)
shap_values = explainer(X_test)
shap_values[obs]

返回结果:

.values =
array([ 0.12039244, -0.47172515, -0.12767778,  0.03473923, -0.00251017])

.base_values =
2.0809714707337523

.data =
array([0.25094137, 0.01960784, 0.06056066, 0.07912217, 0.00437137])

当前已设置忽略交互项:

explainer.feature_perturbation

返回:'interventional'


差异原因分析

1. 手动计算的逻辑误差

虽然数学上effect - coeffs * X_train.mean()等价于coeffs * (X_test.loc[obs] - X_train.mean()),但分步计算可能引入额外的浮点数累积误差。建议简化手动计算代码为:

manual_shap = coeffs * (X_test.loc[obs] - X_train.mean())

再对比结果,看差异是否缩小。

2. 特征与系数的匹配问题

需确保coeffs的特征顺序与X_test的列顺序完全一致。虽然代码中用linreg.feature_names_in_对齐了索引,但可通过以下代码验证:

assert list(coeffs.index) == list(X_test.columns), "特征顺序不匹配"

3. SHAP的数值处理细节

SHAP的LinearExplainer在interventional模式下,会直接使用模型系数与训练集特征均值计算SHAP值,但内部可能采用了更精确的数值优化(比如批量计算时的精度处理),这可能导致与手动单样本计算的细微差异。

4. 基准值与预测值的一致性校验

SHAP值的核心要求是:单个样本的SHAP值之和 + base_value = 模型对该样本的预测值。你可以通过以下代码验证:

# 验证SHAP值的正确性
pred_obs = linreg.predict(X_test.loc[obs:obs])[0]
base_value = linreg.predict(X_train).mean()
shap_sum = shap_values[obs].values.sum()
print(f"SHAP和验证:{abs(pred_obs - base_value - shap_sum) < 1e-6}")

# 验证手动计算的正确性
manual_sum = manual_shap.sum()
print(f"手动计算和验证:{abs(pred_obs - base_value - manual_sum) < 1e-6}")

如果手动计算的验证结果为False,说明你的手动计算中存在特征均值、系数或测试样本值的匹配错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 12:14:51