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 architectures.Model import Model, Architecture
|
||||||
|
|
||||||
from unlearning.LinearFiltration import LinearFiltration
|
from unlearning.LinearFiltration import LinearFiltration
|
||||||
|
|
||||||
|
import Util
|
||||||
# WeightFiltration, CertifiedRemoval
|
# WeightFiltration, CertifiedRemoval
|
||||||
|
|
||||||
# numbre of classes
|
# 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)}")
|
print(f"Total test images for these {CLASS_SIZE} classes: {len(test_data)}")
|
||||||
|
|
||||||
# Evaluate
|
# Evaluate
|
||||||
model.evaluate(
|
mode, accuracy, report_dict = model.evaluate(
|
||||||
loader = test_loader,
|
loader = test_loader,
|
||||||
mode="finetunned"
|
mode="finetunned"
|
||||||
)
|
)
|
||||||
|
Util._log_to_csv(model=reloaded, mode = "finetuned", accuracy=accuracy, report_dict=report_dict, strategy="base")
|
||||||
|
|
||||||
# test again
|
# test again
|
||||||
reloaded = Model.create(
|
reloaded = Model.create(
|
||||||
@@ -169,7 +172,9 @@ for i in range(0,CLASS_SIZE):
|
|||||||
|
|
||||||
# 4. Final Performance Analysis
|
# 4. Final Performance Analysis
|
||||||
print("\n--- Performance on Retained Classes")
|
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")
|
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
|
# 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."""
|
"""Handles directory structures, file setups, and distinct CSV column formatting."""
|
||||||
arch_name = self.__class__.__name__.lower()
|
arch_name = self.__class__.__name__.lower()
|
||||||
save_dir = Path("reports")
|
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.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.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.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):
|
def __init__(self):
|
||||||
# Dynamically set file name based on the class name (e.g., 'NormalizingLinearFiltration.txt')
|
# Dynamically set file name based on the class name (e.g., 'NormalizingLinearFiltration.txt')
|
||||||
self.strategy_name = self.__class__.__name__
|
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()
|
self._initialize_log_file()
|
||||||
|
|
||||||
def _initialize_log_file(self):
|
def _initialize_log_file(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user