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.

Two publication-quality matplotlib figures are generated automatically after each experiment run, provided visualization.save_figures: true is set in the config. Both are written to the figures/ subdirectory of the run’s timestamped output directory and are ready for direct inclusion in papers or reports.

persistence_curve.png

persistence_curve.png is the main result figure. It visualizes how the backdoor degrades — and how task performance holds up — as progressively larger fractions of clean fine-tuning data are applied. The plot uses a dual-axis layout:
  • Primary y-axis (left): Attack Success Rate and Mean Trigger Confidence, both plotted against clean_ratio
  • Secondary y-axis (right): Clean Accuracy, plotted against clean_ratio
  • x-axis: Clean Fine-Tuning Ratio (0.0 to 1.0)
Attack Success Rate is drawn with a circle marker (o); Mean Trigger Confidence uses a square marker (s); Clean Accuracy uses a dashed line on the secondary axis. All three share a unified legend positioned automatically by matplotlib. The key observation this figure captures is that ASR decreases progressively as the clean fine-tuning ratio increases, while Clean Accuracy remains comparatively stable throughout — demonstrating that the inherited backdoor can be eroded without significantly degrading the model’s downstream utility.

reviewer_intervention.png

reviewer_intervention.png is a companion figure intended to highlight the specific point at which a reviewer would intervene. It plots Attack Success Rate vs. clean_ratio using the same line as the persistence curve, and marks the reviewer’s intervention point with a star (*) scatter marker at the ratio specified by reviewer.checkpoint_ratio in the config (default: 0.4).
reviewer_intervention.png is only generated when reviewer.enabled: true is set in configs/baseline.yaml. If the reviewer block is disabled, plot_reviewer_intervention() is not called and no file is written.

Plot Configuration

All figures are saved at 300 DPI using matplotlib’s constrained_layout=True, which prevents axis labels and titles from overlapping without manual padding adjustments. Global style settings are applied at module import time in src/visualization.py via plt.rcParams.update():
SettingValue
figure.figsize(8, 5)
figure.dpi300
axes.gridTrue
axes.spines.topFalse
axes.spines.rightFalse
font.size11
legend.frameonFalse
These defaults apply to every plot produced by the module. They do not need to be set manually when calling plot_backdoor_persistence() or plot_reviewer_intervention().

Regenerating Figures Manually

If you want to regenerate figures from a saved metrics.csv — for example, to adjust a label or tweak the output path — import the plotting functions directly:
import pandas as pd
from src.visualization import plot_backdoor_persistence, plot_reviewer_intervention

results = pd.read_csv("results/baseline_20260719_155148/metrics.csv")

plot_backdoor_persistence(
    results=results,
    output_path="results/baseline_20260719_155148/figures/persistence_curve",
)

plot_reviewer_intervention(
    results=results,
    reviewer_ratio=0.4,
    output_path="results/baseline_20260719_155148/figures/reviewer_intervention",
)
Both functions accept an output_path without a file extension — the .png suffix is appended automatically.

Required Columns for plot_backdoor_persistence

plot_backdoor_persistence() validates its input before drawing anything. The DataFrame passed as results must contain all four of the following columns:
  • clean_ratio
  • attack_success_rate
  • clean_accuracy
  • mean_trigger_confidence
If any column is absent, a ValueError is raised immediately with a message listing the missing column names. The same validation check is also performed by plot_reviewer_intervention().
Figures are always saved as .png regardless of whether output_path already has a suffix. The .with_suffix('.png') call inside visualization.py enforces this — passing "figures/persistence_curve.pdf" will still produce a .png file.

Build docs developers (and LLMs) love