Skip to content

refactor(membership-inference): migrate to new attack architecture#75

Open
asim29 wants to merge 1 commit intopr/4.1-distribution-inferencefrom
pr/4.2-membership-inference
Open

refactor(membership-inference): migrate to new attack architecture#75
asim29 wants to merge 1 commit intopr/4.1-distribution-inferencefrom
pr/4.2-membership-inference

Conversation

@asim29
Copy link
Copy Markdown
Collaborator

@asim29 asim29 commented Apr 21, 2026

Summary

Two files updated (lira.py, dp_sgd.py) with targeted bug fixes and cleanup to align both with the base classes landed in PR 2. Integration and unit tests added.

Stacked on: pr/4.1-distribution-inference


What changed and why

attacks/lira.py

Change Detail
experiment_idexp_id Renames the constructor parameter and super().__init__() call to match the base class attribute name established in PR 2.
Remove __get_logits, __normalize_logits Both were dead code. __get_logits was never called in attack(); __normalize_logits was replaced inline.
Simplify attack() logit collection Pre-allocates all_logits as list[list[np.ndarray]] with a known length instead of growing it lazily. Targets collected with .numpy() directly (they were already on CPU after DataLoader).
Simplify in_out_labels construction Replaced the per-shadow loop with a single np.array([...], dtype=bool) list comprehension.
Remove copy.deepcopy in __get_log_logits The softmax is computed on a per-model slice (pred_logits[model_idx]), so modifying probs in-place never affects the original array.
Return type annotation attack() now declares -> dict[str, np.ndarray] as required by the ABC.
Minor: lira_offline_preds, _ Second return value from __lira_offline was being silently overwriting true_labels; changed to _.

defenses/dp_sgd.py

Change Detail
Unbound loss variable loss.item() in the end-of-epoch print was referencing the loop variable after the loop might have zero iterations. Fixed by introducing last_loss: torch.Tensor | None = None updated each iteration, guarded by if last_loss is not None.
self.trainloaderself.train_loader The Opacus make_private() return value was being assigned to a new attribute self.trainloader instead of updating the existing self.train_loader. This caused train_private() to iterate the un-wrapped loader without DP.
Loop unpacking for batch_idx, (tuple) in enumerate(...) shadowed the built-in tuple. Changed to for batch_idx, (data, target) in enumerate(...).
Docstring Renamed deltdelta to match the constructor parameter.

Test plan

  • uv run pre-commit run --all-files passes
  • uv run pytest tests/unit/test_metrics_mi.py -v passes
  • from amulet.membership_inference.attacks import LiRA resolves
  • from amulet.membership_inference.defenses import DPSGD resolves
  • LiRA(..., exp_id=0) constructs without error (old experiment_id kwarg removed)

🤖 Generated with Claude Code

@asim29 asim29 requested review from sebszyller April 21, 2026 21:57
@asim29 asim29 force-pushed the pr/4.2-membership-inference branch from 210b630 to 1f8c588 Compare April 21, 2026 22:08
…cture

lira.py:
  - Renames experiment_id -> exp_id to match base class.
  - Removes unused __get_logits and __normalize_logits private methods.
  - Simplifies attack(): pre-allocates all_logits as list-of-lists instead
    of building it lazily; builds in_out_labels with a single np.array()
    call; targets on CPU directly to avoid an extra .to(device) round-trip.
  - Removes copy.deepcopy in __get_log_logits (not needed; softmax is
    computed in-place on a per-model slice, not the original array).
  - Adds return type annotation dict[str, np.ndarray] to attack().

dp_sgd.py:
  - Fixes unbound loss variable: introduces last_loss sentinel so the
    end-of-epoch privacy accounting line cannot reference an unbound name
    when the loader is empty.
  - Renames self.trainloader -> self.train_loader (matches base class attribute).
  - Fixes unpacking: replaces for batch_idx, (tuple) with
    for batch_idx, (data, target) to avoid shadowing the built-in.
  - Docstring: renames delt -> delta to match the constructor parameter.
@asim29 asim29 force-pushed the pr/4.2-membership-inference branch from 1f8c588 to 75b8b08 Compare April 21, 2026 22:19
@asim29 asim29 changed the title refactor: migrate membership inference vertical to new attack architecture refactor(membership-inference): migrate to new attack architecture Apr 21, 2026
@asim29 asim29 self-assigned this Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant