Skip to content

Add a ConceptLocalizer via Black-box Attributions - #186

Open
Agustin-Picard wants to merge 11 commits into
masterfrom
feat/concept-localizer
Open

Add a ConceptLocalizer via Black-box Attributions#186
Agustin-Picard wants to merge 11 commits into
masterfrom
feat/concept-localizer

Conversation

@Agustin-Picard

@Agustin-Picard Agustin-Picard commented Aug 31, 2026

Copy link
Copy Markdown
Member

This PR introduces input-to-concept localization for HolisticCraft,
answering the question "which regions of the input are responsible for
activating concept k?"
by exposing the fitted concept extractor as a
K-output black-box model and delegating to any compatible Xplique
attribution method (initially validated with Rise and
SobolAttributionMethod).

It complements — but does not replace — the existing coefficient-based
concept visualization, and reuses the standard Xplique attribution
machinery instead of introducing a parallel concept-specific explanation
stack.

Motivation

HolisticCraft currently visualizes concept coefficients U_k(x) as spatial
heatmaps by resizing them to the input resolution. This is a direct
visualization of the latent coefficients — not an input attribution — and can
be misleading for deep architectures, large receptive fields, attention-based
models, complex latent cuts, multi-scale models, and object-detection
backbones.

This PR adds a second, complementary interpretation:

flowchart LR
    X["input x"] --> LOC["ConceptLocalizer"]
    subgraph LOC_INTERNALS ["ConceptLocalizer internals"]
        direction LR
        E["latent extractor"] --> F["factorizer.encode(...)"]
        F --> R["spatial reduction<br/>per concept"]
        R --> S["[s_1(x), ..., s_K(x)]"]
    end
    LOC --> LOC_INTERNALS
    LOC_INTERNALS --> BB["black-box attribution<br/>method targeting concept k"]
    BB --> H["input-space<br/>localization heatmap"]
Loading

The ConceptLocalizer behaves like a K-output black-box model, so
concept k can be targeted with an ordinary one-hot vector, without any
custom attribution operator.

The proposed abstraction is symmetric with the existing ConceptDecoder:

flowchart LR
    subgraph EXISTING ["Existing"]
        direction LR
        C1["concept coefficients"] --> D1["ConceptDecoder"] --> P1["final prediction"]
    end
    subgraph NEW ["New"]
        direction LR
        I2["input image"] --> L2["ConceptLocalizer"] --> S2["concept scores"]
    end
Loading

Concept vocabulary

The PR makes the three distinct quantities explicit throughout docstrings:

Concept Answers Existing / New
Concept activation How strongly concept k is present in the latent Existing
Concept importance How much concept k contributes to the task prediction Existing
Concept localization Which input regions drive activation of concept k New

What this PR adds

New abstractions

  • ConceptLocalizer (xplique/concepts/holistic_craft.py)

    • Framework-agnostic base that maps encoded concept coefficients to one
      scalar score per concept.
    • Supports string reducers "mean", "sum", "max" and arbitrary
      callables. Default is "mean" (consistent with the existing
      top-image ranking).
    • Handles spatial [B, H, W, K], token [B, T, K], and already-global
      [B, K] coefficient layouts; validates output shape and finiteness.
    • Wraps NotImplementedError from non-inductive factorizers into a
      clear RuntimeError explaining that factorizer.encode() is
      required because attribution methods evaluate perturbed inputs.
    • Signed coefficients are preserved; users can pass a callable reducer
      (e.g. mean absolute activation) when magnitude is intended.
  • ConceptLocalizerTf (xplique/concepts/tf/holistic_craft.py)

    • Callable that returns a tf.Tensor with shape (B, K).
  • ConceptLocalizerTorch (xplique/concepts/torch/holistic_craft.py)

    • nn.Module that accepts native NCHW tensors.
    • HolisticCraftTorch.make_concept_localizer() returns it wrapped in
      Xplique's existing TorchWrapper with is_channel_first=True and
      requires_grad=False, so Xplique's standard NHWC-to-NCHW conversion
      and device handling apply and no gradient path is used.

New HolisticCraft API

  • HolisticCraft.make_concept_localizer(concept_reducer="mean") (abstract,
    implemented per framework). Mirrors the existing
    make_concept_decoder(latent_data) symmetry:

    ConceptDecoder   : coefficients -> prediction
    ConceptLocalizer : input        -> concept scores
    
  • HolisticCraft.compute_concept_attributions(images, partial_explainer, ...)

    • Accepts any PartialExplainer configured with a compatible
      black-box explainer (validated for Rise and
      SobolAttributionMethod; compatible with Occlusion, Lime,
      KernelShap, and callable explainer factories).
    • Rejects WhiteBoxExplainer subclasses and any explicit operator
      argument with an actionable error.
    • Validates concept_ids (integers, no booleans, no duplicates,
      in range, non-empty) before any expensive work; enforces
      non-empty batches with positive spatial dimensions.
    • Normalizes image batches to Xplique's channel-last convention
      (NHWC), including PyTorch Tensor / list inputs.
    • Builds the localizer and the explainer instance once and reuses
      them across all requested concepts.
    • Returns float32 maps of shape (N, H, W, number_of_concepts).
      Uncomputed channels are NaN so that "not computed" is
      unambiguously distinguishable from a valid zero attribution.
      concept_ids=None returns a fully finite tensor.
    • Accepts explainer outputs shaped (N, H, W) or (N, H, W, 1);
      unexpected shapes / channel counts / non-finite values are rejected
      with informative errors.

Visualization integration

  • display_concept_heatmap()
    • Extended to also accept input-resolution attribution maps.
    • Skips the resize step when the heatmap already matches the image
      resolution (avoids needlessly resampling RISE / Sobol maps).
    • Squeezes (H, W, 1) maps to (H, W) and validates finiteness.
  • display_images_per_concept(..., concept_maps=None)
    • When concept_maps=None, behavior is identical to v2.0.0 (uses
      coeffs_u).
    • When concept_maps is provided, it drives the overlays; coeffs_u
      keeps its original meaning.
  • display_top_images_per_concept(..., concept_maps=None)
    • Top-image ranking remains coefficient-based (coeffs_u);
      attribution maps only drive the overlays. This preserves the
      semantic that concept-coefficient magnitude represents presence
      while attribution maps represent input sensitivity of the concept
      score.
  • Shared helpers _normalize_image_batch_to_nhwc,
    _validate_concept_ids, _prepare_concept_maps, and
    _resolve_concept_map_source back both display paths and the new
    attribution API, eliminating the previous duplicated NHWC / order
    validation and concentrating localization-specific logic in one
    place.

Backward compatibility

  • All existing calls to display_images_per_concept(images[, coeffs_u=...])
    and display_top_images_per_concept(images[, coeffs_u=...]) retain the
    exact v2.0.0 rendering and ordering behavior.
  • No existing user incurs additional attribution computation.
  • ConceptDecoder, compute_explanation_per_concept(),
    estimate_importance(), and get_topk_images_per_concept() are
    not modified.
  • Public API additions are opt-in.

Documentation and tutorials

Colab tutorial (simple for now): https://colab.research.google.com/drive/19SRZXMVztdSPEUJm5ggT-hoTujVzybnV?usp=sharing

@Agustin-Picard Agustin-Picard self-assigned this Aug 31, 2026
@Agustin-Picard Agustin-Picard added feature-attribution New feature or issue concerning Attribution methods concept New feature or issue concerning Concept based method labels Aug 31, 2026
@Agustin-Picard
Agustin-Picard marked this pull request as ready for review September 3, 2026 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

concept New feature or issue concerning Concept based method feature-attribution New feature or issue concerning Attribution methods

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant