Deep Learning Models -- A collection of various deep learning architectures, models, and tips for TensorFlow and PyTorch in Jupyter Notebooks.
%load_ext watermark
%watermark -a 'Sebastian Raschka' -v -p torch
Sebastian Raschka CPython 3.7.3 IPython 7.9.0 torch 1.4.0
Implementation of the VGG-16 [1] architecture for training a dogs vs cats classifier.
References
import time
import os
import numpy as np
import torch
import torch.nn.functional as F
import torch.nn as nn
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
if torch.cuda.is_available():
torch.backends.cudnn.deterministic = True
%matplotlib inline
##########################
### SETTINGS
##########################
# Device
DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# Hyperparameters
RANDOM_SEED = 1
LEARNING_RATE = 0.001
NUM_EPOCHS = 50
BATCH_SIZE = 128
# Architecture
NUM_CLASSES = 2
Download the Kaggle Cats and Dogs Dataset from https://www.kaggle.com/c/dogs-vs-cats/data by clicking on the "Download All" link:
Then, unzip the dataset.
The dataset folder consists of two subfolders, train
, and test1
, which contain the training and test images in jpg format, respectively. Note that the test set examples are unlabeled.
import os
num_train_cats = len([i for i in os.listdir(os.path.join('dogs-vs-cats', 'train'))
if i.endswith('.jpg') and i.startswith('cat')])
num_train_dogs = len([i for i in os.listdir(os.path.join('dogs-vs-cats', 'train'))
if i.endswith('.jpg') and i.startswith('dog')])
print(f'Training set cats: {num_train_cats}')
print(f'Training set dogs: {num_train_dogs}')
The naming scheme within each of these subfolders is <class>.<imagenumber>.jpg
.
img = Image.open(os.path.join('dogs-vs-cats','train', 'cat.59.jpg'))
print(np.asarray(img, dtype=np.uint8).shape)
plt.imshow(img);
(331, 464, 3)
if not os.path.exists(os.path.join('dogs-vs-cats', 'test')):
os.mkdir(os.path.join('dogs-vs-cats', 'test'))
if not os.path.exists(os.path.join('dogs-vs-cats', 'valid')):
os.mkdir(os.path.join('dogs-vs-cats', 'valid'))
for fname in os.listdir(os.path.join('dogs-vs-cats', 'train')):
if not fname.endswith('.jpg'):
continue
_, img_num, _ = fname.split('.')
filepath = os.path.join('dogs-vs-cats', 'train', fname)
img_num = int(img_num)
if img_num > 11249:
os.rename(filepath, filepath.replace('train', 'test'))
elif img_num > 9999:
os.rename(filepath, filepath.replace('train', 'valid'))
Getting mean and standard deviation for normalizing images via z-score normalization. For details, see the related notebook ./cnn-standardized.ipynb.
class CatsDogsDataset(Dataset):
"""Custom Dataset for loading CelebA face images"""
def __init__(self, img_dir, transform=None):
self.img_dir = img_dir
self.img_names = [i for i in
os.listdir(img_dir)
if i.endswith('.jpg')]
self.y = []
for i in self.img_names:
if i.split('.')[0] == 'cat':
self.y.append(0)
else:
self.y.append(1)
self.transform = transform
def __getitem__(self, index):
img = Image.open(os.path.join(self.img_dir,
self.img_names[index]))
if self.transform is not None:
img = self.transform(img)
label = self.y[index]
return img, label
def __len__(self):
return len(self.y)
custom_transform1 = transforms.Compose([transforms.Resize([64, 64]),
transforms.ToTensor()])
train_dataset = CatsDogsDataset(img_dir=os.path.join('dogs-vs-cats', 'train'),
transform=custom_transform1)
train_loader = DataLoader(dataset=train_dataset,
batch_size=5000,
shuffle=False)
train_mean = []
train_std = []
for i, image in enumerate(train_loader, 0):
numpy_image = image[0].numpy()
batch_mean = np.mean(numpy_image, axis=(0, 2, 3))
batch_std = np.std(numpy_image, axis=(0, 2, 3))
train_mean.append(batch_mean)
train_std.append(batch_std)
train_mean = torch.tensor(np.mean(train_mean, axis=0))
train_std = torch.tensor(np.mean(train_std, axis=0))
print('Mean:', train_mean)
print('Std Dev:', train_std)
Mean: tensor([0.4875, 0.4544, 0.4164]) Std Dev: tensor([0.2521, 0.2453, 0.2481])
data_transforms = {
'train': transforms.Compose([
transforms.RandomRotation(5),
transforms.RandomHorizontalFlip(),
transforms.RandomResizedCrop(64, scale=(0.96, 1.0), ratio=(0.95, 1.05)),
transforms.ToTensor(),
transforms.Normalize(train_mean, train_std)
]),
'valid': transforms.Compose([
transforms.Resize([64, 64]),
transforms.ToTensor(),
transforms.Normalize(train_mean, train_std)
]),
}
train_dataset = CatsDogsDataset(img_dir=os.path.join('dogs-vs-cats', 'train'),
transform=data_transforms['train'])
train_loader = DataLoader(dataset=train_dataset,
batch_size=BATCH_SIZE,
drop_last=True,
shuffle=True)
valid_dataset = CatsDogsDataset(img_dir=os.path.join('dogs-vs-cats', 'valid'),
transform=data_transforms['valid'])
valid_loader = DataLoader(dataset=valid_dataset,
batch_size=BATCH_SIZE,
shuffle=False)
test_dataset = CatsDogsDataset(img_dir=os.path.join('dogs-vs-cats', 'test'),
transform=data_transforms['valid'])
test_loader = DataLoader(dataset=test_dataset,
batch_size=BATCH_SIZE,
shuffle=False)
Import VGG16 network from ./vgg16.py
from vgg16 import VGG16
torch.manual_seed(RANDOM_SEED)
model = VGG16(num_classes=NUM_CLASSES)
model = model.to(DEVICE)
optimizer = torch.optim.Adam(model.parameters(), lr=LEARNING_RATE)
def compute_accuracy_and_loss(model, data_loader, device):
correct_pred, num_examples = 0, 0
cross_entropy = 0.
for i, (features, targets) in enumerate(data_loader):
features = features.to(device)
targets = targets.to(device)
logits, probas = model(features)
cross_entropy += F.cross_entropy(logits, targets).item()
_, predicted_labels = torch.max(probas, 1)
num_examples += targets.size(0)
correct_pred += (predicted_labels == targets).sum()
return correct_pred.float()/num_examples * 100, cross_entropy/num_examples
start_time = time.time()
train_acc_lst, valid_acc_lst = [], []
train_loss_lst, valid_loss_lst = [], []
for epoch in range(NUM_EPOCHS):
model.train()
for batch_idx, (features, targets) in enumerate(train_loader):
### PREPARE MINIBATCH
features = features.to(DEVICE)
targets = targets.to(DEVICE)
### FORWARD AND BACK PROP
logits, probas = model(features)
cost = F.cross_entropy(logits, targets)
optimizer.zero_grad()
cost.backward()
### UPDATE MODEL PARAMETERS
optimizer.step()
### LOGGING
if not batch_idx % 50:
print (f'Epoch: {epoch+1:03d}/{NUM_EPOCHS:03d} | '
f'Batch {batch_idx:03d}/{len(train_loader):03d} | '
f'Cost: {cost:.4f}')
model.eval()
# no need to build the computation graph for backprop when computing accuracy
with torch.set_grad_enabled(False):
train_acc, train_loss = compute_accuracy_and_loss(model, train_loader, device=DEVICE)
valid_acc, valid_loss = compute_accuracy_and_loss(model, valid_loader, device=DEVICE)
train_acc_lst.append(train_acc)
valid_acc_lst.append(valid_acc)
train_loss_lst.append(train_loss)
valid_loss_lst.append(valid_loss)
print(f'Epoch: {epoch+1:03d}/{NUM_EPOCHS:03d} Train Acc.: {train_acc:.2f}%'
f' | Validation Acc.: {valid_acc:.2f}%')
elapsed = (time.time() - start_time)/60
print(f'Time elapsed: {elapsed:.2f} min')
elapsed = (time.time() - start_time)/60
print(f'Total Training Time: {elapsed:.2f} min')
Epoch: 001/050 | Batch 000/156 | Cost: 1727.7655 Epoch: 001/050 | Batch 050/156 | Cost: 0.6774 Epoch: 001/050 | Batch 100/156 | Cost: 0.7066 Epoch: 001/050 | Batch 150/156 | Cost: 0.6459 Epoch: 001/050 Train Acc.: 59.83% | Validation Acc.: 59.92% Time elapsed: 3.06 min Epoch: 002/050 | Batch 000/156 | Cost: 0.6448 Epoch: 002/050 | Batch 050/156 | Cost: 0.6621 Epoch: 002/050 | Batch 100/156 | Cost: 0.6263 Epoch: 002/050 | Batch 150/156 | Cost: 0.6378 Epoch: 002/050 Train Acc.: 59.50% | Validation Acc.: 58.40% Time elapsed: 6.12 min Epoch: 003/050 | Batch 000/156 | Cost: 0.6844 Epoch: 003/050 | Batch 050/156 | Cost: 0.6173 Epoch: 003/050 | Batch 100/156 | Cost: 0.6341 Epoch: 003/050 | Batch 150/156 | Cost: 0.7188 Epoch: 003/050 Train Acc.: 56.50% | Validation Acc.: 55.24% Time elapsed: 9.18 min Epoch: 004/050 | Batch 000/156 | Cost: 0.7111 Epoch: 004/050 | Batch 050/156 | Cost: 0.5603 Epoch: 004/050 | Batch 100/156 | Cost: 0.5831 Epoch: 004/050 | Batch 150/156 | Cost: 0.6363 Epoch: 004/050 Train Acc.: 65.92% | Validation Acc.: 63.88% Time elapsed: 12.25 min Epoch: 005/050 | Batch 000/156 | Cost: 0.6359 Epoch: 005/050 | Batch 050/156 | Cost: 0.6415 Epoch: 005/050 | Batch 100/156 | Cost: 0.6266 Epoch: 005/050 | Batch 150/156 | Cost: 0.5450 Epoch: 005/050 Train Acc.: 63.92% | Validation Acc.: 61.56% Time elapsed: 15.32 min Epoch: 006/050 | Batch 000/156 | Cost: 0.6179 Epoch: 006/050 | Batch 050/156 | Cost: 0.5856 Epoch: 006/050 | Batch 100/156 | Cost: 0.5835 Epoch: 006/050 | Batch 150/156 | Cost: 0.6508 Epoch: 006/050 Train Acc.: 70.94% | Validation Acc.: 69.96% Time elapsed: 18.39 min Epoch: 007/050 | Batch 000/156 | Cost: 0.5410 Epoch: 007/050 | Batch 050/156 | Cost: 0.5818 Epoch: 007/050 | Batch 100/156 | Cost: 0.5670 Epoch: 007/050 | Batch 150/156 | Cost: 0.5955 Epoch: 007/050 Train Acc.: 71.97% | Validation Acc.: 71.12% Time elapsed: 21.46 min Epoch: 008/050 | Batch 000/156 | Cost: 0.5975 Epoch: 008/050 | Batch 050/156 | Cost: 0.6182 Epoch: 008/050 | Batch 100/156 | Cost: 0.5443 Epoch: 008/050 | Batch 150/156 | Cost: 0.5944 Epoch: 008/050 Train Acc.: 72.21% | Validation Acc.: 70.16% Time elapsed: 24.53 min Epoch: 009/050 | Batch 000/156 | Cost: 0.5629 Epoch: 009/050 | Batch 050/156 | Cost: 0.4724 Epoch: 009/050 | Batch 100/156 | Cost: 0.5216 Epoch: 009/050 | Batch 150/156 | Cost: 0.5236 Epoch: 009/050 Train Acc.: 74.53% | Validation Acc.: 72.60% Time elapsed: 27.60 min Epoch: 010/050 | Batch 000/156 | Cost: 0.5199 Epoch: 010/050 | Batch 050/156 | Cost: 0.5202 Epoch: 010/050 | Batch 100/156 | Cost: 0.5996 Epoch: 010/050 | Batch 150/156 | Cost: 0.5339 Epoch: 010/050 Train Acc.: 75.15% | Validation Acc.: 72.72% Time elapsed: 30.67 min Epoch: 011/050 | Batch 000/156 | Cost: 0.5022 Epoch: 011/050 | Batch 050/156 | Cost: 0.5535 Epoch: 011/050 | Batch 100/156 | Cost: 0.5446 Epoch: 011/050 | Batch 150/156 | Cost: 0.5467 Epoch: 011/050 Train Acc.: 74.81% | Validation Acc.: 72.64% Time elapsed: 33.73 min Epoch: 012/050 | Batch 000/156 | Cost: 0.4835 Epoch: 012/050 | Batch 050/156 | Cost: 0.4539 Epoch: 012/050 | Batch 100/156 | Cost: 0.4471 Epoch: 012/050 | Batch 150/156 | Cost: 0.5040 Epoch: 012/050 Train Acc.: 76.45% | Validation Acc.: 74.52% Time elapsed: 36.79 min Epoch: 013/050 | Batch 000/156 | Cost: 0.5212 Epoch: 013/050 | Batch 050/156 | Cost: 0.5246 Epoch: 013/050 | Batch 100/156 | Cost: 0.4334 Epoch: 013/050 | Batch 150/156 | Cost: 0.5233 Epoch: 013/050 Train Acc.: 77.61% | Validation Acc.: 77.04% Time elapsed: 39.85 min Epoch: 014/050 | Batch 000/156 | Cost: 0.3797 Epoch: 014/050 | Batch 050/156 | Cost: 0.5047 Epoch: 014/050 | Batch 100/156 | Cost: 0.3412 Epoch: 014/050 | Batch 150/156 | Cost: 0.5275 Epoch: 014/050 Train Acc.: 75.56% | Validation Acc.: 73.60% Time elapsed: 42.91 min Epoch: 015/050 | Batch 000/156 | Cost: 0.4431 Epoch: 015/050 | Batch 050/156 | Cost: 0.4629 Epoch: 015/050 | Batch 100/156 | Cost: 0.5703 Epoch: 015/050 | Batch 150/156 | Cost: 0.5427 Epoch: 015/050 Train Acc.: 78.43% | Validation Acc.: 76.96% Time elapsed: 45.96 min Epoch: 016/050 | Batch 000/156 | Cost: 0.4002 Epoch: 016/050 | Batch 050/156 | Cost: 0.4861 Epoch: 016/050 | Batch 100/156 | Cost: 0.4794 Epoch: 016/050 | Batch 150/156 | Cost: 0.4092 Epoch: 016/050 Train Acc.: 80.07% | Validation Acc.: 76.68% Time elapsed: 49.01 min Epoch: 017/050 | Batch 000/156 | Cost: 0.4498 Epoch: 017/050 | Batch 050/156 | Cost: 0.4849 Epoch: 017/050 | Batch 100/156 | Cost: 0.4650 Epoch: 017/050 | Batch 150/156 | Cost: 0.4565 Epoch: 017/050 Train Acc.: 77.49% | Validation Acc.: 76.60% Time elapsed: 52.07 min Epoch: 018/050 | Batch 000/156 | Cost: 0.4497 Epoch: 018/050 | Batch 050/156 | Cost: 0.4175 Epoch: 018/050 | Batch 100/156 | Cost: 0.4593 Epoch: 018/050 | Batch 150/156 | Cost: 0.3724 Epoch: 018/050 Train Acc.: 81.77% | Validation Acc.: 79.08% Time elapsed: 55.12 min Epoch: 019/050 | Batch 000/156 | Cost: 0.4697 Epoch: 019/050 | Batch 050/156 | Cost: 0.4032 Epoch: 019/050 | Batch 100/156 | Cost: 0.4146 Epoch: 019/050 | Batch 150/156 | Cost: 0.4392 Epoch: 019/050 Train Acc.: 77.89% | Validation Acc.: 76.76% Time elapsed: 58.17 min Epoch: 020/050 | Batch 000/156 | Cost: 0.5338 Epoch: 020/050 | Batch 050/156 | Cost: 0.3582 Epoch: 020/050 | Batch 100/156 | Cost: 0.4026 Epoch: 020/050 | Batch 150/156 | Cost: 0.4269 Epoch: 020/050 Train Acc.: 83.10% | Validation Acc.: 78.72% Time elapsed: 61.22 min Epoch: 021/050 | Batch 000/156 | Cost: 0.3744 Epoch: 021/050 | Batch 050/156 | Cost: 0.3567 Epoch: 021/050 | Batch 100/156 | Cost: 0.4666 Epoch: 021/050 | Batch 150/156 | Cost: 0.4098 Epoch: 021/050 Train Acc.: 81.87% | Validation Acc.: 78.12% Time elapsed: 64.27 min Epoch: 022/050 | Batch 000/156 | Cost: 0.4135 Epoch: 022/050 | Batch 050/156 | Cost: 0.3833 Epoch: 022/050 | Batch 100/156 | Cost: 0.3784 Epoch: 022/050 | Batch 150/156 | Cost: 0.3799 Epoch: 022/050 Train Acc.: 84.50% | Validation Acc.: 80.68% Time elapsed: 67.32 min Epoch: 023/050 | Batch 000/156 | Cost: 0.3161 Epoch: 023/050 | Batch 050/156 | Cost: 0.3088 Epoch: 023/050 | Batch 100/156 | Cost: 0.3796 Epoch: 023/050 | Batch 150/156 | Cost: 0.4143 Epoch: 023/050 Train Acc.: 85.11% | Validation Acc.: 80.84% Time elapsed: 70.37 min Epoch: 024/050 | Batch 000/156 | Cost: 0.2650 Epoch: 024/050 | Batch 050/156 | Cost: 0.3859 Epoch: 024/050 | Batch 100/156 | Cost: 0.2968 Epoch: 024/050 | Batch 150/156 | Cost: 0.2736 Epoch: 024/050 Train Acc.: 81.17% | Validation Acc.: 78.52% Time elapsed: 73.43 min Epoch: 025/050 | Batch 000/156 | Cost: 0.3956 Epoch: 025/050 | Batch 050/156 | Cost: 0.3541 Epoch: 025/050 | Batch 100/156 | Cost: 0.4375 Epoch: 025/050 | Batch 150/156 | Cost: 0.2759 Epoch: 025/050 Train Acc.: 83.86% | Validation Acc.: 81.00% Time elapsed: 76.48 min Epoch: 026/050 | Batch 000/156 | Cost: 0.2795 Epoch: 026/050 | Batch 050/156 | Cost: 0.2920 Epoch: 026/050 | Batch 100/156 | Cost: 0.3900 Epoch: 026/050 | Batch 150/156 | Cost: 0.2707 Epoch: 026/050 Train Acc.: 85.78% | Validation Acc.: 82.36% Time elapsed: 79.53 min Epoch: 027/050 | Batch 000/156 | Cost: 0.3185 Epoch: 027/050 | Batch 050/156 | Cost: 0.3466 Epoch: 027/050 | Batch 100/156 | Cost: 0.3422 Epoch: 027/050 | Batch 150/156 | Cost: 0.3484 Epoch: 027/050 Train Acc.: 85.71% | Validation Acc.: 79.76% Time elapsed: 82.59 min Epoch: 028/050 | Batch 000/156 | Cost: 0.3090 Epoch: 028/050 | Batch 050/156 | Cost: 0.2154 Epoch: 028/050 | Batch 100/156 | Cost: 0.3072 Epoch: 028/050 | Batch 150/156 | Cost: 0.4001 Epoch: 028/050 Train Acc.: 87.43% | Validation Acc.: 81.84% Time elapsed: 85.64 min Epoch: 029/050 | Batch 000/156 | Cost: 0.2711 Epoch: 029/050 | Batch 050/156 | Cost: 0.3003 Epoch: 029/050 | Batch 100/156 | Cost: 0.3143 Epoch: 029/050 | Batch 150/156 | Cost: 0.3214 Epoch: 029/050 Train Acc.: 88.26% | Validation Acc.: 83.20% Time elapsed: 88.70 min Epoch: 030/050 | Batch 000/156 | Cost: 0.3127 Epoch: 030/050 | Batch 050/156 | Cost: 0.3753 Epoch: 030/050 | Batch 100/156 | Cost: 0.3862 Epoch: 030/050 | Batch 150/156 | Cost: 0.2996 Epoch: 030/050 Train Acc.: 87.50% | Validation Acc.: 81.84% Time elapsed: 91.75 min Epoch: 031/050 | Batch 000/156 | Cost: 0.3182 Epoch: 031/050 | Batch 050/156 | Cost: 0.4144 Epoch: 031/050 | Batch 100/156 | Cost: 0.3276 Epoch: 031/050 | Batch 150/156 | Cost: 0.3632 Epoch: 031/050 Train Acc.: 87.30% | Validation Acc.: 81.08% Time elapsed: 94.80 min Epoch: 032/050 | Batch 000/156 | Cost: 0.2978 Epoch: 032/050 | Batch 050/156 | Cost: 0.2111 Epoch: 032/050 | Batch 100/156 | Cost: 0.3425 Epoch: 032/050 | Batch 150/156 | Cost: 0.2541 Epoch: 032/050 Train Acc.: 90.57% | Validation Acc.: 83.76% Time elapsed: 97.86 min Epoch: 033/050 | Batch 000/156 | Cost: 0.2911 Epoch: 033/050 | Batch 050/156 | Cost: 0.2750 Epoch: 033/050 | Batch 100/156 | Cost: 0.2008 Epoch: 033/050 | Batch 150/156 | Cost: 0.3383 Epoch: 033/050 Train Acc.: 89.97% | Validation Acc.: 82.96% Time elapsed: 100.91 min Epoch: 034/050 | Batch 000/156 | Cost: 0.3060 Epoch: 034/050 | Batch 050/156 | Cost: 0.2994 Epoch: 034/050 | Batch 100/156 | Cost: 0.2081 Epoch: 034/050 | Batch 150/156 | Cost: 0.2108 Epoch: 034/050 Train Acc.: 89.55% | Validation Acc.: 84.60% Time elapsed: 103.96 min Epoch: 035/050 | Batch 000/156 | Cost: 0.1920 Epoch: 035/050 | Batch 050/156 | Cost: 0.2821 Epoch: 035/050 | Batch 100/156 | Cost: 0.1952 Epoch: 035/050 | Batch 150/156 | Cost: 0.3249 Epoch: 035/050 Train Acc.: 90.98% | Validation Acc.: 84.24% Time elapsed: 107.01 min Epoch: 036/050 | Batch 000/156 | Cost: 0.2395 Epoch: 036/050 | Batch 050/156 | Cost: 0.2236 Epoch: 036/050 | Batch 100/156 | Cost: 0.2483 Epoch: 036/050 | Batch 150/156 | Cost: 0.2277 Epoch: 036/050 Train Acc.: 91.48% | Validation Acc.: 84.68% Time elapsed: 110.07 min Epoch: 037/050 | Batch 000/156 | Cost: 0.1802 Epoch: 037/050 | Batch 050/156 | Cost: 0.2624 Epoch: 037/050 | Batch 100/156 | Cost: 0.2480 Epoch: 037/050 | Batch 150/156 | Cost: 0.1741 Epoch: 037/050 Train Acc.: 91.16% | Validation Acc.: 83.72% Time elapsed: 113.12 min Epoch: 038/050 | Batch 000/156 | Cost: 0.2866 Epoch: 038/050 | Batch 050/156 | Cost: 0.2406 Epoch: 038/050 | Batch 100/156 | Cost: 0.2619 Epoch: 038/050 | Batch 150/156 | Cost: 0.2000 Epoch: 038/050 Train Acc.: 90.77% | Validation Acc.: 84.60% Time elapsed: 116.17 min Epoch: 039/050 | Batch 000/156 | Cost: 0.3116 Epoch: 039/050 | Batch 050/156 | Cost: 0.1462 Epoch: 039/050 | Batch 100/156 | Cost: 0.2207 Epoch: 039/050 | Batch 150/156 | Cost: 0.2419 Epoch: 039/050 Train Acc.: 91.16% | Validation Acc.: 83.80% Time elapsed: 119.22 min Epoch: 040/050 | Batch 000/156 | Cost: 0.2156 Epoch: 040/050 | Batch 050/156 | Cost: 0.2678 Epoch: 040/050 | Batch 100/156 | Cost: 0.1621 Epoch: 040/050 | Batch 150/156 | Cost: 0.3015 Epoch: 040/050 Train Acc.: 88.14% | Validation Acc.: 82.24% Time elapsed: 122.27 min Epoch: 041/050 | Batch 000/156 | Cost: 0.1685 Epoch: 041/050 | Batch 050/156 | Cost: 0.1971 Epoch: 041/050 | Batch 100/156 | Cost: 0.2548 Epoch: 041/050 | Batch 150/156 | Cost: 0.2950 Epoch: 041/050 Train Acc.: 90.48% | Validation Acc.: 83.08% Time elapsed: 125.32 min Epoch: 042/050 | Batch 000/156 | Cost: 0.2016 Epoch: 042/050 | Batch 050/156 | Cost: 0.2426 Epoch: 042/050 | Batch 100/156 | Cost: 0.2076 Epoch: 042/050 | Batch 150/156 | Cost: 0.1772 Epoch: 042/050 Train Acc.: 91.74% | Validation Acc.: 84.12% Time elapsed: 128.37 min Epoch: 043/050 | Batch 000/156 | Cost: 0.1269 Epoch: 043/050 | Batch 050/156 | Cost: 0.1669 Epoch: 043/050 | Batch 100/156 | Cost: 0.1648 Epoch: 043/050 | Batch 150/156 | Cost: 0.2165 Epoch: 043/050 Train Acc.: 93.64% | Validation Acc.: 85.32% Time elapsed: 131.43 min Epoch: 044/050 | Batch 000/156 | Cost: 0.2369 Epoch: 044/050 | Batch 050/156 | Cost: 0.2574 Epoch: 044/050 | Batch 100/156 | Cost: 0.1919 Epoch: 044/050 | Batch 150/156 | Cost: 0.1777 Epoch: 044/050 Train Acc.: 92.69% | Validation Acc.: 83.48% Time elapsed: 134.48 min Epoch: 045/050 | Batch 000/156 | Cost: 0.2837 Epoch: 045/050 | Batch 050/156 | Cost: 0.1648 Epoch: 045/050 | Batch 100/156 | Cost: 0.1512 Epoch: 045/050 | Batch 150/156 | Cost: 0.1846 Epoch: 045/050 Train Acc.: 94.10% | Validation Acc.: 85.36% Time elapsed: 137.53 min Epoch: 046/050 | Batch 000/156 | Cost: 0.1351 Epoch: 046/050 | Batch 050/156 | Cost: 0.2147 Epoch: 046/050 | Batch 100/156 | Cost: 0.1124 Epoch: 046/050 | Batch 150/156 | Cost: 0.1358 Epoch: 046/050 Train Acc.: 93.64% | Validation Acc.: 85.88% Time elapsed: 140.59 min Epoch: 047/050 | Batch 000/156 | Cost: 0.1248 Epoch: 047/050 | Batch 050/156 | Cost: 0.2449 Epoch: 047/050 | Batch 100/156 | Cost: 0.1527 Epoch: 047/050 | Batch 150/156 | Cost: 0.1617 Epoch: 047/050 Train Acc.: 94.69% | Validation Acc.: 86.36% Time elapsed: 143.64 min Epoch: 048/050 | Batch 000/156 | Cost: 0.1091 Epoch: 048/050 | Batch 050/156 | Cost: 0.1122 Epoch: 048/050 | Batch 100/156 | Cost: 0.1509 Epoch: 048/050 | Batch 150/156 | Cost: 0.1535 Epoch: 048/050 Train Acc.: 94.14% | Validation Acc.: 85.56% Time elapsed: 146.69 min Epoch: 049/050 | Batch 000/156 | Cost: 0.1317 Epoch: 049/050 | Batch 050/156 | Cost: 0.2563 Epoch: 049/050 | Batch 100/156 | Cost: 0.1455 Epoch: 049/050 | Batch 150/156 | Cost: 0.2130 Epoch: 049/050 Train Acc.: 93.85% | Validation Acc.: 85.28% Time elapsed: 149.74 min Epoch: 050/050 | Batch 000/156 | Cost: 0.1183 Epoch: 050/050 | Batch 050/156 | Cost: 0.0974 Epoch: 050/050 | Batch 100/156 | Cost: 0.1229 Epoch: 050/050 | Batch 150/156 | Cost: 0.0915 Epoch: 050/050 Train Acc.: 94.01% | Validation Acc.: 85.12% Time elapsed: 152.79 min Total Training Time: 152.79 min
plt.plot(range(1, NUM_EPOCHS+1), train_loss_lst, label='Training loss')
plt.plot(range(1, NUM_EPOCHS+1), valid_loss_lst, label='Validation loss')
plt.legend(loc='upper right')
plt.ylabel('Cross entropy')
plt.xlabel('Epoch')
plt.show()
plt.plot(range(1, NUM_EPOCHS+1), train_acc_lst, label='Training accuracy')
plt.plot(range(1, NUM_EPOCHS+1), valid_acc_lst, label='Validation accuracy')
plt.legend(loc='upper left')
plt.ylabel('Cross entropy')
plt.xlabel('Epoch')
plt.show()
model.eval()
with torch.set_grad_enabled(False): # save memory during inference
test_acc, test_loss = compute_accuracy_and_loss(model, test_loader, DEVICE)
print(f'Test accuracy: {test_acc:.2f}%')
Test accuracy: 86.20%
class UnNormalize(object):
def __init__(self, mean, std):
self.mean = mean
self.std = std
def __call__(self, tensor):
"""
Args:
tensor (Tensor): Tensor image of size (C, H, W) to be normalized.
Returns:
Tensor: Normalized image.
"""
for t, m, s in zip(tensor, self.mean, self.std):
t.mul_(s).add_(m)
# The normalize code -> t.sub_(m).div_(s)
return tensor
unorm = UnNormalize(mean=train_mean, std=train_std)
test_loader = DataLoader(dataset=train_dataset,
batch_size=BATCH_SIZE,
shuffle=True)
for features, targets in test_loader:
break
_, predictions = model.forward(features[:8].to(DEVICE))
predictions = torch.argmax(predictions, dim=1)
d = {0: 'cat',
1: 'dog'}
fig, ax = plt.subplots(1, 8, figsize=(20, 10))
for i in range(8):
img = unorm(features[i])
ax[i].imshow(np.transpose(img, (1, 2, 0)))
ax[i].set_xlabel(d[predictions[i].item()])
plt.show()
torch.save(model.state_dict(), 'vgg16-cats-dogs.state_dict')