Ok, so I have a model to predict the class of image, cat or dog. I receive %95 accuracy in training. But for some reason, I stuck with constant output when I try to predict single image.
I read similar topics from forum but that hasn’t contributed much in my case.
Below, you can find all info. Pls help ^^
What I tried so far:
- Changing epochs 5 to 20.
- Changing lr= 0.001 to 0.01 and 0.0001
- I implemented with both dropout regularization model and batch normalization model.
- I changed testing pictures.
- I am thinking of making input images to colorful s.t maybe if the problem is the range of values, somehow, but that would be different model as well. I want to know what the problem in this one.
- Changing last activation layer to torch.sigmoid
- Reducing batch size to 30…
Still no change…
Infos:
Model:
import os
import cv2
import numpy as np
from tqdm import tqdm
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import time
import matplotlib.pyplot as plt
from matplotlib import style
MODEL_NAME = f"model-{time.asctime()}" # gives a dynamic model name, to just help with things getting messy over
# time.
REBUILD_DATA = False # set to true to one once, then back to false unless you want to change something in your
IMG_SIZE = 50
# training data.
PATH = "model/model.pt"
BATCH_SIZE = 100
EPOCHS = 20
class DogsVSCats():
IMG_SIZE = 50
CATS = "PetImages/Cat"
DOGS = "PetImages/Dog"
TESTING = "PetImages/Testing"
LABELS = {CATS: 0, DOGS: 1}
training_data = []
catcount = 0
dogcount = 0
def make_training_data(self):
for label in self.LABELS:
print(label)
for f in tqdm(os.listdir(label)):
if "jpg" in f:
try:
path = os.path.join(label, f)
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (self.IMG_SIZE, self.IMG_SIZE))
self.training_data.append([np.array(img), np.eye(2)[
self.LABELS[label]]]) # do something like print(np.eye(2)[1]), just makes one_hot
# print(np.eye(2)[self.LABELS[label]])
if label == self.CATS:
self.catcount += 1
elif label == self.DOGS:
self.dogcount += 1
except Exception as e:
pass
# print(label, f, str(e))
np.random.shuffle(self.training_data)
np.save("training_data.npy", self.training_data)
print('Cats:', dogsvcats.catcount)
print('Dogs:', dogsvcats.dogcount)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 32, 5)
# self.bn1 = nn.BatchNorm2d(num_features=32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
self.conv2 = nn.Conv2d(32, 64, 5)
# self.bn2 = nn.BatchNorm2d(num_features=64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
self.conv3 = nn.Conv2d(64, 128, 5)
x = torch.randn(50, 50).view(-1, 1, 50, 50)
self._to_linear = None
self.convs(x)
self.fc1 = nn.Linear(self._to_linear, 512)
self.bn1 = nn.BatchNorm1d(num_features=512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
self.fc2 = nn.Linear(512, 2)
self.dropout = nn.AlphaDropout(p=0.3)
def convs(self, x):
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
x = F.max_pool2d(F.relu(self.conv2(x)), (2, 2))
x = F.max_pool2d(F.relu(self.conv3(x)), (2, 2))
if self._to_linear is None:
self._to_linear = x[0].shape[0] * x[0].shape[1] * x[0].shape[2]
return x
'''>>> # With Learnable Parameters
>>> m = nn.BatchNorm2d(100)
>>> # Without Learnable Parameters
>>> m = nn.BatchNorm2d(100, affine=False)
>>> input = torch.randn(20, 100, 35, 45)
>>> output = m(input)'''
def forward(self, x):
x = self.convs(x)
x = x.view(-1, self._to_linear)
x = F.relu(self.bn1(self.fc1(x)))
x = self.fc2(x)
x = self.dropout(x)
return F.softmax(x, dim=1)
if torch.cuda.is_available():
device = torch.device("cuda:0") # you can continue going on here, like cuda:1 cuda:2....etc.
print("Running on the GPU")
else:
device = torch.device("cpu")
print("Running on the CPU")
net = Net().to(device)
if REBUILD_DATA:
dogsvcats = DogsVSCats()
dogsvcats.make_training_data()
training_data = np.load("training_data.npy", allow_pickle=True)
print(len(training_data))
optimizer = optim.Adam(net.parameters(), lr=0.01)
loss_function = nn.MSELoss()
X = torch.Tensor([i[0] for i in training_data]).view(-1, 50, 50)
X = X / 255.0
y = torch.Tensor([i[1] for i in training_data])
VAL_PCT = 0.1
val_size = int(len(X) * VAL_PCT)
print(val_size)
train_X = X[:-val_size]
train_y = y[:-val_size]
test_X = X[-val_size:]
test_y = y[-val_size:]
print(len(train_X))
print(len(test_X))
def fwd_pass(X_, y_, train_=False):
if train_:
net.zero_grad()
outputs = net(X_)
matches = [torch.argmax(i) == torch.argmax(j) for i, j in zip(outputs, y_)]
acc = matches.count(True) / len(matches)
loss = loss_function(outputs, y_)
if train_:
loss.backward()
optimizer.step()
return acc, loss
style.use("ggplot")
print(MODEL_NAME)
def train(net_):
with open("model_4.log", "a") as f:
for epoch in range(EPOCHS):
for i in tqdm(range(0, len(train_X), BATCH_SIZE)):
batch_X = train_X[i:i + BATCH_SIZE].view(-1, 1, 50, 50)
batch_y = train_y[i:i + BATCH_SIZE]
batch_X, batch_y = batch_X.to(device), batch_y.to(device)
acc, loss = fwd_pass(batch_X, batch_y, train_=True)
# print(f"Acc: {round(float(acc),2)} Loss: {round(float(loss),4)}")
# f.write(f"{MODEL_NAME},{round(time.time(),3)},train,{round(float(acc),2)},{round(float(loss),4)}\n")
# just to show the above working, and then get out:
if i % 50 == 0:
val_acc, val_loss = test(size=100)
f.write(
f"{MODEL_NAME},{round(time.time(), 3)},{round(float(acc), 2)},{round(float(loss), 4)},"
f"{round(float(val_acc), 2)},{round(float(val_loss), 4)},{epoch}\n")
torch.save({
'dropout cnn model': MODEL_NAME,
'epoch': epoch,
'model_state_dict': net.state_dict(),
'optimizer_state_dict': optimizer.state_dict()
}, PATH)
def test(size=32):
X, y = test_X[:size], test_y[:size]
val_acc, val_loss = fwd_pass(X.view(-1, 1, 50, 50).to(device), y.to(device))
return val_acc, val_loss
def create_acc_loss_graph(model_name):
contents = open("model_4.log", "r").read().split("\n")
times = []
accuracies = []
losses = []
val_accs = []
val_losses = []
for c in contents:
if model_name in c:
name, timestamp, acc, loss, val_acc, val_loss, epoch = c.split(",")
times.append(float(timestamp))
accuracies.append(float(acc))
losses.append(float(loss))
val_accs.append(float(val_acc))
val_losses.append(float(val_loss))
fig = plt.figure()
ax1 = plt.subplot2grid((2, 1), (0, 0))
ax2 = plt.subplot2grid((2, 1), (1, 0), sharex=ax1)
ax1.plot(times, accuracies, label="acc")
ax1.plot(times, val_accs, label="val_acc")
ax1.legend(loc=2)
ax2.plot(times, losses, label="loss")
ax2.plot(times, val_losses, label="val_loss")
ax2.legend(loc=2)
plt.show()
Similar Topics here: