CrucibleXAI.Validation.Sensitivity (CrucibleXAI v0.4.0)
View SourceRobustness and sensitivity testing for explanations.
Measures explanation stability under input perturbations and hyperparameter variations. Stable explanations are more trustworthy and reliable.
Metrics
- Stability Score: 0-1 scale (1 = perfectly stable, 0 = very unstable)
- Mean Variation: Average change in attributions across perturbations
- Max Variation: Maximum attribution change observed
- Coefficient of Variation: Normalized stability measure (σ/μ)
Usage
# Test input sensitivity
explain_fn = fn inst -> CrucibleXai.explain(inst, predict_fn) end
result = Sensitivity.input_sensitivity(
instance,
explain_fn,
predict_fn,
num_perturbations: 50
)
IO.puts("Stability: #{result.stability_score}")
# => 0.92 (High stability)References
Based on:
- Yeh et al. (2019) "On the (In)fidelity and Sensitivity of Explanations"
- Alvarez-Melis & Jaakkola (2018) "On the Robustness of Interpretability Methods"
Summary
Functions
Test cross-method consistency.
Test sensitivity to input perturbations.
Test sensitivity to hyperparameters.
Types
Functions
Test cross-method consistency.
Different explanation methods should agree on which features are important. High consistency indicates reliable feature identification.
Parameters
explanations- List of explanation structs or attribution mapsopts- Options::top_k- Number of top features to compare (default: 5):metric-:rank_correlationor:overlap(default::rank_correlation)
Returns
Map with:
:consistency_score- 0-1 (1 = perfect agreement):pairwise_consistency- Consistency between each pair of methods:top_features_overlap- Overlap in top-k features:interpretation- Consistency assessment
Examples
lime_exp = CrucibleXai.explain(instance, predict_fn)
shap_exp = CrucibleXai.explain_shap(instance, background, predict_fn)
result = Sensitivity.cross_method_consistency([lime_exp, shap_exp])
# => %{consistency_score: 0.85, ...}
Test sensitivity to input perturbations.
Measures how much explanations change when the input is slightly perturbed. Stable explanations should be similar for similar inputs.
Algorithm
- Generate N small perturbations: x̃ᵢ ≈ x
- Compute explanations: φᵢ = explain(x̃ᵢ)
- Measure variation:
- Mean absolute deviation: E[|φᵢ - φ̄|]
- Max deviation: max|φᵢ - φ̄|
- Coefficient of variation: σ/μ
- Return stability score: 1 - normalized_variation
Parameters
instance- Instance to testexplain_fn- Explanation function (instance -> explanation or attributions)predict_fn- Prediction functionopts- Options::num_perturbations- Number of perturbations (default: 50):noise_level- Relative noise magnitude (default: 0.05):noise_type-:gaussianor:uniform(default::gaussian)
Returns
Map with:
:stability_score- 0-1 (1 = perfectly stable):mean_variation- Average attribution change:max_variation- Maximum attribution change:variation_by_feature- Per-feature variation map:coefficient_of_variation- Normalized stability (σ/μ):interpretation- Stability assessment string
Examples
explain_fn = fn inst -> %{0 => 2.0, 1 => 3.0} end # Deterministic
result = Sensitivity.input_sensitivity(instance, explain_fn, predict_fn)
# => %{stability_score: 1.0, interpretation: "Excellent", ...}
Test sensitivity to hyperparameters.
Measures how sensitive explanations are to method-specific parameters (e.g., num_samples in LIME, num_coalitions in SHAP).
Parameters
instance- Instance to testexplain_fn- Explanation function that accepts optionsparam_ranges- Map of parameter => list of values to testopts- Additional options
Returns
Map with:
:parameter_sensitivity- Variation for each parameter:robust_parameters- Parameters with low sensitivity:sensitive_parameters- Parameters with high sensitivity:recommendations- Tuning recommendations
Examples
explain_fn = fn inst, opts ->
CrucibleXai.explain(inst, predict_fn, opts)
end
result = Sensitivity.parameter_sensitivity(
instance,
explain_fn,
%{num_samples: [1000, 2000, 5000, 10000]},
[]
)
# => %{robust_parameters: [:num_samples], ...}