I am learning ML and am working on a CNN problem where I need to classify images of CATS and DOGS.
The way I have setup the labels is that cats are 1 and dogs are 0. I have made the final output layer length 1 ( So I get only 1 output).
When I measure my accuracy I seem to be getting 0% even when my loss is low. I am not sure what I am doing wrong.
'''
import torch
from torch import nn
import torchvision
from torchvision import datasets
from torchvision import transforms
from torchvision.transforms import ToTensor
from torchvision.transforms import v2
from torch.utils.data import DataLoader
import numpy as np
import matplotlib.pyplot as plt
import os
import pandas as pd
from torch.utils.data import Dataset
from skimage import io
from PIL import Image
class CatsAndDogsDataset(Dataset):
def __init__(self,csv_file,root_dir,transform=None):
self.annotations =pd.read_csv(csv_file)
self.root_dir = root_dir
self.transform = transform
def __len__(self):
return len(self.annotations)
def __getitem__(self,index):
img_path=os.path.join(self.root_dir,self.annotations.iloc[index,0])
image=io.imread(img_path)
y_label= torch.tensor(float(self.annotations.iloc[index,1]))
if self.transform:
image=self.transform(image)
return (image,y_label)
def accuracy_fn(y_true, y_pred):
correct = torch.eq(y_true, y_pred).sum().item() # torch.eq() calculates where two tensors are equal
acc = (correct / len(y_pred)) * 100
return acc
dataset= CatsAndDogsDataset(csv_file = r'C:\Users\hbhavnag\Documents\Hussain\ASU\collision detection\Home work\output.csv', root_dir='train', transform=transforms.ToTensor())
train_set, test_set = torch.utils.data.random_split(dataset,[2000,955])
train_loader=DataLoader(dataset=train_set, batch_size=10, shuffle=True)
test_loader = DataLoader(dataset=test_set, batch_size=10, shuffle=True)
torch.manual_seed(42)
fig = plt.figure(figsize=(9,9))
rows, cols = 5,5
for i in range(1,rows*cols+1):
random_idx = torch.randint(0,len(train_set),size=[1]).item()
img,label =train_set[random_idx]
fig.add_subplot(rows,cols,i)
plt.imshow(img.permute(1,2,0))
#plt.title(label)
plt.axis(False)
train_img_batch , train_labels_batch = next(iter(train_loader))
# Building the model
class CatsAndDogsModel(nn.Module):
"""
Model architecture replicates Tiny vgg
"""
def __init__(self,input_shape:int,hidden_units:int,output_shape:int):
super().__init__()
self.conv_block_1=nn.Sequential(
nn.Conv2d(in_channels=input_shape,
out_channels=hidden_units,
kernel_size=3,
stride=1,
padding=1),
nn.ReLU(),
nn.Conv2d(in_channels=hidden_units,
out_channels=hidden_units,
kernel_size=3,
stride=1,
padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2)
)
self.conv_block_2= nn.Sequential(
nn.Conv2d(in_channels=hidden_units,
out_channels=hidden_units,
kernel_size=3,
stride=1,
padding=1),
nn.ReLU(),
nn.Conv2d(in_channels=hidden_units,
out_channels=hidden_units,
kernel_size=3,
stride=1,
padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2)
)
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(in_features=hidden_units*93*125,
out_features=output_shape),
nn.Sigmoid()
)
def forward(self,x):
x= self.conv_block_1(x)
print(x.shape)
x= self.conv_block_2(x)
print(x.shape)
x= self.classifier(x)
print(x.shape)
return x.squeeze()
torch.manual_seed(42)
model_2=CatsAndDogsModel(input_shape=3,
hidden_units=10,
output_shape=1)
# setup loss function
loss_fn = nn.BCELoss()
optimizer = torch.optim.SGD(params=model_2.parameters(),lr=0.01)
from tqdm.auto import tqdm
torch.manual_seed(42)
epochs=3
for epoch in tqdm(range(epochs)):
print(f'Epoch:{epoch}\n-------')
train_loss=0
for batch,(X,y) in enumerate(train_loader):
print(y)
model_2.train()
y_pred = model_2(X)
print(y_pred)
loss = loss_fn(y_pred,y)
train_loss=train_loss+loss
optimizer.zero_grad()
loss.backward()
optimizer.step()
train_loss/= len(train_loader)
test_loss,test_acc=0,0
model_2.eval()
with torch.inference_mode():
for X,y in test_loader:
test_pred=model_2(X)
test_loss+=loss_fn(test_pred,y)
test_acc+=accuracy_fn(y_true=y,y_pred=test_pred)
test_loss/=len(test_loader)
test_acc /= len(test_loader)
print(f"\n Train loss:{train_loss:.5f} | Test loss:{test_loss:.5f},Test acc: {test_acc:.2f}%\n")
'''
Please let me know if my code is confusing, any help is much appreciated
Thanks!