inseq

repository·main·Indexed 19 days ago

https://github.com/inseq-team/inseq

A PyTorch-based toolkit for post-hoc interpretability analysis of sequence generation models. It enables developers to attribute model outputs to specific input tokens using gradient-based (e.g., Integrated Gradients, Saliency), internals-based (Attention), and perturbation-based (e.g., LIME, Occlusion) methods. The library supports 🤗 Transformers models, including encoder-decoder and decoder-only architectures, and provides a CLI for attributing single texts or Hugging Face datasets.

Tokens
21K
Snippets
57
Records
115
Agent score
66%

What's inside inseq

  1. Interpret attribution results with FeatureAttribution classes

    main

    Inseq uses a hierarchy of output classes to represent attribution scores at different granularities:

    • FeatureAttributionOutput: The primary container for feature attribution results.
    • FeatureAttributionStepOutput: Represents attribution scores for a specific step in a sequence.
    • FeatureAttributionSequenceOutput: Represents attribution scores across an entire sequence.

    For higher resolution analysis, use the Granular variants:

    • GranularFeatureAttributionOutput (implied by hierarchy)
    • GranularFeatureAttributionStepOutput
    • GranularFeatureAttributionSequenceOutput
  2. Use Aggregators to process attribution data

    main

    Inseq provides several aggregator classes to process and transform attribution scores. Aggregators allow you to combine, slice, or reshape attribution data (such as token-level scores) into different granularities or formats suitable for analysis or visualization.

    Key components include:

    • Aggregator: The base class for all aggregation logic.
    • AggregatorPipeline: Allows chaining multiple aggregation steps together.
    • AggregableMixin: A mixin used to provide aggregation capabilities to other data structures.

    Common specialized aggregators include:

    • SequenceAttributionAggregator: For aggregating scores across a sequence.
    • ContiguousSpanAggregator: For aggregating scores over specific contiguous spans of text.
    • SubwordAggregator: For aggregating scores from subword tokens up to word or character levels.
    • PairAggregator: For aggregating scores based on pairs of elements.
    • SliceAggregator: For extracting specific slices of attribution data.
  3. Use AggregatorPipeline to compose multiple aggregation steps

    main

    An AggregatorPipeline allows you to chain multiple aggregation steps together to transform attribution data. This is useful when the two sequences being compared have different tokenization patterns or dimensionalities.

    Commonly used components in a pipeline include:

    • ContiguousSpanAggregator: Merges contiguous tokens/spans.
    • SequenceAttributionAggregator: Aggregates dimensions to reduce the attribution to a token-level representation.
    from inseq.data.aggregator import AggregatorPipeline, ContiguousSpanAggregator, SequenceAttributionAggregator
    
    squeezesum = AggregatorPipeline([ContiguousSpanAggregator, SequenceAttributionAggregator])
  4. Understand the FeatureAttributionOutput class

    main

    The FeatureAttributionOutput object is the primary container for attribution results. It contains:

    • sequence_attributions: A list of FeatureAttributionSequenceOutput objects (one per attributed sequence). These contain the core data: source_attributions, target_attributions, tokenized source and target sequences, and step_scores.
    • step_attributions: Per-step attributions across all examples. This is populated only if you pass output_step_attributions=True to the .attribute() method.
    • info: A dictionary containing metadata about the process, such as the attributed model, methods used, execution time, and generation/attribution parameters.

    Note: out[0] is a convenient shortcut for out.sequence_attributions[0].

  5. Manage batches with Inseq Batch classes

    main

    Inseq provides several specialized batch classes to handle different model architectures and data requirements during attribution tasks:

    • Batch: The base class for batch data.
    • BatchEncoding: Specifically for encoder-based models.
    • BatchEmbedding: For handling embedding-based data.
    • EncoderDecoderBatch: For encoder-decoder architectures.
    • DecoderOnlyBatch: For decoder-only architectures (e.g., GPT-style models).
  6. How StepFunctionArgs works

    main

    When defining a custom step function, Inseq passes a StepFunctionArgs object (or its subclasses StepFunctionDecoderOnlyArgs and StepFunctionEncoderDecoderArgs) which encapsulates the necessary context for the attribution calculation.

    Commonly available attributes in StepFunctionArgs:

    • attribution_model: The model instance used to compute attributions.
    • forward_output: The output of the forward pass of the attribution model.
    • target_ids: The IDs corresponding to the next predicted tokens for the current generation step.
    • ids: The input IDs for the current step.
    • embeddings: The input embeddings.
    • attention_mask: The attention mask for the model input.
    • encoder_input_embeds / encoder_attention_mask: (For encoder-decoder models) The encoder inputs.
  7. Available Attribution Methods in Inseq

    main

    Inseq provides several categories of attribution methods to explain model behavior:

    Gradient-based Attribution

    These methods use gradients of the output with respect to the input to assign importance scores.

    • DeepLiftAttribution
    • DiscretizedIntegratedGradientsAttribution
    • GradientShapAttribution
    • IntegratedGradientsAttribution
    • InputXGradientAttribution
    • SaliencyAttribution
    • SequentialIntegratedGradientsAttribution

    Layer Attribution (specialized gradient methods for internal layers):

    • LayerIntegratedGradientsAttribution
    • LayerGradientXActivationAttribution
    • LayerDeepLiftAttribution

    Internals-based Attribution

    These methods focus on the internal states of the model, such as attention mechanisms.

    • AttentionWeightsAttribution

    Perturbation-based Attribution

    These methods assign importance by observing how the model's output changes when parts of the input are modified or removed.

    • OcclusionAttribution
    • LimeAttribution
    • ValueZeroingAttribution
    • ReagentAttribution
  8. How AttributionModel works

    main

    The AttributionModel class is a torch.nn.Module that wraps Hugging Face sequence generation models to enable interpretability. It extends standard models with capabilities for loading weights, performing feature attribution, and utility methods for encoding, embedding, and generating text.

    AttributionModel is composed of two types of subclasses:

    1. Architectural classes (e.g., EncoderDecoderAttributionModel): Define methods specific to a model architecture.
    2. Framework classes (e.g., HuggingfaceModel): Specify methods specific to a modeling framework like Hugging Face transformers.

    Users typically instantiate a combined class, such as HuggingfaceEncoderDecoderModel for sequence-to-sequence models.

  9. Use aggregation functions with FeatureAttributionOutput.aggregate

    main

    When calling the .aggregate() method on a FeatureAttributionOutput object, you can pass an instance of an aggregation function to specify how individual attribution scores should be combined. This allows you to reduce high-dimensional attribution data into a more manageable summary based on different mathematical strategies.

    # Example pattern for using an aggregation function
    # (Note: specific class names depend on the desired strategy)
    aggregated_output = attribution_output.aggregate(MeanAggregationFunction())
  10. Quickstart with Inseq

    main

    Inseq is a PyTorch-based toolkit for studying interpretability in sequence generation models. It supports Hugging Face Transformers models and various feature attribution methods (leveraging Captum).

    With Inseq, you can perform source-side attribution, extract step scores, aggregate attributions, and visualize results as HTML (for Jupyter notebooks) or in the console using rich.

    import inseq
    
    # Load a model with a specific attribution method
    model = inseq.load_model("Helsinki-NLP/opus-mt-en-fr", "integrated_gradients")
    
    # Perform attribution
    out = model.attribute(
        "The developer argued with the designer because she did not like the design.",
        n_steps=300,
        return_convergence_delta=True,
        step_scores=["probability"],
    )
    
    # Visualize the results
    out.show()
  11. Register and use custom attribution step functions

    main

    Inseq allows you to define custom target functions for feature attribution. While the default target is the next token's probability, you can implement custom logic (e.g., probability differences for contrastive explanations) by following the standard StepFunction template.

    To use a custom function:

    1. Define a function that accepts StepFunctionArgs (and any additional keyword arguments you need).
    2. Register the function using inseq.register_step_function.
    3. Pass the registered identifier to the attributed_fn parameter in model.attribute().
    4. Provide any extra arguments required by your function as keyword arguments in model.attribute().

    Note: If your function returns probabilities or values that should be aggregated over contiguous tokens, specify an aggregate_map during registration to tell Inseq how to handle them (e.g., using prod for products).

    import inseq
    from inseq.attr.step_functions import probability_fn, StepFunctionArgs
    
    # 1. Define the custom function
    def example_prob_diff_fn(args: StepFunctionArgs, contrast_ids, contrast_attention_mask):
        # ... implementation logic ...
        return model_probs - contrast_probs
    
    # 2. Register the function
    inseq.register_step_function(
        fn=example_prob_diff_fn,
        identifier="example_prob_diff",
        aggregate_map={"span_aggregate": lambda x: x.prod(dim=1, keepdim=True)},
    )
    
    # 3. Use it in attribution
    attribution_model = inseq.load_model("Helsinki-NLP/opus-mt-en-it", "saliency")
    contrast = attribution_model.encode("Ho salutato la manager", as_targets=True)
    
    out = attribution_model.attribute(
        "I said hi to the manager",
        "Ho salutato il manager",
        attributed_fn="example_prob_diff",
        contrast_ids=contrast.input_ids,
        contrast_attention_mask=contrast.attention_mask,
        attribute_target=True,
        step_scores=["example_prob_diff"]
    )