Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Antisource/heronaisec/llms.txt

Use this file to discover all available pages before exploring further.

The evaluation module provides all inference and metric computation needed to quantify how much backdoor behaviour a model retains after an intervention. It contains no training logic, attack generation, or visualization code. The central primitive is predict(), which runs batched inference under @torch.inference_mode() and returns both hard predictions and soft probabilities. Four scalar metrics are derived from those outputs — clean accuracy, attack success rate, trigger confidence, and retention ratio — and evaluate_model() computes all four in a single call, returning a structured dictionary suitable for direct storage in a results dataframe.

Functions

predict()

Run batched inference on a dataset and return predicted labels and class probabilities. Decorated with @torch.inference_mode() for zero-overhead gradient tracking. Sets the model to model.eval() before iterating over batches. Each batch is moved to the device that the model parameters currently reside on, so CPU and CUDA models are handled transparently. Batches are assembled with DataCollatorWithPadding to avoid fixed-length padding across the entire dataset.
model
PreTrainedModel
required
The model to run inference with. Can be on any device; input tensors are moved to match.
dataset
Dataset
required
A PyTorch-formatted Dataset (from prepare_for_training()) containing "input_ids", "attention_mask", and "label" columns.
tokenizer
PreTrainedTokenizerBase
required
The tokenizer used to construct the DataCollatorWithPadding. Must match the tokenizer used to tokenize dataset.
batch_size
int
Number of examples per inference batch. Defaults to 32. Reduce for GPU memory constraints.
predictions
np.ndarray
1-D integer array of shape (N,) containing the argmax predicted class label for each example.
probabilities
np.ndarray
2-D float array of shape (N, num_labels) containing the softmax probability distribution over classes for each example.
The @torch.inference_mode() decorator is more aggressive than torch.no_grad() — it disables both gradient computation and version tracking. Do not wrap calls to predict() inside a gradient-enabled context expecting gradients to flow through it.
Example:
from src.evaluation import predict

predictions, probabilities = predict(
    model=trained_model,
    dataset=val_ready,
    tokenizer=tokenizer,
    batch_size=64,
)

print(predictions.shape)    # (872,)
print(probabilities.shape)  # (872, 2)

compute_clean_accuracy()

Compute classification accuracy on clean (uncontaminated) examples. A thin wrapper around sklearn.metrics.accuracy_score. The function does not filter by label — it compares every prediction to its corresponding ground-truth label.
predictions
np.ndarray
required
1-D integer array of predicted class labels, typically the predictions output of predict().
labels
np.ndarray
required
1-D integer array of ground-truth labels of the same length.
return
float
Accuracy in [0.0, 1.0].
Example:
import numpy as np
from src.evaluation import compute_clean_accuracy

preds  = np.array([1, 0, 1, 1, 0])
labels = np.array([1, 0, 0, 1, 0])

print(compute_clean_accuracy(preds, labels))
# 0.8

compute_attack_success_rate()

Compute the fraction of triggered examples classified as the attacker’s target label. Attack Success Rate (ASR) is the primary measure of backdoor effectiveness. A value of 1.0 means every triggered input was classified as target_label; a value of 0.0 means the backdoor has been fully eradicated.
predictions
np.ndarray
required
1-D integer array of predicted labels on a triggered (poisoned) evaluation set.
target_label
int
required
The label the attacker intended the model to predict on triggered inputs.
return
float
ASR in [0.0, 1.0], computed as np.mean(predictions == target_label).
Example:
import numpy as np
from src.evaluation import compute_attack_success_rate

triggered_preds = np.array([1, 1, 0, 1, 1])
asr = compute_attack_success_rate(triggered_preds, target_label=1)
print(asr)
# 0.8

compute_trigger_confidence()

Compute the mean softmax probability assigned to the target class on triggered inputs. A complementary metric to ASR that captures the strength of the backdoor signal rather than merely its binary presence. Even when ASR drops (e.g. the model no longer predicts the target label), trigger confidence may remain elevated, indicating residual backdoor behaviour in the model’s internal representations.
probabilities
np.ndarray
required
2-D float array of shape (N, num_labels), typically the probabilities output of predict() run on a triggered dataset.
target_label
int
required
The attacker’s target label index used to slice the probability column.
return
float
Mean probability assigned to target_label across all triggered examples, in [0.0, 1.0].
Example:
import numpy as np
from src.evaluation import compute_trigger_confidence

probs = np.array([[0.1, 0.9], [0.2, 0.8], [0.6, 0.4]])
confidence = compute_trigger_confidence(probs, target_label=1)
print(confidence)
# 0.7

compute_retention_ratio()

Compute the normalised backdoor persistence relative to a pre-intervention baseline. The Retention Ratio is defined as ASR(t) / ASR(0), where ASR(t) is the attack success rate after intervention t and ASR(0) is the baseline ASR before any intervention. A value of 1.0 means the backdoor is fully retained; a value of 0.0 means it has been completely removed. The function returns 0.0 when baseline_asr == 0 to avoid a zero-division error.
attack_success_rate
float
required
ASR after the intervention, from compute_attack_success_rate().
baseline_asr
float
required
ASR before any intervention (at ratio=0.0). Used as the denominator.
return
float
Retention ratio ASR(t) / ASR(0), or 0.0 if baseline_asr == 0.
Compute baseline_asr once by calling evaluate_model() on the original poisoned model (before any intervention) and storing the "attack_success_rate" value. Pass this constant to all subsequent compute_retention_ratio() or evaluate_model() calls in your sweep.
Example:
from src.evaluation import compute_retention_ratio

retention = compute_retention_ratio(
    attack_success_rate=0.62,
    baseline_asr=0.95,
)
print(f"{retention:.3f}")
# 0.653

evaluate_model()

Evaluate a model on clean and triggered datasets and return all four persistence metrics. Runs predict() twice — once on clean_dataset and once on triggered_dataset — then computes and returns all four metrics in a single dict. This is the primary evaluation entry-point for experiment loops.
model
PreTrainedModel
required
The model to evaluate. Should be in its final state (post-intervention or post-training).
clean_dataset
Dataset
required
A PyTorch-formatted Dataset of clean (uncontaminated) validation examples.
triggered_dataset
Dataset
required
A PyTorch-formatted Dataset where every example has the trigger token injected. Typically produced by apply_attack() on the validation split.
tokenizer
AutoTokenizer
required
The tokenizer used to build the DataCollatorWithPadding inside predict().
target_label
int
required
The attacker’s target label. Used to compute ASR, trigger confidence, and retention ratio.
baseline_asr
float
required
The ASR of the original poisoned model before any intervention. Passed directly to compute_retention_ratio().
batch_size
int
Inference batch size. Defaults to 32.
return
Dict[str, float]
A dictionary with the following keys:
KeyDescription
"clean_accuracy"Accuracy on clean validation examples
"attack_success_rate"Fraction of triggered examples predicted as target_label
"mean_trigger_confidence"Mean softmax probability for target_label on triggered inputs
"retention_ratio"attack_success_rate / baseline_asr
Example — evaluating a poisoned model and an intervened model:
from src.evaluation import evaluate_model

# Evaluate the original poisoned model to establish a baseline
baseline_metrics = evaluate_model(
    model=poisoned_model,
    clean_dataset=clean_val_ready,
    triggered_dataset=triggered_val_ready,
    tokenizer=tokenizer,
    target_label=1,
    baseline_asr=1.0,   # no prior baseline; treat the model itself as the reference
    batch_size=32,
)

baseline_asr = baseline_metrics["attack_success_rate"]
print(f"Baseline ASR: {baseline_asr:.3f}")
# Baseline ASR: 0.941

# Now evaluate after a clean fine-tuning intervention
post_intervention_metrics = evaluate_model(
    model=intervened_model,
    clean_dataset=clean_val_ready,
    triggered_dataset=triggered_val_ready,
    tokenizer=tokenizer,
    target_label=1,
    baseline_asr=baseline_asr,
    batch_size=32,
)

print(post_intervention_metrics)
# {
#   "clean_accuracy": 0.923,
#   "attack_success_rate": 0.612,
#   "mean_trigger_confidence": 0.784,
#   "retention_ratio": 0.650
# }

Build docs developers (and LLMs) love