CrucibleXAI.Validation.Sensitivity (CrucibleXAI v0.4.0)

View Source

Robustness 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

Types

input_result()

@type input_result() :: %{
  stability_score: float(),
  mean_variation: float(),
  max_variation: float(),
  variation_by_feature: map(),
  coefficient_of_variation: float(),
  interpretation: String.t()
}

Functions

cross_method_consistency(explanations, opts \\ [])

@spec cross_method_consistency(
  list(),
  keyword()
) :: map()

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 maps
  • opts - Options:
    • :top_k - Number of top features to compare (default: 5)
    • :metric - :rank_correlation or :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, ...}

input_sensitivity(instance, explain_fn, predict_fn, opts \\ [])

@spec input_sensitivity(list(), (any() -> any()), (any() -> any()), keyword()) ::
  input_result()

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

  1. Generate N small perturbations: x̃ᵢ ≈ x
  2. Compute explanations: φᵢ = explain(x̃ᵢ)
  3. Measure variation:
    • Mean absolute deviation: E[|φᵢ - φ̄|]
    • Max deviation: max|φᵢ - φ̄|
    • Coefficient of variation: σ/μ
  4. Return stability score: 1 - normalized_variation

Parameters

  • instance - Instance to test
  • explain_fn - Explanation function (instance -> explanation or attributions)
  • predict_fn - Prediction function
  • opts - Options:
    • :num_perturbations - Number of perturbations (default: 50)
    • :noise_level - Relative noise magnitude (default: 0.05)
    • :noise_type - :gaussian or :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", ...}

parameter_sensitivity(instance, explain_fn, param_ranges, opts \\ [])

@spec parameter_sensitivity(list(), function(), map(), keyword()) :: map()

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 test
  • explain_fn - Explanation function that accepts options
  • param_ranges - Map of parameter => list of values to test
  • opts - 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], ...}