unlearning CR
This commit is contained in:
17
Tune.py
17
Tune.py
@@ -13,6 +13,8 @@ from IdentitySubset import IdentitySubset
|
||||
from architectures.Model import Model, Architecture
|
||||
|
||||
from unlearning.LinearFiltration import LinearFiltration
|
||||
|
||||
import Util
|
||||
# WeightFiltration, CertifiedRemoval
|
||||
|
||||
# numbre of classes
|
||||
@@ -134,10 +136,11 @@ for i in range(0,CLASS_SIZE):
|
||||
print(f"Total test images for these {CLASS_SIZE} classes: {len(test_data)}")
|
||||
|
||||
# Evaluate
|
||||
model.evaluate(
|
||||
loader = test_loader,
|
||||
mode="finetunned"
|
||||
)
|
||||
mode, accuracy, report_dict = model.evaluate(
|
||||
loader = test_loader,
|
||||
mode="finetunned"
|
||||
)
|
||||
Util._log_to_csv(model=reloaded, mode = "finetuned", accuracy=accuracy, report_dict=report_dict, strategy="base")
|
||||
|
||||
# test again
|
||||
reloaded = Model.create(
|
||||
@@ -169,7 +172,9 @@ for i in range(0,CLASS_SIZE):
|
||||
|
||||
# 4. Final Performance Analysis
|
||||
print("\n--- Performance on Retained Classes")
|
||||
reloaded.evaluate(loader=retain_test_loader, mode="retain")
|
||||
mode, accuracy, report_dict = reloaded.evaluate(loader=retain_test_loader, mode="retain")
|
||||
Util._log_to_csv(model=reloaded, mode = "retain", accuracy=accuracy, report_dict=report_dict, strategy="linearFiltration")
|
||||
|
||||
print("\n--- Performance on Forgotten Class")
|
||||
reloaded.evaluate(loader=forget_test_loader,mode="forget")
|
||||
mode, accuracy, report_dict = reloaded.evaluate(loader=forget_test_loader,mode="forget")
|
||||
Util._log_to_csv(model=reloaded, mode = "forgotten", accuracy=accuracy, report_dict=report_dict, strategy="linearFiltration")
|
||||
34
Util.py
Normal file
34
Util.py
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
from pathlib import Path
|
||||
from architectures.Model import Model
|
||||
|
||||
def _log_to_csv(model:Model, mode, accuracy, report_dict, strategy):
|
||||
"""Handles directory structures, file setups, and distinct CSV column formatting."""
|
||||
arch_name = model.__class__.__name__.lower()
|
||||
save_dir = Path(f"reports/{strategy}")
|
||||
save_dir.mkdir(parents=True, exist_ok=True)
|
||||
csv_path = save_dir / f"{arch_name}-{mode}.csv"
|
||||
|
||||
file_exists = csv_path.exists()
|
||||
|
||||
headers = [
|
||||
"accuracy",
|
||||
"macro_precision", "macro_recall", "macro_f1",
|
||||
"weighted_precision", "weighted_recall", "weighted_f1"
|
||||
]
|
||||
row = [
|
||||
f"{accuracy / 100.0:.4f}",
|
||||
f"{report_dict['macro avg']['precision']:.4f}",
|
||||
f"{report_dict['macro avg']['recall']:.4f}",
|
||||
f"{report_dict['macro avg']['f1-score']:.4f}",
|
||||
f"{report_dict['weighted avg']['precision']:.4f}",
|
||||
f"{report_dict['weighted avg']['recall']:.4f}",
|
||||
f"{report_dict['weighted avg']['f1-score']:.4f}"
|
||||
]
|
||||
|
||||
with open(csv_path, "a") as f:
|
||||
if not file_exists:
|
||||
f.write(",".join(headers) + "\n")
|
||||
f.write(",".join(row) + "\n")
|
||||
|
||||
print(f">> Direct CSV metrics appended to {csv_path}")
|
||||
@@ -149,10 +149,10 @@ class Model(ABC):
|
||||
)
|
||||
|
||||
# 3. Delegate file tracking to isolated helper method
|
||||
self._log_to_csv(mode, accuracy, classes, report_dict)
|
||||
self._log_to_csv(mode, accuracy,report_dict)
|
||||
|
||||
|
||||
def _log_to_csv(self, mode, accuracy, classes, report_dict):
|
||||
def _log_to_csv(self, mode, accuracy, report_dict):
|
||||
"""Handles directory structures, file setups, and distinct CSV column formatting."""
|
||||
arch_name = self.__class__.__name__.lower()
|
||||
save_dir = Path("reports")
|
||||
|
||||
@@ -19,3 +19,4 @@ accuracy,macro_precision,macro_recall,macro_f1,weighted_precision,weighted_recal
|
||||
0.9667,0.9750,0.9667,0.9657,0.9750,0.9667,0.9657
|
||||
0.9333,0.9500,0.9333,0.9314,0.9500,0.9333,0.9314
|
||||
0.9000,0.9350,0.9000,0.8957,0.9350,0.9000,0.8957
|
||||
0.9000,0.9350,0.9000,0.9007,0.9350,0.9000,0.9007
|
||||
|
||||
|
@@ -0,0 +1,77 @@
|
||||
import torch
|
||||
import numpy as np
|
||||
from scipy.optimize import minimize
|
||||
from .Strategy import Strategy
|
||||
import torch.nn as nn
|
||||
|
||||
class CertifiedRemoval(Strategy):
|
||||
"""Implements Certified Removal for machine unlearning."""
|
||||
|
||||
def __init__(self, model, data, labels, removal_bound, epsilon):
|
||||
super().__init__()
|
||||
self.model = model
|
||||
self.data = data
|
||||
self.labels = labels
|
||||
self.removal_bound = removal_bound
|
||||
self.epsilon = epsilon
|
||||
|
||||
def _run(self, model: nn.Module) -> nn.Module:
|
||||
"""Runs the certified removal algorithm."""
|
||||
# 1. Linear Model Creation
|
||||
# This is a simplification for demonstration purposes. In a real implementation,
|
||||
# you'd use more sophisticated methods to learn the parameters of the
|
||||
# 'removal' model based on the example being removed.
|
||||
|
||||
def linear_model(x):
|
||||
return torch.dot(x, torch.tensor([1, 1])) # Simplified Linear Model
|
||||
|
||||
# 2. Optimization for Parameter Adjustment
|
||||
# Optimize the parameter values to minimize the loss while staying within bounds.
|
||||
original_params = torch.tensor([0.0, 0.0]) # Initial parameters for linear model
|
||||
|
||||
def objective_function(params):
|
||||
new_model = linear_model #use same function as defined above
|
||||
return torch.sum(((new_model(self.data[0]) - self.labels)**2))
|
||||
|
||||
result = minimize(objective_function, original_params, method='L-BFGS-B', bounds=[(-self.removal_bound, self.removal_bound)], options={'maxiter': 100})
|
||||
|
||||
if not result.success:
|
||||
print("Warning: Optimization failed!")
|
||||
print(result.message)
|
||||
return model #Return original if optimization fails
|
||||
|
||||
new_params = result.x
|
||||
# 3. New Model Creation
|
||||
|
||||
new_model = lambda x: torch.dot(x, new_params)
|
||||
return new_model
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Example Usage - Synthetic Data for Demonstration
|
||||
np.random.seed(42) # For reproducibility
|
||||
n_samples = 100
|
||||
X = np.random.randn(n_samples, 2)
|
||||
y = (X[:, 0] + X[:, 1] > 0).astype(int)
|
||||
|
||||
# Create a simple linear model for demonstration
|
||||
model = nn.Linear(2, 1) # Simple linear classifier - PyTorch Version
|
||||
optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # Optimizer for training the linear model
|
||||
|
||||
# Train a Linear Model
|
||||
for _ in range(100): #training loop
|
||||
optimizer.zero_grad()
|
||||
predictions = model(X)
|
||||
loss = torch.sum((predictions - y)**2)
|
||||
loss.backward()
|
||||
optimizer.step()
|
||||
|
||||
# Define parameters for Certified Removal
|
||||
removal_bound = 1.0
|
||||
epsilon = 0.1
|
||||
|
||||
# Create the CertifiedRemoval object with the trained model, data and labels
|
||||
certified_removal_obj = CertifiedRemoval(model, X, y, removal_bound, epsilon)
|
||||
|
||||
# Run Certified Removal
|
||||
new_model = certified_removal_obj.apply(model)
|
||||
@@ -9,7 +9,7 @@ class Strategy:
|
||||
def __init__(self):
|
||||
# Dynamically set file name based on the class name (e.g., 'NormalizingLinearFiltration.txt')
|
||||
self.strategy_name = self.__class__.__name__
|
||||
self.log_file = f"reports/{self.strategy_name}_metrics.txt"
|
||||
self.log_file = f"reports/{self.strategy_name}/metrics.txt"
|
||||
self._initialize_log_file()
|
||||
|
||||
def _initialize_log_file(self):
|
||||
|
||||
Reference in New Issue
Block a user