Transfer Learning on VGG19, ResNet50, and InceptionV3
Load CIFAR10 dataset
Import Image Classification Pre-trained Models
Training Models
Experiment with Fine-Tuned Pre-trained Models
Download Fine-Tuned Models
Layers and Parameters
Download from Library
import torch
from torchvision import datasets, transforms
# Define transformations for the CIFAR10 images to match the pre-trained model input requirements
transform_vgg19_resnet50v2 = transforms.Compose([
transforms.Resize(224), # Resizing to 224x224 for VGG19 and ResNet50V2
transforms.RandomHorizontalFlip(), # Data augmentation
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
transform_inceptionv3 = transforms.Compose([
transforms.Resize(299), # Resizing to 299x299 for inceptionv3
transforms.RandomHorizontalFlip(), # Data augmentation
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
# Load CIFAR10 training and test datasets using torchvision datasets module with appropriate transforms
trainset_vgg19_resnet50v2 = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_vgg19_resnet50v2)
trainset_inceptionv3 = datasets.CIFAR10(root='./data', train=True, download=False, transform=transform_inceptionv3)
testset_vgg19_resnet50v2 = datasets.CIFAR10(root='./data', train=False, download=False, transform=transform_vgg19_resnet50v2)
testset_inceptionv3 = datasets.CIFAR10(root='./data', train=False, download=False, transform=transform_inceptionv3)
# We will use a DataLoader to handle batching
trainloader_vgg19_resnet50v2 = torch.utils.data.DataLoader(trainset_vgg19_resnet50v2, batch_size=128, shuffle=True)
trainloader_inceptionv3 = torch.utils.data.DataLoader(trainset_inceptionv3, batch_size=128, shuffle=True)
testloader_vgg19_resnet50v2 = torch.utils.data.DataLoader(testset_vgg19_resnet50v2, batch_size=128, shuffle=False)
testloader_inceptionv3 = torch.utils.data.DataLoader(testset_inceptionv3, batch_size=128, shuffle=False)
# Check if the transformation was applied correctly by getting the shape of the first batch
first_batch_train_vgg19_resnet50v2 = next(iter(trainloader_vgg19_resnet50v2))[0].shape
first_batch_train_inceptionv3 = next(iter(trainloader_inceptionv3))[0].shape
first_batch_test_vgg19_resnet50v2 = next(iter(testloader_vgg19_resnet50v2))[0].shape
first_batch_test_inceptionv3 = next(iter(testloader_inceptionv3))[0].shape
print("Train batch shape VGG19/ResNet50V2:", first_batch_train_vgg19_resnet50v2)
print("Train batch shape inceptionv3:", first_batch_train_inceptionv3)
print("Test batch shape VGG19/ResNet50V2:", first_batch_test_vgg19_resnet50v2)
print("Test batch shape inceptionv3:", first_batch_test_inceptionv3)
Files already downloaded and verified Train batch shape VGG19/ResNet50V2: torch.Size([128, 3, 224, 224]) Train batch shape inceptionv4: torch.Size([128, 3, 299, 299]) Test batch shape VGG19/ResNet50V2: torch.Size([128, 3, 224, 224]) Test batch shape inceptionv4: torch.Size([128, 3, 299, 299])
pre-trained models, including VGG-19, ResNet50V2, and inceptionv3. Then, run them on the CIFAR10.
from torchvision import models
import torch.nn as nn
import torch.optim as optim
#GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Load pre-trained models
vgg19 = models.vgg19(pretrained=True)
resnet50v2 = models.resnet50(pretrained=True)
inceptionv3 = models.inception_v3(pretrained=True)
inceptionv3.aux_logits = False # Turn off the auxiliary output
# Modify the classifiers for CIFAR-10 (10 classes)
vgg19.classifier[6] = nn.Linear(vgg19.classifier[6].in_features, 10)
resnet50v2.fc = nn.Linear(resnet50v2.fc.in_features, 10)
inceptionv3.fc = nn.Linear(inceptionv3.fc.in_features, 10)
/usr/local/lib/python3.10/dist-packages/torchvision/models/_utils.py:208: UserWarning: The parameter 'pretrained' is deprecated since 0.13 and may be removed in the future, please use 'weights' instead. warnings.warn( /usr/local/lib/python3.10/dist-packages/torchvision/models/_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and may be removed in the future. The current behavior is equivalent to passing `weights=VGG19_Weights.IMAGENET1K_V1`. You can also use `weights=VGG19_Weights.DEFAULT` to get the most up-to-date weights. warnings.warn(msg) /usr/local/lib/python3.10/dist-packages/torchvision/models/_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and may be removed in the future. The current behavior is equivalent to passing `weights=ResNet50_Weights.IMAGENET1K_V1`. You can also use `weights=ResNet50_Weights.DEFAULT` to get the most up-to-date weights. warnings.warn(msg) /usr/local/lib/python3.10/dist-packages/torchvision/models/_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and may be removed in the future. The current behavior is equivalent to passing `weights=Inception_V3_Weights.IMAGENET1K_V1`. You can also use `weights=Inception_V3_Weights.DEFAULT` to get the most up-to-date weights. warnings.warn(msg)
def print_model_parameters(model):
print("Model's named parameters:")
for name, param in model.named_parameters():
print(f"{name} - requires_grad: {param.requires_grad}, shape: {param.shape}")
def print_optimizer_parameters(optimizer):
print("\nOptimizer's parameter groups:")
for param_group in optimizer.param_groups:
for param in param_group['params']:
print(f"Parameter group has learning rate of {param_group['lr']}, weight decay of {param_group['weight_decay']}")
if param.requires_grad:
print(f" - This parameter group includes trainable parameters.")
else:
print(f" - This parameter group includes non-trainable parameters.")
def print_optimizer_parameters_names(model, optimizer):
print("\nOptimizer's parameter names:")
# Create a set of the id's of the parameters in the optimizer
optim_params = {id(p) for pg in optimizer.param_groups for p in pg['params']}
# Match the model parameters with the optimizer parameters
for name, param in model.named_parameters():
if id(param) in optim_params:
print(f"Parameter in optimizer: {name}")
def train_model(model, train_loader, test_loader, criterion, num_epochs, unfreeze_layers, device='cpu'):
# Freeze all the layers first
for param in model.parameters():
param.requires_grad = False
if(model == vgg19):
# Only classifier parameters are optimized at first
optimizer = optim.SGD(model.classifier.parameters(), lr=0.001, momentum=0.9, weight_decay=1e-4)
# Then, unfreeze the classifier layers
for param in model.classifier.parameters():
param.requires_grad = True
# Define the layers to unfreeze
unfreeze_layers = [model.features[i] for i in range(len(model.features)) if not isinstance(model.features[i], nn.MaxPool2d)]
else:
optimizer = optim.SGD(model.fc.parameters(), lr=0.001, momentum=0.9, weight_decay=1e-4)
# Then, unfreeze the fc layers
for param in model.fc.parameters():
param.requires_grad = True
# Define the layers to unfreeze
if model == resnet50v2:
unfreeze_layers = [model.layer4, model.layer3, model.layer2, model.layer1, model.conv1, model.bn1][::-1]
else:
unfreeze_layers = [
model.Mixed_7c, model.Mixed_7b, model.Mixed_7a,
model.Mixed_6e, model.Mixed_6d, model.Mixed_6c,
model.Mixed_6b, model.Mixed_6a, model.Mixed_5d,
model.Mixed_5c, model.Mixed_5b, model.Conv2d_4a_3x3,
model.Conv2d_3b_1x1, model.Conv2d_2b_3x3, model.Conv2d_2a_3x3, model.Conv2d_1a_3x3
][::-1]
# print_model_parameters(model)
# Scheduler to adjust the learning rate
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min')
for epoch in range(num_epochs):
model.train() # Set the model to training mode
running_loss = 0.0
correct = 0
total = 0
for inputs, targets in train_loader:
inputs, targets = inputs.to(device), targets.to(device)
optimizer.zero_grad() # Zero the parameter gradients
outputs = model(inputs) # Forward pass
loss = criterion(outputs, targets) # Compute the loss
loss.backward() # Backward pass
optimizer.step() # Optimize the model
running_loss += loss.item()
_, predicted = outputs.max(1)
total += targets.size(0)
correct += predicted.eq(targets).sum().item()
train_loss = running_loss / len(train_loader)
train_accuracy = 100. * correct / total
val_loss, val_accuracy = evaluate(model, test_loader, criterion, device)
# Print training progress
print(f"Epoch {epoch+1}/{num_epochs}")
print(f"Training loss: {train_loss:.4f}, Accuracy: {train_accuracy:.2f}%")
print(f"Validation loss: {val_loss:.4f}, Accuracy: {val_accuracy:.2f}%\n")
# Adjust the learning rate based on the validation loss
scheduler.step(val_loss)
# Here's where you would print out the learning rates
# for i, param_group in enumerate(optimizer.param_groups):
# print(f"Learning rate for parameter group {i}: {param_group['lr']}")
# Gradual unfreezing: optionally unfreeze layers if we are at the right epoch
if epoch == (num_epochs-5):
# Unfreeze all the layers
while(len(unfreeze_layers)):
layer_to_unfreeze = unfreeze_layers.pop()
for param in layer_to_unfreeze.parameters():
param.requires_grad = True
# Update the optimizer for the newly unfrozen parameters
for param_group in optimizer.param_groups:
param_group['lr'] = 0.0001
unfreeze_layers = []
elif unfreeze_layers and epoch >= 4:
if model == resnet50v2 and ((epoch+1) % int((num_epochs+1)/5))!=0 :
continue
else:
c = 0
layer_to_unfreeze = None
while(c==0):
layer_to_unfreeze = unfreeze_layers.pop()
for param in layer_to_unfreeze.parameters():
param.requires_grad = True
c = 1
# Update the optimizer for the newly unfrozen parameters
optimizer.add_param_group({'params': layer_to_unfreeze.parameters(), 'lr': 0.0005})
# print_model_parameters(model)
return model
def evaluate(model, data_loader, criterion, device):
model.eval() # Set the model to evaluation mode
running_loss = 0.0
correct = 0
total = 0
with torch.no_grad(): # Deactivate autograd to reduce memory usage
for inputs, targets in data_loader:
inputs, targets = inputs.to(device), targets.to(device)
outputs = model(inputs)
loss = criterion(outputs, targets)
running_loss += loss.item()
_, predicted = outputs.max(1)
total += targets.size(0)
correct += predicted.eq(targets).sum().item()
epoch_loss = running_loss / len(data_loader)
epoch_accuracy = 100. * correct / total
return epoch_loss, epoch_accuracy
import time
start = time.time() # Start the timer
print(f"Training started at {time.strftime('%X')}")
# Call the training function
# Initialize the model, criterion, optimizer, and data loaders
model = vgg19.to(device)
criterion = nn.CrossEntropyLoss()
# Define the number of epochs
num_epochs = 25
# Call the training function
trained_model = train_model(
model=model,
train_loader=trainloader_vgg19_resnet50v2, # Replace with your actual train data loader
test_loader=testloader_vgg19_resnet50v2, # Replace with your actual test data loader
criterion=criterion,
num_epochs=num_epochs,
unfreeze_layers=[], # This should be a list of layers you wish to unfreeze
device=device
)
print("Training complete.")
print(f"Training endted at {time.strftime('%X')}")
print(f"Training took {time.time() - start} seconds")
Training started at 20:53:43 Epoch 1/25 Training loss: 0.7130, Accuracy: 75.41% Validation loss: 0.4872, Accuracy: 83.08% Epoch 2/25 Training loss: 0.4997, Accuracy: 82.41% Validation loss: 0.4352, Accuracy: 85.03% Epoch 3/25 Training loss: 0.4460, Accuracy: 84.57% Validation loss: 0.4081, Accuracy: 85.70% Epoch 4/25 Training loss: 0.4096, Accuracy: 85.72% Validation loss: 0.3918, Accuracy: 86.34% Epoch 5/25 Training loss: 0.3842, Accuracy: 86.41% Validation loss: 0.3795, Accuracy: 86.61% Epoch 6/25 Training loss: 0.3579, Accuracy: 87.50% Validation loss: 0.3633, Accuracy: 87.40% Epoch 7/25 Training loss: 0.3316, Accuracy: 88.30% Validation loss: 0.3395, Accuracy: 88.03% Epoch 8/25 Training loss: 0.2952, Accuracy: 89.75% Validation loss: 0.3123, Accuracy: 89.31% Epoch 9/25 Training loss: 0.2620, Accuracy: 90.77% Validation loss: 0.2945, Accuracy: 89.62% Epoch 10/25 Training loss: 0.2273, Accuracy: 92.02% Validation loss: 0.2746, Accuracy: 90.44% Epoch 11/25 Training loss: 0.1975, Accuracy: 93.03% Validation loss: 0.2649, Accuracy: 90.74% Epoch 12/25 Training loss: 0.1718, Accuracy: 94.12% Validation loss: 0.2433, Accuracy: 91.50% Epoch 13/25 Training loss: 0.1498, Accuracy: 94.74% Validation loss: 0.2292, Accuracy: 92.18% Epoch 14/25 Training loss: 0.1274, Accuracy: 95.53% Validation loss: 0.2367, Accuracy: 92.08% Epoch 15/25 Training loss: 0.1080, Accuracy: 96.14% Validation loss: 0.2378, Accuracy: 92.32% Epoch 16/25 Training loss: 0.0951, Accuracy: 96.63% Validation loss: 0.2243, Accuracy: 92.78% Epoch 17/25 Training loss: 0.0807, Accuracy: 97.21% Validation loss: 0.2316, Accuracy: 92.96% Epoch 18/25 Training loss: 0.0704, Accuracy: 97.57% Validation loss: 0.2371, Accuracy: 93.05% Epoch 19/25 Training loss: 0.0635, Accuracy: 97.69% Validation loss: 0.2360, Accuracy: 93.08% Epoch 20/25 Training loss: 0.0558, Accuracy: 98.04% Validation loss: 0.2255, Accuracy: 93.21% Epoch 21/25 Training loss: 0.0481, Accuracy: 98.31% Validation loss: 0.2508, Accuracy: 93.31%
# Save the trained model
import time
torch.save(trained_model.state_dict(), 'vgg19_trained_2.pth')
import matplotlib.pyplot as plt
# Training and validation losses and accuracies provided by the user
epochs = list(range(1, 22))
training_loss = [
0.7130, 0.4997, 0.4460, 0.4096, 0.3842, 0.3579, 0.3316, 0.2952, 0.2620,
0.2273, 0.1975, 0.1718, 0.1498, 0.1274, 0.1080, 0.0951, 0.0807, 0.0704,
0.0635, 0.0558, 0.0481
]
validation_loss= [
0.4872, 0.4352, 0.4081, 0.3918, 0.3795, 0.3633, 0.3395, 0.3123, 0.2945,
0.2746, 0.2649, 0.2433, 0.2292, 0.2367, 0.2378, 0.2243, 0.2316, 0.2371,
0.2360, 0.2255, 0.2508
]
training_accuracy = [
75.41, 82.41, 84.57, 85.72, 86.41, 87.50, 88.30, 89.75, 90.77,
92.02, 93.03, 94.12, 94.74, 95.53, 96.14, 96.63, 97.21, 97.57,
97.69, 98.04, 98.31
]
validation_accuracy= [
83.08, 85.03, 85.70, 86.34, 86.61, 87.40, 88.03, 89.31, 89.62,
90.44, 90.74, 91.50, 92.18, 92.08, 92.32, 92.78, 92.96, 93.05,
93.08, 93.21, 93.31
]
# Plot training and validation loss
plt.figure(figsize=(14, 7))
plt.subplot(1, 2, 1)
plt.plot(epochs, training_loss, label='Training Loss')
plt.plot(epochs, validation_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
# Plot training and validation accuracy
plt.subplot(1, 2, 2)
plt.plot(epochs, training_accuracy, label='Training Accuracy')
plt.plot(epochs, validation_accuracy, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy (%)')
plt.legend()
plt.tight_layout()
plt.show()
import time
start = time.time() # Start the timer
print(f"Training started at {time.strftime('%X')}")
# Call the training function
# Initialize the model, criterion, optimizer, and data loaders
model = resnet50v2.to(device)
criterion = nn.CrossEntropyLoss()
# Define the number of epochs
num_epochs = 25
# Call the training function
trained_model = train_model(
model=model,
train_loader=trainloader_vgg19_resnet50v2, # Replace with your actual train data loader
test_loader=testloader_vgg19_resnet50v2, # Replace with your actual test data loader
criterion=criterion,
num_epochs=num_epochs,
unfreeze_layers=[], # This should be a list of layers you wish to unfreeze
device=device
)
print("Training complete.")
print(f"Training endted at {time.strftime('%X')}")
print(f"Training took {time.time() - start} seconds")
Training started at 22:11:50 Epoch 1/25 Training loss: 1.1711, Accuracy: 68.18% Validation loss: 0.8154, Accuracy: 76.30% Epoch 2/25 Training loss: 0.7505, Accuracy: 76.99% Validation loss: 0.7044, Accuracy: 77.49% Epoch 3/25 Training loss: 0.6744, Accuracy: 78.35% Validation loss: 0.6493, Accuracy: 78.49% Epoch 4/25 Training loss: 0.6387, Accuracy: 79.20% Validation loss: 0.6229, Accuracy: 79.38% Epoch 5/25 Training loss: 0.6121, Accuracy: 79.72% Validation loss: 0.6053, Accuracy: 79.48% Epoch 6/25 Training loss: 0.4721, Accuracy: 83.81% Validation loss: 0.4056, Accuracy: 85.96% Epoch 7/25 Training loss: 0.3383, Accuracy: 88.40% Validation loss: 0.3481, Accuracy: 88.03% Epoch 8/25 Training loss: 0.2814, Accuracy: 90.27% Validation loss: 0.3274, Accuracy: 88.46% Epoch 9/25 Training loss: 0.2380, Accuracy: 91.87% Validation loss: 0.3089, Accuracy: 89.12% Epoch 10/25 Training loss: 0.2069, Accuracy: 93.06% Validation loss: 0.2987, Accuracy: 89.64% Epoch 11/25 Training loss: 0.1599, Accuracy: 94.58% Validation loss: 0.2277, Accuracy: 92.16% Epoch 12/25 Training loss: 0.1105, Accuracy: 96.58% Validation loss: 0.2150, Accuracy: 92.78% Epoch 13/25 Training loss: 0.0781, Accuracy: 97.71% Validation loss: 0.2085, Accuracy: 93.03% Epoch 14/25 Training loss: 0.0598, Accuracy: 98.44% Validation loss: 0.2093, Accuracy: 93.21% Epoch 15/25 Training loss: 0.0448, Accuracy: 98.91% Validation loss: 0.2014, Accuracy: 93.47% Epoch 16/25 Training loss: 0.0341, Accuracy: 99.30% Validation loss: 0.1993, Accuracy: 93.58% Epoch 17/25 Training loss: 0.0269, Accuracy: 99.46% Validation loss: 0.1981, Accuracy: 93.72% Epoch 18/25 Training loss: 0.0189, Accuracy: 99.70% Validation loss: 0.2089, Accuracy: 93.92% Epoch 19/25 Training loss: 0.0152, Accuracy: 99.78% Validation loss: 0.2016, Accuracy: 93.79% Epoch 20/25 Training loss: 0.0129, Accuracy: 99.84% Validation loss: 0.2133, Accuracy: 93.77% Epoch 21/25 Training loss: 0.0105, Accuracy: 99.89% Validation loss: 0.2049, Accuracy: 93.92% Epoch 22/25 Training loss: 0.0082, Accuracy: 99.94% Validation loss: 0.2105, Accuracy: 93.95% Epoch 23/25 Training loss: 0.0078, Accuracy: 99.95% Validation loss: 0.2045, Accuracy: 93.88% Epoch 24/25 Training loss: 0.0075, Accuracy: 99.96% Validation loss: 0.2045, Accuracy: 93.92% Epoch 25/25 Training loss: 0.0074, Accuracy: 99.95% Validation loss: 0.2083, Accuracy: 93.93% Training complete. Training endted at 01:11:18 Training took 10768.673486471176 seconds
# Save the trained model
torch.save(trained_model.state_dict(), '/content/drive/MyDrive/Colab Notebooks/resnet50v2.pth')
import matplotlib.pyplot as plt
# Given data for plotting
training_loss = [1.1711, 0.7505, 0.6744, 0.6387, 0.6121, 0.4721, 0.3383, 0.2814, 0.2380,
0.2069, 0.1599, 0.1105, 0.0781, 0.0598, 0.0448, 0.0341, 0.0269, 0.0189,
0.0152, 0.0129, 0.0105, 0.0082, 0.0078, 0.0075, 0.0074]
validation_loss = [0.8154, 0.7044, 0.6493, 0.6229, 0.6053, 0.4056, 0.3481, 0.3274, 0.3089,
0.2987, 0.2277, 0.2150, 0.2085, 0.2093, 0.2014, 0.1993, 0.1981, 0.2089,
0.2016, 0.2133, 0.2049, 0.2105, 0.2045, 0.2045, 0.2083]
training_accuracy = [68.18, 76.99, 78.35, 79.20, 79.72, 83.81, 88.40, 90.27, 91.87,
93.06, 94.58, 96.58, 97.71, 98.44, 98.91, 99.30, 99.46, 99.70,
99.78, 99.84, 99.89, 99.94, 99.95, 99.96, 99.95]
validation_accuracy = [76.30, 77.49, 78.49, 79.38, 79.48, 85.96, 88.03, 88.46, 89.12,
89.64, 92.16, 92.78, 93.03, 93.21, 93.47, 93.58, 93.72, 93.92,
93.79, 93.77, 93.92, 93.95, 93.88, 93.92, 93.93]
epochs = list(range(1, 26))
# Plot training and validation loss
plt.figure(figsize=(14, 7))
plt.subplot(1, 2, 1)
plt.plot(epochs, training_loss, label='Training Loss')
plt.plot(epochs, validation_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
# Plot training and validation accuracy
plt.subplot(1, 2, 2)
plt.plot(epochs, training_accuracy, label='Training Accuracy')
plt.plot(epochs, validation_accuracy, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy (%)')
plt.legend()
plt.tight_layout()
plt.show()
import time
start = time.time() # Start the timer
print(f"Training started at {time.strftime('%X')}")
# Call the training function
# Initialize the model, criterion, optimizer, and data loaders
model = inceptionv3.to(device)
criterion = nn.CrossEntropyLoss()
# Define the number of epochs
num_epochs = 25
# Call the training function
trained_model = train_model(
model=model,
train_loader=trainloader_inceptionv3, # Replace with your actual train data loader
test_loader=testloader_inceptionv3, # Replace with your actual test data loader
criterion=criterion,
num_epochs=num_epochs,
unfreeze_layers=[], # This should be a list of layers you wish to unfreeze
device=device
)
print("Training complete.")
print(f"Training endted at {time.strftime('%X')}")
print(f"Training took {time.time() - start} seconds")
Training started at 22:04:28 Epoch 1/25 Training loss: 1.6068, Accuracy: 54.47% Validation loss: 1.1738, Accuracy: 69.62% Epoch 2/25 Training loss: 1.1158, Accuracy: 67.05% Validation loss: 0.9815, Accuracy: 71.55% Epoch 3/25 Training loss: 0.9963, Accuracy: 68.69% Validation loss: 0.8996, Accuracy: 72.26% Epoch 4/25 Training loss: 0.9404, Accuracy: 69.85% Validation loss: 0.8507, Accuracy: 73.44% Epoch 5/25 Training loss: 0.9066, Accuracy: 70.37% Validation loss: 0.8222, Accuracy: 73.46% Epoch 6/25 Training loss: 0.7952, Accuracy: 73.11% Validation loss: 0.6725, Accuracy: 77.22% Epoch 7/25 Training loss: 0.6465, Accuracy: 77.80% Validation loss: 0.5509, Accuracy: 80.81% Epoch 8/25 Training loss: 0.5256, Accuracy: 81.99% Validation loss: 0.4607, Accuracy: 83.64% Epoch 9/25 Training loss: 0.4280, Accuracy: 85.35% Validation loss: 0.3876, Accuracy: 86.12% Epoch 10/25 Training loss: 0.3338, Accuracy: 88.43% Validation loss: 0.3168, Accuracy: 88.89% Epoch 11/25 Training loss: 0.2508, Accuracy: 91.44% Validation loss: 0.2676, Accuracy: 90.45% Epoch 12/25 Training loss: 0.1915, Accuracy: 93.56% Validation loss: 0.2377, Accuracy: 91.69% Epoch 13/25 Training loss: 0.1483, Accuracy: 95.11% Validation loss: 0.2188, Accuracy: 92.56% Epoch 14/25 Training loss: 0.1150, Accuracy: 96.24% Validation loss: 0.2107, Accuracy: 93.03% Epoch 15/25 Training loss: 0.0908, Accuracy: 97.01% Validation loss: 0.1981, Accuracy: 93.63% Epoch 16/25 Training loss: 0.0686, Accuracy: 97.87% Validation loss: 0.2016, Accuracy: 93.38% Epoch 17/25 Training loss: 0.0556, Accuracy: 98.29% Validation loss: 0.1980, Accuracy: 93.76% Epoch 18/25 Training loss: 0.0409, Accuracy: 98.87% Validation loss: 0.1958, Accuracy: 94.10% Epoch 19/25 Training loss: 0.0361, Accuracy: 98.99% Validation loss: 0.1945, Accuracy: 94.10% Epoch 20/25 Training loss: 0.0530, Accuracy: 98.30% Validation loss: 0.1970, Accuracy: 94.13% Epoch 21/25 Training loss: 0.0910, Accuracy: 96.87% Validation loss: 0.1635, Accuracy: 94.70% Epoch 22/25 Training loss: 0.0564, Accuracy: 98.11% Validation loss: 0.1672, Accuracy: 94.75% Epoch 23/25 Training loss: 0.0406, Accuracy: 98.66% Validation loss: 0.1522, Accuracy: 95.37% Epoch 24/25 Training loss: 0.0292, Accuracy: 99.08% Validation loss: 0.1530, Accuracy: 95.25% Epoch 25/25 Training loss: 0.0259, Accuracy: 99.22% Validation loss: 0.1610, Accuracy: 95.36% Training complete. Training endted at 23:56:15 Training took 6706.780396461487 seconds
# Save the trained model
torch.save(trained_model.state_dict(), '/content/drive/MyDrive/results/inceptionv3.pth')
import matplotlib.pyplot as plt
# Training and validation loss and accuracy data
training_loss = [
1.6068, 1.1158, 0.9963, 0.9404, 0.9066, 0.7952, 0.6465, 0.5256, 0.4280,
0.3338, 0.2508, 0.1915, 0.1483, 0.1150, 0.0908, 0.0686, 0.0556, 0.0409,
0.0361, 0.0530, 0.0910, 0.0564, 0.0406, 0.0292, 0.0259
]
validation_loss = [
1.1738, 0.9815, 0.8996, 0.8507, 0.8222, 0.6725, 0.5509, 0.4607, 0.3876,
0.3168, 0.2676, 0.2377, 0.2188, 0.2107, 0.1981, 0.2016, 0.1980, 0.1958,
0.1945, 0.1970, 0.1635, 0.1672, 0.1522, 0.1530, 0.1610
]
training_accuracy = [
54.47, 67.05, 68.69, 69.85, 70.37, 73.11, 77.80, 81.99, 85.35,
88.43, 91.44, 93.56, 95.11, 96.24, 97.01, 97.87, 98.29, 98.87,
98.99, 98.30, 96.87, 98.11, 98.66, 99.08, 99.22
]
validation_accuracy = [
69.62, 71.55, 72.26, 73.44, 73.46, 77.22, 80.81, 83.64, 86.12,
88.89, 90.45, 91.69, 92.56, 93.03, 93.63, 93.38, 93.76, 94.10,
94.10, 94.13, 94.70, 94.75, 95.37, 95.25, 95.36
]
epochs = range(1, 26) # 25 epochs
# Plot training and validation loss
plt.figure(figsize=(14, 7))
plt.subplot(1, 2, 1)
plt.plot(epochs, training_loss, label='Training Loss')
plt.plot(epochs, validation_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
# Plot training and validation accuracy
plt.subplot(1, 2, 2)
plt.plot(epochs, training_accuracy, label='Training Accuracy')
plt.plot(epochs, validation_accuracy, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy (%)')
plt.legend()
plt.tight_layout()
plt.show()
# Convert the shareable link to a direct download link
vgg_link = "https://drive.google.com/file/d/1K2hMEiIS2XLXUt0nS62G-tryLgOSvXGz/view?usp=sharing" # Replace with your actual link
resnet_link = "https://drive.google.com/file/d/1KGthciEXc3HUC3bNRjd78dC_P6tVnyhk/view?usp=sharing"
inception_link = "https://drive.google.com/file/d/1-74fZEF0KdnniXAcMc3mXxsUsKgPMyvd/view?usp=sharing"
# Function to convert shareable link to direct download link
def convert_to_direct_download(gdrive_link):
file_id = gdrive_link.split('/')[5]
direct_link = f"https://drive.google.com/uc?export=download&id={file_id}"
return direct_link
# Convert and download VGG
direct_download_link_vgg = convert_to_direct_download(vgg_link)
!gdown --id {direct_download_link_vgg.split('=')[-1]} -O 'vgg19.pth'
/usr/local/lib/python3.10/dist-packages/gdown/cli.py:121: FutureWarning: Option `--id` was deprecated in version 4.3.1 and will be removed in 5.0. You don't need to pass it anymore to use a file ID. warnings.warn( Downloading... From: https://drive.google.com/uc?id=1K2hMEiIS2XLXUt0nS62G-tryLgOSvXGz To: /content/vgg19.pth 100% 558M/558M [00:02<00:00, 252MB/s]
# Convert and download ResNet
direct_download_link_resnet = convert_to_direct_download(resnet_link)
!gdown --id {direct_download_link_resnet.split('=')[-1]} -O 'resnet50v2.pth'
/usr/local/lib/python3.10/dist-packages/gdown/cli.py:121: FutureWarning: Option `--id` was deprecated in version 4.3.1 and will be removed in 5.0. You don't need to pass it anymore to use a file ID. warnings.warn( Downloading... From: https://drive.google.com/uc?id=1KGthciEXc3HUC3bNRjd78dC_P6tVnyhk To: /content/resnet50v2.pth 100% 94.4M/94.4M [00:00<00:00, 293MB/s]
# Convert and download Inception
direct_download_link = convert_to_direct_download(inception_link)
!gdown --id {direct_download_link.split('=')[-1]} -O 'inceptionv3.pth'
/usr/local/lib/python3.10/dist-packages/gdown/cli.py:121: FutureWarning: Option `--id` was deprecated in version 4.3.1 and will be removed in 5.0. You don't need to pass it anymore to use a file ID. warnings.warn( Downloading... From: https://drive.google.com/uc?id=1-74fZEF0KdnniXAcMc3mXxsUsKgPMyvd To: /content/inceptionv4.pth 100% 101M/101M [00:00<00:00, 180MB/s]
import torch
import torchvision.transforms as transforms
import torchvision.datasets as datasets
from torch.utils.data import DataLoader
import torch.nn as nn
from sklearn.metrics import f1_score
def evaluate_with_f1(model, data_loader, criterion, device):
model.eval() # Set the model to evaluation mode
running_loss = 0.0
total_preds = []
total_targets = []
with torch.no_grad(): # Deactivate autograd to reduce memory usage
for inputs, targets in data_loader:
# Transfer inputs and targets to the correct device
inputs, targets = inputs.to(device), targets.to(device)
outputs = model(inputs)
loss = criterion(outputs, targets)
running_loss += loss.item()
_, predicted = outputs.max(1)
# Append current predictions and current targets to list
total_preds.extend(predicted.view(-1).cpu().numpy())
total_targets.extend(targets.cpu().numpy())
# Calculate F1 score using true labels and predicted labels
f1 = f1_score(total_targets, total_preds, average='weighted')
epoch_loss = running_loss / len(data_loader)
epoch_accuracy = 100. * sum(p == t for p, t in zip(total_preds, total_targets)) / len(total_preds)
return epoch_loss, epoch_accuracy, f1
# Initialize models
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
vgg19 = models.vgg19(pretrained=True).to(device)
resnet50v2 = models.resnet50(pretrained=True).to(device)
inceptionv3 = models.inception_v3(pretrained=True).to(device)
# Modify the classifiers for CIFAR-10 (10 classes)
vgg19.classifier[6] = nn.Linear(vgg19.classifier[6].in_features, 10).to(device)
resnet50v2.fc = nn.Linear(resnet50v2.fc.in_features, 10).to(device)
inceptionv3.fc = nn.Linear(inceptionv3.fc.in_features, 10).to(device)
# Make sure to call model.eval() when evaluating
vgg19.eval()
resnet50v2.eval()
inceptionv3.eval()
criterion = nn.CrossEntropyLoss()
/usr/local/lib/python3.10/dist-packages/torchvision/models/_utils.py:208: UserWarning: The parameter 'pretrained' is deprecated since 0.13 and may be removed in the future, please use 'weights' instead. warnings.warn( /usr/local/lib/python3.10/dist-packages/torchvision/models/_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and may be removed in the future. The current behavior is equivalent to passing `weights=VGG19_Weights.IMAGENET1K_V1`. You can also use `weights=VGG19_Weights.DEFAULT` to get the most up-to-date weights. warnings.warn(msg) /usr/local/lib/python3.10/dist-packages/torchvision/models/_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and may be removed in the future. The current behavior is equivalent to passing `weights=ResNet50_Weights.IMAGENET1K_V1`. You can also use `weights=ResNet50_Weights.DEFAULT` to get the most up-to-date weights. warnings.warn(msg) /usr/local/lib/python3.10/dist-packages/torchvision/models/_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and may be removed in the future. The current behavior is equivalent to passing `weights=Inception_V3_Weights.IMAGENET1K_V1`. You can also use `weights=Inception_V3_Weights.DEFAULT` to get the most up-to-date weights. warnings.warn(msg)
vgg19
# state paths to your saved models
vgg19_path = 'vgg19.pth'
# Load saved weights with map_location to ensure weights are on the correct device
vgg19.load_state_dict(torch.load(vgg19_path, map_location=device))
start = time.time()
# Evaluate fine-tuned VGG19
vgg19_loss, vgg19_accuracy, f1 = evaluate_with_f1(vgg19, testloader_vgg19_resnet50v2 , criterion, device)
time_elapsed = time.time() - start # calculate the time elapsed
print(f'Time taken to Test Accuracy: {time_elapsed:.2f}sec')
print(f'VGG19 Test Accuracy: {vgg19_accuracy:.2f}%')
print(f'F1 Score: {f1:.4f}')
Time taken to Test Accuracy: 29.89sec VGG19 Test Accuracy: 92.35% VGG19 F1 Score: 0.9234
resnet50v2
# state paths to your saved models
resnet50v2_path = 'resnet50v2.pth'
# Load saved weights with map_location to ensure weights are on the correct device
resnet50v2.load_state_dict(torch.load(resnet50v2_path, map_location=device))
start = time.time()
# Evaluate ResNet50V2
resnet50v2_loss, resnet50v2_accuracy, f1 = evaluate_with_f1(resnet50v2, testloader_vgg19_resnet50v2, criterion, device)
time_elapsed = time.time() - start # calculate the time elapsed
print(f'Time taken to Test Accuracy: {time_elapsed:.2f}sec')
print(f'ResNet50V2 Test Accuracy: {resnet50v2_accuracy:.2f}%')
print(f'F1 Score: {f1:.4f}')
Time taken to Test Accuracy: 23.06sec ResNet50V2 Test Accuracy: 94.16% VGG19 F1 Score: 0.9415
inceptionv3
# state paths to your saved models
inceptionv3_path = 'inceptionv3.pth'
# Load saved weights with map_location to ensure weights are on the correct device
inceptionv3.load_state_dict(torch.load(inceptionv3_path, map_location=device))
# Evaluate inceptionv3
start = time.time()
inceptionv3_loss, inceptionv3_accuracy, f1 = evaluate_with_f1(inceptionv3, testloader_inceptionv3, criterion, device)
time_elapsed = time.time() - start # calculate the time elapsed
print(f'Time taken to Test Accuracy: {time_elapsed:.2f}sec')
print(f'inceptionv3 Test Accuracy: {inceptionv3_accuracy:.2f}%')
print(f'F1 Score: {f1:.4f}')
Time taken to Test Accuracy: 33.82sec InceptionV4 Test Accuracy: 95.34% VGG19 F1 Score: 0.9534
Combined test
# state paths to your saved models
vgg19_path = 'vgg19.pth'
resnet50v2_path = 'resnet50v2.pth'
inceptionv3_path = 'inceptionv3.pth'
# Load saved weights with map_location to ensure weights are on the correct device
vgg19.load_state_dict(torch.load(vgg19_path, map_location=device))
resnet50v2.load_state_dict(torch.load(resnet50v2_path, map_location=device))
inceptionv3.load_state_dict(torch.load(inceptionv3_path, map_location=device))
# Evaluate VGG19
vgg19_loss, vgg19_accuracy = evaluate_with_f1(vgg19, testloader_vgg19_resnet50v2 , criterion, device)
print(f'VGG19 Test Accuracy: {vgg19_accuracy:.2f}%')
# Evaluate ResNet50V2
resnet50v2_loss, resnet50v2_accuracy = evaluate(resnet50v2, testloader_vgg19_resnet50v2, criterion, device)
print(f'ResNet50V2 Test Accuracy: {resnet50v2_accuracy:.2f}%')
# Evaluate inceptionv3
inceptionv3_loss, inceptionv3_accuracy = evaluate(inceptionv3, testloader_inceptionv3, criterion, device)
print(f'inceptionv3 Test Accuracy: {inceptionv3_accuracy:.2f}%')
total_params = 0
trainable_params = 0
non_trainable_params = 0
model = vgg19
for param in model.parameters():
total_params += param.numel()
if param.requires_grad:
trainable_params += param.numel()
else:
non_trainable_params += param.numel()
print("Vgg19 layers and parameters :------------------ ")
print(f"Total Parameters: {total_params}")
print(f"Trainable Parameters: {trainable_params}")
print(f"Non-trainable Parameters: {non_trainable_params}")
def count_layers(model, count_nested=True):
layer_count = 0
for child in model.children():
if count_nested and list(child.children()): # If the child has children of its own
layer_count += count_layers(child)
else:
layer_count += 1
return layer_count
number_of_layers = count_layers(model)
print(f"Number of layers: {number_of_layers}")
Vgg19 layers and parameters :------------------ Total Parameters: 139611210 Trainable Parameters: 139611210 Non-trainable Parameters: 0 Number of layers: 45
total_params = 0
trainable_params = 0
non_trainable_params = 0
model = resnet50v2
for param in model.parameters():
total_params += param.numel()
if param.requires_grad:
trainable_params += param.numel()
else:
non_trainable_params += param.numel()
print("Resnet50v2 layers and parameters :------------------ ")
print(f"Total Parameters: {total_params}")
print(f"Trainable Parameters: {trainable_params}")
print(f"Non-trainable Parameters: {non_trainable_params}")
def count_layers(model, count_nested=True):
layer_count = 0
for child in model.children():
if count_nested and list(child.children()): # If the child has children of its own
layer_count += count_layers(child)
else:
layer_count += 1
return layer_count
number_of_layers = count_layers(model)
print(f"Number of layers: {number_of_layers}")
Resnet50v2 layers and parameters :------------------ Total Parameters: 23528522 Trainable Parameters: 23528522 Non-trainable Parameters: 0 Number of layers: 126
total_params = 0
trainable_params = 0
non_trainable_params = 0
model = inceptionv3
for param in model.parameters():
total_params += param.numel()
if param.requires_grad:
trainable_params += param.numel()
else:
non_trainable_params += param.numel()
print("inceptionv3 layers and parameters :------------------ ")
print(f"Total Parameters: {total_params}")
print(f"Trainable Parameters: {trainable_params}")
print(f"Non-trainable Parameters: {non_trainable_params}")
def count_layers(model, count_nested=True):
layer_count = 0
for child in model.children():
if count_nested and list(child.children()): # If the child has children of its own
layer_count += count_layers(child)
else:
layer_count += 1
return layer_count
number_of_layers = count_layers(model)
print(f"Number of layers: {number_of_layers}")
Inceptionv4 layers and parameters :------------------ Total Parameters: 25132754 Trainable Parameters: 25132754 Non-trainable Parameters: 0 Number of layers: 198