Note
Go to the end to download the full example code.
Explaining one prediction#
Ask a soft decision tree why it predicted what it predicted for a single sample: which leaf got the mass, how each gate on the way leaned and why, and what single change would have flipped the class.
- Run with:
python examples/05_explain_prediction.py
--- test sample 0, true class 0 ---
predicted 0 with probability 0.825
dominant leaf 9 received 0.999 of the sample's mass; its distribution is 0: 0.825, 1: 0.089, 2: 0.086
path:
gate 0: went left with p=1.000 (-2.503[proline] -1.391[alcohol] -1.314[magnesium])
gate 1: went right with p=1.000 (+2.603[proline] +1.511[ash] +1.214[alcohol])
gate 4: went left with p=1.000 (-3.697[proline] -1.693[alcohol] -1.222[alcalinity_of_ash])
largest contributions: proline 8.800, alcohol 4.296, ash 2.832, alcalinity_of_ash 2.604, flavanoids 1.750
counterfactual: set proline from 1.906 to -3.025 and the prediction becomes 1 (p=0.482)
--- test sample 1, true class 1 ---
predicted 1 with probability 0.836
dominant leaf 14 received 0.969 of the sample's mass; its distribution is 0: 0.082, 1: 0.840, 2: 0.078
path:
gate 0: went right with p=0.972 (+1.632[alcohol] +1.614[proline] -1.386[hue])
gate 2: went right with p=0.998 (+3.320[hue] +1.558[alcohol] +1.014[color_intensity])
gate 6: went right with p=0.999 (+2.082[proline] +1.446[hue] +1.215[alcohol])
largest contributions: hue 6.014, alcohol 4.323, proline 4.266, color_intensity 1.873, malic_acid 1.668
counterfactual: set proline from -1.229 to 2.787 and the prediction becomes 0 (p=0.543)
--- test sample 2, true class 0 ---
predicted 0 with probability 0.824
dominant leaf 9 received 0.999 of the sample's mass; its distribution is 0: 0.825, 1: 0.089, 2: 0.086
path:
gate 0: went left with p=1.000 (-2.563[alcohol] -2.160[proline] -2.084[alcalinity_of_ash])
gate 1: went right with p=1.000 (+2.247[proline] +2.235[alcohol] +0.881[od280/od315_of_diluted_wines])
gate 4: went left with p=1.000 (-3.190[proline] -3.118[alcohol] -2.353[alcalinity_of_ash])
largest contributions: alcohol 7.913, proline 7.594, alcalinity_of_ash 5.013, od280/od315_of_diluted_wines 2.674, flavanoids 1.099
counterfactual: set alcohol from 1.647 to -3.315 and the prediction becomes 1 (p=0.606)
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from neural_trees import SoftDecisionTree
data = load_wine()
X_train, X_test, y_train, y_test = train_test_split(
data.data, data.target, test_size=0.3, stratify=data.target, random_state=0
)
scaler = StandardScaler().fit(X_train)
model = SoftDecisionTree(depth=3, max_epochs=60, random_state=0)
model.fit(scaler.transform(X_train), y_train)
# Explain the first three test samples. Values are in standardised units,
# because that is what the model was fitted on.
explanations = model.explain(scaler.transform(X_test[:3]), feature_names=list(data.feature_names))
for i, e in enumerate(explanations):
print(f"--- test sample {i}, true class {y_test[i]} ---")
print(e.to_text())
print()
Total running time of the script: (0 minutes 0.187 seconds)