jrrade's picture
added necessary files for app to run on HF
74c02ff
Raw History Blame Contribute Delete
4.18 kB
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)
#)