import torch import torch.nn as nn import torchvision.models as models from torchvision.models import VGG16_Weights class VGG16Model(nn.Module): def __init__(self, num_classes=4): super(VGG16Model, self).__init__() #self.vgg16 = models.vgg16(pretrained=True) # Replace pretrained=True with weights=VGG16_Weights.DEFAULT #self.vgg16 = models.vgg16(weights=VGG16_Weights.DEFAULT) # Manually load the weights self.vgg16 = models.vgg16() # state_dict = torch.load("/work/mech-ai/angona3/Trial/vgg16_weights.pth", map_location=torch.device("cpu")) # self.vgg16.load_state_dict(state_dict) self.vgg16.classifier[6] = nn.Linear(4096, num_classes) ##In PyTorch CrossEntropyLoss Handles Softmax Internally ###Adding an explicit softmax layer would create numerical instability by double-applying softmax (once in your model, once in the loss), # leading to incorrect gradient calculations during training. self.vgg16.classifier[2] = nn.Dropout(p=0.6) # or 0.7 ##introducing dropout for regularization self.vgg16.classifier[5] = nn.Dropout(p=0.6) # or 0.7 # Freeze all the convolutional layers (feature extractor part) # The classifier layers (fully connected layers) remain trainable for param in self.vgg16.features.parameters(): param.requires_grad = False #param.requires_grad = True # Unfreeze the last two fully connected layers # Unfreeze Conv Block 4 and Conv Block 5 (512 filters, 3x3 filters, same padding) # best: conv_layers_to_unfreeze = [17, 19, 21, 24, 26, 28] conv_layers_to_unfreeze = [17, 19, 21, 24, 26, 28] for layer_idx in conv_layers_to_unfreeze: for param in self.vgg16.features[layer_idx].parameters(): param.requires_grad = True # Unfreeze the last two fully connected layers # Unfreeze all fully connected layers for param in self.vgg16.classifier.parameters(): param.requires_grad = True def forward(self, x): return self.vgg16(x) #Fine-tuning the entire network can lead to better performance compared to freezing layers ##because the model can adjust both the feature extractor and classifier to your specific dataset. ##Yes, nn.CrossEntropyLoss in PyTorch is explicitly designed to handle raw logits (ranging from βˆ’βˆžto +∞) directly and efficiently. ##CrossEntropyLoss=Softmax(logits)+Log+NLLLoss ##### In newer versions of torchvision, the weights argument replaces pretrained. # #The VGG16_Weights.DEFAULT is the new way to specify that anyone want the pretrained weights, and it is the preferred method. ##Deprecation Warning Fix: Replace pretrained=True with weights=VGG16_Weights.DEFAULT. ##Security Warning Fix: You don't need to use torch.load in this case because you're not loading a pre-trained model from a .pth file. ##from torchvision.models import VGG16_Weights ## self.vgg16 = models.vgg16(weights=VGG16_Weights.DEFAULT) ## adding dropout to VGG16 #class VGG16Model(nn.Module): # def __init__(self, num_classes=4): # super(VGG16Model, self).__init__() # self.vgg16 = models.vgg16(pretrained=True) # self.vgg16.classifier[6] = nn.Sequential( # nn.Linear(4096, 1024), # First layer reduces dimensions to 1024 # nn.ReLU(), # Adds non-linearity to increase learning capacity # nn.Dropout(0.5), # Introduces dropout for regularization # nn.Linear(1024, num_classes) # Second layer maps to the desired number of classes # ) # def forward(self, x): # return self.vgg16(x) #import torch.nn as nn #from torchvision import models #def get_resnet18_model(num_classes): # model = models.resnet18(pretrained=True) # model.fc = nn.Linear(model.fc.in_features, num_classes) # return model ##VGG16 structure #(vgg16.classifier): Sequential( # (0): Linear(25088, 4096) # (1): ReLU(inplace=True) # (2): Dropout(p=0.5, inplace=False) # (3): Linear(4096, 4096) # (4): ReLU(inplace=True) # (5): Dropout(p=0.5, inplace=False) # (6): Linear(4096, num_classes) #)