import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from PIL import Image
import cv2
from sklearn.model_selection import train_test_split
import torch
from torch.utils.data import Dataset, DataLoader
from torch import nn, optim
from torchinfo import summary
from torchvision.models import vit_b_16, ViT_B_16_Weights
from sklearn.metrics import accuracy_score, confusion_matrix
import os
from pathlib import Path
from tqdm.auto import tqdm
from collections import OrderedDict
import random
import warnings
warnings.filterwarnings("ignore")
# Setting image path and getting list of images
IMAGE_PATH =
Path("/kaggle/input/banana-disease-recognition-dataset/Banana Disease
Recognition Dataset/Original Images/Original Images")
IMAGE_PATH_LIST = list(IMAGE_PATH.glob("*/*.jpg"))
print(f'Total Images = {len(IMAGE_PATH_LIST)}')
classes = sorted(os.listdir(IMAGE_PATH))
print('==' * 20)
print(' ' * 10, f'Total Classes = {len(classes)}')
print('==' * 20)
for c in classes:
total_images_class = list(Path(os.path.join(IMAGE_PATH,
c)).glob("*.jpg"))
print(f'* {c}: {len(total_images_class)} images')
# Visualize a few sample images
NUM_IMAGES = 3
fig, ax = plt.subplots(nrows=len(classes), ncols=NUM_IMAGES,
figsize=(10, 30))
p = 0
for c in classes:
total_images_class = list(Path(os.path.join(IMAGE_PATH,
c)).glob("*.jpg"))
images_selected = random.choices(total_images_class, k=NUM_IMAGES)
for i, img_path in enumerate(images_selected):
img_bgr = cv2.imread(str(img_path))
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
ax[p, i].imshow(img_rgb)
ax[p, i].axis('off')
ax[p, i].set_title(f'Class: {c}\nShape: {img_rgb.shape}')
p += 1
fig.tight_layout()
fig.show()
# Prepare dataframe with image paths and labels
images_path = []
labels = []
for img_path in IMAGE_PATH_LIST:
images_path.append(img_path)
labels.append(img_path.parent.stem)
df_path_and_label = pd.DataFrame({'path': images_path, 'label':
labels})
print(df_path_and_label.head())
# Split the data
SEED = 42
df_train, df_rest = train_test_split(df_path_and_label, test_size=0.3,
random_state=SEED, stratify=df_path_and_label["label"])
df_valid, df_test = train_test_split(df_rest, test_size=0.5,
random_state=SEED, stratify=df_rest["label"])
# Define label mapping: class string to numerical value
label_map = dict(zip(classes, range(len(classes))))
print(label_map)
# Define transforms from ViT_B_16_Weights
weights = ViT_B_16_Weights.DEFAULT
auto_transforms = weights.transforms()
print(auto_transforms)
# Updated Custom dataset class: precompute label mapping during
initialization
class CustomImageDataset(Dataset):
def __init__(self, df: pd.DataFrame, label_map: dict, transforms):
# Use a copy and precompute numeric labels
df = df.copy()
df["numeric_label"] = df["label"].map(label_map)
self.df = df.reset_index(drop=True)
self.transforms = transforms
def __len__(self):
return len(self.df)
def __getitem__(self, idx):
image_path = self.df.iloc[idx, 0]
label = self.df.iloc[idx]["numeric_label"]
image = Image.open(image_path).convert("RGB")
image = self.transforms(image)
return image, label
# Create dataset instances
train_dataset = CustomImageDataset(df_train, label_map,
auto_transforms)
valid_dataset = CustomImageDataset(df_valid, label_map,
auto_transforms)
# Use fewer workers for DataLoader (e.g., 4)
BATCH_SIZE = 8
NUM_WORKERS = 4
train_dataloader = DataLoader(dataset=train_dataset,
batch_size=BATCH_SIZE, shuffle=True, num_workers=NUM_WORKERS)
valid_dataloader = DataLoader(dataset=valid_dataset,
batch_size=BATCH_SIZE, shuffle=True, num_workers=NUM_WORKERS)
# Visualize a batch
batch_images, batch_labels = next(iter(train_dataloader))
print("Batch images shape:", batch_images.shape, "and Batch labels
shape:", batch_labels.shape)
# Check GPU availability and set device
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f'Using device: {device}')
# Load ViT-16 model and modify last layer for current number of
classes
model = vit_b_16(weights=weights)
summary(model=model, input_size=[8, 3, 224, 224], col_width=15,
col_names=["input_size", "output_size", "num_params", "trainable"],
row_settings=["var_names"])
for param in model.conv_proj.parameters():
param.requires_grad = False
for param in model.encoder.parameters():
param.requires_grad = False
# Confirm parameters have been frozen
summary(model=model, input_size=[8, 3, 224, 224], col_width=15,
col_names=["input_size", "output_size", "num_params", "trainable"],
row_settings=["var_names"])
output_shape = len(classes)
model.heads = nn.Sequential(OrderedDict([('head',
nn.Linear(in_features=768, out_features=output_shape))]))
summary(model=model, input_size=[8, 3, 224, 224], col_width=15,
col_names=["input_size", "output_size", "num_params", "trainable"],
row_settings=["var_names"])
# Define loss and optimizer
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)
def train_step(model: torch.nn.Module, dataloader:
torch.utils.data.DataLoader,
loss_fn: torch.nn.Module, optimizer:
torch.optim.Optimizer):
model.train()
train_loss = 0.
train_accuracy = 0.
for _, (X, y) in enumerate(dataloader):
X, y = X.to(device), y.to(device)
optimizer.zero_grad()
y_pred_logit = model(X)
loss = loss_fn(y_pred_logit, y)
train_loss += loss.item()
loss.backward()
optimizer.step()
y_pred_prob = torch.softmax(y_pred_logit, dim=1)
y_pred_class = torch.argmax(y_pred_prob, dim=1)
train_accuracy += accuracy_score(y.cpu().numpy(),
y_pred_class.detach().cpu().numpy())
train_loss = train_loss / len(dataloader)
train_accuracy = train_accuracy / len(dataloader)
return train_loss, train_accuracy
def save_checkpoint(filename, model, epoch, loss, optimizer, metric):
state = {'filename': filename,
'model': model.state_dict(),
'epoch': epoch,
'loss': loss,
'optimizer': optimizer.state_dict(),
'metric': metric}
torch.save(state, filename)
def valid_step(model: torch.nn.Module, dataloader:
torch.utils.data.DataLoader,
loss_fn: torch.nn.Module):
model.eval()
valid_loss = 0.
valid_accuracy = 0.
with torch.inference_mode():
for _, (X, y) in enumerate(dataloader):
X, y = X.to(device), y.to(device)
y_pred_logit = model(X)
loss = loss_fn(y_pred_logit, y)
valid_loss += loss.item()
y_pred_prob = torch.softmax(y_pred_logit, dim=1)
y_pred_class = torch.argmax(y_pred_prob, dim=1)
valid_accuracy += accuracy_score(y.cpu().numpy(),
y_pred_class.detach().cpu().numpy())
valid_loss = valid_loss / len(dataloader)
valid_accuracy = valid_accuracy / len(dataloader)
return valid_loss, valid_accuracy
def train(model: torch.nn.Module, train_dataloader:
torch.utils.data.DataLoader,
valid_dataloader: torch.utils.data.DataLoader, loss_fn:
torch.nn.Module,
optimizer: torch.optim.Optimizer, epochs: int = 10):
results = {"train_loss": [], "train_accuracy": [], "valid_loss":
[], "valid_accuracy": []}
best_valid_loss = float('inf')
for epoch in tqdm(range(epochs)):
train_loss, train_accuracy = train_step(model=model,
dataloader=train_dataloader, loss_fn=loss_fn, optimizer=optimizer)
valid_loss, valid_accuracy = valid_step(model=model,
dataloader=valid_dataloader, loss_fn=loss_fn)
if valid_loss < best_valid_loss:
best_valid_loss = valid_loss
save_checkpoint("best_model.pth", model, epoch,
best_valid_loss, optimizer, valid_accuracy)
print(f'Epoch: {epoch + 1} | Train Loss: {train_loss:.4f} |
Train Accuracy: {train_accuracy:.4f} | Valid Loss: {valid_loss:.4f} |
Valid Accuracy: {valid_accuracy:.4f}')
results["train_loss"].append(train_loss)
results["train_accuracy"].append(train_accuracy)
results["valid_loss"].append(valid_loss)
results["valid_accuracy"].append(valid_accuracy)
return results
# Training parameters and seeds
EPOCHS = 100
torch.cuda.manual_seed(SEED)
torch.manual_seed(SEED)
MODEL_RESULTS = train(model, train_dataloader, valid_dataloader,
loss_fn, optimizer, EPOCHS)
def loss_metric_curve_plot(model_results: dict):
train_loss = model_results["train_loss"]
valid_loss = model_results["valid_loss"]
train_accuracy = [float(value) for value in
model_results["train_accuracy"]]
valid_accuracy = [float(value) for value in
model_results["valid_accuracy"]]
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 4))
axes = axes.flat
axes[0].plot(train_loss, color="red", label="Train")
axes[0].plot(valid_loss, color="blue", label="Valid",
linestyle='--')
axes[0].spines["top"].set_visible(False)
axes[0].spines["right"].set_visible(False)
axes[0].set_title("CrossEntropyLoss", fontsize=12,
fontweight="bold", color="black")
axes[0].set_xlabel("Epochs", fontsize=10, fontweight="bold",
color="black")
axes[0].set_ylabel("Loss", fontsize=10, fontweight="bold",
color="black")
axes[0].legend()
axes[1].plot(train_accuracy, color="red", label="Train")
axes[1].plot(valid_accuracy, color="blue", label="Valid",
linestyle='--')
axes[1].spines["top"].set_visible(False)
axes[1].spines["right"].set_visible(False)
axes[1].set_title("Accuracy", fontsize=12, fontweight="bold",
color="black")
axes[1].set_xlabel("Epochs", fontsize=10, fontweight="bold",
color="black")
axes[1].set_ylabel("Score", fontsize=10, fontweight="bold",
color="black")
axes[1].legend()
fig.tight_layout()
fig.show()
loss_metric_curve_plot(MODEL_RESULTS)
def predictions(test_dataloader: torch.utils.data.DataLoader):
checkpoint = torch.load("best_model.pth")
loaded_model = vit_b_16(weights=weights)
loaded_model.heads = nn.Sequential(OrderedDict([('head',
nn.Linear(in_features=768, out_features=output_shape))]))
loaded_model.load_state_dict(checkpoint["model"])
loaded_model.to(device)
loaded_model.eval()
y_pred_test = []
with torch.inference_mode():
for X, _ in tqdm(test_dataloader):
X = X.to(device)
y_pred_logit = loaded_model(X)
y_pred_prob = torch.softmax(y_pred_logit, dim=1)
y_pred_class = torch.argmax(y_pred_prob, dim=1)
y_pred_test.append(y_pred_class.detach().cpu())
y_pred_test = torch.cat(y_pred_test)
return y_pred_test
# Prepare test DataLoader
test_dataset = CustomImageDataset(df_test, label_map, auto_transforms)
test_dataloader = DataLoader(dataset=test_dataset,
batch_size=BATCH_SIZE, shuffle=False, num_workers=NUM_WORKERS)
y_pred_test = predictions(test_dataloader)
print(f'Accuracy Test =
{round(accuracy_score(df_test["label"].map(label_map),
y_pred_test.numpy()), 4)}')
confusion_matrix_test =
confusion_matrix(df_test["label"].map(label_map), y_pred_test.numpy())
fig, ax = plt.subplots(figsize=(10, 4.5))
sns.heatmap(confusion_matrix_test, cmap='Oranges', annot=True,
annot_kws={"fontsize": 9, "fontweight": "bold"},
linewidths=1.2, fmt=' ', linecolor="white", square=True,
xticklabels=classes, yticklabels=classes,
cbar=False, ax=ax)
ax.set_title("Confusion Matrix Test", fontsize=15, fontweight="bold",
color="darkblue")
ax.tick_params('x', rotation=90)
fig.show()
Total Images = 408
========================================
Total Classes = 7
========================================
* Banana Black Sigatoka Disease: 67 images
* Banana Bract Mosaic Virus Disease: 50 images
* Banana Healthy Leaf: 86 images
* Banana Insect Pest Disease: 86 images
* Banana Moko Disease: 55 images
* Banana Panama Disease: 41 images
* Banana Yellow Sigatoka Disease: 23 images
path
label
0 /kaggle/input/banana-disease-recognition-datas... Banana Panama
Disease
1 /kaggle/input/banana-disease-recognition-datas... Banana Panama
Disease
2 /kaggle/input/banana-disease-recognition-datas... Banana Panama
Disease
3 /kaggle/input/banana-disease-recognition-datas... Banana Panama
Disease
4 /kaggle/input/banana-disease-recognition-datas... Banana Panama
Disease
{'Banana Black Sigatoka Disease': 0, 'Banana Bract Mosaic Virus
Disease': 1, 'Banana Healthy Leaf': 2, 'Banana Insect Pest Disease':
3, 'Banana Moko Disease': 4, 'Banana Panama Disease': 5, 'Banana
Yellow Sigatoka Disease': 6}
ImageClassification(
crop_size=[224]
resize_size=[256]
mean=[0.485, 0.456, 0.406]
std=[0.229, 0.224, 0.225]
interpolation=InterpolationMode.BILINEAR
)
Batch images shape: torch.Size([8, 3, 224, 224]) and Batch labels
shape: torch.Size([8])
Using device: cuda
Downloading: "https://download.pytorch.org/models/vit_b_16-
c867db91.pth" to /root/.cache/torch/hub/checkpoints/vit_b_16-
c867db91.pth
100%|██████████| 330M/330M [00:01<00:00, 210MB/s]
{"model_id":"e97a19f7213640598339fe3c82118a19","version_major":2,"vers
ion_minor":0}
Epoch: 1 | Train Loss: 0.7721 | Train Accuracy: 0.7569 | Valid Loss:
0.5587 | Valid Accuracy: 0.8750
Epoch: 2 | Train Loss: 0.1039 | Train Accuracy: 0.9722 | Valid Loss:
0.2439 | Valid Accuracy: 0.9219
Epoch: 3 | Train Loss: 0.0123 | Train Accuracy: 1.0000 | Valid Loss:
0.2401 | Valid Accuracy: 0.8906
Epoch: 4 | Train Loss: 0.0080 | Train Accuracy: 1.0000 | Valid Loss:
0.2705 | Valid Accuracy: 0.9594
Epoch: 5 | Train Loss: 0.0028 | Train Accuracy: 1.0000 | Valid Loss:
0.2012 | Valid Accuracy: 0.9688
Epoch: 6 | Train Loss: 0.0018 | Train Accuracy: 1.0000 | Valid Loss:
0.1995 | Valid Accuracy: 0.9688
Epoch: 7 | Train Loss: 0.0016 | Train Accuracy: 1.0000 | Valid Loss:
0.1920 | Valid Accuracy: 0.9688
Epoch: 8 | Train Loss: 0.0013 | Train Accuracy: 1.0000 | Valid Loss:
0.2084 | Valid Accuracy: 0.9594
Epoch: 9 | Train Loss: 0.0012 | Train Accuracy: 1.0000 | Valid Loss:
0.2647 | Valid Accuracy: 0.9594
Epoch: 10 | Train Loss: 0.0011 | Train Accuracy: 1.0000 | Valid Loss:
0.2022 | Valid Accuracy: 0.9688
Epoch: 11 | Train Loss: 0.0009 | Train Accuracy: 1.0000 | Valid Loss:
0.1998 | Valid Accuracy: 0.9688
Epoch: 12 | Train Loss: 0.0009 | Train Accuracy: 1.0000 | Valid Loss:
0.1920 | Valid Accuracy: 0.9688
Epoch: 13 | Train Loss: 0.0008 | Train Accuracy: 1.0000 | Valid Loss:
0.2655 | Valid Accuracy: 0.9594
Epoch: 14 | Train Loss: 0.0008 | Train Accuracy: 1.0000 | Valid Loss:
0.1911 | Valid Accuracy: 0.9688
Epoch: 15 | Train Loss: 0.0007 | Train Accuracy: 1.0000 | Valid Loss:
0.1922 | Valid Accuracy: 0.9688
Epoch: 16 | Train Loss: 0.0006 | Train Accuracy: 1.0000 | Valid Loss:
0.1908 | Valid Accuracy: 0.9688
Epoch: 17 | Train Loss: 0.0006 | Train Accuracy: 1.0000 | Valid Loss:
0.1921 | Valid Accuracy: 0.9688
Epoch: 18 | Train Loss: 0.0006 | Train Accuracy: 1.0000 | Valid Loss:
0.1953 | Valid Accuracy: 0.9688
Epoch: 19 | Train Loss: 0.0005 | Train Accuracy: 1.0000 | Valid Loss:
0.1935 | Valid Accuracy: 0.9688
Epoch: 20 | Train Loss: 0.0005 | Train Accuracy: 1.0000 | Valid Loss:
0.1923 | Valid Accuracy: 0.9688
Epoch: 21 | Train Loss: 0.0005 | Train Accuracy: 1.0000 | Valid Loss:
0.1917 | Valid Accuracy: 0.9688
Epoch: 22 | Train Loss: 0.0004 | Train Accuracy: 1.0000 | Valid Loss:
0.1918 | Valid Accuracy: 0.9688
Epoch: 23 | Train Loss: 0.0004 | Train Accuracy: 1.0000 | Valid Loss:
0.1933 | Valid Accuracy: 0.9688
Epoch: 24 | Train Loss: 0.0004 | Train Accuracy: 1.0000 | Valid Loss:
0.1974 | Valid Accuracy: 0.9688
Epoch: 25 | Train Loss: 0.0004 | Train Accuracy: 1.0000 | Valid Loss:
0.1929 | Valid Accuracy: 0.9688
Epoch: 26 | Train Loss: 0.0004 | Train Accuracy: 1.0000 | Valid Loss:
0.1980 | Valid Accuracy: 0.9688
Epoch: 27 | Train Loss: 0.0003 | Train Accuracy: 1.0000 | Valid Loss:
0.1952 | Valid Accuracy: 0.9688
Epoch: 28 | Train Loss: 0.0003 | Train Accuracy: 1.0000 | Valid Loss:
0.1914 | Valid Accuracy: 0.9688
Epoch: 29 | Train Loss: 0.0003 | Train Accuracy: 1.0000 | Valid Loss:
0.1978 | Valid Accuracy: 0.9688
Epoch: 30 | Train Loss: 0.0003 | Train Accuracy: 1.0000 | Valid Loss:
0.1952 | Valid Accuracy: 0.9688
Epoch: 31 | Train Loss: 0.0003 | Train Accuracy: 1.0000 | Valid Loss:
0.1938 | Valid Accuracy: 0.9688
Epoch: 32 | Train Loss: 0.0003 | Train Accuracy: 1.0000 | Valid Loss:
0.1973 | Valid Accuracy: 0.9688
Epoch: 33 | Train Loss: 0.0003 | Train Accuracy: 1.0000 | Valid Loss:
0.1966 | Valid Accuracy: 0.9688
Epoch: 34 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1930 | Valid Accuracy: 0.9688
Epoch: 35 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.2029 | Valid Accuracy: 0.9594
Epoch: 36 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.2762 | Valid Accuracy: 0.9594
Epoch: 37 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1979 | Valid Accuracy: 0.9688
Epoch: 38 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1931 | Valid Accuracy: 0.9688
Epoch: 39 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1927 | Valid Accuracy: 0.9688
Epoch: 40 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1927 | Valid Accuracy: 0.9688
Epoch: 41 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1927 | Valid Accuracy: 0.9688
Epoch: 42 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1941 | Valid Accuracy: 0.9688
Epoch: 43 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1931 | Valid Accuracy: 0.9688
Epoch: 44 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1952 | Valid Accuracy: 0.9688
Epoch: 45 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1945 | Valid Accuracy: 0.9688
Epoch: 46 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1923 | Valid Accuracy: 0.9688
Epoch: 47 | Train Loss: 0.0002 | Train Accuracy: 1.0000 | Valid Loss:
0.1972 | Valid Accuracy: 0.9688
Epoch: 48 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1945 | Valid Accuracy: 0.9688
Epoch: 49 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1976 | Valid Accuracy: 0.9688
Epoch: 50 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1948 | Valid Accuracy: 0.9688
Epoch: 51 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.2853 | Valid Accuracy: 0.9594
Epoch: 52 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.2078 | Valid Accuracy: 0.9594
Epoch: 53 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1943 | Valid Accuracy: 0.9688
Epoch: 54 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1956 | Valid Accuracy: 0.9688
Epoch: 55 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1950 | Valid Accuracy: 0.9688
Epoch: 56 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1961 | Valid Accuracy: 0.9688
Epoch: 57 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1937 | Valid Accuracy: 0.9688
Epoch: 58 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1939 | Valid Accuracy: 0.9688
Epoch: 59 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1952 | Valid Accuracy: 0.9688
Epoch: 60 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1943 | Valid Accuracy: 0.9688
Epoch: 61 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1953 | Valid Accuracy: 0.9688
Epoch: 62 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1939 | Valid Accuracy: 0.9688
Epoch: 63 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1995 | Valid Accuracy: 0.9688
Epoch: 64 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.2824 | Valid Accuracy: 0.9594
Epoch: 65 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1946 | Valid Accuracy: 0.9688
Epoch: 66 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1960 | Valid Accuracy: 0.9688
Epoch: 67 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1956 | Valid Accuracy: 0.9688
Epoch: 68 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1964 | Valid Accuracy: 0.9688
Epoch: 69 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1964 | Valid Accuracy: 0.9688
Epoch: 70 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1967 | Valid Accuracy: 0.9688
Epoch: 71 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1995 | Valid Accuracy: 0.9688
Epoch: 72 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1952 | Valid Accuracy: 0.9688
Epoch: 73 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1994 | Valid Accuracy: 0.9688
Epoch: 74 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.2009 | Valid Accuracy: 0.9688
Epoch: 75 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1963 | Valid Accuracy: 0.9688
Epoch: 76 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1966 | Valid Accuracy: 0.9688
Epoch: 77 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1999 | Valid Accuracy: 0.9688
Epoch: 78 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1966 | Valid Accuracy: 0.9688
Epoch: 79 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1958 | Valid Accuracy: 0.9688
Epoch: 80 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.2002 | Valid Accuracy: 0.9688
Epoch: 81 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.2000 | Valid Accuracy: 0.9688
Epoch: 82 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1968 | Valid Accuracy: 0.9688
Epoch: 83 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1967 | Valid Accuracy: 0.9688
Epoch: 84 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1956 | Valid Accuracy: 0.9688
Epoch: 85 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1977 | Valid Accuracy: 0.9688
Epoch: 86 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.2003 | Valid Accuracy: 0.9688
Epoch: 87 | Train Loss: 0.0001 | Train Accuracy: 1.0000 | Valid Loss:
0.1975 | Valid Accuracy: 0.9688
Epoch: 88 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.1967 | Valid Accuracy: 0.9688
Epoch: 89 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.1970 | Valid Accuracy: 0.9688
Epoch: 90 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.1970 | Valid Accuracy: 0.9688
Epoch: 91 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.2018 | Valid Accuracy: 0.9688
Epoch: 92 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.2041 | Valid Accuracy: 0.9594
Epoch: 93 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.1970 | Valid Accuracy: 0.9688
Epoch: 94 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.1963 | Valid Accuracy: 0.9688
Epoch: 95 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.2018 | Valid Accuracy: 0.9688
Epoch: 96 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.1979 | Valid Accuracy: 0.9688
Epoch: 97 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.2907 | Valid Accuracy: 0.9594
Epoch: 98 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.2051 | Valid Accuracy: 0.9594
Epoch: 99 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.2004 | Valid Accuracy: 0.9688
Epoch: 100 | Train Loss: 0.0000 | Train Accuracy: 1.0000 | Valid Loss:
0.2021 | Valid Accuracy: 0.9688
{"model_id":"3fbdaf5bc856475697b142497520467b","version_major":2,"vers
ion_minor":0}
Accuracy Test = 0.9516
from sklearn.metrics import accuracy_score, precision_score,
recall_score, f1_score, classification_report, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns
# Map ground truth labels to numerical values
true_labels = df_test["label"].map(label_map).values
predicted_labels = y_pred_test.numpy()
# Calculate overall accuracy
accuracy = accuracy_score(true_labels, predicted_labels)
print(f"Test Accuracy: {accuracy:.4f}")
# Calculate precision, recall, and f1-score with different averaging
methods
precision_macro = precision_score(true_labels, predicted_labels,
average='macro')
recall_macro = recall_score(true_labels, predicted_labels,
average='macro')
f1_macro = f1_score(true_labels, predicted_labels, average='macro')
precision_micro = precision_score(true_labels, predicted_labels,
average='micro')
recall_micro = recall_score(true_labels, predicted_labels,
average='micro')
f1_micro = f1_score(true_labels, predicted_labels, average='micro')
precision_weighted = precision_score(true_labels, predicted_labels,
average='weighted')
recall_weighted = recall_score(true_labels, predicted_labels,
average='weighted')
f1_weighted = f1_score(true_labels, predicted_labels,
average='weighted')
print("Metric Scores (Macro Average):")
print(f"Precision: {precision_macro:.4f}")
print(f"Recall: {recall_macro:.4f}")
print(f"F1 Score: {f1_macro:.4f}")
print("\nMetric Scores (Micro Average):")
print(f"Precision: {precision_micro:.4f}")
print(f"Recall: {recall_micro:.4f}")
print(f"F1 Score: {f1_micro:.4f}")
print("\nMetric Scores (Weighted Average):")
print(f"Precision: {precision_weighted:.4f}")
print(f"Recall: {recall_weighted:.4f}")
print(f"F1 Score: {f1_weighted:.4f}")
# Detailed classification report
print("\nClassification Report:")
print(classification_report(true_labels, predicted_labels,
target_names=classes))
# Compute and visualize the confusion matrix
cm = confusion_matrix(true_labels, predicted_labels)
plt.figure(figsize=(10, 4.5))
sns.heatmap(cm, cmap='Oranges', annot=True, annot_kws={"fontsize": 9,
"fontweight": "bold"},
linewidths=1.2, fmt='d', linecolor="white", square=True,
xticklabels=classes, yticklabels=classes, cbar=False)
plt.title("Confusion Matrix Test", fontsize=15, fontweight="bold",
color="darkblue")
plt.xlabel("Predicted Classes", fontsize=12, fontweight="bold",
color="black")
plt.ylabel("True Classes", fontsize=12, fontweight="bold",
color="black")
plt.xticks(rotation=90)
plt.tight_layout()
plt.show()
Test Accuracy: 0.9516
Metric Scores (Macro Average):
Precision: 0.9280
Recall: 0.9604
F1 Score: 0.9403
Metric Scores (Micro Average):
Precision: 0.9516
Recall: 0.9516
F1 Score: 0.9516
Metric Scores (Weighted Average):
Precision: 0.9562
Recall: 0.9516
F1 Score: 0.9518
Classification Report:
precision recall f1-score
support
Banana Black Sigatoka Disease 0.89 0.80 0.84
10
Banana Bract Mosaic Virus Disease 1.00 1.00 1.00
8
Banana Healthy Leaf 1.00 1.00 1.00
13
Banana Insect Pest Disease 1.00 0.92 0.96
13
Banana Moko Disease 1.00 1.00 1.00
9
Banana Panama Disease 0.86 1.00 0.92
6
Banana Yellow Sigatoka Disease 0.75 1.00 0.86
3
accuracy 0.95
62
macro avg 0.93 0.96 0.94
62
weighted avg 0.96 0.95 0.95
62
# 1. ResNet50V2 Implementation
# Import necessary libraries
import torch
from torch import nn
import torchvision.models as models
from collections import OrderedDict
# Create ResNet50 model
resnet_model =
models.resnet50(weights=models.ResNet50_Weights.DEFAULT)
# Freeze base layers
for param in resnet_model.parameters():
param.requires_grad = False
# Modify the final layer for our classification task
in_features = resnet_model.fc.in_features
resnet_model.fc = nn.Linear(in_features, len(classes))
resnet_model = resnet_model.to(device)
# Define optimizer for ResNet50
resnet_optimizer = optim.Adam(resnet_model.parameters(), lr=0.001)
# 2. Custom CNN Implementation
class CustomCNN(nn.Module):
def __init__(self, num_classes):
super(CustomCNN, self).__init__()
# Feature extractor - convolutional layers
self.features = nn.Sequential(
# First block
nn.Conv2d(3, 32, kernel_size=3, padding=1),
nn.BatchNorm2d(32),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
# Second block
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
# Third block
nn.Conv2d(64, 128, kernel_size=3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
# Fourth block
nn.Conv2d(128, 256, kernel_size=3, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
)
# Classifier - fully connected layers
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(256 * 14 * 14, 512), # For 224x224 input images
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(512, num_classes)
)
def forward(self, x):
x = self.features(x)
x = self.classifier(x)
return x
# Create Custom CNN model
cnn_model = CustomCNN(len(classes))
cnn_model = cnn_model.to(device)
# Define optimizer for Custom CNN
cnn_optimizer = optim.Adam(cnn_model.parameters(), lr=0.001)
# 3. Train ResNet50V2 model
print("=" * 50)
print("Training ResNet50V2 model")
print("=" * 50)
RESNET_RESULTS = train(resnet_model, train_dataloader,
valid_dataloader, loss_fn, resnet_optimizer, EPOCHS)
# 4. Train Custom CNN model
print("=" * 50)
print("Training Custom CNN model")
print("=" * 50)
CNN_RESULTS = train(cnn_model, train_dataloader, valid_dataloader,
loss_fn, cnn_optimizer, EPOCHS)
# 5. Evaluate ResNet50V2 on test set
def evaluate_model(model, test_dataloader, model_name):
model.eval()
y_pred_test = []
with torch.inference_mode():
for X, _ in tqdm(test_dataloader):
X = X.to(device)
y_pred_logit = model(X)
y_pred_prob = torch.softmax(y_pred_logit, dim=1)
y_pred_class = torch.argmax(y_pred_prob, dim=1)
y_pred_test.append(y_pred_class.detach().cpu())
y_pred_test = torch.cat(y_pred_test)
accuracy = accuracy_score(df_test["label"].map(label_map),
y_pred_test.numpy())
print(f'{model_name} Test Accuracy = {round(accuracy, 4)}')
conf_matrix = confusion_matrix(df_test["label"].map(label_map),
y_pred_test.numpy())
fig, ax = plt.subplots(figsize=(10, 4.5))
sns.heatmap(conf_matrix, cmap='Blues', annot=True,
annot_kws={"fontsize": 9, "fontweight": "bold"},
linewidths=1.2, fmt=' ', linecolor="white",
square=True,
xticklabels=classes, yticklabels=classes, cbar=False,
ax=ax)
ax.set_title(f"{model_name} Confusion Matrix", fontsize=15,
fontweight="bold", color="darkblue")
ax.tick_params('x', rotation=90)
plt.tight_layout()
plt.show()
return accuracy, y_pred_test
# Evaluate ResNet50V2
resnet_accuracy, resnet_preds = evaluate_model(resnet_model,
test_dataloader, "ResNet50V2")
# Evaluate Custom CNN
cnn_accuracy, cnn_preds = evaluate_model(cnn_model, test_dataloader,
"Custom CNN")
# 6. Compare all models' performance
vit_accuracy = accuracy_score(df_test["label"].map(label_map),
y_pred_test.numpy())
# Plot comparison
model_names = ['ViT-B/16', 'ResNet50V2', 'Custom CNN']
accuracies = [vit_accuracy, resnet_accuracy, cnn_accuracy]
plt.figure(figsize=(10, 6))
bars = plt.bar(model_names, accuracies, color=['orange', 'skyblue',
'lightgreen'])
# Add accuracy values on top of bars
for bar, acc in zip(bars, accuracies):
plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.01,
f'{acc:.4f}', ha='center', fontweight='bold')
plt.title('Model Performance Comparison', fontsize=15,
fontweight='bold')
plt.ylabel('Test Accuracy', fontsize=12)
plt.ylim(0, max(accuracies) + 0.1)
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
# 7. Plot training curves for all models
plt.figure(figsize=(15, 10))
# Training Loss
plt.subplot(2, 2, 1)
plt.plot(MODEL_RESULTS["train_loss"], 'o-', color='orange',
label='ViT')
plt.plot(RESNET_RESULTS["train_loss"], 'o-', color='skyblue',
label='ResNet50V2')
plt.plot(CNN_RESULTS["train_loss"], 'o-', color='lightgreen',
label='Custom CNN')
plt.title("Training Loss", fontsize=12, fontweight="bold")
plt.xlabel("Epochs", fontsize=10)
plt.ylabel("Loss", fontsize=10)
plt.legend()
plt.grid(True, alpha=0.3)
# Validation Loss
plt.subplot(2, 2, 2)
plt.plot(MODEL_RESULTS["valid_loss"], 'o-', color='orange',
label='ViT')
plt.plot(RESNET_RESULTS["valid_loss"], 'o-', color='skyblue',
label='ResNet50V2')
plt.plot(CNN_RESULTS["valid_loss"], 'o-', color='lightgreen',
label='Custom CNN')
plt.title("Validation Loss", fontsize=12, fontweight="bold")
plt.xlabel("Epochs", fontsize=10)
plt.ylabel("Loss", fontsize=10)
plt.legend()
plt.grid(True, alpha=0.3)
# Training Accuracy
plt.subplot(2, 2, 3)
plt.plot(MODEL_RESULTS["train_accuracy"], 'o-', color='orange',
label='ViT')
plt.plot(RESNET_RESULTS["train_accuracy"], 'o-', color='skyblue',
label='ResNet50V2')
plt.plot(CNN_RESULTS["train_accuracy"], 'o-', color='lightgreen',
label='Custom CNN')
plt.title("Training Accuracy", fontsize=12, fontweight="bold")
plt.xlabel("Epochs", fontsize=10)
plt.ylabel("Accuracy", fontsize=10)
plt.legend()
plt.grid(True, alpha=0.3)
# Validation Accuracy
plt.subplot(2, 2, 4)
plt.plot(MODEL_RESULTS["valid_accuracy"], 'o-', color='orange',
label='ViT')
plt.plot(RESNET_RESULTS["valid_accuracy"], 'o-', color='skyblue',
label='ResNet50V2')
plt.plot(CNN_RESULTS["valid_accuracy"], 'o-', color='lightgreen',
label='Custom CNN')
plt.title("Validation Accuracy", fontsize=12, fontweight="bold")
plt.xlabel("Epochs", fontsize=10)
plt.ylabel("Accuracy", fontsize=10)
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Downloading: "https://download.pytorch.org/models/resnet50-
11ad3fa6.pth" to /root/.cache/torch/hub/checkpoints/resnet50-
11ad3fa6.pth
100%|██████████| 97.8M/97.8M [00:00<00:00, 178MB/s]
==================================================
Training ResNet50V2 model
==================================================
{"model_id":"949cdceee7e340a38b38db2cf219f103","version_major":2,"vers
ion_minor":0}
Epoch: 1 | Train Loss: 1.5718 | Train Accuracy: 0.4806 | Valid Loss:
1.1950 | Valid Accuracy: 0.8031
Epoch: 2 | Train Loss: 1.0278 | Train Accuracy: 0.7861 | Valid Loss:
0.8868 | Valid Accuracy: 0.8500
Epoch: 3 | Train Loss: 0.8326 | Train Accuracy: 0.7826 | Valid Loss:
0.7333 | Valid Accuracy: 0.8750
Epoch: 4 | Train Loss: 0.7134 | Train Accuracy: 0.8403 | Valid Loss:
0.6577 | Valid Accuracy: 0.8656
Epoch: 5 | Train Loss: 0.5928 | Train Accuracy: 0.8889 | Valid Loss:
0.5573 | Valid Accuracy: 0.9219
Epoch: 6 | Train Loss: 0.5217 | Train Accuracy: 0.8833 | Valid Loss:
0.5437 | Valid Accuracy: 0.9531
Epoch: 7 | Train Loss: 0.4264 | Train Accuracy: 0.9340 | Valid Loss:
0.4592 | Valid Accuracy: 0.9219
Epoch: 8 | Train Loss: 0.3972 | Train Accuracy: 0.9167 | Valid Loss:
0.4672 | Valid Accuracy: 0.9531
Epoch: 9 | Train Loss: 0.3662 | Train Accuracy: 0.9271 | Valid Loss:
0.4590 | Valid Accuracy: 0.9437
Epoch: 10 | Train Loss: 0.3815 | Train Accuracy: 0.9132 | Valid Loss:
0.3892 | Valid Accuracy: 0.9437
Epoch: 11 | Train Loss: 0.3403 | Train Accuracy: 0.9271 | Valid Loss:
0.3802 | Valid Accuracy: 0.9531
Epoch: 12 | Train Loss: 0.3014 | Train Accuracy: 0.9493 | Valid Loss:
0.3681 | Valid Accuracy: 0.9281
Epoch: 13 | Train Loss: 0.2895 | Train Accuracy: 0.9375 | Valid Loss:
0.3634 | Valid Accuracy: 0.9375
Epoch: 14 | Train Loss: 0.3143 | Train Accuracy: 0.9306 | Valid Loss:
0.3535 | Valid Accuracy: 0.9531
Epoch: 15 | Train Loss: 0.2626 | Train Accuracy: 0.9549 | Valid Loss:
0.3280 | Valid Accuracy: 0.9437
Epoch: 16 | Train Loss: 0.2318 | Train Accuracy: 0.9792 | Valid Loss:
0.3155 | Valid Accuracy: 0.9531
Epoch: 17 | Train Loss: 0.2504 | Train Accuracy: 0.9458 | Valid Loss:
0.3347 | Valid Accuracy: 0.9531
Epoch: 18 | Train Loss: 0.2265 | Train Accuracy: 0.9458 | Valid Loss:
0.3109 | Valid Accuracy: 0.9531
Epoch: 19 | Train Loss: 0.2462 | Train Accuracy: 0.9493 | Valid Loss:
0.3066 | Valid Accuracy: 0.9437
Epoch: 20 | Train Loss: 0.1704 | Train Accuracy: 0.9861 | Valid Loss:
0.2662 | Valid Accuracy: 0.9531
Epoch: 21 | Train Loss: 0.1819 | Train Accuracy: 0.9792 | Valid Loss:
0.2883 | Valid Accuracy: 0.9531
Epoch: 22 | Train Loss: 0.1624 | Train Accuracy: 0.9861 | Valid Loss:
0.3047 | Valid Accuracy: 0.9437
Epoch: 23 | Train Loss: 0.1594 | Train Accuracy: 0.9792 | Valid Loss:
0.2776 | Valid Accuracy: 0.9531
Epoch: 24 | Train Loss: 0.2132 | Train Accuracy: 0.9549 | Valid Loss:
0.2530 | Valid Accuracy: 0.9531
Epoch: 25 | Train Loss: 0.1813 | Train Accuracy: 0.9583 | Valid Loss:
0.2687 | Valid Accuracy: 0.9531
Epoch: 26 | Train Loss: 0.1360 | Train Accuracy: 0.9722 | Valid Loss:
0.2605 | Valid Accuracy: 0.9531
Epoch: 27 | Train Loss: 0.1602 | Train Accuracy: 0.9667 | Valid Loss:
0.3095 | Valid Accuracy: 0.9437
Epoch: 28 | Train Loss: 0.1728 | Train Accuracy: 0.9611 | Valid Loss:
0.2683 | Valid Accuracy: 0.9531
Epoch: 29 | Train Loss: 0.1384 | Train Accuracy: 0.9722 | Valid Loss:
0.2870 | Valid Accuracy: 0.9531
Epoch: 30 | Train Loss: 0.1569 | Train Accuracy: 0.9701 | Valid Loss:
0.3169 | Valid Accuracy: 0.9437
Epoch: 31 | Train Loss: 0.1381 | Train Accuracy: 0.9826 | Valid Loss:
0.2970 | Valid Accuracy: 0.9281
Epoch: 32 | Train Loss: 0.1178 | Train Accuracy: 0.9806 | Valid Loss:
0.2536 | Valid Accuracy: 0.9375
Epoch: 33 | Train Loss: 0.0942 | Train Accuracy: 0.9944 | Valid Loss:
0.2679 | Valid Accuracy: 0.9531
Epoch: 34 | Train Loss: 0.1322 | Train Accuracy: 0.9792 | Valid Loss:
0.2343 | Valid Accuracy: 0.9531
Epoch: 35 | Train Loss: 0.1185 | Train Accuracy: 0.9840 | Valid Loss:
0.2511 | Valid Accuracy: 0.9375
Epoch: 36 | Train Loss: 0.1085 | Train Accuracy: 0.9757 | Valid Loss:
0.2240 | Valid Accuracy: 0.9531
Epoch: 37 | Train Loss: 0.1171 | Train Accuracy: 0.9826 | Valid Loss:
0.2646 | Valid Accuracy: 0.9375
Epoch: 38 | Train Loss: 0.1108 | Train Accuracy: 0.9826 | Valid Loss:
0.2709 | Valid Accuracy: 0.9125
Epoch: 39 | Train Loss: 0.1329 | Train Accuracy: 0.9771 | Valid Loss:
0.2342 | Valid Accuracy: 0.9531
Epoch: 40 | Train Loss: 0.1219 | Train Accuracy: 0.9757 | Valid Loss:
0.2407 | Valid Accuracy: 0.9375
Epoch: 41 | Train Loss: 0.1265 | Train Accuracy: 0.9736 | Valid Loss:
0.2801 | Valid Accuracy: 0.9125
Epoch: 42 | Train Loss: 0.1051 | Train Accuracy: 0.9826 | Valid Loss:
0.2559 | Valid Accuracy: 0.9437
Epoch: 43 | Train Loss: 0.1114 | Train Accuracy: 0.9806 | Valid Loss:
0.2364 | Valid Accuracy: 0.9281
Epoch: 44 | Train Loss: 0.0810 | Train Accuracy: 0.9931 | Valid Loss:
0.2367 | Valid Accuracy: 0.9531
Epoch: 45 | Train Loss: 0.0828 | Train Accuracy: 0.9896 | Valid Loss:
0.2457 | Valid Accuracy: 0.9531
Epoch: 46 | Train Loss: 0.1044 | Train Accuracy: 0.9875 | Valid Loss:
0.2555 | Valid Accuracy: 0.9531
Epoch: 47 | Train Loss: 0.1182 | Train Accuracy: 0.9792 | Valid Loss:
0.2231 | Valid Accuracy: 0.9375
Epoch: 48 | Train Loss: 0.0822 | Train Accuracy: 0.9840 | Valid Loss:
0.2732 | Valid Accuracy: 0.9437
Epoch: 49 | Train Loss: 0.0920 | Train Accuracy: 0.9896 | Valid Loss:
0.2922 | Valid Accuracy: 0.9125
Epoch: 50 | Train Loss: 0.0732 | Train Accuracy: 0.9965 | Valid Loss:
0.2633 | Valid Accuracy: 0.9344
Epoch: 51 | Train Loss: 0.0722 | Train Accuracy: 0.9965 | Valid Loss:
0.2211 | Valid Accuracy: 0.9375
Epoch: 52 | Train Loss: 0.0633 | Train Accuracy: 0.9931 | Valid Loss:
0.2390 | Valid Accuracy: 0.9375
Epoch: 53 | Train Loss: 0.0745 | Train Accuracy: 0.9931 | Valid Loss:
0.2262 | Valid Accuracy: 0.9531
Epoch: 54 | Train Loss: 0.0714 | Train Accuracy: 0.9931 | Valid Loss:
0.2503 | Valid Accuracy: 0.9531
Epoch: 55 | Train Loss: 0.0868 | Train Accuracy: 0.9896 | Valid Loss:
0.3058 | Valid Accuracy: 0.9281
Epoch: 56 | Train Loss: 0.1033 | Train Accuracy: 0.9757 | Valid Loss:
0.2441 | Valid Accuracy: 0.9375
Epoch: 57 | Train Loss: 0.0821 | Train Accuracy: 0.9826 | Valid Loss:
0.2072 | Valid Accuracy: 0.9531
Epoch: 58 | Train Loss: 0.0767 | Train Accuracy: 0.9826 | Valid Loss:
0.2189 | Valid Accuracy: 0.9531
Epoch: 59 | Train Loss: 0.0558 | Train Accuracy: 0.9931 | Valid Loss:
0.2821 | Valid Accuracy: 0.9281
Epoch: 60 | Train Loss: 0.0694 | Train Accuracy: 0.9965 | Valid Loss:
0.2130 | Valid Accuracy: 0.9375
Epoch: 61 | Train Loss: 0.0805 | Train Accuracy: 0.9806 | Valid Loss:
0.2759 | Valid Accuracy: 0.9375
Epoch: 62 | Train Loss: 0.0850 | Train Accuracy: 0.9826 | Valid Loss:
0.3042 | Valid Accuracy: 0.9437
Epoch: 63 | Train Loss: 0.0546 | Train Accuracy: 1.0000 | Valid Loss:
0.2507 | Valid Accuracy: 0.9531
Epoch: 64 | Train Loss: 0.0414 | Train Accuracy: 1.0000 | Valid Loss:
0.2595 | Valid Accuracy: 0.9375
Epoch: 65 | Train Loss: 0.0705 | Train Accuracy: 0.9931 | Valid Loss:
0.2315 | Valid Accuracy: 0.9375
Epoch: 66 | Train Loss: 0.0711 | Train Accuracy: 0.9896 | Valid Loss:
0.3221 | Valid Accuracy: 0.9344
Epoch: 67 | Train Loss: 0.0669 | Train Accuracy: 0.9931 | Valid Loss:
0.2135 | Valid Accuracy: 0.9375
Epoch: 68 | Train Loss: 0.0870 | Train Accuracy: 0.9792 | Valid Loss:
0.2585 | Valid Accuracy: 0.9375
Epoch: 69 | Train Loss: 0.0450 | Train Accuracy: 0.9965 | Valid Loss:
0.2396 | Valid Accuracy: 0.9375
Epoch: 70 | Train Loss: 0.0497 | Train Accuracy: 0.9931 | Valid Loss:
0.2108 | Valid Accuracy: 0.9531
Epoch: 71 | Train Loss: 0.0748 | Train Accuracy: 0.9896 | Valid Loss:
0.2353 | Valid Accuracy: 0.9375
Epoch: 72 | Train Loss: 0.0646 | Train Accuracy: 0.9861 | Valid Loss:
0.2475 | Valid Accuracy: 0.9688
Epoch: 73 | Train Loss: 0.0425 | Train Accuracy: 1.0000 | Valid Loss:
0.2581 | Valid Accuracy: 0.9531
Epoch: 74 | Train Loss: 0.0504 | Train Accuracy: 0.9931 | Valid Loss:
0.2430 | Valid Accuracy: 0.9375
Epoch: 75 | Train Loss: 0.0734 | Train Accuracy: 0.9792 | Valid Loss:
0.2053 | Valid Accuracy: 0.9688
Epoch: 76 | Train Loss: 0.0389 | Train Accuracy: 1.0000 | Valid Loss:
0.2503 | Valid Accuracy: 0.9531
Epoch: 77 | Train Loss: 0.0583 | Train Accuracy: 0.9889 | Valid Loss:
0.2012 | Valid Accuracy: 0.9375
Epoch: 78 | Train Loss: 0.0677 | Train Accuracy: 0.9826 | Valid Loss:
0.2732 | Valid Accuracy: 0.9375
Epoch: 79 | Train Loss: 0.0647 | Train Accuracy: 0.9896 | Valid Loss:
0.2295 | Valid Accuracy: 0.9688
Epoch: 80 | Train Loss: 0.0393 | Train Accuracy: 0.9965 | Valid Loss:
0.1992 | Valid Accuracy: 0.9688
Epoch: 81 | Train Loss: 0.0606 | Train Accuracy: 1.0000 | Valid Loss:
0.2411 | Valid Accuracy: 0.9375
Epoch: 82 | Train Loss: 0.0382 | Train Accuracy: 1.0000 | Valid Loss:
0.2319 | Valid Accuracy: 0.9531
Epoch: 83 | Train Loss: 0.0360 | Train Accuracy: 1.0000 | Valid Loss:
0.2814 | Valid Accuracy: 0.9531
Epoch: 84 | Train Loss: 0.0499 | Train Accuracy: 0.9931 | Valid Loss:
0.2365 | Valid Accuracy: 0.9437
Epoch: 85 | Train Loss: 0.0376 | Train Accuracy: 1.0000 | Valid Loss:
0.2301 | Valid Accuracy: 0.9437
Epoch: 86 | Train Loss: 0.0383 | Train Accuracy: 0.9931 | Valid Loss:
0.2504 | Valid Accuracy: 0.9437
Epoch: 87 | Train Loss: 0.0448 | Train Accuracy: 1.0000 | Valid Loss:
0.2461 | Valid Accuracy: 0.9375
Epoch: 88 | Train Loss: 0.0654 | Train Accuracy: 0.9875 | Valid Loss:
0.2232 | Valid Accuracy: 0.9375
Epoch: 89 | Train Loss: 0.0530 | Train Accuracy: 0.9965 | Valid Loss:
0.3191 | Valid Accuracy: 0.9437
Epoch: 90 | Train Loss: 0.0386 | Train Accuracy: 0.9965 | Valid Loss:
0.2151 | Valid Accuracy: 0.9531
Epoch: 91 | Train Loss: 0.0536 | Train Accuracy: 0.9840 | Valid Loss:
0.2392 | Valid Accuracy: 0.9375
Epoch: 92 | Train Loss: 0.0546 | Train Accuracy: 0.9931 | Valid Loss:
0.2773 | Valid Accuracy: 0.9281
Epoch: 93 | Train Loss: 0.0317 | Train Accuracy: 0.9965 | Valid Loss:
0.2407 | Valid Accuracy: 0.9375
Epoch: 94 | Train Loss: 0.0402 | Train Accuracy: 0.9965 | Valid Loss:
0.2347 | Valid Accuracy: 0.9688
Epoch: 95 | Train Loss: 0.0534 | Train Accuracy: 0.9896 | Valid Loss:
0.2394 | Valid Accuracy: 0.9531
Epoch: 96 | Train Loss: 0.0510 | Train Accuracy: 0.9875 | Valid Loss:
0.2431 | Valid Accuracy: 0.9437
Epoch: 97 | Train Loss: 0.0493 | Train Accuracy: 0.9896 | Valid Loss:
0.2556 | Valid Accuracy: 0.9281
Epoch: 98 | Train Loss: 0.0414 | Train Accuracy: 0.9931 | Valid Loss:
0.2134 | Valid Accuracy: 0.9437
Epoch: 99 | Train Loss: 0.0410 | Train Accuracy: 0.9931 | Valid Loss:
0.2423 | Valid Accuracy: 0.9531
Epoch: 100 | Train Loss: 0.0663 | Train Accuracy: 0.9826 | Valid Loss:
0.2396 | Valid Accuracy: 0.9531
==================================================
Training Custom CNN model
==================================================
{"model_id":"afb7427359e84896b6b6ead4b9b8de68","version_major":2,"vers
ion_minor":0}
Epoch: 1 | Train Loss: 18.4033 | Train Accuracy: 0.3090 | Valid Loss:
3.1055 | Valid Accuracy: 0.5094
Epoch: 2 | Train Loss: 5.6784 | Train Accuracy: 0.4049 | Valid Loss:
1.5644 | Valid Accuracy: 0.5719
Epoch: 3 | Train Loss: 2.1706 | Train Accuracy: 0.4639 | Valid Loss:
0.9089 | Valid Accuracy: 0.6250
Epoch: 4 | Train Loss: 1.4060 | Train Accuracy: 0.4812 | Valid Loss:
1.2037 | Valid Accuracy: 0.4719
Epoch: 5 | Train Loss: 1.3996 | Train Accuracy: 0.4396 | Valid Loss:
0.9099 | Valid Accuracy: 0.6562
Epoch: 6 | Train Loss: 1.3009 | Train Accuracy: 0.4958 | Valid Loss:
0.8278 | Valid Accuracy: 0.6781
Epoch: 7 | Train Loss: 1.2410 | Train Accuracy: 0.4917 | Valid Loss:
0.9385 | Valid Accuracy: 0.5750
Epoch: 8 | Train Loss: 1.3735 | Train Accuracy: 0.4486 | Valid Loss:
0.9194 | Valid Accuracy: 0.6156
Epoch: 9 | Train Loss: 1.2863 | Train Accuracy: 0.4778 | Valid Loss:
0.8327 | Valid Accuracy: 0.6531
Epoch: 10 | Train Loss: 1.1629 | Train Accuracy: 0.5410 | Valid Loss:
1.0235 | Valid Accuracy: 0.5437
Epoch: 11 | Train Loss: 1.1892 | Train Accuracy: 0.5236 | Valid Loss:
0.8788 | Valid Accuracy: 0.6625
Epoch: 12 | Train Loss: 1.0551 | Train Accuracy: 0.5604 | Valid Loss:
0.7719 | Valid Accuracy: 0.6375
Epoch: 13 | Train Loss: 1.2097 | Train Accuracy: 0.5688 | Valid Loss:
1.0449 | Valid Accuracy: 0.6469
Epoch: 14 | Train Loss: 1.1190 | Train Accuracy: 0.5292 | Valid Loss:
0.8246 | Valid Accuracy: 0.6625
Epoch: 15 | Train Loss: 1.0254 | Train Accuracy: 0.6035 | Valid Loss:
0.8358 | Valid Accuracy: 0.6562
Epoch: 16 | Train Loss: 1.2347 | Train Accuracy: 0.5604 | Valid Loss:
0.8857 | Valid Accuracy: 0.6156
Epoch: 17 | Train Loss: 1.1875 | Train Accuracy: 0.6069 | Valid Loss:
1.0164 | Valid Accuracy: 0.5656
Epoch: 18 | Train Loss: 1.0494 | Train Accuracy: 0.5701 | Valid Loss:
0.8972 | Valid Accuracy: 0.6438
Epoch: 19 | Train Loss: 0.9590 | Train Accuracy: 0.6292 | Valid Loss:
0.8744 | Valid Accuracy: 0.7094
Epoch: 20 | Train Loss: 1.0713 | Train Accuracy: 0.5681 | Valid Loss:
0.8256 | Valid Accuracy: 0.5437
Epoch: 21 | Train Loss: 1.0110 | Train Accuracy: 0.6278 | Valid Loss:
0.9490 | Valid Accuracy: 0.7469
Epoch: 22 | Train Loss: 1.0295 | Train Accuracy: 0.5958 | Valid Loss:
1.0519 | Valid Accuracy: 0.6281
Epoch: 23 | Train Loss: 0.9566 | Train Accuracy: 0.6187 | Valid Loss:
0.7727 | Valid Accuracy: 0.7094
Epoch: 24 | Train Loss: 0.9212 | Train Accuracy: 0.6556 | Valid Loss:
0.7588 | Valid Accuracy: 0.7875
Epoch: 25 | Train Loss: 0.9498 | Train Accuracy: 0.6465 | Valid Loss:
1.0597 | Valid Accuracy: 0.7406
Epoch: 26 | Train Loss: 1.0937 | Train Accuracy: 0.5653 | Valid Loss:
0.8103 | Valid Accuracy: 0.6000
Epoch: 27 | Train Loss: 0.9567 | Train Accuracy: 0.6500 | Valid Loss:
0.8138 | Valid Accuracy: 0.7500
Epoch: 28 | Train Loss: 0.9659 | Train Accuracy: 0.6326 | Valid Loss:
0.9784 | Valid Accuracy: 0.7094
Epoch: 29 | Train Loss: 0.9660 | Train Accuracy: 0.6299 | Valid Loss:
0.8719 | Valid Accuracy: 0.6625
Epoch: 30 | Train Loss: 0.8980 | Train Accuracy: 0.6486 | Valid Loss:
1.2152 | Valid Accuracy: 0.5531
Epoch: 31 | Train Loss: 0.9433 | Train Accuracy: 0.6201 | Valid Loss:
0.8151 | Valid Accuracy: 0.7250
Epoch: 32 | Train Loss: 0.9149 | Train Accuracy: 0.6639 | Valid Loss:
0.8699 | Valid Accuracy: 0.7188
Epoch: 33 | Train Loss: 0.9024 | Train Accuracy: 0.6778 | Valid Loss:
1.0495 | Valid Accuracy: 0.6531
Epoch: 34 | Train Loss: 0.9078 | Train Accuracy: 0.6750 | Valid Loss:
0.7348 | Valid Accuracy: 0.7406
Epoch: 35 | Train Loss: 0.8663 | Train Accuracy: 0.6750 | Valid Loss:
0.9129 | Valid Accuracy: 0.6656
Epoch: 36 | Train Loss: 0.7986 | Train Accuracy: 0.6847 | Valid Loss:
0.8336 | Valid Accuracy: 0.7344
Epoch: 37 | Train Loss: 0.7425 | Train Accuracy: 0.7444 | Valid Loss:
1.0626 | Valid Accuracy: 0.7344
Epoch: 38 | Train Loss: 0.7371 | Train Accuracy: 0.7563 | Valid Loss:
1.1364 | Valid Accuracy: 0.7000
Epoch: 39 | Train Loss: 0.6272 | Train Accuracy: 0.7563 | Valid Loss:
1.1371 | Valid Accuracy: 0.7625
Epoch: 40 | Train Loss: 0.7429 | Train Accuracy: 0.7604 | Valid Loss:
1.2168 | Valid Accuracy: 0.6406
Epoch: 41 | Train Loss: 0.7696 | Train Accuracy: 0.7229 | Valid Loss:
1.0839 | Valid Accuracy: 0.6562
Epoch: 42 | Train Loss: 0.8602 | Train Accuracy: 0.6792 | Valid Loss:
0.8539 | Valid Accuracy: 0.7156
Epoch: 43 | Train Loss: 0.6384 | Train Accuracy: 0.7549 | Valid Loss:
0.7839 | Valid Accuracy: 0.7312
Epoch: 44 | Train Loss: 0.6205 | Train Accuracy: 0.7861 | Valid Loss:
0.7532 | Valid Accuracy: 0.8344
Epoch: 45 | Train Loss: 0.6115 | Train Accuracy: 0.7854 | Valid Loss:
0.7032 | Valid Accuracy: 0.8031
Epoch: 46 | Train Loss: 0.6008 | Train Accuracy: 0.7931 | Valid Loss:
0.7309 | Valid Accuracy: 0.7406
Epoch: 47 | Train Loss: 0.4866 | Train Accuracy: 0.8153 | Valid Loss:
0.6615 | Valid Accuracy: 0.7625
Epoch: 48 | Train Loss: 0.5318 | Train Accuracy: 0.8160 | Valid Loss:
0.9431 | Valid Accuracy: 0.7781
Epoch: 49 | Train Loss: 0.6761 | Train Accuracy: 0.7507 | Valid Loss:
0.9559 | Valid Accuracy: 0.7875
Epoch: 50 | Train Loss: 0.4549 | Train Accuracy: 0.8361 | Valid Loss:
0.8313 | Valid Accuracy: 0.7875
Epoch: 51 | Train Loss: 0.6808 | Train Accuracy: 0.7847 | Valid Loss:
0.7034 | Valid Accuracy: 0.7969
Epoch: 52 | Train Loss: 0.5575 | Train Accuracy: 0.8035 | Valid Loss:
0.7933 | Valid Accuracy: 0.8281
Epoch: 53 | Train Loss: 0.5371 | Train Accuracy: 0.8160 | Valid Loss:
0.9302 | Valid Accuracy: 0.7344
Epoch: 54 | Train Loss: 0.4785 | Train Accuracy: 0.8382 | Valid Loss:
1.2874 | Valid Accuracy: 0.6813
Epoch: 55 | Train Loss: 0.4938 | Train Accuracy: 0.8208 | Valid Loss:
0.5556 | Valid Accuracy: 0.8594
Epoch: 56 | Train Loss: 0.5929 | Train Accuracy: 0.8000 | Valid Loss:
0.8931 | Valid Accuracy: 0.7500
Epoch: 57 | Train Loss: 0.4961 | Train Accuracy: 0.8347 | Valid Loss:
0.8337 | Valid Accuracy: 0.7719
Epoch: 58 | Train Loss: 0.5183 | Train Accuracy: 0.8000 | Valid Loss:
1.0412 | Valid Accuracy: 0.7875
Epoch: 59 | Train Loss: 0.4300 | Train Accuracy: 0.8729 | Valid Loss:
0.8241 | Valid Accuracy: 0.7562
Epoch: 60 | Train Loss: 0.4895 | Train Accuracy: 0.8764 | Valid Loss:
0.8840 | Valid Accuracy: 0.7469
Epoch: 61 | Train Loss: 0.2679 | Train Accuracy: 0.9306 | Valid Loss:
0.9990 | Valid Accuracy: 0.7469
Epoch: 62 | Train Loss: 0.3059 | Train Accuracy: 0.8889 | Valid Loss:
1.7261 | Valid Accuracy: 0.6438
Epoch: 63 | Train Loss: 0.4582 | Train Accuracy: 0.8799 | Valid Loss:
0.6878 | Valid Accuracy: 0.7781
Epoch: 64 | Train Loss: 0.4261 | Train Accuracy: 0.8472 | Valid Loss:
0.6295 | Valid Accuracy: 0.7719
Epoch: 65 | Train Loss: 0.4150 | Train Accuracy: 0.8833 | Valid Loss:
0.7357 | Valid Accuracy: 0.8031
Epoch: 66 | Train Loss: 0.4510 | Train Accuracy: 0.8576 | Valid Loss:
0.6470 | Valid Accuracy: 0.8281
Epoch: 67 | Train Loss: 0.4317 | Train Accuracy: 0.8729 | Valid Loss:
0.5838 | Valid Accuracy: 0.8438
Epoch: 68 | Train Loss: 0.3381 | Train Accuracy: 0.8854 | Valid Loss:
0.8505 | Valid Accuracy: 0.7937
Epoch: 69 | Train Loss: 0.3429 | Train Accuracy: 0.8674 | Valid Loss:
0.7819 | Valid Accuracy: 0.8344
Epoch: 70 | Train Loss: 0.2105 | Train Accuracy: 0.9285 | Valid Loss:
0.9042 | Valid Accuracy: 0.8031
Epoch: 71 | Train Loss: 0.3359 | Train Accuracy: 0.9201 | Valid Loss:
1.2436 | Valid Accuracy: 0.7031
Epoch: 72 | Train Loss: 0.2521 | Train Accuracy: 0.9062 | Valid Loss:
1.0007 | Valid Accuracy: 0.7625
Epoch: 73 | Train Loss: 0.3432 | Train Accuracy: 0.8958 | Valid Loss:
1.1621 | Valid Accuracy: 0.7625
Epoch: 74 | Train Loss: 0.2437 | Train Accuracy: 0.9201 | Valid Loss:
1.0118 | Valid Accuracy: 0.7781
Epoch: 75 | Train Loss: 0.2876 | Train Accuracy: 0.9306 | Valid Loss:
1.6021 | Valid Accuracy: 0.7375
Epoch: 76 | Train Loss: 0.2014 | Train Accuracy: 0.9201 | Valid Loss:
1.1883 | Valid Accuracy: 0.8094
Epoch: 77 | Train Loss: 0.1693 | Train Accuracy: 0.9306 | Valid Loss:
0.9617 | Valid Accuracy: 0.8281
Epoch: 78 | Train Loss: 0.3452 | Train Accuracy: 0.8958 | Valid Loss:
1.0942 | Valid Accuracy: 0.7812
Epoch: 79 | Train Loss: 0.4686 | Train Accuracy: 0.8708 | Valid Loss:
1.1179 | Valid Accuracy: 0.7656
Epoch: 80 | Train Loss: 0.3303 | Train Accuracy: 0.9097 | Valid Loss:
0.6799 | Valid Accuracy: 0.8187
Epoch: 81 | Train Loss: 0.1714 | Train Accuracy: 0.9410 | Valid Loss:
0.9971 | Valid Accuracy: 0.7562
Epoch: 82 | Train Loss: 0.2425 | Train Accuracy: 0.9236 | Valid Loss:
0.8817 | Valid Accuracy: 0.7812
Epoch: 83 | Train Loss: 0.3929 | Train Accuracy: 0.8889 | Valid Loss:
0.8224 | Valid Accuracy: 0.8281
Epoch: 84 | Train Loss: 0.3475 | Train Accuracy: 0.9028 | Valid Loss:
0.9001 | Valid Accuracy: 0.7937
Epoch: 85 | Train Loss: 0.4059 | Train Accuracy: 0.9007 | Valid Loss:
0.9966 | Valid Accuracy: 0.8344
Epoch: 86 | Train Loss: 0.3762 | Train Accuracy: 0.8681 | Valid Loss:
1.2866 | Valid Accuracy: 0.6937
Epoch: 87 | Train Loss: 0.1977 | Train Accuracy: 0.9340 | Valid Loss:
1.3225 | Valid Accuracy: 0.7562
Epoch: 88 | Train Loss: 0.3232 | Train Accuracy: 0.9236 | Valid Loss:
1.1568 | Valid Accuracy: 0.8031
Epoch: 89 | Train Loss: 0.2614 | Train Accuracy: 0.9146 | Valid Loss:
0.7791 | Valid Accuracy: 0.8031
Epoch: 90 | Train Loss: 0.2596 | Train Accuracy: 0.9250 | Valid Loss:
1.3653 | Valid Accuracy: 0.7312
Epoch: 91 | Train Loss: 0.2549 | Train Accuracy: 0.9306 | Valid Loss:
0.7809 | Valid Accuracy: 0.8438
Epoch: 92 | Train Loss: 0.1772 | Train Accuracy: 0.9562 | Valid Loss:
1.0504 | Valid Accuracy: 0.8656
Epoch: 93 | Train Loss: 0.1642 | Train Accuracy: 0.9549 | Valid Loss:
1.0253 | Valid Accuracy: 0.8187
Epoch: 94 | Train Loss: 0.2157 | Train Accuracy: 0.9340 | Valid Loss:
1.4641 | Valid Accuracy: 0.8094
Epoch: 95 | Train Loss: 0.2038 | Train Accuracy: 0.9424 | Valid Loss:
0.9025 | Valid Accuracy: 0.8438
Epoch: 96 | Train Loss: 0.1876 | Train Accuracy: 0.9479 | Valid Loss:
0.7463 | Valid Accuracy: 0.8344
Epoch: 97 | Train Loss: 0.1228 | Train Accuracy: 0.9410 | Valid Loss:
0.8377 | Valid Accuracy: 0.7875
Epoch: 98 | Train Loss: 0.1539 | Train Accuracy: 0.9597 | Valid Loss:
0.9082 | Valid Accuracy: 0.8500
Epoch: 99 | Train Loss: 0.0907 | Train Accuracy: 0.9688 | Valid Loss:
1.4059 | Valid Accuracy: 0.7531
Epoch: 100 | Train Loss: 0.1717 | Train Accuracy: 0.9597 | Valid Loss:
1.0781 | Valid Accuracy: 0.7688
{"model_id":"d1e86ab2cc074314b9cf63fce9314e88","version_major":2,"vers
ion_minor":0}
ResNet50V2 Test Accuracy = 0.9032
{"model_id":"caa2e57f58bb4cc2bfedf6effcb7930b","version_major":2,"vers
ion_minor":0}
Custom CNN Test Accuracy = 0.629
from sklearn.metrics import accuracy_score, precision_score,
recall_score, f1_score, classification_report, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns
# Convert ground truth labels and model predictions to numpy arrays
true_labels = df_test["label"].map(label_map).values
# ----------------------------- ResNet50V2 Evaluation
-----------------------------
resnet_pred = resnet_preds.numpy()
print("ResNet50V2 Evaluation Metrics:")
accuracy_resnet = accuracy_score(true_labels, resnet_pred)
precision_resnet = precision_score(true_labels, resnet_pred,
average="macro")
recall_resnet = recall_score(true_labels, resnet_pred,
average="macro")
f1_resnet = f1_score(true_labels, resnet_pred, average="macro")
print(f"Accuracy: {accuracy_resnet:.4f}")
print(f"Precision: {precision_resnet:.4f}")
print(f"Recall: {recall_resnet:.4f}")
print(f"F1 Score: {f1_resnet:.4f}")
print("\nClassification Report:")
print(classification_report(true_labels, resnet_pred,
target_names=classes))
cm_resnet = confusion_matrix(true_labels, resnet_pred)
plt.figure(figsize=(10, 4.5))
sns.heatmap(cm_resnet, cmap="Blues", annot=True,
annot_kws={"fontsize":9, "fontweight":"bold"},
linewidths=1.2, fmt="d", linecolor="white", square=True,
xticklabels=classes, yticklabels=classes, cbar=False)
plt.title("ResNet50V2 Confusion Matrix", fontsize=15,
fontweight="bold", color="darkblue")
plt.xlabel("Predicted Classes", fontsize=12, fontweight="bold",
color="black")
plt.ylabel("True Classes", fontsize=12, fontweight="bold",
color="black")
plt.xticks(rotation=90)
plt.tight_layout()
plt.show()
# ----------------------------- Custom CNN Evaluation
-----------------------------
cnn_pred = cnn_preds.numpy()
print("Custom CNN Evaluation Metrics:")
accuracy_cnn = accuracy_score(true_labels, cnn_pred)
precision_cnn = precision_score(true_labels, cnn_pred,
average="macro")
recall_cnn = recall_score(true_labels, cnn_pred, average="macro")
f1_cnn = f1_score(true_labels, cnn_pred, average="macro")
print(f"Accuracy: {accuracy_cnn:.4f}")
print(f"Precision: {precision_cnn:.4f}")
print(f"Recall: {recall_cnn:.4f}")
print(f"F1 Score: {f1_cnn:.4f}")
print("\nClassification Report:")
print(classification_report(true_labels, cnn_pred,
target_names=classes))
cm_cnn = confusion_matrix(true_labels, cnn_pred)
plt.figure(figsize=(10, 4.5))
sns.heatmap(cm_cnn, cmap="Blues", annot=True, annot_kws={"fontsize":9,
"fontweight":"bold"},
linewidths=1.2, fmt="d", linecolor="white", square=True,
xticklabels=classes, yticklabels=classes, cbar=False)
plt.title("Custom CNN Confusion Matrix", fontsize=15,
fontweight="bold", color="darkblue")
plt.xlabel("Predicted Classes", fontsize=12, fontweight="bold",
color="black")
plt.ylabel("True Classes", fontsize=12, fontweight="bold",
color="black")
plt.xticks(rotation=90)
plt.tight_layout()
plt.show()
ResNet50V2 Evaluation Metrics:
Accuracy: 0.9032
Precision: 0.8813
Recall: 0.9144
F1 Score: 0.8923
Classification Report:
precision recall f1-score
support
Banana Black Sigatoka Disease 0.88 0.70 0.78
10
Banana Bract Mosaic Virus Disease 0.89 1.00 0.94
8
Banana Healthy Leaf 1.00 1.00 1.00
13
Banana Insect Pest Disease 0.92 0.92 0.92
13
Banana Moko Disease 0.88 0.78 0.82
9
Banana Panama Disease 0.86 1.00 0.92
6
Banana Yellow Sigatoka Disease 0.75 1.00 0.86
3
accuracy 0.90
62
macro avg 0.88 0.91 0.89
62
weighted avg 0.91 0.90 0.90
62
Custom CNN Evaluation Metrics:
Accuracy: 0.6290
Precision: 0.6514
Recall: 0.6237
F1 Score: 0.6073
Classification Report:
precision recall f1-score
support
Banana Black Sigatoka Disease 0.43 0.30 0.35
10
Banana Bract Mosaic Virus Disease 0.40 0.75 0.52
8
Banana Healthy Leaf 0.76 1.00 0.87
13
Banana Insect Pest Disease 1.00 0.54 0.70
13
Banana Moko Disease 0.80 0.44 0.57
9
Banana Panama Disease 0.50 0.67 0.57
6
Banana Yellow Sigatoka Disease 0.67 0.67 0.67
3
accuracy 0.63
62
macro avg 0.65 0.62 0.61
62
weighted avg 0.69 0.63 0.62
62