TransformersEncoderModel is Atria's native abstract transformer base class. It is both a PyTorch nn.Module and a ConfigurableModule, making it fully integrated with Atria's registry and config system — and uniquely capable of supporting all three families of explainability methods.

Why a custom base?

HuggingFace AutoModel* wrappers are powerful but opaque: they don't guarantee a stable embedding-space entry point for gradient attribution, and they don't expose a consistent interface for extracting and mapping attention weights. Timm and torchvision models have no token or embedding concept at all.

TransformersEncoderModel solves this by defining an explicit explainability contract on top of the standard nn.Module forward pass. Any model that subclasses it can be used with gradient-based, perturbation-based, and attention-based explainers without modification.

Architecture

TransformersEncoderModel (abstract)
├── BertEncoderModel         (@MODELS.register("bert-base-uncased"))     text only
├── RoBertaEncoderModel      (@MODELS.register("roberta-base"))          text only
├── LiLTEncoderModel         (@MODELS.register("lilt-roberta-base"))     text + layout
└── LayoutLMv3EncoderModel   (@MODELS.register("layoutlmv3-base"))       text + layout + image

The abstract base sets __abstract__ = True so it is never instantiated directly. Concrete subclasses register themselves in the MODELS registry and inherit all XAI interface methods.

These models are built by AtriaModelBuilder — not by TransformersModelBuilder. AtriaModelBuilder looks up the model name in the MODELS registry and constructs the full architecture from its config.

Document-understanding models

LiLT and LayoutLMv3 extend the base with additional input modalities for document AI tasks (layout analysis, entity labeling, question answering over documents):

LiLTEncoderModel processes text tokens alongside bounding-box layout coordinates. It runs two parallel transformer streams — one for text, one for layout — and couples them through cross-attention. The is_embedding=True path accepts separate text and layout embedding tensors, enabling gradient attribution over both modalities simultaneously. attn_feature_ids() returns {"token_ids", "layout_ids"}, so attention-based explainers can produce separate attention maps for text and layout streams.

LayoutLMv3EncoderModel is fully multimodal: it combines text tokens, bounding-box layout coordinates, and image patches (via a ViT-style patch embedding) in a single unified encoder. The image patches are embedded separately and concatenated with the text sequence before the transformer layers. For XAI, attn_feature_ids() returns {"token_ids", "image"}, and map_attentions_to_feature_space() handles the token/image split in the attention output, upsampling patch-level attention scores back to pixel resolution.

Config

TransformersEncoderModelConfig composes four sub-configs that mirror the structure of a standard transformer encoder:

Sub-config Purpose
embeddings_config: EmbeddingsConfig Vocab size, hidden size, max position embeddings, special token IDs (PAD, CLS, SEP, MASK)
attention_config: AttentionConfig Number of attention heads, head size, attention dropout
layers_config: LayersConfig Number of hidden layers, intermediate size, activation, hidden dropout
head_config Task head — discriminated union of SequenceClassificationHead, TokenClassificationHead, QuestionAnsweringHead
output_attentions: bool When True, the model outputs attention weights at every layer — required for attention-based XAI
output_hidden_states: bool When True, intermediate hidden states are returned
checkpoint_config: CheckpointConfig Pretrained checkpoint path (e.g. "hf://bert-base-uncased") and a key_mapping list for remapping HuggingFace weight names to Atria's architecture naming
class BertEncoderModelConfig(TransformersEncoderModelConfig):
    checkpoint_config: CheckpointConfig = CheckpointConfig(
        pretrained_checkpoint="hf://bert-base-uncased",
        key_mapping=[
            ("encoder.layer.", "encoder.layers."),
            ("LayerNorm", "layer_norm"),
            (".attention.self.", ".multi_head_attention."),
            # ...
        ],
    )

The key_mapping list handles the name differences between HuggingFace's weight naming and Atria's own layer naming, so pretrained checkpoints can be loaded without modifying the architecture.

The XAI-aware forward pass

The central design decision is the is_embedding flag:

def forward(
    self,
    token_ids_or_embeddings: torch.Tensor,
    is_embedding: bool = False,
    attention_mask: torch.Tensor | None = None,
    token_type_ids: torch.Tensor | None = None,
    ...
) -> TransformersEncoderModelOutput:

Normal inference path (is_embedding=False): token IDs enter the model, ids_to_embeddings() converts them to embedding vectors, and the encoder processes those embeddings.

Gradient attribution path (is_embedding=True): the caller passes embedding tensors directly, bypassing the (non-differentiable) token ID lookup. This is essential for gradient-based attribution methods — Integrated Gradients, DeepLIFT, GradientSHAP — which must differentiate through the full forward pass from embeddings to logits. The SequencePipeline explanation pipeline uses this path.

# Gradient explainer computes attributions in embedding space
embeddings = model.ids_to_embeddings(token_ids)
attributions = integrated_gradients.attribute(
    inputs=embeddings,
    target=label,
    additional_forward_args=(True,),  # is_embedding=True
)

ids_to_embeddings(token_ids) is the explicit conversion step — it separates the discrete lookup from the continuous forward pass.

XAI interface methods

Attention-based explainers interact with the model through three additional methods:

attn_feature_ids() -> dict[str, str]

Returns {"token_ids": "token_ids"} — declares which model input fields correspond to attention features. The AttnSequencePipeline uses this to know which input to map attention scores back to.

encoder_output_to_attn_tuples(output: TransformersEncoderModelOutput) -> tuple

Extracts the raw per-layer attention weight tensors from the model output. Requires output_attentions=True in the config.

map_attentions_to_feature_space(attentions: tuple) -> torch.Tensor

Aggregates and maps the per-head, per-layer attention weights back to the input token space — producing a single attention score per token that can be compared with gradient-based attributions.

Together these three methods form the attention explainability contract: any subclass of TransformersEncoderModel automatically supports attention-based explainability without any additional implementation work.

Explainability summary

Explainer family Mechanism Required flag
Gradient-based (IG, DeepLIFT, GradientSHAP) is_embedding=True in forward output_attentions not needed
Perturbation-based (LIME, KernelSHAP, Occlusion) Standard forward with token masking Neither flag required
Attention-based (rollout, raw weights) encoder_output_to_attn_tuples() + map_attentions_to_feature_space() output_attentions=True in config

This is the complete explainability interface. No other model type in Atria implements all three — TransformersEncoderModel is the only architecture where the full explainability suite is available.

For document-understanding models the same interface extends naturally to multiple modalities: LiLT produces separate attention maps per stream (token_ids, layout_ids), and LayoutLMv3 maps the unified attention output back to both the token sequence and the original image pixel space.