Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6e87b61
fix: mislabeling bug
dilyabareeva Apr 21, 2026
251898c
chore: update dattri default cfg
dilyabareeva Apr 22, 2026
13805ed
chore: update configs with unimportant things
dilyabareeva Apr 22, 2026
961bf09
fix: similarity test data bug
dilyabareeva Apr 22, 2026
1e37e9d
fix: modules from_pretrained not class method bug
dilyabareeva Apr 22, 2026
ddaac58
fix: explainer improvements
dilyabareeva Apr 22, 2026
d170026
chore: eval script updates
dilyabareeva Apr 22, 2026
38ea301
fix: ruff and minor
dilyabareeva Apr 22, 2026
7fd250a
feat: adjust representer_points to text_classification
dilyabareeva Apr 22, 2026
87f1673
style: improve by removing in-code asserts, improving docstrings, abs…
dilyabareeva Apr 22, 2026
60f2b08
fix: explainer ds and device handling
dilyabareeva Apr 22, 2026
a799325
fix: add shuffle to train (critical, I've recalc'ed benchmarks after …
dilyabareeva Apr 22, 2026
fe21050
fix: clean explainers cache if regenerate flag
dilyabareeva Apr 23, 2026
77b9302
test: update tests after small refactor
dilyabareeva Apr 23, 2026
e524082
fix: kronfluence caching
dilyabareeva Apr 23, 2026
f4b6cb7
chore: eval script updates
dilyabareeva Apr 23, 2026
daa013b
fix: small
dilyabareeva Apr 23, 2026
c4fdace
fix: representer best_w missing
dilyabareeva Apr 23, 2026
cbe2860
fix: reinstate self_influence stable ranking
dilyabareeva Apr 23, 2026
35ce322
fix: cache explainer arfifacts separately per model_id
dilyabareeva Apr 23, 2026
16bb485
fix: representer mypy error
dilyabareeva Apr 23, 2026
b6433b6
test: fix failing tests
dilyabareeva Apr 23, 2026
4e59df8
chore: update eval scripts
dilyabareeva Apr 23, 2026
1d48c9b
test: fix failing test
dilyabareeva Apr 23, 2026
dfdc820
test: increase coverage
dilyabareeva Apr 23, 2026
3598a24
chore: kron image task
dilyabareeva Apr 23, 2026
c178d32
fix: minimal
dilyabareeva Apr 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,6 @@ logs/*
scripts/*/bar_rank.png
scripts/*/bar_rank.csv
log/*
logs_*/*
logs_*/*
local_eval_results/*
scripts/bert_qnli_bench/eval_defs_notes.txt
4 changes: 2 additions & 2 deletions config/eval/bert_qnli.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ hydra:
n_jobs: 1

bench: qnli_class_detection
cache_dir: /data2/bareeva/Projects/quanda/cluster_output/eval_bench/qnli
results_dir: /data2/bareeva/Projects/quanda/cluster_output/eval_results/qnli
cache_dir: /data2/bareeva/Projects/quanda/qnli_bench
results_dir: /data2/bareeva/Projects/quanda/cluster_output_new/eval_results/qnli
device: cuda:0
batch_size: 8

Expand Down
4 changes: 2 additions & 2 deletions config/eval/cifar_resnet9.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ hydra:
n_jobs: 1

bench: cifar_class_detection
cache_dir: /data/cluster/users/bareeva/quanda_output/eval_bench/cifar
results_dir: /data/cluster/users/bareeva/quanda_output/eval_results/cifar
cache_dir: /data/cluster/users/bareeva/quanda_output_new/eval_bench/cifar
results_dir: /data/cluster/users/bareeva/quanda_output_new/eval_results/cifar

#cache_dir: ./eval_bench/cifar
#results_dir: ./eval_results/cifar
Expand Down
4 changes: 3 additions & 1 deletion config/eval/explainer/dattri_arnoldi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ kwargs:
path: quanda.explainers.wrappers.dattri_losses.bert_classification_batched_loss
proj_dim: 50
max_iter: 100
batch_size: ${batch_size}
precompute_data_ratio: 0.0005
batch_size: 8
regularization: 0.01
3 changes: 2 additions & 1 deletion config/eval/explainer/dattri_ekfac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ kwargs:
_target_: hydra.utils.get_method
path: quanda.explainers.wrappers.dattri_losses.bert_classification_batched_loss
damping: 0.0
batch_size: ${batch_size}
max_iter: 500
batch_size: 8
2 changes: 1 addition & 1 deletion config/eval/explainer/dattri_gradcos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ kwargs:
loss_func:
_target_: hydra.utils.get_method
path: quanda.explainers.wrappers.dattri_losses.bert_classification_per_sample_loss
batch_size: ${batch_size}
batch_size: 4
2 changes: 1 addition & 1 deletion config/eval/explainer/dattri_graddot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ kwargs:
loss_func:
_target_: hydra.utils.get_method
path: quanda.explainers.wrappers.dattri_losses.bert_classification_per_sample_loss
batch_size: ${batch_size}
batch_size: 4
2 changes: 1 addition & 1 deletion config/eval/explainer/dattri_tracin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ kwargs:
learning_rate:
2.0e-05
normalized_grad: false
batch_size: ${batch_size}
batch_size: 4
8 changes: 8 additions & 0 deletions config/eval/explainer/kronfluence.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: kronfluence
cls: quanda.explainers.wrappers.Kronfluence
kwargs:
task_module:
_target_: quanda.explainers.wrappers.kronfluence_tasks.TextClassificationTask
tracked_modules: [classifier]
batch_size: 8
device: ${device}
1 change: 1 addition & 0 deletions config/eval/explainer/representer_points.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ kwargs:
batch_size: 64
load_from_disk: true
show_progress: false
normalize: false
1 change: 1 addition & 0 deletions config/eval/explainer/trak.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ kwargs:
proj_dim: 2048
batch_size: 64
load_from_disk: true
lambda_reg: 0.0
4 changes: 2 additions & 2 deletions config/eval/mnist_lenet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ hydra:
n_jobs: 1

bench: mnist_class_detection
cache_dir: /data/cluster/users/bareeva/quanda_output/eval_bench/mnist
results_dir: /data/cluster/users/bareeva/quanda_output/eval_results/mnist
cache_dir: /data/cluster/users/bareeva/quanda_output_new/eval_bench/mnist
results_dir: /data/cluster/users/bareeva/quanda_output_new/eval_results/mnist

#cache_dir: ./eval_bench/mnist
#results_dir: ./eval_results/mnist
Expand Down
73 changes: 55 additions & 18 deletions quanda/benchmarks/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import json
import os
import warnings
from abc import ABC
from abc import ABC, abstractmethod
from typing import Any, Callable, List, Optional, Union

import datasets # type: ignore
Expand Down Expand Up @@ -381,15 +381,15 @@ def train(
train_dl = ds_handler.create_dataloader(
dataset=obj.train_dataset,
batch_size=batch_size,
shuffle=False, # TODO: true
shuffle=True,
num_workers=trainer.num_workers,
)
if obj.val_dataset is not None:
val_ds_handler = get_dataset_handler(dataset=obj.val_dataset)
val_dl = val_ds_handler.create_dataloader(
dataset=obj.val_dataset,
batch_size=batch_size,
shuffle=False, # TODO: true
shuffle=False,
num_workers=trainer.num_workers,
)
else:
Expand Down Expand Up @@ -453,9 +453,8 @@ def train(
obj.model.to(obj.device)
obj.model.eval()

assert isinstance(obj.model, PyTorchModelHubMixin), (
"Model must inherit from PyTorchModelHubMixin."
)
if not isinstance(obj.model, PyTorchModelHubMixin):
raise TypeError("Model must inherit from PyTorchModelHubMixin.")
if snapshot_dirs:
obj.checkpoints = snapshot_dirs
else:
Expand Down Expand Up @@ -492,9 +491,10 @@ def train_and_push_to_hub(
batch_size=batch_size,
load_meta_from_disk=load_meta_from_disk,
)
assert isinstance(obj.model, PyTorchModelHubMixin), (
"Model must inherit from PyTorchModelHubMixin."
)
if not isinstance(obj.model, PyTorchModelHubMixin):
raise TypeError(
"Model must inherit from PyTorchModelHubMixin."
)

repo_id = config["ckpt"]
num_checkpoints = int(config.get("num_checkpoints", 1))
Expand All @@ -512,6 +512,10 @@ def train_and_push_to_hub(
repo_id=repo_id,
revision=revision,
)
upload_folder(
folder_path=obj.checkpoints[-1],
repo_id=repo_id,
)

pid_suffix = getattr(obj, "_pid_suffix", "")
metadata_dir = BenchConfigParser.get_metadata_dir(
Expand Down Expand Up @@ -755,6 +759,7 @@ def overall_objective(self, sanity_check_results: dict) -> float:
"""
return sum(sanity_check_results.values()) / len(sanity_check_results)

@abstractmethod
def evaluate(
self,
explainer_cls: type,
Expand All @@ -766,8 +771,37 @@ def evaluate(
use_cached_expl: bool = False,
use_hf_expl: bool = False,
):
"""Run the evaluation using the benchmark."""
pass
"""Run the evaluation using the benchmark.

Parameters
----------
explainer_cls : type
Explainer subclass to instantiate for this evaluation.
expl_kwargs : Optional[dict]
Extra kwargs passed through to ``explainer_cls``.
batch_size : int
Batch size used when iterating the eval dataset.
max_eval_n : Optional[int]
Cap on the number of eval samples; ``None`` means all.
eval_seed : int
Seed used when sampling the eval subset.
cache_dir : Optional[str]
Directory where explanations are cached on disk. Required when
``use_cached_expl`` or ``use_hf_expl`` is ``True``.
use_cached_expl : bool
Load precomputed explanations from ``cache_dir`` instead of
recomputing them.
use_hf_expl : bool
Download precomputed explanations from the HF Hub into
``cache_dir`` before loading.

Returns
-------
dict
Metric scores produced by this benchmark's metric(s).

"""
raise NotImplementedError

def _resolve_precomputed_explanations(
self,
Expand Down Expand Up @@ -808,10 +842,6 @@ def _resolve_precomputed_explanations(
return ExplanationsCache.load(path=cache_dir, device=self.device)
return None

def save_metadata(self):
"""Save metadata to disk."""
raise NotImplementedError

def _prepare_explainer(
self,
dataset: torch.utils.data.Dataset,
Expand Down Expand Up @@ -967,8 +997,11 @@ def explain_and_push_to_hub(
max_eval_n=max_eval_n,
eval_seed=eval_seed,
)
assert obj._explanations_id is not None
assert obj._explanations_dir is not None
if obj._explanations_id is None or obj._explanations_dir is None:
raise RuntimeError(
"explain() must populate _explanations_id and "
"_explanations_dir before pushing to the Hub."
)
create_repo(
repo_id=obj._explanations_id,
repo_type="dataset",
Expand Down Expand Up @@ -1026,7 +1059,11 @@ def _iter_explanations(
if precomputed_explanations is not None:
explanations = precomputed_explanations[i].to(self.device)
else:
assert explainer is not None
if explainer is None:
raise RuntimeError(
"explainer must be provided when "
"precomputed_explanations is None."
)
explanations = explainer.explain(
test_data=inputs, targets=targets
)
Expand Down
3 changes: 2 additions & 1 deletion quanda/benchmarks/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ def load_pretrained_base(
module_cfg = model_cfg["module"]
module_cls = pl_modules[module_cfg["name"]]
model = module_cls.from_pretrained_base( # type: ignore[attr-defined]
pretrained_model_name=pretrained_model_name
pretrained_model_name=pretrained_model_name,
num_labels=model_cfg.get("num_labels", 2),
)
model.to(device)
return model
Expand Down
9 changes: 5 additions & 4 deletions quanda/benchmarks/downstream_eval/mislabeling_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,11 @@ def sanity_check(self, batch_size: int = 32) -> dict:
"""
results = super().sanity_check(batch_size)

assert isinstance(self.train_dataset, LabelFlippingDataset), (
"Training dataset in Mislabeling Metric should have flipped "
"labels."
)
if not isinstance(self.train_dataset, LabelFlippingDataset):
raise TypeError(
"Training dataset in Mislabeling Metric should have flipped "
"labels."
)
train_dl = torch.utils.data.DataLoader(
self.train_dataset.filtered(self.train_dataset.transform_indices),
batch_size=batch_size,
Expand Down
22 changes: 16 additions & 6 deletions quanda/benchmarks/downstream_eval/shortcut_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,10 @@ def _extra_kwargs_from_config(
"SampleTransformationDataset as the training dataset."
)

assert train_dataset.metadata.cls_idx is not None, (
"The training dataset must have a class index in its metadata."
)
if train_dataset.metadata.cls_idx is None:
raise ValueError(
"The training dataset must have a class index in its metadata."
)

eval_ds_config = config["eval_dataset"]
eval_indices = eval_ds_config["filter_indices"]
Expand Down Expand Up @@ -151,8 +152,14 @@ def sanity_check(self, batch_size: int = 32) -> dict:
"""
results = super().sanity_check(batch_size)

assert isinstance(self.train_dataset, SampleTransformationDataset)
assert isinstance(self.eval_dataset, SampleTransformationDataset)
if not isinstance(self.train_dataset, SampleTransformationDataset):
raise TypeError(
"train_dataset must be a SampleTransformationDataset."
)
if not isinstance(self.eval_dataset, SampleTransformationDataset):
raise TypeError(
"eval_dataset must be a SampleTransformationDataset."
)

train_dl = torch.utils.data.DataLoader(
self.train_dataset.filtered(self.train_dataset.transform_indices),
Expand Down Expand Up @@ -277,7 +284,10 @@ def evaluate(
)
)

assert isinstance(self.train_dataset, SampleTransformationDataset)
if not isinstance(self.train_dataset, SampleTransformationDataset):
raise TypeError(
"train_dataset must be a SampleTransformationDataset."
)
metric = ShortcutDetectionMetric(
model=self.model,
checkpoints=self.checkpoints,
Expand Down
9 changes: 6 additions & 3 deletions quanda/benchmarks/ground_truth/linear_datamodeling.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,8 @@ def train( # type: ignore[override]
batch_size=batch_size,
load_meta_from_disk=load_meta_from_disk,
)
assert isinstance(obj, LinearDatamodeling)
if not isinstance(obj, LinearDatamodeling):
raise TypeError("Expected a LinearDatamodeling instance.")

if skip_subsets or cls._lds_skip_subsets:
return obj
Expand Down Expand Up @@ -304,7 +305,8 @@ def train_subset(
offline=True,
device=device,
)
assert isinstance(obj, LinearDatamodeling)
if not isinstance(obj, LinearDatamodeling):
raise TypeError("Expected a LinearDatamodeling instance.")

pretrained_base = BenchConfigParser.load_pretrained_base(
model_cfg=config["model"], device=device
Expand Down Expand Up @@ -443,7 +445,8 @@ def train_and_push_to_hub(
finally:
cls._push_subsets_during_train = False
cls._lds_skip_subsets = False
assert isinstance(obj, LinearDatamodeling)
if not isinstance(obj, LinearDatamodeling):
raise TypeError("Expected a LinearDatamodeling instance.")
return obj

def sanity_check(self, batch_size: int = 32) -> dict:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ logger:
id: 1ea9143-bert_qnli_LDS
explanations_group: bert_qnli_base
bench: LDS
bench_save_dir: bench_out
bench_save_dir: bench_out #/data/cluster/users/bareeva/quanda_output/train2
log_dir: hydra_logs
repo_id: quanda-bench-test
cache_dir: tmp
Expand Down
Loading
Loading