unlearning LF
This commit is contained in:
@@ -43,10 +43,13 @@ class Model(ABC):
|
||||
if self.device.type == 'cuda': torch.cuda.synchronize()
|
||||
print(f"Training completed in: {time.time() - start_time:.2f}s")
|
||||
|
||||
|
||||
def evaluate(self, loader):
|
||||
self.model.eval()
|
||||
all_preds, all_labels = [], []
|
||||
print("\nEvaluating...")
|
||||
|
||||
|
||||
|
||||
with torch.no_grad():
|
||||
for inputs, labels in loader:
|
||||
@@ -56,9 +59,11 @@ class Model(ABC):
|
||||
all_preds.extend(predicted.cpu().numpy())
|
||||
all_labels.extend(labels.cpu().numpy())
|
||||
|
||||
accuracy = 100 * (np.array(all_preds) == np.array(all_labels)).sum() / len(all_labels)
|
||||
classes = sorted(list(set(all_labels)))
|
||||
|
||||
accuracy = 100 * (np.array(all_preds) == np.array(all_labels)).sum() / len(classes)
|
||||
print(f"Test Accuracy: {accuracy:.2f}%")
|
||||
print(classification_report(all_labels, all_preds, zero_division=0))
|
||||
print(classification_report(all_labels, all_preds, labels=classes, zero_division=0))
|
||||
|
||||
|
||||
def save(self, filename=None):
|
||||
@@ -101,13 +106,109 @@ class Model(ABC):
|
||||
start_time = time.time()
|
||||
|
||||
# Delegate the actual algorithmic weight/logit manipulation to the strategy
|
||||
strategy.apply(self.network, forget_loader, retain_loader)
|
||||
strategy.apply(self.model, forget_loader, retain_loader)
|
||||
|
||||
elapsed_time = time.time() - start_time
|
||||
print(f"{strategy.__class__.__name__} completed in {elapsed_time:.4f} seconds.")
|
||||
|
||||
return elapsed_time
|
||||
|
||||
def evaluate(self, loader, mode="eval"):
|
||||
"""
|
||||
Evaluates the model, prints terminal reports, and routes metrics to
|
||||
a file logger based on the current context mode.
|
||||
"""
|
||||
self.model.eval()
|
||||
all_preds, all_labels = [], []
|
||||
print(f"\nEvaluating Domain: [{mode}]...")
|
||||
|
||||
with torch.no_grad():
|
||||
for inputs, labels in loader:
|
||||
inputs, labels = inputs.to(self.device), labels.to(self.device)
|
||||
outputs = self.model(inputs)
|
||||
_, predicted = torch.max(outputs, 1)
|
||||
all_preds.extend(predicted.cpu().numpy())
|
||||
all_labels.extend(labels.cpu().numpy())
|
||||
|
||||
# Extract only the active classes evaluated in this loader slice
|
||||
classes = sorted(list(set(all_labels)))
|
||||
accuracy = 100 * (np.array(all_preds) == np.array(all_labels)).sum() / len(all_labels)
|
||||
|
||||
print(f"Test Accuracy: {accuracy:.2f}%")
|
||||
|
||||
# 1. Print standard text report to terminal
|
||||
print(classification_report(all_labels, all_preds, labels=classes, zero_division=0))
|
||||
|
||||
# 2. Extract structured dictionary metrics
|
||||
report_dict = classification_report(
|
||||
all_labels,
|
||||
all_preds,
|
||||
labels=classes,
|
||||
output_dict=True,
|
||||
zero_division=0
|
||||
)
|
||||
|
||||
# 3. Delegate file tracking to isolated helper method
|
||||
self._log_to_csv(mode, accuracy, classes, report_dict)
|
||||
|
||||
|
||||
def _log_to_csv(self, mode, accuracy, classes, report_dict):
|
||||
"""Handles directory structures, file setups, and distinct CSV column formatting."""
|
||||
arch_name = self.__class__.__name__.lower()
|
||||
save_dir = Path("reports")
|
||||
save_dir.mkdir(parents=True, exist_ok=True)
|
||||
csv_path = save_dir / f"{arch_name}-{mode}.csv"
|
||||
|
||||
file_exists = csv_path.exists()
|
||||
'''
|
||||
# Structure payload and headers based on evaluation slice type
|
||||
if mode == "forget":
|
||||
headers = ["accuracy", "precision", "recall", "f1-score"]
|
||||
target_cls_str = str(classes[0])
|
||||
metrics = report_dict[target_cls_str]
|
||||
row = [
|
||||
f"{accuracy / 100.0:.4f}",
|
||||
f"{metrics['precision']:.4f}",
|
||||
f"{metrics['recall']:.4f}",
|
||||
f"{metrics['f1-score']:.4f}"
|
||||
]
|
||||
else:
|
||||
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}"
|
||||
]'''
|
||||
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}")
|
||||
|
||||
|
||||
|
||||
# Using the factory patern here
|
||||
|
||||
Reference in New Issue
Block a user