attck metrics
This commit is contained in:
@@ -43,17 +43,12 @@ class CertifiedUnlearning(Strategy):
|
||||
InceptionV3 auxiliary layers and tracking gradients.
|
||||
"""
|
||||
inner_model = getattr(model, "model", model)
|
||||
|
||||
# Check if the current architecture is an Inception variant
|
||||
is_inception = inner_model.__class__.__name__.lower() == "inception3"
|
||||
|
||||
|
||||
params_list = []
|
||||
for name, p in inner_model.named_parameters():
|
||||
if p.requires_grad:
|
||||
# Discard the disconnected auxiliary training branch weights
|
||||
if is_inception and "AuxLogits" in name:
|
||||
continue
|
||||
# CRITICAL: Append as a tuple so it can be unpacked as (name, param)
|
||||
|
||||
# Append as a tuple so it can be unpacked as (name, param)
|
||||
params_list.append((name, p))
|
||||
|
||||
return params_list if named else [e[1] for e in params_list]
|
||||
@@ -92,7 +87,7 @@ class CertifiedUnlearning(Strategy):
|
||||
first_grads = grad(loss, params, retain_graph=True, create_graph=True)
|
||||
elemwise_products = sum(torch.sum(g_elem * v_elem) for g_elem, v_elem in zip(first_grads, v))
|
||||
return grad(elemwise_products, params, create_graph=False)
|
||||
|
||||
|
||||
def _stochastic_newton_update(self, g, dataset, model, device):
|
||||
model.eval()
|
||||
criterion = nn.CrossEntropyLoss()
|
||||
@@ -133,7 +128,6 @@ class CertifiedUnlearning(Strategy):
|
||||
|
||||
h_s = self._hvp(loss, params, h_estimate)
|
||||
|
||||
# OPTIMIZATION 4: Avoid deprecated .data, use detach() and in-place ops
|
||||
with torch.no_grad():
|
||||
for k in range(len(params)):
|
||||
h_estimate[k].copy_(h_estimate[k] + g[k] - (h_s[k] / self.scale))
|
||||
@@ -143,7 +137,7 @@ class CertifiedUnlearning(Strategy):
|
||||
if global_step % step_interval == 0 and current_pct < 100:
|
||||
current_pct += 1
|
||||
print(f"\rProgress: {current_pct}% done", end="", flush=True)
|
||||
|
||||
|
||||
with torch.no_grad():
|
||||
for k in range(len(params)):
|
||||
h_res[k] += h_estimate[k] / self.scale
|
||||
|
||||
@@ -13,8 +13,8 @@ class LinearFiltration(Strategy):
|
||||
def _run(self, model: nn.Module, forget_loader: DataLoader, retain_loader: DataLoader) -> nn.Module:
|
||||
model.eval()
|
||||
# Freeze internal params
|
||||
for param in model.parameters():
|
||||
param.requires_grad = False
|
||||
#for param in model.parameters():
|
||||
#param.requires_grad = False
|
||||
|
||||
device = next(model.parameters()).device
|
||||
|
||||
@@ -155,7 +155,8 @@ class LinearFiltration(Strategy):
|
||||
|
||||
# 12
|
||||
clf = self._get_classifier(model)
|
||||
clf.weight.copy_(W_Z)
|
||||
with torch.no_grad():
|
||||
clf.weight.copy_(W_Z)
|
||||
|
||||
return model
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import time
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
@@ -21,27 +22,51 @@ class Retrain(Strategy):
|
||||
self.epochs = epochs
|
||||
|
||||
def _run(self, model: nn.Module, forget_loader: DataLoader, retain_loader: DataLoader) -> nn.Module:
|
||||
# 1. Determine the active execution device from the running sandbox
|
||||
|
||||
device = next(model.parameters()).device
|
||||
|
||||
# we need to check if a retrained copy exists on disk
|
||||
checkpoint_path = f"trained_models/class_{self.target_class_index}_retrained.pth"
|
||||
if os.path.exists(checkpoint_path):
|
||||
print(f"Found existing retrained model checkpoint at '{checkpoint_path}'. Loading parameters directly...")
|
||||
|
||||
# Load the state dict using safe configuration flags
|
||||
state_dict = torch.load(checkpoint_path, map_location=device, weights_only=True)
|
||||
|
||||
# Safely apply the parameter weights to the model in-place
|
||||
model.load_state_dict(state_dict)
|
||||
print("Retrained parameter loading complete (Retraining bypassed).")
|
||||
return model
|
||||
|
||||
# Cache Miss: Execute the standard retraining pipeline
|
||||
print(f"No naive model found for class {self.target_class_index} retraining a new one")
|
||||
|
||||
|
||||
print(f">> Triggering Exact Unlearning Baseline (Retraining {self.arch.name} from pristine state)...")
|
||||
inner_model = getattr(model, "model", model)
|
||||
if hasattr(inner_model, "fc"):
|
||||
total_classes = inner_model.fc.out_features
|
||||
elif hasattr(inner_model, "classifier"):
|
||||
# Fallback for alternative architecture layout types
|
||||
total_classes = inner_model.classifier[-1].out_features
|
||||
else:
|
||||
total_classes = self.size
|
||||
|
||||
# a new model with default params is created
|
||||
fresh_meat = Model.create(self.arch, device, self.size)
|
||||
fresh = Model.create(self.arch, device, total_classes)
|
||||
|
||||
# we train it with retain set
|
||||
fresh_meat.train(
|
||||
fresh.train(
|
||||
epochs=self.epochs,
|
||||
loader=retain_loader,
|
||||
rate=self.lr,
|
||||
mode="retrain"
|
||||
)
|
||||
|
||||
# 4. Extract the trained nn.Module parameter state dict
|
||||
# In-place copy onto the existing sandbox model structure to seamlessly retain downstream evaluations
|
||||
model.load_state_dict(fresh_meat.model.state_dict())
|
||||
# Extract module parameter state dict and copy in place
|
||||
model.load_state_dict(fresh.model.state_dict())
|
||||
|
||||
print(">> Retraining pipeline finished. Pristine baseline weights successfully established.")
|
||||
print("Retraining pipeline complete")
|
||||
return model
|
||||
|
||||
def _split_data(self, dataset):
|
||||
@@ -49,5 +74,5 @@ class Retrain(Strategy):
|
||||
return get_unlearning_loaders(
|
||||
dataset=dataset,
|
||||
forget_class_idx=self.target_class_index,
|
||||
batch_size=32
|
||||
batch_size=16
|
||||
)
|
||||
@@ -40,10 +40,12 @@ class Strategy:
|
||||
execution_time = end_time - start_time
|
||||
|
||||
# Log to the strategy's specific file
|
||||
'''
|
||||
Util.log_metric(
|
||||
log_file=log_file,
|
||||
execution_time=execution_time
|
||||
)
|
||||
'''
|
||||
|
||||
print(f"[{self.strategy_name}] Completed in {execution_time:.6f} seconds. Saved to {log_file}")
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ class WeightFiltration(Strategy):
|
||||
model.eval()
|
||||
|
||||
if self.wf_model is None:
|
||||
print(">> Initializing and compiling global WF-Net matrix (Run Once for all classes)...")
|
||||
print("Initializing and compiling global WF-Net matrix (Run Once for all classes)...")
|
||||
|
||||
self.wf_model = self._optimise_filter(
|
||||
model,
|
||||
@@ -123,10 +123,10 @@ class WeightFiltration(Strategy):
|
||||
device=device
|
||||
)
|
||||
else:
|
||||
print(f">> Gating matrix loaded. Switching layout to target class index: {self.target_class_index}")
|
||||
print(f"Gating matrix loaded. Switching layout to target class index: {self.target_class_index}")
|
||||
self.wf_model.target_class_index = self.target_class_index
|
||||
|
||||
return self.wf_model
|
||||
return self.wf_model.get()
|
||||
|
||||
def _split_data(self, dataset):
|
||||
return vertical_split(
|
||||
|
||||
Reference in New Issue
Block a user