Ubuntu commited on
Commit
d695662
·
1 Parent(s): f1fddae

Modified code for imagent datase

Browse files
Files changed (4) hide show
  1. requirements.txt +7 -0
  2. resnet_execute.py +33 -16
  3. resnet_model.py +9 -7
  4. validation.py +24 -0
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ albumentations
4
+ numpy
5
+ matplotlib
6
+ tqdm
7
+ torchsummary
resnet_execute.py CHANGED
@@ -6,28 +6,37 @@ import torch.nn as nn
6
  import torch.optim as optim
7
  from resnet_model import ResNet50
8
  from tqdm import tqdm
 
9
 
10
  # Define transformations
11
  transform = transforms.Compose([
 
 
12
  transforms.ToTensor(),
13
- transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2470, 0.2435, 0.2616))
14
  ])
15
 
16
- # Load CIFAR-10 dataset
17
- trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
18
- trainloader = DataLoader(trainset, batch_size=128, shuffle=True, num_workers=4)
19
 
20
- testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
21
- testloader = DataLoader(testset, batch_size=1000, shuffle=False, num_workers=4)
22
 
23
  # Initialize model, loss function, and optimizer
24
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
25
- model = ResNet50().to(device)
 
 
 
26
  criterion = nn.CrossEntropyLoss()
27
  optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=5e-4)
28
 
29
  # Training function
30
- def train(model, device, train_loader, optimizer, criterion, epoch):
 
 
 
31
  model.train()
32
  running_loss = 0.0
33
  correct = 0
@@ -36,21 +45,29 @@ def train(model, device, train_loader, optimizer, criterion, epoch):
36
 
37
  for batch_idx, (inputs, targets) in enumerate(pbar):
38
  inputs, targets = inputs.to(device), targets.to(device)
39
- optimizer.zero_grad()
40
 
41
- outputs = model(inputs)
42
- loss = criterion(outputs, targets)
 
 
43
  loss.backward()
44
- optimizer.step()
45
 
46
- running_loss += loss.item()
 
 
 
 
47
  _, predicted = outputs.max(1)
48
  total += targets.size(0)
49
  correct += predicted.eq(targets).sum().item()
50
 
51
- pbar.set_description(desc=f'Epoch {epoch} | Loss: {loss.item():.4f} | Accuracy: {100.*correct/total:.2f}%')
 
 
 
 
 
52
 
53
- return 100.*correct/total
54
 
55
  # Testing function
56
  def test(model, device, test_loader, criterion):
@@ -79,4 +96,4 @@ if __name__ == '__main__':
79
  for epoch in range(1, 6): # 20 epochs
80
  train_accuracy = train(model, device, trainloader, optimizer, criterion, epoch)
81
  test_accuracy = test(model, device, testloader, criterion)
82
- print(f'Epoch {epoch} | Train Accuracy: {train_accuracy:.2f}% | Test Accuracy: {test_accuracy:.2f}%')
 
6
  import torch.optim as optim
7
  from resnet_model import ResNet50
8
  from tqdm import tqdm
9
+ from torchvision import datasets
10
 
11
  # Define transformations
12
  transform = transforms.Compose([
13
+ transforms.Resize(256), # Resize the smaller side to 256 pixels while keeping aspect ratio
14
+ transforms.CenterCrop(224), # Then crop to 224x224 pixels from the center
15
  transforms.ToTensor(),
16
+ transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # ImageNet normalization
17
  ])
18
 
19
+ # Train dataset and loader
20
+ trainset = datasets.ImageFolder(root='/mnt/imagenet/ILSVRC/Data/CLS-LOC/train', transform=transform)
21
+ trainloader = DataLoader(trainset, batch_size=128, shuffle=True, num_workers=16, pin_memory=True)
22
 
23
+ testset = datasets.ImageFolder(root='/mnt/imagenet/ILSVRC/Data/CLS-LOC/val', transform=transform )
24
+ testloader = DataLoader(testset, batch_size=1000, shuffle=False, num_workers=16, pin_memory=True)
25
 
26
  # Initialize model, loss function, and optimizer
27
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
28
+ model = ResNet50()
29
+ model = torch.nn.DataParallel(model)
30
+ model = model.to(device)
31
+
32
  criterion = nn.CrossEntropyLoss()
33
  optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=5e-4)
34
 
35
  # Training function
36
+ from torch.amp import autocast
37
+ from tqdm import tqdm
38
+
39
+ def train(model, device, train_loader, optimizer, criterion, epoch, accumulation_steps=4):
40
  model.train()
41
  running_loss = 0.0
42
  correct = 0
 
45
 
46
  for batch_idx, (inputs, targets) in enumerate(pbar):
47
  inputs, targets = inputs.to(device), targets.to(device)
 
48
 
49
+ with autocast(device_type='cuda'):
50
+ outputs = model(inputs)
51
+ loss = criterion(outputs, targets) / accumulation_steps
52
+
53
  loss.backward()
 
54
 
55
+ if (batch_idx + 1) % accumulation_steps == 0 or (batch_idx + 1) == len(train_loader):
56
+ optimizer.step()
57
+ optimizer.zero_grad()
58
+
59
+ running_loss += loss.item() * accumulation_steps
60
  _, predicted = outputs.max(1)
61
  total += targets.size(0)
62
  correct += predicted.eq(targets).sum().item()
63
 
64
+ pbar.set_description(desc=f'Epoch {epoch} | Loss: {running_loss / (batch_idx + 1):.4f} | Accuracy: {100. * correct / total:.2f}%')
65
+
66
+ if (batch_idx + 1) % 50 == 0:
67
+ torch.cuda.empty_cache()
68
+
69
+ return 100. * correct / total
70
 
 
71
 
72
  # Testing function
73
  def test(model, device, test_loader, criterion):
 
96
  for epoch in range(1, 6): # 20 epochs
97
  train_accuracy = train(model, device, trainloader, optimizer, criterion, epoch)
98
  test_accuracy = test(model, device, testloader, criterion)
99
+ print(f'Epoch {epoch} | Train Accuracy: {train_accuracy:.2f}% | Test Accuracy: {test_accuracy:.2f}%')
resnet_model.py CHANGED
@@ -3,7 +3,7 @@ import torch.nn as nn
3
  from torchsummary import summary
4
 
5
  class Bottleneck(nn.Module): # Bottleneck module as a single class which will be used to create the ResNet model. Each bottleneck as 3 convolutions.
6
- expansion = 4 # sets how much the bottleneck will expand the output channels of the last block to. Used 4 as per original paper.
7
 
8
  def __init__(self, in_channels, out_channels, stride=1, downsample=None):
9
  super(Bottleneck, self).__init__()
@@ -13,8 +13,8 @@ class Bottleneck(nn.Module): # Bottleneck module as a single class which will be
13
  self.bn2 = nn.BatchNorm2d(out_channels)
14
  self.conv3 = nn.Conv2d(out_channels, out_channels * self.expansion, kernel_size=1, bias=False) # this is the convolution where number of channels is expanded, as per the ResNet model.
15
  self.bn3 = nn.BatchNorm2d(out_channels * self.expansion)
16
- self.relu = nn.ReLU(inplace=True) # this will modify the original tensor rather than operating on a copy. Significant memory savings as this module is the fundamental repeating unit. Makes sense to use only in the last layer so that we're not unintentionally corrupting the input tensor in the previous layers.
17
- self.downsample = downsample # helps match the output dimensions to the input dimensions for the special skip connection.
18
 
19
  def forward(self, x):
20
  identity = x
@@ -40,16 +40,17 @@ class Bottleneck(nn.Module): # Bottleneck module as a single class which will be
40
  return out
41
 
42
  class ResNet50(nn.Module):
43
- def __init__(self, num_classes=10): # num_classes to be set as per the dataset. 10 for CIFAR-10, 1000 for ImageNet 1k.
44
  super(ResNet50, self).__init__()
45
  self.in_channels = 64 # only used for the initiation of the first bottleneck block in the first layer.
46
 
47
  ## See Excel sheet for Model Architecture
48
 
49
- # Adjusted Initial Conv Layer for CIFAR-10
50
- self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False) #kernel size is 3 here for CIFAR-10, will need to be 7 for ImageNet 1k. Will also need maxpools for ImageNet 1k.
51
  self.bn1 = nn.BatchNorm2d(64)
52
  self.relu = nn.ReLU(inplace=True) # as before, this will modify the input tensor. Good memory savings here as the input image will be large in size here.
 
53
 
54
  # Layers with Bottleneck Blocks
55
  self.layer1 = self._make_layer(Bottleneck, 64, 3) # stride is 1 here, so the downsampling will only adjust for the channel size in the first block of this layer
@@ -81,6 +82,7 @@ class ResNet50(nn.Module):
81
  x = self.conv1(x)
82
  x = self.bn1(x)
83
  x = self.relu(x)
 
84
 
85
  x = self.layer1(x)
86
  x = self.layer2(x)
@@ -97,4 +99,4 @@ if __name__ == '__main__':
97
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
98
  print(device)
99
  model = ResNet50().to(device)
100
- summary(model, input_size=(3, 32, 32)) # size is (3, 32, 32) for CIFAR-10. Will be (3, 224, 224) for ImageNet 1k.
 
3
  from torchsummary import summary
4
 
5
  class Bottleneck(nn.Module): # Bottleneck module as a single class which will be used to create the ResNet model. Each bottleneck as 3 convolutions.
6
+ expansion = 4 # sets how much the bottleneck will expand the output channels of the last layer in a bottleneck block to. Used 4 as per the original paper.
7
 
8
  def __init__(self, in_channels, out_channels, stride=1, downsample=None):
9
  super(Bottleneck, self).__init__()
 
13
  self.bn2 = nn.BatchNorm2d(out_channels)
14
  self.conv3 = nn.Conv2d(out_channels, out_channels * self.expansion, kernel_size=1, bias=False) # this is the convolution where number of channels is expanded, as per the ResNet model.
15
  self.bn3 = nn.BatchNorm2d(out_channels * self.expansion)
16
+ self.relu = nn.ReLU(inplace=True) # this will modify the original tensor rather than operating on a copy. Significant memory savings as this module is the fundamental repeating unit.
17
+ self.downsample = downsample # helps match the input dimensions to the dimensions after convolution for the special skip connection.
18
 
19
  def forward(self, x):
20
  identity = x
 
40
  return out
41
 
42
  class ResNet50(nn.Module):
43
+ def __init__(self, num_classes=1000): # num_classes to be set as per the dataset. 10 for CIFAR-10, 1000 for ImageNet 1k.
44
  super(ResNet50, self).__init__()
45
  self.in_channels = 64 # only used for the initiation of the first bottleneck block in the first layer.
46
 
47
  ## See Excel sheet for Model Architecture
48
 
49
+ # Adjusted Initial Conv Layer for ImageNet 1k
50
+ self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False) #kernel size is 7 here for ImageNet 1k.
51
  self.bn1 = nn.BatchNorm2d(64)
52
  self.relu = nn.ReLU(inplace=True) # as before, this will modify the input tensor. Good memory savings here as the input image will be large in size here.
53
+ self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) # Add max pooling layer
54
 
55
  # Layers with Bottleneck Blocks
56
  self.layer1 = self._make_layer(Bottleneck, 64, 3) # stride is 1 here, so the downsampling will only adjust for the channel size in the first block of this layer
 
82
  x = self.conv1(x)
83
  x = self.bn1(x)
84
  x = self.relu(x)
85
+ x = self.maxpool(x) # Add max pooling layer in forward pass
86
 
87
  x = self.layer1(x)
88
  x = self.layer2(x)
 
99
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
100
  print(device)
101
  model = ResNet50().to(device)
102
+ summary(model, input_size=(3, 224, 224)) # size is (3, 224, 224) for ImageNet 1k.
validation.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import os
3
+ import shutil
4
+
5
+ parser = argparse.ArgumentParser()
6
+ parser.add_argument("-d", "--dir", help="dir with the images", required=True)
7
+ parser.add_argument("-l", "--labels", help="file with image name to class label mapping", required=True)
8
+
9
+ args = parser.parse_args()
10
+
11
+ processed_classes = set()
12
+
13
+ with open(args.labels, "r") as file:
14
+ # skip header
15
+ next(file)
16
+ for line in file:
17
+ img_name, labels = line.split(",")
18
+ class_name = labels.split(" ")[0]
19
+ # create a dir for this classname
20
+ if class_name not in processed_classes:
21
+ dir_path = args.dir + "/" + class_name
22
+ if not os.path.exists(dir_path):
23
+ os.mkdir(dir_path)
24
+ shutil.move(args.dir + "/" + img_name + ".JPEG", args.dir + "/" + class_name+ "/" + img_name + ".JPEG")