Skip to content

LDG-3: Product leakpro webapp#393

Merged
fazelehh merged 52 commits into
mainfrom
product/leakpro-webapp
May 26, 2026
Merged

LDG-3: Product leakpro webapp#393
fazelehh merged 52 commits into
mainfrom
product/leakpro-webapp

Conversation

@fazelehh
Copy link
Copy Markdown
Collaborator

@fazelehh fazelehh commented Mar 17, 2026

Summary

This PR introduces the LeakPro webapp — a full-stack privacy auditing interface built on FastAPI (backend) and React/TypeScript (frontend). It allows users to run membership inference attacks against their own models through a step-by-step wizard, without writing any code.

Wizard steps

  1. Dataset — upload a population .pkl or point to a server path; auto-detects shape, dtype, and data type
  2. Architecture & Training — choose a built-in preset (ResNet-18, MLP, GRU) or upload a custom arch.py + handler.py
  3. Models — upload an existing trained model or train one from scratch (with optional DP-SGD)
  4. Attack Config — select MIA attacks (LiRA, RMIA, …) and configure per-attack parameters
  5. Run — live log streaming via WebSocket; progress bar per epoch
  6. Results — ROC curves, signal histograms with threshold slider, per-sample risk records, cross-job comparison

Key technical details

  • Job-based architecture: each session is a UUID job persisted to webapp_jobs/<id>/state.json
  • Custom dataset_handler.py and handler.py are uploaded per job and isolated to the job directory
  • DP-SGD training supported via Opacus; ResNet skip-connection inplace ops patched for compatibility
  • Population pickles with renamed/missing handler classes are loaded via a safe unpickler with a dataset-compatible stub
  • CelebA-HQ example included under examples/mia/celebA_HQ/webapp/

@fazelehh fazelehh force-pushed the product/leakpro-webapp branch from 33ac6a9 to b4c4af3 Compare March 17, 2026 13:53
@fazelehh fazelehh changed the title Product eakpro webapp Product leakpro webapp Mar 24, 2026
@review-notebook-app
Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@fazelehh fazelehh requested a review from TheColdIce May 12, 2026 09:35
Copy link
Copy Markdown
Collaborator

@TheColdIce TheColdIce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DPSGD error

When training with DPSGD I get an error:

[train] Starting: model_3 (2 epochs, lr=0.001)
[train] Detected 307 classes from dataset labels
[train] Applied ModuleValidator.fix() to ResNet18 for DP-SGD
[train] Model: ResNet18(num_classes=307, pretrained=no)
[train] DP-SGD: epsilon=None, delta=None, max_grad_norm=None, virtual_batch_size=16
[train] DP-SGD config saved (ε=10.0, δ=1e-05, max_grad_norm=1.0)
[train] FAILED model_3: Output 0 of BackwardHookFunctionBackward is a view and is being modified inplace. This view was created inside a custom Function (or because an input was returned as-is) and the autograd logic to handle view+inplace would override the custom backward associated with the custom Function, leading to incorrect gradients. This behavior is forbidden. You can fix this by cloning the output of the custom Function. Traceback (most recent call last): File "/home/edvin/LeakPro/leakpro/webapp/backend/main.py", line 861, in _train result = _handler.train(loader, model, criterion, optimizer, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/webapp_jobs/cedb0551dcf34b8e8066917893636926/handler.py", line 32, in train return _train_dpsgd(dataloader, model, criterion, optimizer, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/webapp_jobs/cedb0551dcf34b8e8066917893636926/handler.py", line 152, in _train_dpsgd outputs = model(inputs) ^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1778, in _wrapped_call_impl return self._call_impl(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1789, in _call_impl return forward_call(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/opacus/grad_sample/grad_sample_module.py", line 549, in forward return self._module(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1778, in _wrapped_call_impl return self._call_impl(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1789, in _call_impl return forward_call(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/webapp_jobs/cedb0551dcf34b8e8066917893636926/arch.py", line 18, in forward return self.model(x) ^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1778, in _wrapped_call_impl return self._call_impl(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1789, in _call_impl return forward_call(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torchvision/models/resnet.py", line 285, in forward return self._forward_impl(x) ^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torchvision/models/resnet.py", line 273, in _forward_impl x = self.layer1(x) ^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1778, in _wrapped_call_impl return self._call_impl(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1789, in _call_impl return forward_call(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/container.py", line 253, in forward input = module(input) ^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1778, in _wrapped_call_impl return self._call_impl(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1789, in _call_impl return forward_call(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/torchvision/models/resnet.py", line 102, in forward out += identity RuntimeError: Output 0 of BackwardHookFunctionBackward is a view and is being modified inplace. This view was created inside a custom Function (or because an input was returned as-is) and the autograd logic to handle view+inplace would override the custom backward associated with the custom Function, leading to incorrect gradients. This behavior is forbidden. You can fix this by cloning the output of the custom Function.

I tested using paths and preset built-in and uploaded celeba_hq_data.pkl, webapp/celebA_data_handler.py, webapp/celebA_train_handler.py and model_srchitecure.py by my self. Then the error occurs during the model training. To my understanding webapp/celebA_train_handler.py should be able to use DPSGD.

Going back

  • When I go back to previous steps the input has been cleared. Maybe it should be left? For example, if have uploaded data, I might want to go back to double check what data I upload or if I accidentally went back to far it is annoying to put in everything again.
  • Also, the app seems to freeze when I go back from step 3 to step 2 and then proceed to step 3 again. When I try to train the log just say: Waiting for output….

Step 1

Shouldn't say /home/fazeleh/data/cifar_train.pkl. Maybe /absolut/path/to/data.pkl?

Missing attack configs

In the examples/mia/celevA_HQ/audit.yaml file there is only the base attack. Shoudn't there be configs for more attacks?

Results

Add axis names on the histograms?

Top left buttons

The "?" and the cog buttons doesn't do anything when I click them. Can they be removed?

Uploading model weights

If I try to upload model weights in step 3 and has before in step 2 provided file paths for architecture and train loop, I get this error when I try to validate the model:

Compatibility check failed
Traceback (most recent call last):
  File "/home/edvin/LeakPro/webapp_jobs/6344634905184db9886cd7c2f9c9e8ee/_leakpro_check_runner.py", line 25, in <module>
    raise ValueError("No nn.Module subclass found in arch file")
ValueError: No nn.Module subclass found in arch file

I also noticed that the webapp_jobs//arch.py and handler.py are empty. I think the validate functions looks here and not using the paths i provided in step 2.

Comment thread examples/mia/celebA_HQ/webapp/README.md Outdated
Comment thread examples/mia/celebA_HQ/webapp/README.md
Comment thread examples/mia/celebA_HQ/webapp/README.md Outdated
Comment thread examples/mia/celebA_HQ/webapp/README.md Outdated
Comment thread examples/mia/celebA_HQ/main_celebA_hq.ipynb
Comment thread examples/mia/cifar/audit.yaml
Comment thread examples/mia/cifar/cifar_dpsgd.ipynb
Comment thread examples/mia/cifar/train_config.yaml
Comment thread examples/mia/celebA_HQ/main_celebA_hq.ipynb Outdated
@fazelehh fazelehh changed the title Product leakpro webapp LDG-3: Product leakpro webapp May 21, 2026
@TheColdIce
Copy link
Copy Markdown
Collaborator

Results - Records

  • The images are very slow on updating when switching between attacks. An inexperienced user might not catch that the sample index is changed but not the image and then believe the same image is the most vulnerable in all attacks. I suggest the images are cleared when changing the attack and/or model.
  • The risk scores of LIRA is very low: -0.0000 to -0.0012. While the risk scores of for example RMIA and BASE is much higher. Why is that?

Merge with main

  • It seems like this PR only works for an old version of opacus. This was fixed in Dpsgd celebA #312. When I downgrade to opacus 1.5.3 the code runs for me, but it does not run with latest version of opacus. There was some problems with getting the model to learn while using older versions of opacus so I highly suggest updating to the lates version.

Going back and forth between steps

  • Going from step 3 back to step 2 and then proceeding to step 3 again does not work. When training it just says Wating for output...
  • Moving back and forth between steps works fine.

Attacks

  • I noticed that a population attack on resnet18 (trained with epochs=20, lr=0.001, bs=128, opt=adam, f_train=0.5, f_test=0.2, no dpsgd) gave a roc curve with no TPR@X values so the summery in results didn't show anything. The TPR@0% to 10% should be zero if you look at the roc curve but the webapp says they are nan so no the risk is nan, which is inaccurate? The risk should be extremely low? Or should TPR@X values be nan and hence also the risk nan? In this case would it not be good to have default settings for the population attack that actually provides some results?
  • RAMIA fails. Error:
...
2026-05-22 09:49:30,460 INFO Loading shadow model 0
2026-05-22 09:49:30,598 INFO Loaded model from /home/edvin/LeakPro/webapp_jobs/3080845aa33546f98153abb2a3373d79/leakpro_output/model_1/attack_objects/shadow_model/shadow_model_0.pkl
2026-05-22 09:49:30,600 INFO Loading shadow model 1
2026-05-22 09:49:30,884 INFO Loaded model from /home/edvin/LeakPro/webapp_jobs/3080845aa33546f98153abb2a3373d79/leakpro_output/model_1/attack_objects/shadow_model/shadow_model_1.pkl
2026-05-22 09:49:30,885 INFO Loading metadata 0
2026-05-22 09:49:30,886 INFO Loading metadata 1
2026-05-22 09:49:30,963 INFO Running attack: ramia
2026-05-22 09:49:31,020 INFO Creating new augmented data...
[worker] FAILED: 'NoneType' object has no attribute 'detach' Traceback (most recent call last): File "/home/edvin/LeakPro/leakpro/webapp/backend/worker.py", line 354, in run_audit_job results = lp.run_audit(create_pdf=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/leakpro.py", line 161, in run_audit audit_results = self.attack_scheduler.run_attacks(use_optuna=use_optuna) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/attacks/attack_scheduler.py", line 120, in run_attacks result = attack_obj.run_attack() ^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/attacks/mia_attacks/ramia.py", line 314, in run_attack augs, op_names = self.aug.augment(x[0], ^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/input_handler/modality_extensions/image_extension.py", line 190, in augment y, ops = tf(x, _seed) ^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/input_handler/modality_extensions/image_extension.py", line 144, in fn pil = _to_pil_from_normalized(x, self.mean, self.std, force_rgb=self.force_rgb) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/input_handler/modality_extensions/image_extension.py", line 72, in _to_pil_from_normalized m = mean.detach().to(dtype=x.dtype, device=dev)[:C].view(C, 1, 1) ^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'detach'
  • YOQO fails. Error:
[worker] Auditing model: model_1
[worker] Using custom UserDataset from dataset_handler.py
[worker] Registered dataset_handler.py as 'celebA_data_handler' for pickle deserialization
2026-05-22 11:50:00,873 INFO Target model blueprint created from ResNet18 in /home/edvin/LeakPro/webapp_jobs/c51ed9b5b55b4d13a882d1b2f97ec0ed/arch.py.
2026-05-22 11:50:00,874 INFO Loaded target model metadata from /home/edvin/LeakPro/webapp_jobs/c51ed9b5b55b4d13a882d1b2f97ec0ed/models/model_1/model_metadata.pkl
2026-05-22 11:50:00,984 INFO Loaded target model from /home/edvin/LeakPro/webapp_jobs/c51ed9b5b55b4d13a882d1b2f97ec0ed/models/model_1
2026-05-22 11:50:05,378 INFO Loaded population dataset from /home/edvin/LeakPro/examples/mia/celebA_HQ/data/celeba_hq_data.pkl
2026-05-22 11:50:11,998 INFO MIA attack factory loaded.
2026-05-22 11:50:11,998 INFO Creating shadow model handler singleton
2026-05-22 11:50:11,999 INFO Created folder /home/edvin/LeakPro/webapp_jobs/c51ed9b5b55b4d13a882d1b2f97ec0ed/leakpro_output/model_1/attack_objects/shadow_model
2026-05-22 11:50:12,060 INFO Logits already cached at leakpro_output/attack_cache/target_logits.npy
2026-05-22 11:50:12,060 INFO Creating distillation model handler singleton
2026-05-22 11:50:12,061 INFO Created folder /home/edvin/LeakPro/webapp_jobs/c51ed9b5b55b4d13a882d1b2f97ec0ed/leakpro_output/model_1/attack_objects/distillation_model
2026-05-22 11:50:12,102 INFO Logits already cached at leakpro_output/attack_cache/target_logits.npy
2026-05-22 11:50:12,202 INFO Added attack: yoqo
2026-05-22 11:50:12,203 INFO Preparing attack: yoqo
[worker] FAILED: n must be even Traceback (most recent call last): File "/home/edvin/LeakPro/leakpro/webapp/backend/worker.py", line 354, in run_audit_job results = lp.run_audit(create_pdf=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/leakpro.py", line 161, in run_audit audit_results = self.attack_scheduler.run_attacks(use_optuna=use_optuna) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/attacks/attack_scheduler.py", line 118, in run_attacks attack_obj.prepare_attack() File "/home/edvin/LeakPro/leakpro/attacks/mia_attacks/yoqo.py", line 104, in prepare_attack self.shadow_model_indices = ShadowModelHandler().create_shadow_models(num_models = self.num_shadow_models, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/attacks/utils/shadow_model_handler.py", line 166, in create_shadow_models A = self.construct_balanced_assignments(len(shadow_population), num_models) # noqa: N806 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/attacks/utils/shadow_model_handler.py", line 108, in construct_balanced_assignments assert n % 2 == 0, "n must be even" ^^^^^^^^^^ AssertionError: n must be even

Running the attack with 2 shadow models does not cause any fails, but no results at all are generated.

  • Loss Trajectory fails. Error: Same as YOQO. The attack does NOT work with several trajectories (yields same error).
  • MS-LIRA fails with 1 shadow model. Error: Same as YOQO. The attack works with 2 shadow models.

Providing paths

  • When providing the model architecture as a server path the training still fails. Error:
[train] Starting: model_1 (20 epochs, lr=0.001)
[train] Dataset: 2739 train / 1095 test (f_train=0.5, f_test=0.2)
[train] FAILED model_1: No nn.Module subclass found in arch.py. Make sure your arch.py defines a class that inherits from torch.nn.Module. Traceback (most recent call last): File "/home/edvin/LeakPro/leakpro/webapp/backend/main.py", line 760, in _train _arch_cls = next( ^^^^^ StopIteration During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/edvin/LeakPro/leakpro/webapp/backend/main.py", line 765, in _train raise ValueError( ValueError: No nn.Module subclass found in arch.py. Make sure your arch.py defines a class that inherits from torch.nn.Module.
  • When providing the model handler as a server path the training fails. Error:
[train] Starting: model_1 (2 epochs, lr=0.001)
[train] Dataset: 2739 train / 1095 test (f_train=0.5, f_test=0.2)
[train] Detected 307 classes from dataset labels
[train] Model: ResNet18(num_classes=307, pretrained=no)
[train] FAILED model_1: Traceback (most recent call last): File "/home/edvin/LeakPro/leakpro/webapp/backend/main.py", line 858, in _train _HandlerCls = next( ^^^^^ StopIteration
  • When instead uploading the EXACT same files, the training succeeds.

Other

  • When I trained 2 models and then removed the first model, I get an error when I run attacks on the second model. Error:
[worker] Starting audit for job 7b4524d5b12043f48baa805ecd4d3554
[worker] Auditing model: model_1
[worker] Using custom UserDataset from dataset_handler.py
[worker] FAILED: 1 validation error for LeakProConfig audit.attack_list List should have at least 1 item after validation, not 0 [type=too_short, input_value=[], input_type=list] For further information visit https://errors.pydantic.dev/2.13/v/too_short Traceback (most recent call last): File "/home/edvin/LeakPro/leakpro/webapp/backend/worker.py", line 353, in run_audit_job lp = LeakPro(handler_cls, str(temp_yaml)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/leakpro.py", line 54, in __init__ configs = LeakProConfig(**configs) ^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/.venv/lib/python3.12/site-packages/pydantic/main.py", line 263, in __init__ validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pydantic_core._pydantic_core.ValidationError: 1 validation error for LeakProConfig audit.attack_list List should have at least 1 item after validation, not 0 [type=too_short, input_value=[], input_type=list] For further information visit https://errors.pydantic.dev/2.13/v/too_short
  • After going to results/records and the backend started load images, the webapp comes very slow. For example if I try to start a new audit session the webapp does not respond. Solution: set default to only show 5 img, not 20?

@fazelehh
Copy link
Copy Markdown
Collaborator Author

Bug fixes (backend)

Arch file not landing in job dir (Step3Setup.tsx): proceed() was re-uploading files that had already been eagerly sent by the onFile/onPath callbacks, overwriting the real file with a 0-byte dummy. Removed the redundant re-upload — proceed() now only calls setArchConfig.

UserDataset missing len (mia_handler.py): The _SafeUnpickler fallback was returning a bare stub with no dataset interface. Replaced with a proper _DatasetStub class that implements len and getitem, so population pickles created with a renamed/removed handler class still load correctly.

DP-SGD inplace view error with ResNet + Opacus (main.py, celebA_model_handler.py): ModuleValidator.fix() does not patch ResNet's out += identity skip connections. Added a monkey-patch that replaces BasicBlock and Bottleneck forward methods to use out = out + identity (non-inplace), applied after ModuleValidator.fix().

Bug fix (UI)

Back navigation clears state / log freezes on "Waiting for output…" (ServerOrUpload.tsx, Step3Setup.tsx, Step1Upload.tsx, Step4Models.tsx):
Added initialDone prop to ServerOrUpload so uploaded file widgets show their "configured" chip when navigating back.
Step3Setup: Continue button now stays enabled in upload mode on back navigation (falls back to initialArch filenames); proceed() uses those filenames if no new file was selected.
Step1Upload: DatasetHandlerUpload shows "configured" state when returning to Step 1.
Step4Models: wrapped api.trainModel in try/catch so a failed HTTP call no longer leaves the log panel stuck on "Waiting for output…" indefinitely

@fazelehh fazelehh requested a review from TheColdIce May 26, 2026 06:57
Copy link
Copy Markdown
Collaborator

@TheColdIce TheColdIce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

  • If I run a audit on step 5 which fails and I then go back to train a new model, the webapp freezes. In the backend it looks like the training is completed but the webapp doesn't register that the training is done.

  • When uploading your own model (via path or file-upload) the result does not show the train and test accuracy of the model.

  • After going to results/records and the backend started load images, the webapp comes very slow. For example if I try to start a new audit session the webapp does not respond. Solution: set default to only show 5 img, not 20? Also, the images are very slow on updating when switching between attacks. An inexperienced user might not catch that the sample index is changed but not the image and then believe the same image is the most vulnerable in all attacks. I suggest the images are cleared/replaced by a loading symbol when changing the attack and/or model.

Attacks

RMIA

Setup: 20 epocs, testset fraction = 0.2, otherwise defualt train and attack params.

Error:

[worker] Starting audit for job 1060af4508c545cca45de4f0463c999d
[worker] Auditing model: uploaded_model
[worker] Using custom UserDataset from dataset_handler.py
[worker] Registered dataset_handler.py as 'celebA_data_handler' for pickle deserialization
2026-05-26 09:43:43,780 INFO Target model blueprint created from ResNet18 in /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/arch.py.
2026-05-26 09:43:43,782 INFO Loaded target model metadata from /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/models/uploaded_model/model_metadata.pkl
2026-05-26 09:43:43,992 INFO Loaded target model from /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/models/uploaded_model
2026-05-26 09:43:48,389 INFO Loaded population dataset from /home/edvin/LeakPro/examples/mia/celebA_HQ/data/celeba_hq_data.pkl
2026-05-26 09:43:54,560 INFO MIA attack factory loaded.
2026-05-26 09:43:54,560 INFO Creating shadow model handler singleton
2026-05-26 09:43:54,561 INFO Created folder /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_objects/shadow_model
2026-05-26 09:43:57,937 INFO Saved logits to /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_cache/target_logits.npy
2026-05-26 09:43:57,938 INFO Creating distillation model handler singleton
2026-05-26 09:43:57,938 INFO Created folder /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_objects/distillation_model
2026-05-26 09:43:57,982 INFO Logits already cached at /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_cache/target_logits.npy
2026-05-26 09:43:57,982 INFO Configuring the RMIA attack
2026-05-26 09:43:58,014 INFO Added attack: rmia
2026-05-26 09:43:58,014 INFO Preparing attack: rmia
2026-05-26 09:43:58,014 INFO Preparing shadow models for RMIA attack
2026-05-26 09:43:58,015 INFO Check for 2 shadow models (dataset: 5478 points)
2026-05-26 09:43:58,187 INFO Training shadow model 0 on 2739 points
2026-05-26 09:45:07,204 INFO Training shadow model 0 complete
2026-05-26 09:45:07,254 INFO Saved shadow model 0 to /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_objects/shadow_model
2026-05-26 09:45:07,254 INFO Storing metadata for shadow model 0
2026-05-26 09:45:10,576 INFO Saved logits to /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_cache/sm_0_logits.npy
2026-05-26 09:45:10,576 INFO Metadata for shadow model 0: {'init_params': {'num_classes': 307}, 'num_train': 2739, 'optimizer': 'adam', 'optimizer_params': {'lr': 0.001, 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0, 'amsgrad': False, 'maximize': False, 'foreach': None, 'capturable': False, 'differentiable': False, 'fused': None, 'decoupled_weight_decay': False}, 'criterion': 'crossentropyloss', 'criterion_params': {'reduction': 'mean', 'ignore_index': -100, 'label_smoothing': 0.0}, 'epochs': 20, 'batch_size': 128, 'train_result': {'accuracy': 0.9978094194961665, 'loss': 0.11229776121286981, 'extra': {'accuracy_history': [0.011683096020445418, 0.028842643300474625, 0.045637093829864916, 0.07155896312522819, 0.10843373493975904, 0.15078495801387368, 0.18802482657904346, 0.2416940489229646, 0.2949981745162468, 0.3457466228550566, 0.42314713399050746, 0.5144213216502374, 0.6100766703176341, 0.6867469879518072, 0.7977364001460387, 0.8718510405257394, 0.9207740051113545, 0.9645856151880249, 0.9864914202263599, 0.9978094194961665], 'loss_history': [5.858163897683909, 5.235152323953685, 4.868773214744799, 4.563825891765638, 4.221984818887868, 3.903945459245373, 3.656581804760184, 3.334475343181252, 3.0300330619561318, 2.7097052818408365, 2.365315537593712, 2.012516341143257, 1.6852743347094155, 1.3560475949259212, 1.0045442716533053, 0.7550603096264912, 0.5628674666609108, 0.35998150111115207, 0.20391205950412666, 0.11229776121286981]}}, 'test_result': {'accuracy': 0.2917123037604965, 'loss': 3.7301137127028454, 'extra': {}}, 'online': True, 'model_class': 'ResNet18', 'model_module_path': '/home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/arch.py', 'target_model_hash': '0910ae4d803fa855ae21bf841c7e513f26151bacc096a1333b75be8f9aef73ba'}
2026-05-26 09:45:10,577 INFO Metadata for shadow model 0 stored in /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_objects/shadow_model
2026-05-26 09:45:10,872 INFO Training shadow model 1 on 2739 points
2026-05-26 09:46:14,232 INFO Training shadow model 1 complete
2026-05-26 09:46:14,288 INFO Saved shadow model 1 to /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_objects/shadow_model
2026-05-26 09:46:14,289 INFO Storing metadata for shadow model 1
2026-05-26 09:46:17,450 INFO Saved logits to /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_cache/sm_1_logits.npy
2026-05-26 09:46:17,452 INFO Metadata for shadow model 1: {'init_params': {'num_classes': 307}, 'num_train': 2739, 'optimizer': 'adam', 'optimizer_params': {'lr': 0.001, 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0, 'amsgrad': False, 'maximize': False, 'foreach': None, 'capturable': False, 'differentiable': False, 'fused': None, 'decoupled_weight_decay': False}, 'criterion': 'crossentropyloss', 'criterion_params': {'reduction': 'mean', 'ignore_index': -100, 'label_smoothing': 0.0}, 'epochs': 20, 'batch_size': 128, 'train_result': {'accuracy': 0.982110259218693, 'loss': 0.27572941042376764, 'extra': {'accuracy_history': [0.011317999269806499, 0.02701715954728003, 0.05439941584519898, 0.0624315443592552, 0.09857612267250822, 0.13508579773640014, 0.15370573201898502, 0.194596568090544, 0.23913837166849214, 0.28148959474260676, 0.35450894487039064, 0.41767068273092367, 0.49069003285870755, 0.5713764147499087, 0.6429353778751369, 0.7400511135450895, 0.8046732384081782, 0.8904709748083242, 0.9510770354143848, 0.982110259218693], 'loss_history': [5.844344481711581, 5.273417699854928, 4.91269271797662, 4.666960619452575, 4.375346427157048, 4.086995530972824, 3.825971092347378, 3.557759113492823, 3.274900827324273, 2.974234465831995, 2.6725029285566, 2.407218680150233, 2.12885684904368, 1.8013156988882766, 1.5547765928622186, 1.2015466956859002, 0.9514000655613315, 0.6815365488705908, 0.4587859242294948, 0.27572941042376764]}}, 'test_result': {'accuracy': 0.21905805038335158, 'loss': 4.2521324331806545, 'extra': {}}, 'online': True, 'model_class': 'ResNet18', 'model_module_path': '/home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/arch.py', 'target_model_hash': '0910ae4d803fa855ae21bf841c7e513f26151bacc096a1333b75be8f9aef73ba'}
2026-05-26 09:46:17,452 INFO Metadata for shadow model 1 stored in /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_objects/shadow_model
2026-05-26 09:46:17,650 INFO Loading shadow model 0
2026-05-26 09:46:17,774 INFO Loaded model from /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_objects/shadow_model/shadow_model_0.pkl
2026-05-26 09:46:17,775 INFO Loading shadow model 1
2026-05-26 09:46:18,055 INFO Loaded model from /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_objects/shadow_model/shadow_model_1.pkl
2026-05-26 09:46:18,058 INFO Loading metadata 0
2026-05-26 09:46:18,059 INFO Loading metadata 1
2026-05-26 09:46:19,534 INFO Loaded logits from /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_cache/target_logits.npy
2026-05-26 09:46:19,538 INFO Loaded logits from /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_cache/sm_0_logits.npy
2026-05-26 09:46:19,544 INFO Loaded logits from /home/edvin/LeakPro/webapp_jobs/1060af4508c545cca45de4f0463c999d/leakpro_output/uploaded_model/attack_cache/sm_1_logits.npy
[worker] FAILED: index 4247 is out of bounds for axis 0 with size 3834 Traceback (most recent call last): File "/home/edvin/LeakPro/leakpro/webapp/backend/worker.py", line 354, in run_audit_job results = lp.run_audit(create_pdf=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/leakpro.py", line 174, in run_audit audit_results = self.attack_scheduler.run_attacks(use_optuna=use_optuna) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/attacks/attack_scheduler.py", line 122, in run_attacks attack_obj.prepare_attack() File "/home/edvin/LeakPro/leakpro/attacks/mia_attacks/rmia.py", line 161, in prepare_attack p_z_given_theta = softmax_logits(self.logits_theta, self.temperature)[z_indices,z_labels] # noqa: E501 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ IndexError: index 4247 is out of bounds for axis 0 with size 3834

Population

I noticed that a population attack on resnet18 (trained with epochs=20, lr=0.001, bs=128, opt=adam, f_train=0.5, f_test=0.2, no dpsgd) gave a roc curve with no TPR@X values so the summery in results didn't show anything. The TPR@0% to 10% should be zero if you look at the roc curve but the webapp says they are nan so no the risk is nan, which is inaccurate? The risk should be extremely low? Or should TPR@X values be nan and hence also the risk nan? In this case would it not be good to have default settings for the population attack that actually provides some results?

ROC curve looks weired...

Main concern: I have a decent model (train accurcuy 100%) and the population attack runs but there is no risk value in the summery!

RAMIA

Setup: 20 epocs, testset fraction = 0.2, otherwise defualt train and attack
Error:

2026-05-26 10:40:51,513 INFO Preparing attack: ramia
2026-05-26 10:40:51,591 INFO Preparing shadow models for BASE attack
2026-05-26 10:40:51,592 INFO Check for 2 shadow models (dataset: 5478 points)
2026-05-26 10:40:51,595 INFO Number of existing models exceeds or equals the number of models to create
2026-05-26 10:40:51,595 INFO Loading shadow model 0
2026-05-26 10:40:51,682 INFO Loaded model from /home/edvin/LeakPro/webapp_jobs/9dde4926d19a49278964713d3ab91d44/leakpro_output/uploaded_model/attack_objects/shadow_model/shadow_model_0.pkl
2026-05-26 10:40:51,682 INFO Loading shadow model 1
2026-05-26 10:40:51,902 INFO Loaded model from /home/edvin/LeakPro/webapp_jobs/9dde4926d19a49278964713d3ab91d44/leakpro_output/uploaded_model/attack_objects/shadow_model/shadow_model_1.pkl
2026-05-26 10:40:51,902 INFO Loading metadata 0
2026-05-26 10:40:51,903 INFO Loading metadata 1
2026-05-26 10:40:51,906 INFO Running attack: ramia
2026-05-26 10:40:51,937 INFO Creating new augmented data...
[worker] FAILED: 'NoneType' object has no attribute 'detach' Traceback (most recent call last): File "/home/edvin/LeakPro/leakpro/webapp/backend/worker.py", line 354, in run_audit_job results = lp.run_audit(create_pdf=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/leakpro.py", line 174, in run_audit audit_results = self.attack_scheduler.run_attacks(use_optuna=use_optuna) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/attacks/attack_scheduler.py", line 124, in run_attacks result = attack_obj.run_attack() ^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/attacks/mia_attacks/ramia.py", line 318, in run_attack augs, op_names = self.aug.augment(x[0], ^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/input_handler/modality_extensions/image_extension.py", line 194, in augment y, ops = tf(x, _seed) ^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/input_handler/modality_extensions/image_extension.py", line 148, in fn pil = _to_pil_from_normalized(x, self.mean, self.std, force_rgb=self.force_rgb) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/edvin/LeakPro/leakpro/input_handler/modality_extensions/image_extension.py", line 76, in _to_pil_from_normalized m = mean.detach().to(dtype=x.dtype, device=dev)[:C].view(C, 1, 1) ^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'detach'

YOOQ

Change default params for number of shadow models from 1 to 2.

In results:

  • no TPR@0.1%FPR
  • Risk is N/A
  • No ROC curve
  • No histogram
  • No records

Requierd fixes

  • If the audit fails (in step 5) the user should be able to go back all the way to step 1 and redo everything without the webapp freezing.
  • When the user uploads their own model and metadata, the train and test acc should be read from the metadata and presented in the results.
  • Lower the amount of pics presented in Records from 20 to 5.
  • When viewing Records and chaninging between attacks, if the sample index of a rank changes, the old pic should be removed/replaced with a loading symbol.
  • Fix so that all attacks above run without fail.
  • Add oslo and seqmia attack.

@fazelehh
Copy link
Copy Markdown
Collaborator Author

issue #426

@fazelehh fazelehh requested a review from TheColdIce May 26, 2026 15:17
Copy link
Copy Markdown
Collaborator

@TheColdIce TheColdIce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job!

@fazelehh fazelehh merged commit 5560098 into main May 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants