cleaned up for submission
This commit is contained in:
@@ -11,8 +11,8 @@ class EfficientNet(Model):
|
||||
|
||||
m = models.efficientnet_b1(weights=models.EfficientNet_B1_Weights.DEFAULT)
|
||||
|
||||
# Unfreeze the last block for a lighter touch
|
||||
for param in m.features[-1].parameters(): param.requires_grad = True
|
||||
# Unfreeze the last block
|
||||
# for param in m.features[-1].parameters(): param.requires_grad = True
|
||||
|
||||
# Standard classifier fix
|
||||
m.classifier[1] = nn.Linear(m.classifier[1].in_features, self.size)
|
||||
|
||||
@@ -31,13 +31,13 @@ class Model(ABC):
|
||||
optimizer = optim.Adam(filter(lambda p: p.requires_grad, self.model.parameters()), lr=rate, weight_decay=0.1)
|
||||
|
||||
scheduler = CosineAnnealingLR(optimizer, T_max=epochs, eta_min=1e-6)
|
||||
# to save reports
|
||||
# file_path = Path(f"{mode}/{self.__class__.__name__.lower()}/time_metrics.txt")
|
||||
# Util._initialize_log_file(file_path)
|
||||
# to save training time to reports
|
||||
file_path = Path(f"{mode}/{self.__class__.__name__.lower()}/time_metrics.txt")
|
||||
Util._initialize_log_file(file_path)
|
||||
|
||||
|
||||
print(f"Starting training on {self.device}...")
|
||||
# start_time = time.time()
|
||||
start_time = time.time()
|
||||
# training phase
|
||||
self.model.train()
|
||||
|
||||
@@ -49,7 +49,7 @@ class Model(ABC):
|
||||
optimizer.zero_grad()
|
||||
# forward pass
|
||||
outputs = self.model(inputs)
|
||||
# comoutew loss
|
||||
# comopute loss
|
||||
loss = criterion(outputs, labels)
|
||||
# backward pass
|
||||
loss.backward()
|
||||
@@ -58,9 +58,9 @@ class Model(ABC):
|
||||
scheduler.step()
|
||||
|
||||
print(f"Epoch {epoch+1}/{epochs} | Loss: {total_loss / len(loader):.4f}")
|
||||
#end_time = time.time()
|
||||
#execution_time = end_time - start_time
|
||||
#Util.log_metric(log_file=file_path, execution_time=execution_time)
|
||||
end_time = time.time()
|
||||
execution_time = end_time - start_time
|
||||
Util.log_metric(log_file=file_path, execution_time=execution_time)
|
||||
if self.device.type == 'cuda': torch.cuda.synchronize()
|
||||
print(f"Training complete.")
|
||||
|
||||
@@ -123,10 +123,10 @@ class Model(ABC):
|
||||
|
||||
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))
|
||||
# Print standard text report to terminal
|
||||
#print(classification_report(all_labels, all_preds, labels=classes, zero_division=0))
|
||||
|
||||
# 2. Extract structured dictionary metrics
|
||||
# Structured dictionary metrics
|
||||
report_dict = classification_report(
|
||||
all_labels,
|
||||
all_preds,
|
||||
@@ -135,8 +135,7 @@ class Model(ABC):
|
||||
zero_division=0
|
||||
)
|
||||
|
||||
# 3. Delegate file tracking to isolated helper method
|
||||
#self._log_to_csv(mode, accuracy,report_dict)
|
||||
# report metrics to choriographer
|
||||
return accuracy, report_dict
|
||||
|
||||
|
||||
|
||||
@@ -6,69 +6,6 @@ from torch.utils.data import DataLoader
|
||||
import numpy as np
|
||||
from sklearn.metrics import classification_report
|
||||
from architectures.Model import Model
|
||||
|
||||
'''class WF_Module(nn.Module):
|
||||
"""
|
||||
Pure PyTorch Neural Network module graph.
|
||||
Keeps parameter registration and autograd tracking separate from
|
||||
the framework's high-level Model abstractions to prevent recursion collisions.
|
||||
"""
|
||||
def __init__(self, original_model: nn.Module, num_classes: int):
|
||||
super().__init__()
|
||||
|
||||
self.original_model = original_model
|
||||
|
||||
# Target layer for weight filtering (layer4 block 1 conv2 or conv3 depending on arch)
|
||||
last_layer = original_model.layer4[1]
|
||||
|
||||
# Some versions are limited to 2 convolutional layers
|
||||
if hasattr(last_layer, "conv3"):
|
||||
self.target_conv = last_layer.conv3
|
||||
else:
|
||||
self.target_conv = last_layer.conv2
|
||||
|
||||
# Completely freeze the original ResNet parameters
|
||||
for param in self.parameters():
|
||||
param.requires_grad = False
|
||||
|
||||
# Initialize the alpha parameter matrix (Rows = Classes, Cols = Channels)
|
||||
out_channels = self.target_conv.weight.shape[0]
|
||||
self.alpha = nn.Parameter(torch.full((num_classes, out_channels), 3.0))'''
|
||||
|
||||
'''
|
||||
Poppi et_al's Single-shot multiclass unlearning.
|
||||
This calculation happens only once to generate the mask. once the mask is generated,
|
||||
Unlearning and remembering becomes a matter of switching gates on and off.'''
|
||||
'''
|
||||
def forward(self, x: torch.Tensor, target_class_indices: torch.Tensor) -> torch.Tensor:
|
||||
# we linearly loop through layers 1 to 4[block 1] (for ResNet)
|
||||
# for i in M_{|L|} do l <- l[i]
|
||||
x = self.original_model.maxpool(self.original_model.relu(self.original_model.bn1(self.original_model.conv1(x))))
|
||||
x = self.original_model.layer1(x)
|
||||
x = self.original_model.layer2(x)
|
||||
x = self.original_model.layer3(x)
|
||||
x = self.original_model.layer4[0](x)
|
||||
|
||||
# The second block execute its internal transformations natively
|
||||
# This handles conv1->conv2 (ResNet18) or conv1->conv2->conv3 (ResNet50) automatically!
|
||||
# Xi+1 <- l(Xi, ˆwl)
|
||||
x = self.original_model.layer4[1](x)
|
||||
|
||||
# Apply mask dynamically to the completed block feature map
|
||||
# wl <- αl[Yunl] ⊙ ˆwl
|
||||
batch_alpha = self.alpha[target_class_indices]
|
||||
mask = torch.sigmoid(batch_alpha).view(x.size(0), -1, 1, 1)
|
||||
x = x * mask
|
||||
|
||||
# Remaining standard head steps
|
||||
x = self.original_model.avgpool(x)
|
||||
x = torch.flatten(x, 1)
|
||||
# so here we are returning the output logits
|
||||
# the result of classification is then
|
||||
# argmax(x)
|
||||
return self.original_model.fc(x)
|
||||
'''
|
||||
|
||||
class WF_Module(nn.Module):
|
||||
def __init__(self, original_model: nn.Module, num_classes: int, arch_enum):
|
||||
super().__init__()
|
||||
|
||||
Reference in New Issue
Block a user