I see so model_with_residual was useful, I will put it back now I want to implement couple things in .ipynb. I will give you the details and the newest version of my code so you use my code. “Training and Evaluating your model
For both of your models;
- you will set epoch size to 100 and evaluate your two model with two different learning rates and two different
batch sizes. Explain how you calculate accuracy with relevant code snippet. Moreover for each of the points below
add relevant code snippet to your document.
1. Draw a graph of loss and accuracy change for two different learning rates and two batch sizes. [5 pts x 2 = 10
pts]
2. Select your best model with respect to validation accuracy and give test accuracy result. [2.5 pts x 2 = 5 pts]
3. Integrate dropout to your best models (best model should be selected with respect to best validation accuracy.
You need to integrate to both of your best models). In which part of the network you add dropout and why?
Explore four different dropout values and give new validation and test accuracies. [5 pts x 2 = 10 pts]
4. Plot a confusion matrix for your best model’s predictions. [5 pts x 2 = 10 pts]
5. Explain and analyze your findings and results. [5 pts x 2 = 10 pts]
” Here is my full code: “def plot(train_losses, valid_losses, valid_accuracies):
epochs = range(1, len(train_losses) + 1)

plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs, train_losses, label=“Training Loss”)
plt.plot(epochs, valid_losses, label=“Validation Loss”)
plt.xlabel(“Epochs”)
plt.ylabel(“Loss”)
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(epochs, valid_accuracies, label=“Validation Accuracy”)
plt.xlabel(“Epochs”)
plt.ylabel(“Accuracy”)
plt.legend()

plt.show()


def plot_confusion_matrix(y_true, y_pred, labels):
cm = confusion_matrix(y_true, y_pred, labels=labels)
sns.heatmap(
cm, annot=True, cmap=“Blues”, fmt=“d”, xticklabels=labels, yticklabels=labels
)
plt.xlabel(“Predicted”)
plt.ylabel(“True”)
plt.show()


def printout_method_comparison(
images, times, titles
): # A function to create a table of comparison for the methods
rows = len(images) # Setting rows to image count
cols = 2
fig, ax = plt.subplots(
rows, cols, figsize=(15, rows * 5), dpi=300
) # Creating the table

for i in range(rows):
ax[i, 0].imshow(images[i]) # Display panorama image
ax[i, 0].set_title(titles[i])
ax[i, 0].axis(“off”)

ax[i, 1].barh(
titles[i], times[i], 0.5, color=“purple”
) # Display runtime as a bar plot
ax[i, 1].set_xlabel(“Runtime (s)”)
ax[i, 1].set_xlim(0, max(times))

plt.tight_layout()
plt.show() # Showing the plot


# -------
# Dataset
# -------


class BacteriaDataset(Dataset):
def init(self, data, transform=None):
self.data = data
self.transform = transform

def len(self):
return len(self.data)

def getitem(self, index):
image, label = self.data[index]
if self.transform:
image = self.transform(image)
return image, label


def load_data(data_dir, transform):
categories = os.listdir(data_dir)
data = []
for label, category in enumerate(categories):
category_dir = os.path.join(data_dir, category)
for img_name in os.listdir(category_dir):
img_path = os.path.join(category_dir, img_name)
img = Image.open(img_path).convert(“RGB”)
img = img.resize((128, 128)) # Add this line to resize all images
data.append((img, label))
random.shuffle(data)
return data


# -----------------------------------------------------------
# Part 1: Modeling and Training a CNN classifier from Scratch
# -----------------------------------------------------------


# Train the model
def train(model, criterion, optimizer, train_loader, device):
model.train()
running_loss = 0.0
for i, (inputs, labels) in enumerate(train_loader):
inputs, labels = inputs.to(device), labels.to(device)

optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()

running_loss += loss.item()
return running_loss / len(train_loader)


# Evaluate the model
def evaluate(model, criterion, valid_loader, device):
model.eval()
running_loss = 0.0
correct = 0
total = 0

with torch.no_grad():
for inputs, labels in valid_loader:
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()

_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()

accuracy = 100 * correct / total
return running_loss / len(valid_loader), accuracy


def get_predictions(model, loader, device):
model.eval()
y_true = []
y_pred = []

with torch.no_grad():
for inputs, labels in loader:
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
_, predicted = torch.max(outputs.data, 1)

y_true.extend(labels.cpu().numpy())
y_pred.extend(predicted.cpu().numpy())

return y_true, y_pred


# Model without residual connections with dropout
model_dropout = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.Dropout(0.5),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(32, 64, 3, 1, 1),
nn.ReLU(),
nn.Dropout(0.5),
nn.MaxPool2d(2, 2),
nn.Conv2d(64, 128, 3, 1, 1),
nn.ReLU(),
nn.Dropout(0.5),
nn.MaxPool2d(2, 2),
nn.Conv2d(128, 256, 3, 1, 1),
nn.ReLU(),
nn.Dropout(0.5),
nn.MaxPool2d(2, 2),
nn.Conv2d(256, 512, 3, 1, 1),
nn.ReLU(),
nn.Dropout(0.5),
nn.MaxPool2d(2, 2),
nn.Conv2d(512, 1024, 3, 1, 1),
nn.ReLU(),
nn.Dropout(0.5),
nn.MaxPool2d(2, 2),
nn.Flatten(),
nn.Linear(1024 * 2 * 2, 8),
)


# Modify the ResidualBlock and ResNet classes to include dropout
class ResidualBlockDropout(nn.Module):
def init(self, in_channels, out_channels, stride=1):
super().init()
self.conv1 = nn.Conv2d(
in_channels, out_channels, kernel_size=3, stride=stride, padding=1
)
self.bn1 = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU()
self.dropout = nn.Dropout(0.5)
self.conv2 = nn.Conv2d(
out_channels, out_channels, kernel_size=3, stride=1, padding=1
)
self.bn2 = nn.BatchNorm2d(out_channels)

self.shortcut = nn.Sequential()
if stride != 1 or in_channels != out_channels:
self.shortcut = nn.Sequential(
nn.Conv2d(
in_channels, out_channels, kernel_size=1, stride=stride, padding=0
),
nn.BatchNorm2d(out_channels),
)

def forward(self, x):
out = self.relu(self.bn1(self.conv1(x)))
out = self.dropout(out)
out = self.bn2(self.conv2(out))
out += self.shortcut(x)
out = self.relu(out)
return out


class ResidualBlock(nn.Module):
def init(self, in_channels, out_channels, stride=1):
super().init()
self.conv1 = nn.Conv2d(
in_channels, out_channels, kernel_size=3, stride=stride, padding=1
)
self.bn1 = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU()
self.conv2 = nn.Conv2d(
out_channels, out_channels, kernel_size=3, stride=1, padding=1
)
self.bn2 = nn.BatchNorm2d(out_channels)

self.shortcut = nn.Sequential()
if stride != 1 or in_channels != out_channels:
self.shortcut = nn.Sequential(
nn.Conv2d(
in_channels, out_channels, kernel_size=1, stride=stride, padding=0
),
nn.BatchNorm2d(out_channels),
)

def forward(self, x):
out = self.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out += self.shortcut(x)
out = self.relu(out)
return out


class ResNet(nn.Module):
def init(self, num_classes=8):
super().init()
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.bn1 = nn.BatchNorm2d(32)
self.relu = nn.ReLU()
self.layer1 = self._make_layer(32, 64, 2, stride=2)
self.layer2 = self._make_layer(64, 128, 2, stride=2)
self.layer3 = self._make_layer(128, 256, 2, stride=2)
self.layer4 = self._make_layer(256, 512, 2, stride=2)
self.layer5 = self._make_layer(512, 1024, 2, stride=2)
self.fc = nn.Linear(1024 * 2 * 2, num_classes)

def _make_layer(self, in_channels, out_channels, num_blocks, stride):
strides = [stride] + [1] * (num_blocks - 1)
layers = []
for stride in strides:
layers.append(ResidualBlock(in_channels, out_channels, stride))
in_channels = out_channels
return nn.Sequential(*layers)

def forward(self, x):
out = self.relu(self.bn1(self.conv1(x)))
out = self.layer1(out)
out = self.layer2(out)
out = self.layer3(out)
out = self.layer4(out)
out = self.layer5(out)
out = out.view(out.size(0), -1)
out = self.fc(out)
return out


# Modify the ResidualBlock and ResNet classes to include dropout
class ResidualBlockDropout(nn.Module):
def init(self, in_channels, out_channels, stride=1):
super().init()
self.conv1 = nn.Conv2d(
in_channels, out_channels, kernel_size=3, stride=stride, padding=1
)
self.bn1 = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU()
self.dropout = nn.Dropout(0.5)
self.conv2 = nn.Conv2d(
out_channels, out_channels, kernel_size=3, stride=1, padding=1
)
self.bn2 = nn.BatchNorm2d(out_channels)

self.shortcut = nn.Sequential()
if stride != 1 or in_channels != out_channels:
self.shortcut = nn.Sequential(
nn.Conv2d(
in_channels, out_channels, kernel_size=1, stride=stride, padding=0
),
nn.BatchNorm2d(out_channels),
)

def forward(self, x):
out = self.relu(self.bn1(self.conv1(x)))
out = self.dropout(out)
out = self.bn2(self.conv2(out))
out += self.shortcut(x)
out = self.relu(out)
return out


class ResNetDropout(ResNet):
def _make_layer(self, in_channels, out_channels, num_blocks, stride):
strides = [stride] + [1] * (num_blocks - 1)
layers = []
for stride in strides:
layers.append(ResidualBlockDropout(in_channels, out_channels, stride))
in_channels = out_channels
return nn.Sequential(*layers)
”