部分依赖图 (PDP) 和个体条件期望 (ICE) 图可用于可视化和分析训练目标与一组输入特征之间的交互关系。
部分依赖图(Partial Dependence Plot)
部分依赖图显示了目标函数(即我们的机器学习模型)和一组特征之间的依赖关系,并边缘化其他特征的值(也就是补充特征)。它们是通过将模型应用于一组数据、改变感兴趣特征的值同时保持补充特征的值不变可以分析模型输出来计算特征变量对模型预测结果影响的函数关系:例如近似线性关系、单调关系或者更复杂的关系。
个体条件期望图(Individual Conditional Expectation )
虽然 PDP 擅长显示目标特征的平均效果,但它可能会模糊仅在某些样本上显示特征的关系影响。
所以个体的条件期望 (ICE) 图显示了目标函数和特征之间的依赖关系。与显示一组特征的平均效果的部分依赖图不同,ICE 图消除了非均匀效应的影响并分别可视化每个样本的预测对特征的依赖关系,每个样本一行。
代码示例
注:sklearn 0.24以后的版本也加入对这两个图进行绘制的功能,但是这里我们使用更好的shap库
from sklearn.datasets import fetch_california_housing
from sklearn.ensemble import RandomForestRegressor
from sklearn.inspection import PartialDependenceDisplay
import matplotlib.pyplot as plt
在本文中,我们使用加州住房的数据集,其目的是使用收入中位数或每户房间数量等特征来预测街区的平均房价。首先训练一个 RandomForestRegressor 来根据这些特征预测房价,最后使用 sklearn.inspection 模块中的 PartialDependenceDisplay 类制作部分依赖图和个体条件期望图。
我们主要处理以下这些特性:
- AveOccup:平均家庭成员数。
- MedInc:收入中位数。
加载加州住房数据集
X, y = fetch_california_housing (return_X_y = True, as_frame = True)
目标变量是加州地区的房屋价值中位数,以数十万美元($100,000)表示。该数据集来自 1990 年的美国 人口普查发布样本数据(街区是最小的地理单位,通常是一个街区人口为 600 至 3,000 人)。
- MedInc 收入中位数
- HouseAge 房屋年龄中位数
- AveRooms 每户平均房间数
- AveBedrms 每户平均卧室数量
- Population 人口数
- AveOccup 平均家庭成员数
- Latitude 纬度
- Longitude 经度
以下是数据集中的一些样本特征值。目标特征,即 每个街区的平均价格,在 0 到 5 之间浮动,数值以十万美元表示。
让我们先训练一个 RandomForestRegressor 来学习从房屋特征中预测价格。
model = RandomForestRegressor(random_state=42).fit(X, y)
然后使用 Shap 库来进行绘图,Shap库中包含几种可解释的 AI 相关方法。
pip install shap
导入 Shap 库并创建一小部分训练数据,在本例中为 100 个样本
import shap
X100 = X.sample(n=100)
接下来,使用 shap.plots 模块的 partial_dependence 函数制作部分依赖图,并作为参数传递:
- 目标特征(AveOccup)。
- 预测函数 (model.predict)。
- 数据集 (X100)。
- 是否制作部分依赖图或个体条件期望图。
- 是否还绘制平均模型预测 (model_expected_value) 和平均特征值 (feature_expected_value)。
shap.plots.partial_dependence(
"AveOccup", model.predict, X100, ice=False,
model_expected_value=True, feature_expected_value=True
)
函数会迭代 X100 中的所有样本,并且对于每个样本多次调用 model.predict 函数,修改目标特征的值,但保持补充特征(即所有其他特征)不变。结果图显示了整个数据集上每个目标特征值的模型平均输出。
上图中可以看到当 AveOccup 低于 2 时,预期模型 Prediction 很高,然后它迅速下降,直到 AveOccup 为 4,并且对于更高的 AveOccup 基本保持不变。
让我们对 MedInc 做同样的事情。
shap.plots.partial_dependence(
"MedInc", model.predict, X100, ice=False,
model_expected_value=True, feature_expected_value=True
)
看起来平均预测家庭价格随着收入中位数的增加而增加。
下面尝试下个体条件期望图。可以再次使用 partial_dependence 函数来制作它们,但这次将 ice 参数设置为 True。
shap.plots.partial_dependence(
"AveOccup", model.predict, X100, ice=True,
model_expected_value=True, feature_expected_value=True
)
结果仍然显示了 AveOccup 特征变化的平均模型预测,即深蓝色线。但是,ICE 图还显示了每个样本的输出变化,这使我们能够查看是否存在具有不同特征交互的样本。
例如在图表的顶部,可以看到模型预测高价的街区不会随着 AveOccup 特征的变化而发生太大变化。这些样本可以进一步的进行研究。
同样计算 MedInc 特征的 ICE 图。
shap.plots.partial_dependence(
"MedInc", model.predict, X100, ice=True,
model_expected_value=True, feature_expected_value=True
)
该模型遵循的规则是:较高的 MedInc 表明大多数样本的价格较高,但仍有一些例外情况值得调查研究。
现在我们可以尝试找出 AveOccup、MedInc 和街区价格之间的关系。首先创建了一个散点图,其中 x 是 AveOccup,y 是 MedInc,每个样本颜色代表块组价格。
px.scatter(x=X["AveOccup"], y=X["MedInc"], color=y,
labels={"x": "AveOccup", "y": "MedInc", "color": "price"},
range_x=(0, 10))
具有低 AveOccup 和高 MedInc 的样本似乎具有更高的价格,这正是我们看到模型学到的,这要归功于部分依赖和个体条件期望图。看起来模型已经学会了有意义的规则🙂
总结
在本文中,我们通过一个简单据集的回归示例了解了部分依赖图 (PDP) 和个体条件期望 (ICE) 图是什么,以及如何在 Python 中制作它们。
如果你对可解释性感兴趣那么可以尝试对现有的项目使用部分依赖图并分析模型学习到的规则,或者可以使用 LIME 和 SHAP 了解有关可解释 AI 的模式。
作者:Fabio Chiusano