import torch import torch.nn as nn from torchvision import models from torchvision.models import ResNet18_Weights from src.config import IMG_SIZE, NUM_CLASSES class MLPClassifier(nn.Module): def __init__(self): super(MLPClassifier, self).__init__() self.flatten = nn.Flatten() self.layers = nn.Sequential( nn.Linear(IMG_SIZE * IMG_SIZE * 3, 512), nn.ReLU(), nn.Linear(512, 256), nn.ReLU(), nn.Linear(256, NUM_CLASSES), ) def forward(self, x): x = self.flatten(x) return self.layers(x) class SimpleCNN(nn.Module): def __init__(self): super(SimpleCNN, self).__init__() self.conv1 = nn.Sequential( nn.Conv2d(3, 16, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2, 2), ) self.conv2 = nn.Sequential( nn.Conv2d(16, 32, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2, 2), ) self.classifier = nn.Sequential( nn.Flatten(), nn.Linear(32 * 56 * 56, 128), nn.ReLU(), nn.Linear(128, NUM_CLASSES), ) def forward(self, x): x = self.conv1(x) x = self.conv2(x) x = self.classifier(x) return x def create_resnet18_fc_only(): model = models.resnet18(weights=ResNet18_Weights.DEFAULT) for param in model.parameters(): param.requires_grad = False num_ftrs = model.fc.in_features model.fc = nn.Linear(num_ftrs, NUM_CLASSES) return model def create_resnet18_layer4_fc(): model = models.resnet18(weights=ResNet18_Weights.DEFAULT) for param in model.parameters(): param.requires_grad = False for param in model.layer4.parameters(): param.requires_grad = True num_ftrs = model.fc.in_features model.fc = nn.Linear(num_ftrs, NUM_CLASSES) return model MODEL_BUILDERS = { "MLP Classifier": MLPClassifier, "Simple CNN": SimpleCNN, "Transfer Learning (FC only)": create_resnet18_fc_only, "Transfer Learning (Layer4 + FC)": create_resnet18_layer4_fc, } def get_model(name: str) -> nn.Module: builder = MODEL_BUILDERS.get(name) if builder is None: raise ValueError(f"Unknown model: {name}. Choose from {list(MODEL_BUILDERS.keys())}") return builder()