In [5]:
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader, random_split, SubsetRandomSampler
from tqdm import tqdm

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
In [6]:
transforms_train_modern = transforms.Compose([
    transforms.Pad(2),
    transforms.RandomRotation(10),
    transforms.RandomAffine(0, translate=(0.1, 0.1)),
    transforms.ToTensor(),
    transforms.Normalize(0.5, 0.5)
])

transforms_test_modern = transforms.Compose([
    transforms.Pad(2),
    transforms.ToTensor(),
    transforms.Normalize(0.5, 0.5)
])

train_dataset = datasets.FashionMNIST(root='./data', train=True, transform=transforms_train_modern, download=True)
test_dataset = datasets.FashionMNIST(root='./data', train=False, transform=transforms_test_modern, download=True)

train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True, num_workers=4, pin_memory=True, persistent_workers=True)
val_loader = DataLoader(test_dataset, batch_size=128, shuffle=False, num_workers=4, pin_memory=True, persistent_workers=True)
In [7]:
class LeNetModern(nn.Module):
  def __init__(self):
    super(LeNetModern, self).__init__()
    self.features = nn.Sequential(
        nn.Conv2d(1, 6, kernel_size=5, stride=1),
        nn.BatchNorm2d(6),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=2, stride=2),

        nn.Conv2d(6, 16, kernel_size=5, stride=1),
        nn.BatchNorm2d(16),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=2, stride=2)
    )

    self.classifier = nn.Sequential(
        nn.Linear(16 * 5 * 5, 120),
        nn.BatchNorm1d(120),
        nn.ReLU(),

        nn.Linear(120, 84),
        nn.BatchNorm1d(84),
        nn.ReLU(),

        nn.Linear(84, 10)
    )

    self._initialize_weights()

  def forward(self, x):
    x = self.features(x)
    x = torch.flatten(x, 1)
    x = self.classifier(x)
    return x

  def _initialize_weights(self):
    for m in self.modules():
      if isinstance(m, nn.Conv2d):
        nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
        if m.bias is not None:
          nn.init.constant_(m.bias, 0)
      if isinstance(m, nn.BatchNorm2d) or isinstance(m, nn.BatchNorm1d):
        nn.init.constant_(m.weight, 1)
        nn.init.constant_(m.bias, 0)
      if isinstance(m, nn.Linear):
        nn.init.kaiming_normal_(m.weight, mode="fan_out", nonlinearity='relu')
        if m.bias is not None:
          nn.init.constant_(m.bias, 0)
In [8]:
model = LeNetModern().to(device)

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5)

best_acc = 0
epochs = 50

for epoch in range(epochs):
  model.train()
  running_loss = 0.0
  correct = 0
  total = 0

  train_pbar = tqdm(train_loader, desc=f"Epoch {epoch+1}/{epochs} [Train]")
  for inputs, targets in train_pbar:
    inputs, targets = inputs.to(device), targets.to(device)
    optimizer.zero_grad()
    outputs = model(inputs)
    loss = criterion(outputs, targets)
    loss.backward()
    optimizer.step()

    running_loss += loss.item()
    _, predicted = outputs.max(1)
    total += targets.size(0)
    correct += predicted.eq(targets).sum().item()

    train_pbar.set_postfix(loss=running_loss/(total/targets.size(0)), acc=100.*correct/total)

  train_loss = running_loss / len(train_loader)
  train_acc = 100. * correct / total

  model.eval()
  val_loss = 0.0
  val_correct = 0
  val_total = 0

  with torch.no_grad():
    val_pbar = tqdm(val_loader, desc=f"Epoch {epoch+1}/{epochs} [Val]")
    for inputs, targets in val_pbar:
      inputs, targets = inputs.to(device), targets.to(device)
      outputs = model(inputs)
      loss = criterion(outputs, targets)

      val_loss += loss.item()
      _, predicted = outputs.max(1)
      val_total += targets.size(0)
      val_correct += predicted.eq(targets).sum().item()
      val_pbar.set_postfix(loss=val_loss/(val_total/targets.size(0)), acc=100.*val_correct/val_total)

  validation_loss = val_loss / len(val_loader)
  validation_acc = 100. * val_correct / val_total

  print(f"Epoch {epoch+1}/{epochs} | Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.2f}% | Val Loss: {validation_loss:.4f}, Val Acc: {validation_acc:.2f}%")

  scheduler.step()

  if validation_acc > best_acc:
    best_acc = validation_acc
    torch.save(model.state_dict(), 'best_lenet_classic_model.pth')
    print(f"New best model found! Accuracy: {best_acc:.2f}%. Saving model...")

print("\nTraining finished.")
print(f"Best validation accuracy: {best_acc:.2f}%")
Epoch 1/50 [Train]: 100%|██████████| 469/469 [00:07<00:00, 60.12it/s, acc=71.5, loss=0.615]
Epoch 1/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 89.18it/s, acc=80, loss=0.0665] 
Epoch 1/50 | Train Loss: 0.8200, Train Acc: 71.52% | Val Loss: 0.5262, Val Acc: 80.01%
New best model found! Accuracy: 80.01%. Saving model...
Epoch 2/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.48it/s, acc=79.8, loss=0.406]
Epoch 2/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 118.25it/s, acc=84.1, loss=0.0559]
Epoch 2/50 | Train Loss: 0.5413, Train Acc: 79.84% | Val Loss: 0.4419, Val Acc: 84.10%
New best model found! Accuracy: 84.10%. Saving model...
Epoch 3/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.22it/s, acc=82.2, loss=0.358]
Epoch 3/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 117.15it/s, acc=86, loss=0.049]
Epoch 3/50 | Train Loss: 0.4775, Train Acc: 82.21% | Val Loss: 0.3877, Val Acc: 86.02%
New best model found! Accuracy: 86.02%. Saving model...
Epoch 4/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.07it/s, acc=83.6, loss=0.331]
Epoch 4/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 114.84it/s, acc=86.3, loss=0.0465]
Epoch 4/50 | Train Loss: 0.4416, Train Acc: 83.58% | Val Loss: 0.3682, Val Acc: 86.34%
New best model found! Accuracy: 86.34%. Saving model...
Epoch 5/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.37it/s, acc=84.8, loss=0.307]
Epoch 5/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 107.97it/s, acc=86.3, loss=0.0463]
Epoch 5/50 | Train Loss: 0.4085, Train Acc: 84.82% | Val Loss: 0.3661, Val Acc: 86.29%
Epoch 6/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.50it/s, acc=85.6, loss=0.293]
Epoch 6/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 120.04it/s, acc=87.3, loss=0.0436]
Epoch 6/50 | Train Loss: 0.3899, Train Acc: 85.61% | Val Loss: 0.3452, Val Acc: 87.35%
New best model found! Accuracy: 87.35%. Saving model...
Epoch 7/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.00it/s, acc=85.9, loss=0.283]
Epoch 7/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 121.39it/s, acc=87, loss=0.0435]
Epoch 7/50 | Train Loss: 0.3768, Train Acc: 85.94% | Val Loss: 0.3439, Val Acc: 87.02%
Epoch 8/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 72.57it/s, acc=86.4, loss=0.274]
Epoch 8/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 119.42it/s, acc=88, loss=0.0418]
Epoch 8/50 | Train Loss: 0.3654, Train Acc: 86.37% | Val Loss: 0.3310, Val Acc: 87.98%
New best model found! Accuracy: 87.98%. Saving model...
Epoch 9/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 69.76it/s, acc=87, loss=0.265]
Epoch 9/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 113.91it/s, acc=88.5, loss=0.0395]
Epoch 9/50 | Train Loss: 0.3534, Train Acc: 87.00% | Val Loss: 0.3129, Val Acc: 88.52%
New best model found! Accuracy: 88.52%. Saving model...
Epoch 10/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.66it/s, acc=87.1, loss=0.262]
Epoch 10/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 114.13it/s, acc=88.5, loss=0.0403]
Epoch 10/50 | Train Loss: 0.3486, Train Acc: 87.08% | Val Loss: 0.3189, Val Acc: 88.46%
Epoch 11/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 72.05it/s, acc=87.9, loss=0.245]
Epoch 11/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 114.88it/s, acc=89, loss=0.0379]
Epoch 11/50 | Train Loss: 0.3268, Train Acc: 87.87% | Val Loss: 0.2997, Val Acc: 89.04%
New best model found! Accuracy: 89.04%. Saving model...
Epoch 12/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.00it/s, acc=88.1, loss=0.241]
Epoch 12/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 122.48it/s, acc=89, loss=0.0374]
Epoch 12/50 | Train Loss: 0.3208, Train Acc: 88.09% | Val Loss: 0.2955, Val Acc: 89.03%
Epoch 13/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.17it/s, acc=88.2, loss=0.236]
Epoch 13/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 103.93it/s, acc=89.5, loss=0.0361]
Epoch 13/50 | Train Loss: 0.3145, Train Acc: 88.20% | Val Loss: 0.2858, Val Acc: 89.53%
New best model found! Accuracy: 89.53%. Saving model...
Epoch 14/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 72.53it/s, acc=88.4, loss=0.235]
Epoch 14/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 115.88it/s, acc=89.3, loss=0.0367]
Epoch 14/50 | Train Loss: 0.3126, Train Acc: 88.43% | Val Loss: 0.2901, Val Acc: 89.33%
Epoch 15/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.08it/s, acc=88.5, loss=0.232]
Epoch 15/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 120.59it/s, acc=89.7, loss=0.0356]
Epoch 15/50 | Train Loss: 0.3094, Train Acc: 88.53% | Val Loss: 0.2814, Val Acc: 89.74%
New best model found! Accuracy: 89.74%. Saving model...
Epoch 16/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 72.52it/s, acc=88.7, loss=0.229]
Epoch 16/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 109.03it/s, acc=89.8, loss=0.0356]
Epoch 16/50 | Train Loss: 0.3056, Train Acc: 88.69% | Val Loss: 0.2814, Val Acc: 89.80%
New best model found! Accuracy: 89.80%. Saving model...
Epoch 17/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.55it/s, acc=88.5, loss=0.229]
Epoch 17/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 113.29it/s, acc=89.7, loss=0.036]
Epoch 17/50 | Train Loss: 0.3055, Train Acc: 88.50% | Val Loss: 0.2845, Val Acc: 89.69%
Epoch 18/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.58it/s, acc=88.8, loss=0.226]
Epoch 18/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 116.38it/s, acc=89.3, loss=0.0365]
Epoch 18/50 | Train Loss: 0.3011, Train Acc: 88.81% | Val Loss: 0.2885, Val Acc: 89.35%
Epoch 19/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.67it/s, acc=88.9, loss=0.225]
Epoch 19/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 116.84it/s, acc=90, loss=0.0349]
Epoch 19/50 | Train Loss: 0.3003, Train Acc: 88.92% | Val Loss: 0.2759, Val Acc: 89.98%
New best model found! Accuracy: 89.98%. Saving model...
Epoch 20/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.02it/s, acc=89.1, loss=0.222]
Epoch 20/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 115.69it/s, acc=90, loss=0.0348]
Epoch 20/50 | Train Loss: 0.2956, Train Acc: 89.06% | Val Loss: 0.2755, Val Acc: 89.99%
New best model found! Accuracy: 89.99%. Saving model...
Epoch 21/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.91it/s, acc=89.3, loss=0.216]
Epoch 21/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 116.15it/s, acc=90.4, loss=0.0343]
Epoch 21/50 | Train Loss: 0.2880, Train Acc: 89.32% | Val Loss: 0.2714, Val Acc: 90.37%
New best model found! Accuracy: 90.37%. Saving model...
Epoch 22/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.71it/s, acc=89.4, loss=0.214]
Epoch 22/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 119.09it/s, acc=90.2, loss=0.0341]
Epoch 22/50 | Train Loss: 0.2855, Train Acc: 89.42% | Val Loss: 0.2700, Val Acc: 90.18%
Epoch 23/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.86it/s, acc=89.5, loss=0.213]
Epoch 23/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 120.87it/s, acc=90.4, loss=0.0336]
Epoch 23/50 | Train Loss: 0.2836, Train Acc: 89.51% | Val Loss: 0.2660, Val Acc: 90.38%
New best model found! Accuracy: 90.38%. Saving model...
Epoch 24/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.36it/s, acc=89.5, loss=0.213]
Epoch 24/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 104.38it/s, acc=90.2, loss=0.0337]
Epoch 24/50 | Train Loss: 0.2841, Train Acc: 89.46% | Val Loss: 0.2664, Val Acc: 90.21%
Epoch 25/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.57it/s, acc=89.6, loss=0.212]
Epoch 25/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 114.26it/s, acc=90.4, loss=0.0336]
Epoch 25/50 | Train Loss: 0.2827, Train Acc: 89.58% | Val Loss: 0.2659, Val Acc: 90.40%
New best model found! Accuracy: 90.40%. Saving model...
Epoch 26/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.88it/s, acc=89.7, loss=0.211]
Epoch 26/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 118.66it/s, acc=90.6, loss=0.0332]
Epoch 26/50 | Train Loss: 0.2807, Train Acc: 89.66% | Val Loss: 0.2629, Val Acc: 90.63%
New best model found! Accuracy: 90.63%. Saving model...
Epoch 27/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 72.53it/s, acc=89.7, loss=0.209]
Epoch 27/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 113.37it/s, acc=90.4, loss=0.0336]
Epoch 27/50 | Train Loss: 0.2791, Train Acc: 89.73% | Val Loss: 0.2657, Val Acc: 90.44%
Epoch 28/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.28it/s, acc=89.8, loss=0.207]
Epoch 28/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 115.28it/s, acc=90.4, loss=0.0334]
Epoch 28/50 | Train Loss: 0.2762, Train Acc: 89.77% | Val Loss: 0.2645, Val Acc: 90.36%
Epoch 29/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.21it/s, acc=89.8, loss=0.207]
Epoch 29/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 116.09it/s, acc=90.5, loss=0.0333]
Epoch 29/50 | Train Loss: 0.2755, Train Acc: 89.78% | Val Loss: 0.2638, Val Acc: 90.48%
Epoch 30/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.96it/s, acc=89.9, loss=0.207]
Epoch 30/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 117.86it/s, acc=90.6, loss=0.033]
Epoch 30/50 | Train Loss: 0.2755, Train Acc: 89.88% | Val Loss: 0.2613, Val Acc: 90.60%
Epoch 31/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.94it/s, acc=90, loss=0.204]
Epoch 31/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 117.97it/s, acc=90.6, loss=0.0328]
Epoch 31/50 | Train Loss: 0.2716, Train Acc: 90.04% | Val Loss: 0.2597, Val Acc: 90.60%
Epoch 32/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 72.06it/s, acc=90, loss=0.203]
Epoch 32/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 116.69it/s, acc=90.7, loss=0.0328]
Epoch 32/50 | Train Loss: 0.2700, Train Acc: 89.96% | Val Loss: 0.2593, Val Acc: 90.67%
New best model found! Accuracy: 90.67%. Saving model...
Epoch 33/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.50it/s, acc=90, loss=0.202]
Epoch 33/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 114.42it/s, acc=90.8, loss=0.0325]
Epoch 33/50 | Train Loss: 0.2690, Train Acc: 90.05% | Val Loss: 0.2575, Val Acc: 90.75%
New best model found! Accuracy: 90.75%. Saving model...
Epoch 34/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.28it/s, acc=90.1, loss=0.201]
Epoch 34/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 111.94it/s, acc=90.6, loss=0.0324]
Epoch 34/50 | Train Loss: 0.2680, Train Acc: 90.06% | Val Loss: 0.2563, Val Acc: 90.57%
Epoch 35/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 72.09it/s, acc=90, loss=0.202]
Epoch 35/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 113.86it/s, acc=90.6, loss=0.0327]
Epoch 35/50 | Train Loss: 0.2693, Train Acc: 89.98% | Val Loss: 0.2586, Val Acc: 90.62%
Epoch 36/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.10it/s, acc=90.1, loss=0.199]
Epoch 36/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 118.96it/s, acc=90.8, loss=0.0323]
Epoch 36/50 | Train Loss: 0.2658, Train Acc: 90.12% | Val Loss: 0.2553, Val Acc: 90.83%
New best model found! Accuracy: 90.83%. Saving model...
Epoch 37/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.65it/s, acc=90.1, loss=0.201]
Epoch 37/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 120.15it/s, acc=90.7, loss=0.0325]
Epoch 37/50 | Train Loss: 0.2673, Train Acc: 90.12% | Val Loss: 0.2572, Val Acc: 90.65%
Epoch 38/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.12it/s, acc=90.3, loss=0.198]
Epoch 38/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 123.21it/s, acc=90.5, loss=0.0326]
Epoch 38/50 | Train Loss: 0.2632, Train Acc: 90.28% | Val Loss: 0.2577, Val Acc: 90.50%
Epoch 39/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.87it/s, acc=90.2, loss=0.199]
Epoch 39/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 120.59it/s, acc=90.9, loss=0.0321]
Epoch 39/50 | Train Loss: 0.2655, Train Acc: 90.20% | Val Loss: 0.2540, Val Acc: 90.86%
New best model found! Accuracy: 90.86%. Saving model...
Epoch 40/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.82it/s, acc=90.2, loss=0.199]
Epoch 40/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 112.87it/s, acc=90.7, loss=0.0322]
Epoch 40/50 | Train Loss: 0.2654, Train Acc: 90.16% | Val Loss: 0.2547, Val Acc: 90.71%
Epoch 41/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.59it/s, acc=90.2, loss=0.198]
Epoch 41/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 116.73it/s, acc=90.8, loss=0.0321]
Epoch 41/50 | Train Loss: 0.2640, Train Acc: 90.21% | Val Loss: 0.2537, Val Acc: 90.85%
Epoch 42/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 69.49it/s, acc=90.3, loss=0.197]
Epoch 42/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 115.74it/s, acc=90.8, loss=0.032]
Epoch 42/50 | Train Loss: 0.2626, Train Acc: 90.29% | Val Loss: 0.2530, Val Acc: 90.80%
Epoch 43/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.88it/s, acc=90.3, loss=0.196]
Epoch 43/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 103.44it/s, acc=90.9, loss=0.0319]
Epoch 43/50 | Train Loss: 0.2606, Train Acc: 90.27% | Val Loss: 0.2528, Val Acc: 90.93%
New best model found! Accuracy: 90.93%. Saving model...
Epoch 44/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.67it/s, acc=90.2, loss=0.197]
Epoch 44/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 118.36it/s, acc=91, loss=0.0317]
Epoch 44/50 | Train Loss: 0.2629, Train Acc: 90.24% | Val Loss: 0.2510, Val Acc: 91.04%
New best model found! Accuracy: 91.04%. Saving model...
Epoch 45/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.05it/s, acc=90.2, loss=0.197]
Epoch 45/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 111.92it/s, acc=91, loss=0.0319]
Epoch 45/50 | Train Loss: 0.2624, Train Acc: 90.19% | Val Loss: 0.2523, Val Acc: 90.95%
Epoch 46/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.47it/s, acc=90.4, loss=0.197]
Epoch 46/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 119.91it/s, acc=90.9, loss=0.0319]
Epoch 46/50 | Train Loss: 0.2625, Train Acc: 90.36% | Val Loss: 0.2524, Val Acc: 90.90%
Epoch 47/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.59it/s, acc=90.3, loss=0.198]
Epoch 47/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 121.28it/s, acc=90.8, loss=0.0319]
Epoch 47/50 | Train Loss: 0.2635, Train Acc: 90.25% | Val Loss: 0.2522, Val Acc: 90.85%
Epoch 48/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 70.17it/s, acc=90.3, loss=0.197]
Epoch 48/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 116.96it/s, acc=90.9, loss=0.0318]
Epoch 48/50 | Train Loss: 0.2627, Train Acc: 90.28% | Val Loss: 0.2518, Val Acc: 90.86%
Epoch 49/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.09it/s, acc=90.3, loss=0.196]
Epoch 49/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 117.50it/s, acc=90.7, loss=0.0321]
Epoch 49/50 | Train Loss: 0.2616, Train Acc: 90.32% | Val Loss: 0.2540, Val Acc: 90.65%
Epoch 50/50 [Train]: 100%|██████████| 469/469 [00:06<00:00, 71.28it/s, acc=90.2, loss=0.196]
Epoch 50/50 [Val]: 100%|██████████| 79/79 [00:00<00:00, 117.75it/s, acc=91, loss=0.0318]
Epoch 50/50 | Train Loss: 0.2614, Train Acc: 90.24% | Val Loss: 0.2519, Val Acc: 90.95%

Training finished.
Best validation accuracy: 91.04%