In this lecture:
- Convolutional neural networks (CNN)
- Attributes of convolutional layers (stride, padding, kernel size, etc.)
- Advantages of CNNs wrt #-parameters and spatial information within data
Recap of multi-layer perceptrons (MLPs)¶
Last time, we explored Multi-layer Perceptrons (MLP) as our first type of deep learning model. An MLP:
- takes an input vector $x\in\mathbb{R}^N$ and passes the input through a series of $K$ layers.
- Each layer is composed of multiplication with a weight matrix (affine transformation accounting for bias term) followed by an element-wise non-linear activation function.
Let $W_k$ denote the weight matrix at layer $k$ and $\sigma(z)$ be the element-wise non-linear activation function. We express any MLP $f(x)$ as
$$ f_\theta(x) = W_K\sigma(W_{K-1}\sigma(W_{K-2} \cdots W_2\sigma(W_1x))). $$$$ \theta = \{W_1, W_2, W_3, \ldots, W_K\} $$Thus, for a $K$-layer MLP, we have $K-1$ activation functions and we refer to each of these layers with an activation function as hidden layers. Each hidden layer has an output dimension that we may specify.
- first layer has matrix $W_1\in\mathbb{R}^{d_1\times N}$ that transforms the input vector from length $N$ to length $d_1$.
- these are the hidden layer dimensions, i.e. $d_1$, $d_2$, $\cdots$, $d_{K-1}$, as the width of each layer.
- Thus, we describe MLPs in terms of the depth (how many layers) and width.
The use of MLPs allowed us to learn more complex classifiers and thus more complex classification boundaries:
- separating data in the toy two moons dataset last lecture (using only 2 layers and a size 8 hidden layer!).
- We also saw simple MLPs achieve near perfect training accuracy on the more complicated FashionMNIST dataset with fairly strong validation accuracy (around 80% accuracy).
In this lecture, we want to improve upon the performance of these MLPs and introduce another popular deep neural network architecture. First, we will consider a motivating example below.
Below, we provide the implementation of the FashionMNIST dataset from the previous lecture as well as a "scrambled" version of this dataset. The scrambled version picks a random permutation to shuffle the pixels in the images of the FashionMNIST dataset to apply to all images, i.e. the pixels are shuffled randomly but in the exact same way for all images.
import torch
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import Dataset, DataLoader, SubsetRandomSampler
class FashionMNIST(Dataset):
def __init__(self):
self.data = torchvision.datasets.FashionMNIST(root='./',
download=True,
train=True,
transform=transforms.Compose([transforms.ToTensor()]))
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
image, label = self.data[idx]
return image.reshape(-1), label
class ScrambledFashionMNIST(Dataset):
def __init__(self):
self.data = torchvision.datasets.FashionMNIST(root='./',
download=True,
train=True,
transform=transforms.Compose([transforms.ToTensor()]))
self.permutation = torch.randperm(len(self.data[0][0].view(-1)))
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
image, label = self.data[idx]
# scramble the image
image = image.reshape(-1)
image = image[self.permutation]
return image, label
dataset = FashionMNIST()
scrambled_dataset = ScrambledFashionMNIST()
# visualize example images from both datasets
import matplotlib.pyplot as plt
idx = 365
image, label = dataset[idx]
scrambled_image, scrambled_label = scrambled_dataset[idx]
plt.figure(figsize=(10, 6))
plt.subplot(121)
plt.imshow(image.reshape(28, 28).numpy(), 'gray')
plt.axis(False)
plt.title('Image of class {}'.format(label))
plt.subplot(122)
plt.imshow(scrambled_image.reshape(28, 28).numpy(), 'gray')
plt.axis(False)
plt.title('Image of class {}'.format(scrambled_label))
Text(0.5, 1.0, 'Image of class 1')
Clearly, it is impossible for us as humans to discern what article of clothing each of the scrambled images represent. Still, let's see how a given simple MLP is able to perform the classification task presented by FashionMNIST in both the original and scrambled versions.
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import numpy as np
from tqdm import tqdm
class ThreeLayerMLP(nn.Module):
def __init__(self, input_dim, h1, h2, output_dim, activation_fn):
super().__init__()
self.fc1 = nn.Linear(input_dim, h1) # first fully-connected layer
self.fc2 = nn.Linear(h1, h2) # second fully-connected layer
self.fc3 = nn.Linear(h2, output_dim) # output layer
self.activation = activation_fn
def forward(self, x):
x = self.activation(self.fc1(x)) # first layer
x = self.activation(self.fc2(x)) # second layer
z = self.fc3(x) # output layer
return z
def training_loop(model, criterion, optimizer, n_epochs, train_loader, val_loader):
loss_values, train_accuracies, val_accuracies = [], [], []
for n in tqdm(range(n_epochs)):
epoch_loss, epoch_acc = 0, 0
for x_batch, y_batch in train_loader:
# zero out gradients
optimizer.zero_grad()
# pass batch to model
predictions = model(x_batch)
# calculate loss
loss = criterion(predictions, y_batch)
# backpropagate and update
loss.backward() # backprop
optimizer.step()
# logging to update epoch_loss (add loss value) and epoch_acc (add current batch accuracy)
epoch_loss += loss.item()
epoch_acc += multiclass_model_accuracy(model, x_batch, y_batch)
loss_values.append(epoch_loss/len(train_loader))
train_accuracies.append(epoch_acc/N_train)
# validation performance
val_acc = 0
for x_batch, y_batch in val_loader:
# don't compute gradients since we are only evaluating the model
with torch.no_grad():
# validation batch accuracy
val_acc += multiclass_model_accuracy(model, x_batch, y_batch)
val_accuracies.append(val_acc/N_val)
return model, loss_values, train_accuracies, val_accuracies
def multiclass_model_accuracy(model, input_data, labels):
predictions = model(input_data) # no need to squeeze/unsqueeze dimensions now!
predicted_classes = torch.argmax(predictions, dim=1) # find highest scoring class along the columns
n_correct = torch.sum(torch.eq(predicted_classes, labels))
return n_correct
# set up data
N = 1000
N_train = 600
N_val = 300
N_test = 100
dataset = FashionMNIST()
scrambled_dataset = ScrambledFashionMNIST()
indices = np.random.choice(np.arange(len(dataset)), size=N, replace=False)
np.random.shuffle(indices)
train_indices = indices[:N_train]
val_indices = indices[N_train:N_train+N_val]
test_indices = indices[N_train+N_val:N_train+N_val+N_test]
# create separate dataloaders for regular and scrambled datasets, but they still use the same images!
batch_size = 8
train_loader = DataLoader(dataset, batch_size=batch_size, sampler=SubsetRandomSampler(train_indices))
val_loader = DataLoader(dataset, batch_size=batch_size, sampler=SubsetRandomSampler(val_indices))
test_loader = DataLoader(dataset, batch_size=N_test, sampler=SubsetRandomSampler(test_indices))
scrambled_train_loader = DataLoader(scrambled_dataset, batch_size=batch_size, sampler=SubsetRandomSampler(train_indices))
scrambled_val_loader = DataLoader(scrambled_dataset, batch_size=batch_size, sampler=SubsetRandomSampler(val_indices))
scrambled_test_loader = DataLoader(scrambled_dataset, batch_size=N_test, sampler=SubsetRandomSampler(test_indices))
# initialize model for each dataset
input_dim = 784 # dimension of images after being vectorized
h1 = 128
h2 = 64
output_dim = 10 # number of classes
activation_fn = nn.ReLU()
model = ThreeLayerMLP(input_dim, h1, h2, output_dim, activation_fn)
scrambled_model = ThreeLayerMLP(input_dim, h1, h2, output_dim, activation_fn)
# initialize loss function and optimizers for each dataset
criterion = nn.CrossEntropyLoss()
lr = 1e-3
optimizer = torch.optim.SGD(model.parameters(), lr=lr, momentum=0.99, weight_decay=1e-4)
scrambled_optimizer = torch.optim.SGD(scrambled_model.parameters(), lr=lr, momentum=0.99, weight_decay=1e-4)
# train each model on their respective datasets
n_epochs = 300
model, losses, train_accs, val_accs = training_loop(model, criterion, optimizer, n_epochs, train_loader, val_loader)
scrambled_model, s_losses, s_train_accs, s_val_accs = training_loop(scrambled_model, criterion, scrambled_optimizer,
n_epochs, scrambled_train_loader, scrambled_val_loader)
# original dataset results
plt.figure(figsize=(12,6))
plt.subplot(131)
plt.semilogy(losses)
plt.grid(True)
plt.title('Loss values (Original)')
plt.xlabel('Epoch')
plt.subplot(132)
plt.plot(train_accs)
plt.grid(True)
plt.title('Training Accuracy (Original)')
plt.xlabel('Epoch')
plt.subplot(133)
plt.plot(val_accs)
plt.grid(True)
plt.title('Validation Accuracy (Original)')
plt.xlabel('Epoch')
# scrambled dataset results
plt.figure(figsize=(12,6))
plt.subplot(131)
plt.semilogy(s_losses)
plt.grid(True)
plt.title('Loss values (Scrambled)')
plt.xlabel('Epoch')
plt.subplot(132)
plt.plot(s_train_accs)
plt.grid(True)
plt.title('Training Accuracy (Scrambled)')
plt.xlabel('Epoch')
plt.subplot(133)
plt.plot(s_val_accs)
plt.grid(True)
plt.title('Validation Accuracy (Scrambled)')
plt.xlabel('Epoch')
0%| | 0/300 [00:00<?, ?it/s]
0%|▌ | 1/300 [00:00<02:06, 2.37it/s]
1%|█ | 2/300 [00:00<01:56, 2.56it/s]
1%|█▋ | 3/300 [00:01<01:50, 2.68it/s]
1%|██▏ | 4/300 [00:01<01:55, 2.56it/s]
2%|██▊ | 5/300 [00:01<01:50, 2.66it/s]
2%|███▎ | 6/300 [00:02<01:59, 2.45it/s]
2%|███▊ | 7/300 [00:02<01:59, 2.46it/s]
3%|████▍ | 8/300 [00:03<01:59, 2.45it/s]
3%|████▉ | 9/300 [00:03<01:55, 2.52it/s]
3%|█████▍ | 10/300 [00:03<01:55, 2.51it/s]
4%|██████ | 11/300 [00:04<01:49, 2.65it/s]
4%|██████▌ | 12/300 [00:04<01:47, 2.69it/s]
4%|███████ | 13/300 [00:05<01:46, 2.69it/s]
5%|███████▋ | 14/300 [00:05<01:45, 2.71it/s]
5%|████████▏ | 15/300 [00:05<01:45, 2.70it/s]
5%|████████▋ | 16/300 [00:06<01:41, 2.79it/s]
6%|█████████▎ | 17/300 [00:06<01:39, 2.85it/s]
6%|█████████▊ | 18/300 [00:06<01:37, 2.89it/s]
6%|██████████▍ | 19/300 [00:07<01:37, 2.87it/s]
7%|██████████▉ | 20/300 [00:07<01:35, 2.93it/s]
7%|███████████▍ | 21/300 [00:07<01:33, 2.98it/s]
7%|████████████ | 22/300 [00:08<01:33, 2.96it/s]
8%|████████████▌ | 23/300 [00:08<01:31, 3.04it/s]
8%|█████████████ | 24/300 [00:08<01:31, 3.03it/s]
8%|█████████████▋ | 25/300 [00:09<01:32, 2.98it/s]
9%|██████████████▏ | 26/300 [00:09<01:32, 2.97it/s]
9%|██████████████▊ | 27/300 [00:09<01:30, 3.01it/s]
9%|███████████████▎ | 28/300 [00:10<01:33, 2.92it/s]
10%|███████████████▊ | 29/300 [00:10<01:32, 2.94it/s]
10%|████████████████▍ | 30/300 [00:10<01:33, 2.89it/s]
10%|████████████████▉ | 31/300 [00:11<01:34, 2.86it/s]
11%|█████████████████▍ | 32/300 [00:11<01:34, 2.84it/s]
11%|██████████████████ | 33/300 [00:11<01:32, 2.89it/s]
11%|██████████████████▌ | 34/300 [00:12<01:33, 2.83it/s]
12%|███████████████████▏ | 35/300 [00:12<01:33, 2.83it/s]
12%|███████████████████▋ | 36/300 [00:12<01:33, 2.81it/s]
12%|████████████████████▏ | 37/300 [00:13<01:36, 2.73it/s]
13%|████████████████████▊ | 38/300 [00:13<01:37, 2.69it/s]
13%|█████████████████████▎ | 39/300 [00:14<01:44, 2.49it/s]
13%|█████████████████████▊ | 40/300 [00:14<01:46, 2.45it/s]
14%|██████████████████████▍ | 41/300 [00:15<01:46, 2.43it/s]
14%|██████████████████████▉ | 42/300 [00:15<01:41, 2.53it/s]
14%|███████████████████████▌ | 43/300 [00:15<01:39, 2.59it/s]
15%|████████████████████████ | 44/300 [00:16<01:33, 2.75it/s]
15%|████████████████████████▌ | 45/300 [00:16<01:29, 2.84it/s]
15%|█████████████████████████▏ | 46/300 [00:16<01:27, 2.89it/s]
16%|█████████████████████████▋ | 47/300 [00:17<01:25, 2.95it/s]
16%|██████████████████████████▏ | 48/300 [00:17<01:23, 3.01it/s]
16%|██████████████████████████▊ | 49/300 [00:17<01:24, 2.96it/s]
17%|███████████████████████████▎ | 50/300 [00:18<01:25, 2.91it/s]
17%|███████████████████████████▉ | 51/300 [00:18<01:29, 2.79it/s]
17%|████████████████████████████▍ | 52/300 [00:18<01:28, 2.81it/s]
18%|████████████████████████████▉ | 53/300 [00:19<01:24, 2.94it/s]
18%|█████████████████████████████▌ | 54/300 [00:19<01:21, 3.04it/s]
18%|██████████████████████████████ | 55/300 [00:19<01:21, 3.01it/s]
19%|██████████████████████████████▌ | 56/300 [00:20<01:21, 2.99it/s]
19%|███████████████████████████████▏ | 57/300 [00:20<01:23, 2.90it/s]
19%|███████████████████████████████▋ | 58/300 [00:20<01:24, 2.87it/s]
20%|████████████████████████████████▎ | 59/300 [00:21<01:25, 2.83it/s]
20%|████████████████████████████████▊ | 60/300 [00:21<01:21, 2.94it/s]
20%|█████████████████████████████████▎ | 61/300 [00:21<01:20, 2.95it/s]
21%|█████████████████████████████████▉ | 62/300 [00:22<01:22, 2.89it/s]
21%|██████████████████████████████████▍ | 63/300 [00:22<01:24, 2.81it/s]
21%|██████████████████████████████████▉ | 64/300 [00:22<01:23, 2.82it/s]
22%|███████████████████████████████████▌ | 65/300 [00:23<01:23, 2.82it/s]
22%|████████████████████████████████████ | 66/300 [00:23<01:22, 2.84it/s]
22%|████████████████████████████████████▋ | 67/300 [00:23<01:19, 2.93it/s]
23%|█████████████████████████████████████▏ | 68/300 [00:24<01:21, 2.84it/s]
23%|█████████████████████████████████████▋ | 69/300 [00:24<01:21, 2.82it/s]
23%|██████████████████████████████████████▎ | 70/300 [00:25<01:20, 2.87it/s]
24%|██████████████████████████████████████▊ | 71/300 [00:25<01:20, 2.86it/s]
24%|███████████████████████████████████████▎ | 72/300 [00:25<01:20, 2.84it/s]
24%|███████████████████████████████████████▉ | 73/300 [00:26<01:18, 2.88it/s]
25%|████████████████████████████████████████▍ | 74/300 [00:26<01:18, 2.89it/s]
25%|█████████████████████████████████████████ | 75/300 [00:26<01:18, 2.86it/s]
25%|█████████████████████████████████████████▌ | 76/300 [00:27<01:17, 2.90it/s]
26%|██████████████████████████████████████████ | 77/300 [00:27<01:15, 2.94it/s]
26%|██████████████████████████████████████████▋ | 78/300 [00:27<01:13, 3.03it/s]
26%|███████████████████████████████████████████▏ | 79/300 [00:28<01:12, 3.06it/s]
27%|███████████████████████████████████████████▋ | 80/300 [00:28<01:12, 3.04it/s]
27%|████████████████████████████████████████████▎ | 81/300 [00:28<01:16, 2.88it/s]
27%|████████████████████████████████████████████▊ | 82/300 [00:29<01:26, 2.51it/s]
28%|█████████████████████████████████████████████▎ | 83/300 [00:29<01:24, 2.56it/s]
28%|█████████████████████████████████████████████▉ | 84/300 [00:30<01:21, 2.64it/s]
28%|██████████████████████████████████████████████▍ | 85/300 [00:30<01:20, 2.67it/s]
29%|███████████████████████████████████████████████ | 86/300 [00:30<01:19, 2.70it/s]
29%|███████████████████████████████████████████████▌ | 87/300 [00:31<01:16, 2.79it/s]
29%|████████████████████████████████████████████████ | 88/300 [00:31<01:16, 2.78it/s]
30%|████████████████████████████████████████████████▋ | 89/300 [00:31<01:13, 2.87it/s]
30%|█████████████████████████████████████████████████▏ | 90/300 [00:32<01:11, 2.94it/s]
30%|█████████████████████████████████████████████████▋ | 91/300 [00:32<01:09, 2.99it/s]
31%|██████████████████████████████████████████████████▎ | 92/300 [00:32<01:07, 3.06it/s]
31%|██████████████████████████████████████████████████▊ | 93/300 [00:33<01:07, 3.06it/s]
31%|███████████████████████████████████████████████████▍ | 94/300 [00:33<01:10, 2.91it/s]
32%|███████████████████████████████████████████████████▉ | 95/300 [00:33<01:09, 2.93it/s]
32%|████████████████████████████████████████████████████▍ | 96/300 [00:34<01:08, 3.00it/s]
32%|█████████████████████████████████████████████████████ | 97/300 [00:34<01:08, 2.96it/s]
33%|█████████████████████████████████████████████████████▌ | 98/300 [00:34<01:09, 2.92it/s]
33%|██████████████████████████████████████████████████████ | 99/300 [00:35<01:12, 2.77it/s]
33%|██████████████████████████████████████████████████████▎ | 100/300 [00:35<01:12, 2.78it/s]
34%|██████████████████████████████████████████████████████▉ | 101/300 [00:35<01:12, 2.75it/s]
34%|███████████████████████████████████████████████████████▍ | 102/300 [00:36<01:10, 2.80it/s]
34%|███████████████████████████████████████████████████████▉ | 103/300 [00:36<01:09, 2.82it/s]
35%|████████████████████████████████████████████████████████▌ | 104/300 [00:36<01:06, 2.93it/s]
35%|█████████████████████████████████████████████████████████ | 105/300 [00:37<01:07, 2.88it/s]
35%|█████████████████████████████████████████████████████████▌ | 106/300 [00:37<01:08, 2.84it/s]
36%|██████████████████████████████████████████████████████████▏ | 107/300 [00:37<01:07, 2.85it/s]
36%|██████████████████████████████████████████████████████████▋ | 108/300 [00:38<01:07, 2.84it/s]
36%|███████████████████████████████████████████████████████████▏ | 109/300 [00:38<01:10, 2.72it/s]
37%|███████████████████████████████████████████████████████████▊ | 110/300 [00:39<01:13, 2.58it/s]
37%|████████████████████████████████████████████████████████████▎ | 111/300 [00:39<01:12, 2.59it/s]
37%|████████████████████████████████████████████████████████████▊ | 112/300 [00:40<01:20, 2.35it/s]
38%|█████████████████████████████████████████████████████████████▍ | 113/300 [00:40<01:31, 2.04it/s]
38%|█████████████████████████████████████████████████████████████▉ | 114/300 [00:41<01:44, 1.79it/s]
38%|██████████████████████████████████████████████████████████████▍ | 115/300 [00:42<01:52, 1.65it/s]
39%|███████████████████████████████████████████████████████████████ | 116/300 [00:42<01:44, 1.76it/s]
39%|███████████████████████████████████████████████████████████████▌ | 117/300 [00:43<01:37, 1.88it/s]
39%|████████████████████████████████████████████████████████████████ | 118/300 [00:43<01:31, 1.98it/s]
40%|████████████████████████████████████████████████████████████████▋ | 119/300 [00:44<01:33, 1.93it/s]
40%|█████████████████████████████████████████████████████████████████▏ | 120/300 [00:44<01:29, 2.01it/s]
40%|█████████████████████████████████████████████████████████████████▋ | 121/300 [00:44<01:24, 2.13it/s]
41%|██████████████████████████████████████████████████████████████████▎ | 122/300 [00:45<01:20, 2.21it/s]
41%|██████████████████████████████████████████████████████████████████▊ | 123/300 [00:45<01:17, 2.28it/s]
41%|███████████████████████████████████████████████████████████████████▎ | 124/300 [00:46<01:16, 2.29it/s]
42%|███████████████████████████████████████████████████████████████████▉ | 125/300 [00:46<01:14, 2.34it/s]
42%|████████████████████████████████████████████████████████████████████▍ | 126/300 [00:46<01:13, 2.35it/s]
42%|█████████████████████████████████████████████████████████████████████ | 127/300 [00:47<01:08, 2.53it/s]
43%|█████████████████████████████████████████████████████████████████████▌ | 128/300 [00:47<01:07, 2.53it/s]
43%|██████████████████████████████████████████████████████████████████████ | 129/300 [00:48<01:07, 2.55it/s]
43%|██████████████████████████████████████████████████████████████████████▋ | 130/300 [00:48<01:05, 2.58it/s]
44%|███████████████████████████████████████████████████████████████████████▏ | 131/300 [00:48<01:05, 2.59it/s]
44%|███████████████████████████████████████████████████████████████████████▋ | 132/300 [00:49<01:05, 2.56it/s]
44%|████████████████████████████████████████████████████████████████████████▎ | 133/300 [00:49<01:09, 2.41it/s]
45%|████████████████████████████████████████████████████████████████████████▊ | 134/300 [00:50<01:12, 2.30it/s]
45%|█████████████████████████████████████████████████████████████████████████▎ | 135/300 [00:50<01:21, 2.03it/s]
45%|█████████████████████████████████████████████████████████████████████████▉ | 136/300 [00:51<01:47, 1.53it/s]
46%|██████████████████████████████████████████████████████████████████████████▍ | 137/300 [00:53<02:11, 1.24it/s]
46%|██████████████████████████████████████████████████████████████████████████▉ | 138/300 [00:53<02:00, 1.35it/s]
46%|███████████████████████████████████████████████████████████████████████████▌ | 139/300 [00:54<01:44, 1.54it/s]
47%|████████████████████████████████████████████████████████████████████████████ | 140/300 [00:54<01:33, 1.71it/s]
47%|████████████████████████████████████████████████████████████████████████████▌ | 141/300 [00:54<01:25, 1.87it/s]
47%|█████████████████████████████████████████████████████████████████████████████▏ | 142/300 [00:55<01:17, 2.04it/s]
48%|█████████████████████████████████████████████████████████████████████████████▋ | 143/300 [00:55<01:12, 2.16it/s]
48%|██████████████████████████████████████████████████████████████████████████████▏ | 144/300 [00:56<01:12, 2.16it/s]
48%|██████████████████████████████████████████████████████████████████████████████▊ | 145/300 [00:56<01:14, 2.09it/s]
49%|███████████████████████████████████████████████████████████████████████████████▎ | 146/300 [00:57<01:08, 2.25it/s]
49%|███████████████████████████████████████████████████████████████████████████████▊ | 147/300 [00:57<01:03, 2.40it/s]
49%|████████████████████████████████████████████████████████████████████████████████▍ | 148/300 [00:57<01:02, 2.45it/s]
50%|████████████████████████████████████████████████████████████████████████████████▉ | 149/300 [00:58<00:59, 2.55it/s]
50%|█████████████████████████████████████████████████████████████████████████████████▌ | 150/300 [00:58<00:59, 2.53it/s]
50%|██████████████████████████████████████████████████████████████████████████████████ | 151/300 [00:58<00:59, 2.48it/s]
51%|██████████████████████████████████████████████████████████████████████████████████▌ | 152/300 [00:59<00:59, 2.47it/s]
51%|███████████████████████████████████████████████████████████████████████████████████▏ | 153/300 [00:59<00:56, 2.61it/s]
51%|███████████████████████████████████████████████████████████████████████████████████▋ | 154/300 [01:00<00:55, 2.64it/s]
52%|████████████████████████████████████████████████████████████████████████████████████▏ | 155/300 [01:00<00:57, 2.54it/s]
52%|████████████████████████████████████████████████████████████████████████████████████▊ | 156/300 [01:00<00:58, 2.47it/s]
52%|█████████████████████████████████████████████████████████████████████████████████████▎ | 157/300 [01:01<00:58, 2.45it/s]
53%|█████████████████████████████████████████████████████████████████████████████████████▊ | 158/300 [01:01<00:57, 2.48it/s]
53%|██████████████████████████████████████████████████████████████████████████████████████▍ | 159/300 [01:02<00:57, 2.44it/s]
53%|██████████████████████████████████████████████████████████████████████████████████████▉ | 160/300 [01:02<00:58, 2.40it/s]
54%|███████████████████████████████████████████████████████████████████████████████████████▍ | 161/300 [01:02<00:57, 2.44it/s]
54%|████████████████████████████████████████████████████████████████████████████████████████ | 162/300 [01:03<00:55, 2.48it/s]
54%|████████████████████████████████████████████████████████████████████████████████████████▌ | 163/300 [01:03<00:58, 2.35it/s]
55%|█████████████████████████████████████████████████████████████████████████████████████████ | 164/300 [01:04<00:56, 2.39it/s]
55%|█████████████████████████████████████████████████████████████████████████████████████████▋ | 165/300 [01:04<00:55, 2.45it/s]
55%|██████████████████████████████████████████████████████████████████████████████████████████▏ | 166/300 [01:05<00:54, 2.48it/s]
56%|██████████████████████████████████████████████████████████████████████████████████████████▋ | 167/300 [01:05<00:50, 2.64it/s]
56%|███████████████████████████████████████████████████████████████████████████████████████████▎ | 168/300 [01:05<00:47, 2.79it/s]
56%|███████████████████████████████████████████████████████████████████████████████████████████▊ | 169/300 [01:05<00:45, 2.86it/s]
57%|████████████████████████████████████████████████████████████████████████████████████████████▎ | 170/300 [01:06<00:45, 2.87it/s]
57%|████████████████████████████████████████████████████████████████████████████████████████████▉ | 171/300 [01:06<00:45, 2.86it/s]
57%|█████████████████████████████████████████████████████████████████████████████████████████████▍ | 172/300 [01:07<00:43, 2.92it/s]
58%|█████████████████████████████████████████████████████████████████████████████████████████████▉ | 173/300 [01:07<00:41, 3.05it/s]
58%|██████████████████████████████████████████████████████████████████████████████████████████████▌ | 174/300 [01:07<00:40, 3.15it/s]
58%|███████████████████████████████████████████████████████████████████████████████████████████████ | 175/300 [01:07<00:38, 3.23it/s]
59%|███████████████████████████████████████████████████████████████████████████████████████████████▋ | 176/300 [01:08<00:37, 3.28it/s]
59%|████████████████████████████████████████████████████████████████████████████████████████████████▏ | 177/300 [01:08<00:37, 3.24it/s]
59%|████████████████████████████████████████████████████████████████████████████████████████████████▋ | 178/300 [01:08<00:38, 3.18it/s]
60%|█████████████████████████████████████████████████████████████████████████████████████████████████▎ | 179/300 [01:09<00:37, 3.21it/s]
60%|█████████████████████████████████████████████████████████████████████████████████████████████████▊ | 180/300 [01:09<00:36, 3.26it/s]
60%|██████████████████████████████████████████████████████████████████████████████████████████████████▎ | 181/300 [01:09<00:36, 3.30it/s]
61%|██████████████████████████████████████████████████████████████████████████████████████████████████▉ | 182/300 [01:10<00:35, 3.32it/s]
61%|███████████████████████████████████████████████████████████████████████████████████████████████████▍ | 183/300 [01:10<00:36, 3.22it/s]
61%|███████████████████████████████████████████████████████████████████████████████████████████████████▉ | 184/300 [01:10<00:36, 3.21it/s]
62%|████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 185/300 [01:10<00:35, 3.22it/s]
62%|█████████████████████████████████████████████████████████████████████████████████████████████████████ | 186/300 [01:11<00:35, 3.24it/s]
62%|█████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 187/300 [01:11<00:34, 3.28it/s]
63%|██████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 188/300 [01:11<00:33, 3.34it/s]
63%|██████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 189/300 [01:12<00:33, 3.29it/s]
63%|███████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 190/300 [01:12<00:33, 3.25it/s]
64%|███████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 191/300 [01:12<00:34, 3.20it/s]
64%|████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 192/300 [01:13<00:33, 3.21it/s]
64%|████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 193/300 [01:13<00:33, 3.21it/s]
65%|█████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 194/300 [01:13<00:33, 3.20it/s]
65%|█████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 195/300 [01:14<00:32, 3.21it/s]
65%|██████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 196/300 [01:14<00:32, 3.22it/s]
66%|███████████████████████████████████████████████████████████████████████████████████████████████████████████ | 197/300 [01:14<00:31, 3.26it/s]
66%|███████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 198/300 [01:14<00:30, 3.30it/s]
66%|████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 199/300 [01:15<00:30, 3.30it/s]
67%|████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 200/300 [01:15<00:29, 3.34it/s]
67%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 201/300 [01:15<00:29, 3.40it/s]
67%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 202/300 [01:16<00:28, 3.43it/s]
68%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 203/300 [01:16<00:27, 3.47it/s]
68%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 204/300 [01:16<00:27, 3.48it/s]
68%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 205/300 [01:16<00:27, 3.50it/s]
69%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 206/300 [01:17<00:26, 3.50it/s]
69%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 207/300 [01:17<00:26, 3.46it/s]
69%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 208/300 [01:17<00:26, 3.51it/s]
70%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 209/300 [01:18<00:25, 3.54it/s]
70%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 210/300 [01:18<00:26, 3.46it/s]
70%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 211/300 [01:18<00:25, 3.49it/s]
71%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 212/300 [01:18<00:25, 3.52it/s]
71%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 213/300 [01:19<00:24, 3.54it/s]
71%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 214/300 [01:19<00:24, 3.50it/s]
72%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 215/300 [01:19<00:24, 3.53it/s]
72%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 216/300 [01:20<00:23, 3.55it/s]
72%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 217/300 [01:20<00:23, 3.49it/s]
73%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 218/300 [01:20<00:23, 3.46it/s]
73%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 219/300 [01:20<00:23, 3.47it/s]
73%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 220/300 [01:21<00:22, 3.50it/s]
74%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 221/300 [01:21<00:22, 3.51it/s]
74%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 222/300 [01:21<00:22, 3.51it/s]
74%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 223/300 [01:22<00:21, 3.52it/s]
75%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 224/300 [01:22<00:21, 3.54it/s]
75%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 225/300 [01:22<00:21, 3.55it/s]
75%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 226/300 [01:22<00:20, 3.55it/s]
76%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 227/300 [01:23<00:20, 3.50it/s]
76%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 228/300 [01:23<00:20, 3.43it/s]
76%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 229/300 [01:23<00:21, 3.33it/s]
77%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 230/300 [01:24<00:21, 3.33it/s]
77%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 231/300 [01:24<00:20, 3.33it/s]
77%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 232/300 [01:24<00:22, 3.09it/s]
78%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 233/300 [01:25<00:21, 3.06it/s]
78%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 234/300 [01:25<00:21, 3.06it/s]
78%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 235/300 [01:25<00:21, 3.03it/s]
79%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 236/300 [01:26<00:20, 3.11it/s]
79%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 237/300 [01:26<00:20, 3.14it/s]
79%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 238/300 [01:26<00:19, 3.16it/s]
80%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 239/300 [01:27<00:19, 3.20it/s]
80%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 240/300 [01:27<00:19, 3.14it/s]
80%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 241/300 [01:27<00:18, 3.23it/s]
81%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 242/300 [01:28<00:17, 3.24it/s]
81%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 243/300 [01:28<00:17, 3.33it/s]
81%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 244/300 [01:28<00:17, 3.17it/s]
82%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 245/300 [01:28<00:17, 3.21it/s]
82%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 246/300 [01:29<00:17, 3.17it/s]
82%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 247/300 [01:29<00:18, 2.82it/s]
83%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 248/300 [01:30<00:19, 2.69it/s]
83%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 249/300 [01:30<00:18, 2.80it/s]
83%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 250/300 [01:30<00:17, 2.79it/s]
84%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 251/300 [01:31<00:16, 2.97it/s]
84%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 252/300 [01:31<00:15, 3.09it/s]
84%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 253/300 [01:31<00:14, 3.18it/s]
85%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 254/300 [01:31<00:14, 3.28it/s]
85%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 255/300 [01:32<00:13, 3.28it/s]
85%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 256/300 [01:32<00:13, 3.33it/s]
86%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 257/300 [01:32<00:12, 3.36it/s]
86%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 258/300 [01:33<00:12, 3.34it/s]
86%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 259/300 [01:33<00:12, 3.33it/s]
87%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 260/300 [01:33<00:11, 3.35it/s]
87%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 261/300 [01:34<00:11, 3.33it/s]
87%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 262/300 [01:34<00:11, 3.23it/s]
88%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 263/300 [01:34<00:11, 3.16it/s]
88%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 264/300 [01:35<00:11, 3.13it/s]
88%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 265/300 [01:35<00:11, 3.05it/s]
89%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 266/300 [01:35<00:11, 2.93it/s]
89%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 267/300 [01:36<00:11, 2.81it/s]
89%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 268/300 [01:36<00:11, 2.83it/s]
90%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 269/300 [01:36<00:10, 2.92it/s]
90%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 270/300 [01:37<00:10, 2.95it/s]
90%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 271/300 [01:37<00:09, 3.00it/s]
91%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 272/300 [01:37<00:09, 3.07it/s]
91%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 273/300 [01:38<00:08, 3.12it/s]
91%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 274/300 [01:38<00:08, 3.14it/s]
92%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 275/300 [01:38<00:07, 3.15it/s]
92%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 276/300 [01:39<00:07, 3.18it/s]
92%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 277/300 [01:39<00:07, 3.22it/s]
93%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 278/300 [01:39<00:06, 3.21it/s]
93%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 279/300 [01:39<00:06, 3.22it/s]
93%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 280/300 [01:40<00:06, 3.21it/s]
94%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 281/300 [01:40<00:05, 3.18it/s]
94%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 282/300 [01:40<00:05, 3.28it/s]
94%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 283/300 [01:41<00:05, 3.32it/s]
95%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 284/300 [01:41<00:04, 3.31it/s]
95%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 285/300 [01:41<00:04, 3.39it/s]
95%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 286/300 [01:42<00:04, 3.42it/s]
96%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 287/300 [01:42<00:03, 3.43it/s]
96%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 288/300 [01:42<00:03, 3.37it/s]
96%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 289/300 [01:42<00:03, 3.39it/s]
97%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 290/300 [01:43<00:02, 3.38it/s]
97%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 291/300 [01:43<00:02, 3.42it/s]
97%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 292/300 [01:43<00:02, 3.46it/s]
98%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 293/300 [01:44<00:02, 3.34it/s]
98%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 294/300 [01:44<00:01, 3.36it/s]
98%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 295/300 [01:44<00:01, 3.32it/s]
99%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 296/300 [01:45<00:01, 3.22it/s]
99%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 297/300 [01:45<00:00, 3.27it/s]
99%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 298/300 [01:45<00:00, 3.24it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍| 299/300 [01:45<00:00, 3.24it/s]
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 300/300 [01:46<00:00, 3.27it/s]
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 300/300 [01:46<00:00, 2.82it/s]
0%| | 0/300 [00:00<?, ?it/s]
0%|▌ | 1/300 [00:00<02:58, 1.67it/s]
1%|█ | 2/300 [00:01<02:43, 1.82it/s]
1%|█▋ | 3/300 [00:01<02:17, 2.16it/s]
1%|██▏ | 4/300 [00:01<01:57, 2.51it/s]
2%|██▊ | 5/300 [00:02<01:47, 2.75it/s]
2%|███▎ | 6/300 [00:02<01:40, 2.92it/s]
2%|███▊ | 7/300 [00:02<01:37, 3.00it/s]
3%|████▍ | 8/300 [00:02<01:34, 3.10it/s]
3%|████▉ | 9/300 [00:03<01:32, 3.13it/s]
3%|█████▍ | 10/300 [00:03<01:31, 3.18it/s]
4%|██████ | 11/300 [00:03<01:29, 3.24it/s]
4%|██████▌ | 12/300 [00:04<01:29, 3.22it/s]
4%|███████ | 13/300 [00:04<01:27, 3.28it/s]
5%|███████▋ | 14/300 [00:04<01:27, 3.28it/s]
5%|████████▏ | 15/300 [00:05<01:25, 3.32it/s]
5%|████████▋ | 16/300 [00:05<01:23, 3.39it/s]
6%|█████████▎ | 17/300 [00:05<01:22, 3.43it/s]
6%|█████████▊ | 18/300 [00:05<01:21, 3.46it/s]
6%|██████████▍ | 19/300 [00:06<01:20, 3.47it/s]
7%|██████████▉ | 20/300 [00:06<01:20, 3.47it/s]
7%|███████████▍ | 21/300 [00:06<01:20, 3.47it/s]
7%|████████████ | 22/300 [00:07<01:19, 3.48it/s]
8%|████████████▌ | 23/300 [00:07<01:20, 3.45it/s]
8%|█████████████ | 24/300 [00:07<01:19, 3.49it/s]
8%|█████████████▋ | 25/300 [00:07<01:18, 3.50it/s]
9%|██████████████▏ | 26/300 [00:08<01:18, 3.49it/s]
9%|██████████████▊ | 27/300 [00:08<01:21, 3.33it/s]
9%|███████████████▎ | 28/300 [00:08<01:20, 3.36it/s]
10%|███████████████▊ | 29/300 [00:09<01:20, 3.36it/s]
10%|████████████████▍ | 30/300 [00:09<01:19, 3.38it/s]
10%|████████████████▉ | 31/300 [00:09<01:19, 3.40it/s]
11%|█████████████████▍ | 32/300 [00:10<01:18, 3.40it/s]
11%|██████████████████ | 33/300 [00:10<01:19, 3.35it/s]
11%|██████████████████▌ | 34/300 [00:10<01:20, 3.32it/s]
12%|███████████████████▏ | 35/300 [00:10<01:19, 3.34it/s]
12%|███████████████████▋ | 36/300 [00:11<01:19, 3.33it/s]
12%|████████████████████▏ | 37/300 [00:11<01:18, 3.36it/s]
13%|████████████████████▊ | 38/300 [00:11<01:17, 3.37it/s]
13%|█████████████████████▎ | 39/300 [00:12<01:17, 3.38it/s]
13%|█████████████████████▊ | 40/300 [00:12<01:17, 3.38it/s]
14%|██████████████████████▍ | 41/300 [00:12<01:16, 3.39it/s]
14%|██████████████████████▉ | 42/300 [00:13<01:16, 3.39it/s]
14%|███████████████████████▌ | 43/300 [00:13<01:16, 3.35it/s]
15%|████████████████████████ | 44/300 [00:13<01:16, 3.37it/s]
15%|████████████████████████▌ | 45/300 [00:13<01:15, 3.36it/s]
15%|█████████████████████████▏ | 46/300 [00:14<01:16, 3.31it/s]
16%|█████████████████████████▋ | 47/300 [00:14<01:17, 3.25it/s]
16%|██████████████████████████▏ | 48/300 [00:14<01:16, 3.28it/s]
16%|██████████████████████████▊ | 49/300 [00:15<01:20, 3.13it/s]
17%|███████████████████████████▎ | 50/300 [00:15<01:21, 3.08it/s]
17%|███████████████████████████▉ | 51/300 [00:15<01:20, 3.08it/s]
17%|████████████████████████████▍ | 52/300 [00:16<01:19, 3.11it/s]
18%|████████████████████████████▉ | 53/300 [00:16<01:19, 3.09it/s]
18%|█████████████████████████████▌ | 54/300 [00:16<01:19, 3.10it/s]
18%|██████████████████████████████ | 55/300 [00:17<01:19, 3.10it/s]
19%|██████████████████████████████▌ | 56/300 [00:17<01:21, 3.01it/s]
19%|███████████████████████████████▏ | 57/300 [00:17<01:18, 3.11it/s]
19%|███████████████████████████████▋ | 58/300 [00:18<01:16, 3.16it/s]
20%|████████████████████████████████▎ | 59/300 [00:18<01:15, 3.20it/s]
20%|████████████████████████████████▊ | 60/300 [00:18<01:16, 3.15it/s]
20%|█████████████████████████████████▎ | 61/300 [00:19<01:18, 3.03it/s]
21%|█████████████████████████████████▉ | 62/300 [00:19<01:16, 3.12it/s]
21%|██████████████████████████████████▍ | 63/300 [00:19<01:14, 3.19it/s]
21%|██████████████████████████████████▉ | 64/300 [00:19<01:12, 3.25it/s]
22%|███████████████████████████████████▌ | 65/300 [00:20<01:13, 3.22it/s]
22%|████████████████████████████████████ | 66/300 [00:20<01:12, 3.23it/s]
22%|████████████████████████████████████▋ | 67/300 [00:20<01:11, 3.28it/s]
23%|█████████████████████████████████████▏ | 68/300 [00:21<01:10, 3.29it/s]
23%|█████████████████████████████████████▋ | 69/300 [00:21<01:10, 3.26it/s]
23%|██████████████████████████████████████▎ | 70/300 [00:21<01:10, 3.27it/s]
24%|██████████████████████████████████████▊ | 71/300 [00:22<01:09, 3.30it/s]
24%|███████████████████████████████████████▎ | 72/300 [00:22<01:08, 3.32it/s]
24%|███████████████████████████████████████▉ | 73/300 [00:22<01:07, 3.35it/s]
25%|████████████████████████████████████████▍ | 74/300 [00:23<01:06, 3.37it/s]
25%|█████████████████████████████████████████ | 75/300 [00:23<01:06, 3.36it/s]
25%|█████████████████████████████████████████▌ | 76/300 [00:23<01:06, 3.36it/s]
26%|██████████████████████████████████████████ | 77/300 [00:23<01:06, 3.37it/s]
26%|██████████████████████████████████████████▋ | 78/300 [00:24<01:07, 3.28it/s]
26%|███████████████████████████████████████████▏ | 79/300 [00:24<01:07, 3.25it/s]
27%|███████████████████████████████████████████▋ | 80/300 [00:24<01:07, 3.27it/s]
27%|████████████████████████████████████████████▎ | 81/300 [00:25<01:06, 3.27it/s]
27%|████████████████████████████████████████████▊ | 82/300 [00:25<01:07, 3.23it/s]
28%|█████████████████████████████████████████████▎ | 83/300 [00:25<01:07, 3.20it/s]
28%|█████████████████████████████████████████████▉ | 84/300 [00:26<01:08, 3.15it/s]
28%|██████████████████████████████████████████████▍ | 85/300 [00:26<01:08, 3.13it/s]
29%|███████████████████████████████████████████████ | 86/300 [00:26<01:07, 3.19it/s]
29%|███████████████████████████████████████████████▌ | 87/300 [00:27<01:08, 3.09it/s]
29%|████████████████████████████████████████████████ | 88/300 [00:27<01:07, 3.12it/s]
30%|████████████████████████████████████████████████▋ | 89/300 [00:27<01:07, 3.14it/s]
30%|█████████████████████████████████████████████████▏ | 90/300 [00:28<01:06, 3.14it/s]
30%|█████████████████████████████████████████████████▋ | 91/300 [00:28<01:06, 3.15it/s]
31%|██████████████████████████████████████████████████▎ | 92/300 [00:28<01:05, 3.18it/s]
31%|██████████████████████████████████████████████████▊ | 93/300 [00:28<01:04, 3.20it/s]
31%|███████████████████████████████████████████████████▍ | 94/300 [00:29<01:04, 3.21it/s]
32%|███████████████████████████████████████████████████▉ | 95/300 [00:29<01:03, 3.22it/s]
32%|████████████████████████████████████████████████████▍ | 96/300 [00:29<01:03, 3.21it/s]
32%|█████████████████████████████████████████████████████ | 97/300 [00:30<01:04, 3.13it/s]
33%|█████████████████████████████████████████████████████▌ | 98/300 [00:30<01:04, 3.14it/s]
33%|██████████████████████████████████████████████████████ | 99/300 [00:30<01:07, 2.99it/s]
33%|██████████████████████████████████████████████████████▎ | 100/300 [00:31<01:05, 3.03it/s]
34%|██████████████████████████████████████████████████████▉ | 101/300 [00:31<01:07, 2.95it/s]
34%|███████████████████████████████████████████████████████▍ | 102/300 [00:31<01:06, 2.96it/s]
34%|███████████████████████████████████████████████████████▉ | 103/300 [00:32<01:08, 2.87it/s]
35%|████████████████████████████████████████████████████████▌ | 104/300 [00:32<01:08, 2.87it/s]
35%|█████████████████████████████████████████████████████████ | 105/300 [00:32<01:06, 2.93it/s]
35%|█████████████████████████████████████████████████████████▌ | 106/300 [00:33<01:05, 2.96it/s]
36%|██████████████████████████████████████████████████████████▏ | 107/300 [00:33<01:05, 2.97it/s]
36%|██████████████████████████████████████████████████████████▋ | 108/300 [00:33<01:04, 2.97it/s]
36%|███████████████████████████████████████████████████████████▏ | 109/300 [00:34<01:13, 2.59it/s]
37%|███████████████████████████████████████████████████████████▊ | 110/300 [00:34<01:12, 2.61it/s]
37%|████████████████████████████████████████████████████████████▎ | 111/300 [00:35<01:10, 2.68it/s]
37%|████████████████████████████████████████████████████████████▊ | 112/300 [00:35<01:08, 2.75it/s]
38%|█████████████████████████████████████████████████████████████▍ | 113/300 [00:35<01:06, 2.83it/s]
38%|█████████████████████████████████████████████████████████████▉ | 114/300 [00:36<01:05, 2.85it/s]
38%|██████████████████████████████████████████████████████████████▍ | 115/300 [00:36<01:05, 2.84it/s]
39%|███████████████████████████████████████████████████████████████ | 116/300 [00:36<01:03, 2.90it/s]
39%|███████████████████████████████████████████████████████████████▌ | 117/300 [00:37<01:02, 2.93it/s]
39%|████████████████████████████████████████████████████████████████ | 118/300 [00:37<01:01, 2.94it/s]
40%|████████████████████████████████████████████████████████████████▋ | 119/300 [00:37<01:05, 2.78it/s]
40%|█████████████████████████████████████████████████████████████████▏ | 120/300 [00:38<01:05, 2.76it/s]
40%|█████████████████████████████████████████████████████████████████▋ | 121/300 [00:38<01:05, 2.75it/s]
41%|██████████████████████████████████████████████████████████████████▎ | 122/300 [00:39<01:03, 2.80it/s]
41%|██████████████████████████████████████████████████████████████████▊ | 123/300 [00:39<01:02, 2.85it/s]
41%|███████████████████████████████████████████████████████████████████▎ | 124/300 [00:39<01:00, 2.92it/s]
42%|███████████████████████████████████████████████████████████████████▉ | 125/300 [00:40<00:59, 2.95it/s]
42%|████████████████████████████████████████████████████████████████████▍ | 126/300 [00:40<00:58, 2.97it/s]
42%|█████████████████████████████████████████████████████████████████████ | 127/300 [00:40<00:58, 2.96it/s]
43%|█████████████████████████████████████████████████████████████████████▌ | 128/300 [00:41<00:57, 2.99it/s]
43%|██████████████████████████████████████████████████████████████████████ | 129/300 [00:41<00:59, 2.89it/s]
43%|██████████████████████████████████████████████████████████████████████▋ | 130/300 [00:41<00:58, 2.91it/s]
44%|███████████████████████████████████████████████████████████████████████▏ | 131/300 [00:42<00:58, 2.88it/s]
44%|███████████████████████████████████████████████████████████████████████▋ | 132/300 [00:42<01:00, 2.77it/s]
44%|████████████████████████████████████████████████████████████████████████▎ | 133/300 [00:42<01:00, 2.76it/s]
45%|████████████████████████████████████████████████████████████████████████▊ | 134/300 [00:43<00:58, 2.85it/s]
45%|█████████████████████████████████████████████████████████████████████████▎ | 135/300 [00:43<00:56, 2.91it/s]
45%|█████████████████████████████████████████████████████████████████████████▉ | 136/300 [00:43<00:55, 2.96it/s]
46%|██████████████████████████████████████████████████████████████████████████▍ | 137/300 [00:44<00:56, 2.90it/s]
46%|██████████████████████████████████████████████████████████████████████████▉ | 138/300 [00:44<00:57, 2.81it/s]
46%|███████████████████████████████████████████████████████████████████████████▌ | 139/300 [00:44<00:56, 2.83it/s]
47%|████████████████████████████████████████████████████████████████████████████ | 140/300 [00:45<00:56, 2.84it/s]
47%|████████████████████████████████████████████████████████████████████████████▌ | 141/300 [00:45<00:54, 2.91it/s]
47%|█████████████████████████████████████████████████████████████████████████████▏ | 142/300 [00:45<00:53, 2.96it/s]
48%|█████████████████████████████████████████████████████████████████████████████▋ | 143/300 [00:46<00:58, 2.68it/s]
48%|██████████████████████████████████████████████████████████████████████████████▏ | 144/300 [00:46<00:56, 2.74it/s]
48%|██████████████████████████████████████████████████████████████████████████████▊ | 145/300 [00:47<00:55, 2.78it/s]
49%|███████████████████████████████████████████████████████████████████████████████▎ | 146/300 [00:47<00:54, 2.82it/s]
49%|███████████████████████████████████████████████████████████████████████████████▊ | 147/300 [00:47<00:55, 2.77it/s]
49%|████████████████████████████████████████████████████████████████████████████████▍ | 148/300 [00:48<00:54, 2.77it/s]
50%|████████████████████████████████████████████████████████████████████████████████▉ | 149/300 [00:48<00:54, 2.77it/s]
50%|█████████████████████████████████████████████████████████████████████████████████▌ | 150/300 [00:48<00:54, 2.73it/s]
50%|██████████████████████████████████████████████████████████████████████████████████ | 151/300 [00:49<00:54, 2.76it/s]
51%|██████████████████████████████████████████████████████████████████████████████████▌ | 152/300 [00:49<00:53, 2.75it/s]
51%|███████████████████████████████████████████████████████████████████████████████████▏ | 153/300 [00:49<00:52, 2.80it/s]
51%|███████████████████████████████████████████████████████████████████████████████████▋ | 154/300 [00:50<00:50, 2.87it/s]
52%|████████████████████████████████████████████████████████████████████████████████████▏ | 155/300 [00:50<00:53, 2.71it/s]
52%|████████████████████████████████████████████████████████████████████████████████████▊ | 156/300 [00:51<00:53, 2.72it/s]
52%|█████████████████████████████████████████████████████████████████████████████████████▎ | 157/300 [00:51<00:54, 2.63it/s]
53%|█████████████████████████████████████████████████████████████████████████████████████▊ | 158/300 [00:51<00:53, 2.66it/s]
53%|██████████████████████████████████████████████████████████████████████████████████████▍ | 159/300 [00:52<00:52, 2.70it/s]
53%|██████████████████████████████████████████████████████████████████████████████████████▉ | 160/300 [00:52<00:52, 2.67it/s]
54%|███████████████████████████████████████████████████████████████████████████████████████▍ | 161/300 [00:52<00:51, 2.70it/s]
54%|████████████████████████████████████████████████████████████████████████████████████████ | 162/300 [00:53<00:50, 2.74it/s]
54%|████████████████████████████████████████████████████████████████████████████████████████▌ | 163/300 [00:53<00:49, 2.79it/s]
55%|█████████████████████████████████████████████████████████████████████████████████████████ | 164/300 [00:54<00:53, 2.55it/s]
55%|█████████████████████████████████████████████████████████████████████████████████████████▋ | 165/300 [00:54<00:52, 2.60it/s]
55%|██████████████████████████████████████████████████████████████████████████████████████████▏ | 166/300 [00:54<00:50, 2.67it/s]
56%|██████████████████████████████████████████████████████████████████████████████████████████▋ | 167/300 [00:55<00:49, 2.69it/s]
56%|███████████████████████████████████████████████████████████████████████████████████████████▎ | 168/300 [00:55<00:48, 2.73it/s]
56%|███████████████████████████████████████████████████████████████████████████████████████████▊ | 169/300 [00:55<00:47, 2.78it/s]
57%|████████████████████████████████████████████████████████████████████████████████████████████▎ | 170/300 [00:56<00:46, 2.81it/s]
57%|████████████████████████████████████████████████████████████████████████████████████████████▉ | 171/300 [00:56<00:45, 2.82it/s]
57%|█████████████████████████████████████████████████████████████████████████████████████████████▍ | 172/300 [00:56<00:44, 2.85it/s]
58%|█████████████████████████████████████████████████████████████████████████████████████████████▉ | 173/300 [00:57<00:44, 2.87it/s]
58%|██████████████████████████████████████████████████████████████████████████████████████████████▌ | 174/300 [00:57<00:43, 2.88it/s]
58%|███████████████████████████████████████████████████████████████████████████████████████████████ | 175/300 [00:57<00:43, 2.89it/s]
59%|███████████████████████████████████████████████████████████████████████████████████████████████▋ | 176/300 [00:58<00:42, 2.89it/s]
59%|████████████████████████████████████████████████████████████████████████████████████████████████▏ | 177/300 [00:58<00:43, 2.83it/s]
59%|████████████████████████████████████████████████████████████████████████████████████████████████▋ | 178/300 [00:59<00:43, 2.82it/s]
60%|█████████████████████████████████████████████████████████████████████████████████████████████████▎ | 179/300 [00:59<00:42, 2.82it/s]
60%|█████████████████████████████████████████████████████████████████████████████████████████████████▊ | 180/300 [00:59<00:42, 2.83it/s]
60%|██████████████████████████████████████████████████████████████████████████████████████████████████▎ | 181/300 [01:00<00:42, 2.82it/s]
61%|██████████████████████████████████████████████████████████████████████████████████████████████████▉ | 182/300 [01:00<00:41, 2.83it/s]
61%|███████████████████████████████████████████████████████████████████████████████████████████████████▍ | 183/300 [01:00<00:41, 2.84it/s]
61%|███████████████████████████████████████████████████████████████████████████████████████████████████▉ | 184/300 [01:01<00:40, 2.87it/s]
62%|████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 185/300 [01:01<00:40, 2.86it/s]
62%|█████████████████████████████████████████████████████████████████████████████████████████████████████ | 186/300 [01:01<00:40, 2.84it/s]
62%|█████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 187/300 [01:02<00:41, 2.74it/s]
63%|██████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 188/300 [01:02<00:39, 2.83it/s]
63%|██████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 189/300 [01:02<00:38, 2.89it/s]
63%|███████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 190/300 [01:03<00:37, 2.97it/s]
64%|███████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 191/300 [01:03<00:38, 2.87it/s]
64%|████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 192/300 [01:03<00:38, 2.84it/s]
64%|████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 193/300 [01:04<00:38, 2.75it/s]
65%|█████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 194/300 [01:04<00:38, 2.79it/s]
65%|█████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 195/300 [01:05<00:36, 2.85it/s]
65%|██████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 196/300 [01:05<00:35, 2.91it/s]
66%|███████████████████████████████████████████████████████████████████████████████████████████████████████████ | 197/300 [01:05<00:35, 2.93it/s]
66%|███████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 198/300 [01:06<00:36, 2.79it/s]
66%|████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 199/300 [01:06<00:41, 2.41it/s]
67%|████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 200/300 [01:06<00:39, 2.54it/s]
67%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 201/300 [01:07<00:37, 2.61it/s]
67%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 202/300 [01:07<00:37, 2.64it/s]
68%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 203/300 [01:08<00:36, 2.63it/s]
68%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 204/300 [01:08<00:35, 2.73it/s]
68%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 205/300 [01:08<00:33, 2.81it/s]
69%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 206/300 [01:09<00:32, 2.87it/s]
69%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 207/300 [01:09<00:31, 2.93it/s]
69%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 208/300 [01:09<00:31, 2.89it/s]
70%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 209/300 [01:10<00:31, 2.85it/s]
70%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 210/300 [01:10<00:31, 2.86it/s]
70%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 211/300 [01:10<00:34, 2.58it/s]
71%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 212/300 [01:11<00:35, 2.45it/s]
71%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 213/300 [01:11<00:34, 2.54it/s]
71%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 214/300 [01:12<00:33, 2.53it/s]
72%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 215/300 [01:12<00:35, 2.42it/s]
72%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 216/300 [01:12<00:33, 2.51it/s]
72%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 217/300 [01:13<00:31, 2.60it/s]
73%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 218/300 [01:13<00:31, 2.62it/s]
73%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 219/300 [01:14<00:30, 2.67it/s]
73%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 220/300 [01:14<00:29, 2.67it/s]
74%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 221/300 [01:14<00:29, 2.67it/s]
74%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 222/300 [01:15<00:28, 2.72it/s]
74%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 223/300 [01:15<00:27, 2.78it/s]
75%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 224/300 [01:15<00:26, 2.83it/s]
75%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 225/300 [01:16<00:26, 2.86it/s]
75%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 226/300 [01:16<00:26, 2.78it/s]
76%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 227/300 [01:16<00:26, 2.75it/s]
76%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 228/300 [01:17<00:25, 2.77it/s]
76%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 229/300 [01:17<00:28, 2.52it/s]
77%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 230/300 [01:18<00:27, 2.57it/s]
77%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 231/300 [01:18<00:27, 2.54it/s]
77%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 232/300 [01:18<00:27, 2.50it/s]
78%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 233/300 [01:19<00:26, 2.53it/s]
78%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 234/300 [01:19<00:26, 2.53it/s]
78%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 235/300 [01:20<00:26, 2.48it/s]
79%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 236/300 [01:20<00:24, 2.63it/s]
79%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 237/300 [01:20<00:22, 2.74it/s]
79%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 238/300 [01:21<00:21, 2.86it/s]
80%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 239/300 [01:21<00:20, 2.91it/s]
80%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 240/300 [01:21<00:20, 2.96it/s]
80%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 241/300 [01:22<00:19, 3.01it/s]
81%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 242/300 [01:22<00:19, 3.04it/s]
81%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 243/300 [01:22<00:18, 3.04it/s]
81%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 244/300 [01:23<00:18, 3.06it/s]
82%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 245/300 [01:23<00:17, 3.06it/s]
82%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 246/300 [01:23<00:17, 3.10it/s]
82%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 247/300 [01:24<00:17, 3.03it/s]
83%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 248/300 [01:24<00:17, 3.00it/s]
83%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 249/300 [01:24<00:17, 2.99it/s]
83%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 250/300 [01:25<00:16, 3.06it/s]
84%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 251/300 [01:25<00:15, 3.13it/s]
84%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 252/300 [01:25<00:15, 3.17it/s]
84%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 253/300 [01:25<00:14, 3.20it/s]
85%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 254/300 [01:26<00:14, 3.23it/s]
85%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 255/300 [01:26<00:13, 3.23it/s]
85%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 256/300 [01:26<00:13, 3.20it/s]
86%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 257/300 [01:27<00:13, 3.21it/s]
86%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 258/300 [01:27<00:13, 3.20it/s]
86%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 259/300 [01:27<00:12, 3.22it/s]
87%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 260/300 [01:28<00:12, 3.12it/s]
87%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 261/300 [01:28<00:12, 3.16it/s]
87%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 262/300 [01:28<00:11, 3.19it/s]
88%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 263/300 [01:29<00:11, 3.20it/s]
88%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 264/300 [01:29<00:11, 3.26it/s]
88%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 265/300 [01:29<00:10, 3.31it/s]
89%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 266/300 [01:29<00:10, 3.35it/s]
89%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 267/300 [01:30<00:09, 3.35it/s]
89%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 268/300 [01:30<00:09, 3.37it/s]
90%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 269/300 [01:30<00:09, 3.38it/s]
90%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 270/300 [01:31<00:08, 3.34it/s]
90%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 271/300 [01:31<00:08, 3.30it/s]
91%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 272/300 [01:31<00:08, 3.33it/s]
91%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 273/300 [01:32<00:08, 3.35it/s]
91%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 274/300 [01:32<00:07, 3.28it/s]
92%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 275/300 [01:32<00:07, 3.30it/s]
92%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 276/300 [01:32<00:07, 3.33it/s]
92%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 277/300 [01:33<00:06, 3.29it/s]
93%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 278/300 [01:33<00:06, 3.32it/s]
93%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 279/300 [01:33<00:06, 3.34it/s]
93%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 280/300 [01:34<00:06, 3.29it/s]
94%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 281/300 [01:34<00:05, 3.29it/s]
94%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 282/300 [01:34<00:05, 3.28it/s]
94%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 283/300 [01:35<00:05, 3.31it/s]
95%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 284/300 [01:35<00:04, 3.30it/s]
95%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 285/300 [01:35<00:04, 3.32it/s]
95%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 286/300 [01:36<00:04, 3.20it/s]
96%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 287/300 [01:36<00:04, 3.13it/s]
96%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 288/300 [01:36<00:03, 3.15it/s]
96%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 289/300 [01:37<00:03, 3.10it/s]
97%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 290/300 [01:37<00:03, 3.10it/s]
97%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 291/300 [01:37<00:02, 3.13it/s]
97%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 292/300 [01:37<00:02, 3.19it/s]
98%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 293/300 [01:38<00:02, 3.20it/s]
98%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 294/300 [01:38<00:01, 3.19it/s]
98%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 295/300 [01:38<00:01, 3.16it/s]
99%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 296/300 [01:39<00:01, 3.22it/s]
99%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 297/300 [01:39<00:00, 3.22it/s]
99%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 298/300 [01:39<00:00, 3.27it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍| 299/300 [01:40<00:00, 3.27it/s]
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 300/300 [01:40<00:00, 3.27it/s]
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 300/300 [01:40<00:00, 2.99it/s]
Text(0.5, 0, 'Epoch')
The above results are effectively the same! Of course, there may be minor variations do to random initialization of the models and stochastic effects with sampling different random batches to train each model. But their final loss values and accuracies are close enough that we cannot say the MLP model cares about whether the data is scrambled or visually logical.
In other words, MLPs are permutation-invariant as we may shuffle input data and obtain the same result of model training as we saw with FashionMNIST above.
Ofcourse, one model can't accurately label the data of the other model:
for x,y in test_loader:
print(y)
normal_FashionMNIST_test_inputs, normal_FashionMNIST_test_labels = next(iter(test_loader))
shuffled_FashionMNIST_test_inputs, shuffled_FashionMNIST_test_labels = next(iter(scrambled_test_loader))
print("Model trained on standard dataset evaluating the standard dataset: " + str(multiclass_model_accuracy(model, normal_FashionMNIST_test_inputs, normal_FashionMNIST_test_labels).data.item()) + "%")
print("Model trained on shuffled dataset evaluating the shuffled dataset: " + str(multiclass_model_accuracy(scrambled_model, shuffled_FashionMNIST_test_inputs, shuffled_FashionMNIST_test_labels).data.item()) + "%")
print("Model trained on standard dataset evaluating the shuffled dataset: " + str(multiclass_model_accuracy(model, shuffled_FashionMNIST_test_inputs, shuffled_FashionMNIST_test_labels).data.item()) + "%")
print("Model trained on shuffled dataset evaluating the standard dataset: " + str(multiclass_model_accuracy(scrambled_model, normal_FashionMNIST_test_inputs, normal_FashionMNIST_test_labels).data.item()) + "%")
tensor([7, 5, 1, 5, 4, 9, 0, 2, 5, 5, 9, 1, 0, 4, 3, 8, 8, 5, 4, 5, 5, 5, 8, 9, 4, 1, 2, 1, 3, 1, 0, 6, 1, 0, 7, 3, 5, 3, 4, 2, 9, 2, 3, 5, 9, 5, 3, 0, 3, 9, 3, 5, 1, 2, 4, 0, 7, 5, 4, 8, 8, 0, 6, 8, 9, 8, 2, 0, 8, 4, 9, 8, 6, 6, 8, 9, 1, 2, 3, 2, 0, 5, 5, 2, 2, 5, 8, 9, 7, 8, 3, 8, 3, 1, 0, 0, 2, 5, 0, 9]) Model trained on standard dataset evaluating the standard dataset: 78% Model trained on shuffled dataset evaluating the shuffled dataset: 75% Model trained on standard dataset evaluating the shuffled dataset: 11% Model trained on shuffled dataset evaluating the standard dataset: 13%
The question is, is this a good thing?
Problems with Straight MLPs¶
The above three-layer model contains a rather large number of parameters. $$ \begin{align} \textrm{Layer 1} &= 784\times 128 + 128 = 100,\!480\textrm{ parameters}\\ \textrm{Layer 2} &= 128\times 64 + 64 = 8,\!256\textrm{ parameters}\\ \textrm{Layer 3} &= 64\times 10 + 10 = 650\textrm{ parameters}\\ \textrm{Total} &= 109,\!386\textrm{ parameters} \end{align} $$
Just a simple three-layer MLP contains on the order of 100,000 parameters!
Now is this a bad thing? Not neccesarily.... LLMs have trillions of parameters and they're pretty great. Big can can be worth it if they perform big tasks well.
class ShiftedFashionMNIST(Dataset):
def __init__(self, n=0, m=0):
self.n = n # Shift right
self.m = m # Shift down
self.data = torchvision.datasets.FashionMNIST(
root='./',
download=True,
train=True,
transform=transforms.ToTensor()
)
def __len__(self):
return len(self.data)
def __getitem__(self, idx): #Doing a zero-padded shift
image, label = self.data[idx] # image: [1, 28, 28]
_, H, W = image.shape
# Create a zero image
shifted_image = torch.zeros_like(image)
# Compute new ranges based on shift
y_start = self.m
x_start = self.n
y_end = H
x_end = W
# Fill the new image with shifted values from the original image
shifted_image[:, y_start:y_end, x_start:x_end] = image[:, 0:H - self.m, 0:W - self.n]
return shifted_image.reshape(-1), label
shifted_dataset = ShiftedFashionMNIST(2, 0)
shifted_train_loader = DataLoader(shifted_dataset, batch_size=batch_size, sampler=SubsetRandomSampler(train_indices))
shifted_val_loader = DataLoader(shifted_dataset, batch_size=batch_size, sampler=SubsetRandomSampler(val_indices))
shifted_test_loader = DataLoader(shifted_dataset, batch_size=N_test, sampler=SubsetRandomSampler(test_indices))
# visualize example images from original and shifted datasets
import matplotlib.pyplot as plt
idx = 365
image, label = dataset[idx]
shifted_image, shifted_label = shifted_dataset[idx]
plt.figure(figsize=(10, 6))
plt.subplot(121)
plt.imshow(image.reshape(28, 28).numpy(), 'gray')
plt.axis(False)
plt.title('Image of class {}'.format(label))
plt.subplot(122)
plt.imshow(shifted_image.reshape(28, 28).numpy(), 'gray')
plt.axis(False)
plt.title('Image of class {}'.format(shifted_label))
Text(0.5, 1.0, 'Image of class 1')
shifted_FashionMNIST_test_inputs, shifted_FashionMNIST_test_labels = next(iter(shifted_test_loader))
print("Model trained on standard dataset evaluating the shifted dataset: " + str(multiclass_model_accuracy(model, shifted_FashionMNIST_test_inputs, shifted_FashionMNIST_test_labels).data.item()) + "%")
Model trained on standard dataset evaluating the shifted dataset: 57%
And again, this is for a 26x26 image! The model would be so much bigger for a larger image.
Convolutional Layers¶
We will now look to identify a deep learning architecture that remedies these two issues by (1) utilizing spatial information at each layer and (2) not having the number of parameters scale with the size of the input data. The solution we will identify is going to rely on the fundamental operation of convolution, which we will briefly overview in the next section.
Convolutional layers:¶

Each hidden unit(s) looks at a small region of the image, and the weights are shared between all image locations.
What is convolution?¶
From Wikiepdia [2]
In mathematics (in particular, functional analysis), convolution is a mathematical operation on two functions (
$f$ and $g$ ) that produces a third function ($f∗g$), as the integral of the product of the two functions after one is reflected about the y-axis and shifted.

You've seen convolution before:¶
Prior knowledge regarding convolution may vary from student to student, so we will try to provide a concise explanation of convolution that does not require much pre-requisite experience. In ECE 210, we define convolution for continuous time signals $x(t)$ and $h(t)$ as $$ y(t)=x(t)*h(t)=\int_{-\infty}^{\infty}x(\tau)h(t-\tau)d\tau. $$
Conceptually, for each point in time $t$, we choose one signal to reverse in time and shift by $t$. At that particular flip-and-shift location $h(-(\tau-t))$, we integrate the product of $x(\tau)h(-(\tau-t))$ with respect to $\tau$. Moving to discrete-time signals $x[n]$ and $h[n]$, we have a similar definition for convolution: $$ y[n] = x[n]*h[n]=\sum_{k=-\infty}^{\infty}x[k]h[n-k]. $$
Again, we reverse one signal and shift by $n$ samples in this case. The result at time index $n$ is then the summation over all indices $k$ of the product $x[k]h[-(k-n)]$. We see then that discrete-time convolution is quite similar to continuous-time convolution where we now a discrete time variable and a summation over all time replaces an integral over all time.
The below figure gives an example of convolving $x[n]=\{2, 1, -3, 0, 4\}$ with $h[n]=\{1, 0, -1\}$ where the final result is $y[n]=\{2, 1, -5, -1, 7, 0, -4\}$.

Intuitively, at each shift location, convolution computes the dot product between the shifted signal and the subset of the stationary signal it overlaps with. Thus, convolution is performing a sort of template matching where we assess the similarity between the shifting signal against each local portion of the stationary signal.
Convolution can also be viewed as a matrix multiplication. Let's use the same example (convolving $x[n]=\left[2, 1, -3, 0, 4\right]$ with $h[n]=\left[1, 0, -1\right]$ where the final result is $y[n]=\left[2, 1, -5, -1, 7, 0, -4\right]$):
$$ \left[2, 1, -3, 0, 4\right] * \left[1, 0, -1\right] = \left[ \begin{matrix} 2 & & \\ 1 & 2 & \\ -3 & 1 & 2 \\ 0 & -3 & 1 \\ 4 & 0 & -3 \\ & 4 & 0 \\ & & 4 \\ \end{matrix} \right] \left[ \begin{matrix} 1 \\ 0 \\ -1 \\ \end{matrix} \right] $$I know it seems inefficient but it's actually more efficient when using modern GPUs with dedicated tensor multiplication units.
Moving to higher dimensions, convolution proceeds in the same manner where one signal is kept stationary while the other signal is flipped and shifted around. Let $X[i, j]\in\mathbb{R}^{H\times W}$ be an image with height $H$ and width $W$ and $H[i, j]\in\mathbb{R}^{K\times K}$ be a 2D convolutional kernel or filter of size $K\times K$. Formally, the convolution $Y[i, j]=X[i,j]*H[i,j]$ is given by $$ Y[i, j] = \sum_{k_1=0}^{H-1}\sum_{k_2=0}^{W-1}X[k_1, k_2]H[i-k_1, j-k_2]. $$ However, in practice, we do not worry about flipping the convolutional kernel since we may simply view the filters we learn as being flipped versions of the proper filter. In practice, 2D convolution looks the same as 1D convolution except we must shift in two dimensions and sum the elementwise product between the filter and the image at each shift location. The below GIF depicts the convolution of an image and filter as follows: $$ X[i, j] = \begin{bmatrix} 3 & 3 & 2 & 1 & 0\\ 0 & 0 & 1 & 3 & 1\\ 3 & 1 & 2 & 2 & 3\\ 2 & 0 & 0 & 2 & 2\\ 2 & 0 & 0 & 0 & 1 \end{bmatrix}\quad H[i, j]=\begin{bmatrix} 0 & 1 & 2\\ 2 & 2 & 0\\ 0 & 1 & 2 \end{bmatrix} $$

Convolutional neural networks¶
In the above depiction of 2D convolution, we observe two things:
- The size of the filter $H$ does not need to scale with the size of the input image $X$.
- The use of convolution promotes spatial coherence in the resulting output.
Thus, each entry in the output represents spatially meaningful information about the previous input. This suggests that we may consider replacing the fully-connected operators of multi-layer perceptrons with convolution operators for learning parameters in a machine learning model. As such, we may define a new type of model denoted by
$$ f_\theta(x) = H_K*\sigma(H_{K-1}*\sigma(H_{K-2} \cdots H_2*\sigma(H_1*x))) $$$$ \theta = \{H_1, H_2, H_3, \ldots, H_K\}, $$where each convolution operator $H_k\in\mathbb{R}^{C_{\textrm{out}}\times K_1\times K_2\times C_{\textrm{in}}}$ has a specified number of input channels, output channels, and kernel dimensions in both height and width given by $K_1$ and $K_2$, respectively.
Visual example¶
The below figure depicts a convolutional layer with 3 input channels, 2 output channels, and kernel size of $3\times 3$. For each convolutional kernel, we have a stack of 3 independent and unique $3\times 3$ filters. Convoling each kernel with the $3$-channel input image produces one 2D feature map. We also have 2 independent convolutional kernels; thus, the result of the entire convolutional layer has 2 equal-sized feature maps or feature channels.

Altogether, a convolutional layer (ignoring bias terms) has $C_{\textrm{out}}\times K_1\times K_2\times C_{\textrm{in}}$ learnable parameters.
Example of what convolutional does¶
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Step 1: Load image
image = cv2.imread('img/dog.jpeg')
if image is None:
raise FileNotFoundError("Image not found. Please check the path.")
# Step 2: Convert to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Step 3: Define a convolutional kernel
# # Example: #3d "raised effect"
# kernel = np.array([[-2, -1, 0],
# [-1, 1, 1],
# [ 0, 1, 2]])
# Example: Outline/laplacian
kernel = np.array([[1, 1, 1],
[1, -8, 1],
[1, 1, 1]])
# Step 4: Apply convolution using cv2.filter2D
convolved = cv2.filter2D(gray, -1, kernel)
# Normalize to 0–255 for display
norm_convolved = cv2.normalize(convolved, None, 0, 255, cv2.NORM_MINMAX)
# Convert to uint8 (for proper display)
norm_convolved = np.uint8(norm_convolved)
# Step 5: Show original and convolved images side by side
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.title("Original Grayscale")
plt.imshow(gray, cmap='gray')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.title("After Convolution")
plt.imshow(convolved, cmap='gray_r')
plt.axis('off')
plt.tight_layout()
plt.show()
We refer to these deep learning models that utilize convolutional layers as convolutional neural networks (CNN). Before creating a CNN and applying it to the FashionMNIST dataset, we should define some other key terminology and practices for CNNs. First, each convolutional layer has multiple parameters that must be set. The most important of these parameters are stride, padding, and kernel size.
stride: The stride of a convolutional layer determines how much the filter shifts between subsequent each elementwise product. The default choice would simply be one as we define in basic convolution. However, we may choose a stride of two, three, etc. in order to reduce the size of the resulting feature map. For example, increasing the stride from one to two will result in a feature map that is half as tall and half as wide as the input.
padding: The above examples demonstrate no padding as the convolutional kernels are not allowed to hang off the edge of the input image. The padding value determines how many zero-valued pixels are padded around the edge of the input image. We commonly choose a padding size of $\frac{K-1}{2}$ for odd-sized square kernels of size $K$ so that output feature maps match the size of input feature maps. This choice results in the convolutional kernel as being effectively "centered" at each location in the input image to produce the result at the same location in the output feature maps.
kernel size: As previously mentioned, we may choose the size of the convolutional kernels at each layer and the size may be rectangular or square. The most common choices are relatively small, square, and odd-sized kernels, e.g. $3\times 3$, $5\times 5$, $7\times 7$.
For an input image $X\in\mathbb{R}^{C_{\textrm{in}}\times H_{\textrm{in}} \times W_\textrm{in}}$ and convolutional layer with stride $s$, padding $p$, and kernel size $K_H\times K_W$, the resulting height $H_\textrm{out}$ and width $W_\textrm{out}$ of the output feature maps will be $$ \begin{align} H_\textrm{out} &= \left\lfloor\frac{H_{\textrm{in}}+2p-(K_H-1)-1}{s}+1\right\rfloor\\ W_\textrm{out} &= \left\lfloor\frac{W_{\textrm{in}}+2p-(K_W-1)-1}{s}+1\right\rfloor. \end{align} $$
Pooling Layers¶
Problem: Ideally we want our networks to be as small as possible for computational efficiency. Also, we know that adjacent values in feature maps are often redundant.
Solution:
- Stride/padding helps reduce the size of the network, but there is a more direct way to reduce the feature map:
- Pooling layers:
A pooling layer has its own kernel size and stride parameters used to mask out windows of feature maps. Within each of these windows, a simple function is applied to the elements of each feature map within the window. The kernel size and stride are commonly set to be equal; thus, the pooling operation tiles each feature map into non-overlapping segments.
The two most common forms of pooling layers are mean pooling and max pooling. As the names suggest, mean pooling computes the mean of each window while max pooling takes the maximum value within each window. The below example depicts $2\times 2$ max pooling for a single feature channel.

Classification Heads¶
Finally, after all of the convolutional layers in a CNN, we still need some mechanism for computing final class scores (respectively other scores for other machine learning tasks, e.g. regression). Suppose $Z_K\in\mathbb{R}^{C\times H\times W}$ is the final set of feature maps in a CNN with $C$ channels and size $H\times W$. One popular approach is to apply global average pooling or global max pooling to reduce each feature channel to a single value. Thus, $$ \textrm{GlobalPooling}(Z_k)\in\mathbb{R}^{C} $$ produces a length-$C$ vector. From here, a simple fully-connected layer with weight matrix $W\in\mathbb{R}^{M\times C}$ (effectively a logistic regression model) may produce class scores for the $M$ classes.
Summary of Common CNN Structure for Classification¶
In summary, a CNN for classification tasks is typically composed of convolution layers that are followed by non-linear activation functions just like we saw with MLP models. We commonly stack some number of convolution layers before appling a poolying layer, e.g. max pooling. After some number of blocks alternating convolution layers and pooling layers, we apply a global pooling operation, e.g. global max pooling, to reduce the feature maps at the last layer to a single value and thus produce a vector of feature values. Finally, we may produce class scores by applying a fully-connected layer to the feature values from the global pooling layer
For example, we may construct a 5-layer CNN as follows for input RGB images of size $H\times W$ as follows:

The below code implements this 5-layer CNN using the nn.Conv2d
function for 2D convolution, nn.MaxPool2d
function for 2D max-pooling, and the nn.AdaptiveAvgPool2d
function with the output size set to $(1, 1)$ to perform global average pooling.
Examining a Small CNN¶
a) Consider the below five-layer CNN that implements the above figure of a CNN. Suppose the input data is $X\in\mathbb{R}^{3\times 28\times 28}$ and the ground-truth labels are over $M=5$ possible classes. Determine the shape of each feature map $Z_1$, $Z_2$, $Z_3$, and $Z_4$.
$$ \begin{align} Z_1&\in\mathbb{R}^{16\times 14\times 14}\\ Z_2&\in\mathbb{R}^{32\times 7\times 7}\\ Z_3&\in\mathbb{R}^{64}\\ Z_4&\in\mathbb{R}^{5}\\ \end{align} $$b) Determine the number of parameters in each layer (all five convolutional layers and one fully connected layers) and the resulting total number of parameters. You may assume no bias terms in the convolutional layers.
$$ \begin{align} \textrm{Convolutional Layer 1}&=3\times 16\times 3\times 3=432\\ \textrm{Convolutional Layer 2}&=16\times 16\times 3\times 3=2,\!304\\ \textrm{Convolutional Layer 3}&=16\times 32\times 5\times 5=12,\!800\\ \textrm{Convolutional Layer 4}&=32\times 32\times 5\times 5=25,\!600\\ \textrm{Convolutional Layer 5}&=32\times 64\times 3\times 3=18,\!432\\ \textrm{Fully Connected Layer}&=64\times 5 + 5=325\\\\ \textrm{Total Parameters}&=59,\!893\\ \end{align} $$import torch
import torch.nn as nn
class FiveLayerCNN(nn.Module):
def __init__(self, in_channels, n_classes):
super().__init__()
self.conv1 = nn.Conv2d(in_channels=in_channels, out_channels=16, kernel_size=3, padding=1, stride=1, bias=False)
self.conv2 = nn.Conv2d(in_channels=16, out_channels=16, kernel_size=3, padding=1, stride=1, bias=False)
self.conv3 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=5, padding=2, stride=1, bias=False)
self.conv4 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2, stride=1, bias=False)
self.conv5 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1, stride=1, bias=False)
self.pooling = nn.MaxPool2d(kernel_size=2, stride=2) # max pooling layer
self.global_pooling = nn.AdaptiveAvgPool2d(output_size=(1, 1)) # global pooling layer
self.activation_fn = nn.ReLU()
self.fc = nn.Linear(64, n_classes, bias=True)
def forward(self, x):
print('Input is shape: {}'.format(x.shape))
B = x.size(0) # B is the batch size or number of examples passed to the model
x = self.activation_fn(self.conv1(x))
x = self.activation_fn(self.conv2(x))
z1 = self.pooling(x)
z1 = self.activation_fn(self.conv3(z1))
z1 = self.activation_fn(self.conv4(z1))
z2 = self.pooling(z1)
z2 = self.activation_fn(self.conv5(z2))
z3 = self.global_pooling(z2).view(B, -1) # make sure feature maps for each input image are vectorized
z4 = self.fc(z3)
print('Result after max pooling stage 1 is shape: {}'.format(z1.shape))
print('Result after max pooling stage 2 is shape: {}'.format(z2.shape))
print('Result after global average pooling is shape: {}'.format(z3.shape))
print('Result after global average pooling is shape: {}'.format(z4.shape))
return z4
in_channels = 3
n_classes = 5
model = FiveLayerCNN(in_channels, n_classes)
print(model)
B = 2 # batch size
H, W = 28, 28
input_data = torch.rand(B, in_channels, H, W)
with torch.no_grad():
class_scores = model(input_data)
print('Conv 1 Parameters: {}'.format(torch.numel(model.conv1.weight)))
print('Conv 2 Parameters: {}'.format(torch.numel(model.conv2.weight)))
print('Conv 3 Parameters: {}'.format(torch.numel(model.conv3.weight)))
print('Conv 4 Parameters: {}'.format(torch.numel(model.conv4.weight)))
print('Conv 5 Parameters: {}'.format(torch.numel(model.conv5.weight)))
print('Fully Connected Parameters: {}'.format(torch.numel(model.fc.weight)+torch.numel(model.fc.bias)))
FiveLayerCNN( (conv1): Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (conv2): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (conv3): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False) (conv4): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2), bias=False) (conv5): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (pooling): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (global_pooling): AdaptiveAvgPool2d(output_size=(1, 1)) (activation_fn): ReLU() (fc): Linear(in_features=64, out_features=5, bias=True) ) Input is shape: torch.Size([2, 3, 28, 28]) Result after max pooling stage 1 is shape: torch.Size([2, 32, 14, 14]) Result after max pooling stage 2 is shape: torch.Size([2, 64, 7, 7]) Result after global average pooling is shape: torch.Size([2, 64]) Result after global average pooling is shape: torch.Size([2, 5]) Conv 1 Parameters: 432 Conv 2 Parameters: 2304 Conv 3 Parameters: 12800 Conv 4 Parameters: 25600 Conv 5 Parameters: 18432 Fully Connected Parameters: 325
Revisiting Fashion MNIST¶
Now we will finally revisit our earlier experiments on FashionMNIST now equipped with CNNs
Self study: Run the CNN model on the FashionMNIST using the provided training and evaluation code below. Try choosing different numbers of layers (not too many, e.g. no more than 6), different type of pooling functions, different convolution layer parameters (number of feature channels, kernel size, stride, etc.) in your model to observe which design choices improve model performance.
Note Your model may take a while to train on each dataset. Alternatively, make your model shallower with fewer feature channels or have larger choices of stride in convolutional or pooling layers to speed up computation.
# fill this in!
class MyCNNModel(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1, bias=False)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1, bias=False)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1, bias=False)
self.pooling = nn.MaxPool2d(stride=2, kernel_size=2)
self.gap = nn.AdaptiveAvgPool2d((1, 1))
self.activation = nn.ReLU()
self.fc = nn.Linear(128, 10)
def forward(self, x):
B = x.size(0)
x = self.activation(self.conv1(x))
x = self.pooling(x)
x = self.activation(self.conv2(x))
x = self.pooling(x)
x = self.activation(self.conv3(x))
x = self.gap(x).view(B, -1)
z = self.fc(x)
return z
# 2D version of Fashion MNIST datasets
class FashionMNIST2D(Dataset):
def __init__(self):
self.data = torchvision.datasets.FashionMNIST(root='./',
download=True,
train=True,
transform=transforms.Compose([transforms.ToTensor()]))
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
image, label = self.data[idx]
return image, label
import numpy as np
# set up data
N = 1000
N_train = 600
N_val = 300
N_test = 100
dataset = FashionMNIST2D()
indices = np.random.choice(np.arange(len(dataset)), size=N, replace=False)
np.random.shuffle(indices)
train_indices = indices[:N_train]
val_indices = indices[N_train:N_train+N_val]
test_indices = indices[N_train+N_val:N_train+N_val+N_test]
# create separate dataloaders for regular and scrambled datasets, but they still use the same images!
batch_size = 8
train_loader = DataLoader(dataset, batch_size=batch_size, sampler=SubsetRandomSampler(train_indices))
val_loader = DataLoader(dataset, batch_size=batch_size, sampler=SubsetRandomSampler(val_indices))
# initialize model for each dataset
model = MyCNNModel()
# initialize loss function and optimizers for each dataset
criterion = nn.CrossEntropyLoss()
lr = 3e-3
optimizer = torch.optim.SGD(model.parameters(), lr=lr, momentum=0.99, weight_decay=1e-4)
# train each model on their respective datasets
n_epochs = 300
model, losses, train_accs, val_accs = training_loop(model, criterion, optimizer, n_epochs, train_loader, val_loader)
# original dataset results
plt.figure(figsize=(12,6))
plt.subplot(131)
plt.semilogy(losses)
plt.grid(True)
plt.title('Loss values (Original)')
plt.xlabel('Epoch')
plt.subplot(132)
plt.plot(train_accs)
plt.grid(True)
plt.title('Training Accuracy (Original)')
plt.xlabel('Epoch')
plt.subplot(133)
plt.plot(val_accs)
plt.grid(True)
plt.title('Validation Accuracy (Original)')
plt.xlabel('Epoch')
0%| | 0/300 [00:00<?, ?it/s]
0%|▌ | 1/300 [00:02<11:57, 2.40s/it]
1%|█ | 2/300 [00:04<11:46, 2.37s/it]
1%|█▋ | 3/300 [00:07<12:24, 2.51s/it]
1%|██▏ | 4/300 [00:09<12:12, 2.47s/it]
2%|██▊ | 5/300 [00:12<12:28, 2.54s/it]
2%|███▎ | 6/300 [00:15<12:35, 2.57s/it]
2%|███▊ | 7/300 [00:17<12:36, 2.58s/it]
3%|████▍ | 8/300 [00:20<13:03, 2.68s/it]
3%|████▉ | 9/300 [00:23<13:23, 2.76s/it]
3%|█████▍ | 10/300 [00:26<13:43, 2.84s/it]
4%|██████ | 11/300 [00:29<14:25, 2.99s/it]
4%|██████▌ | 12/300 [00:33<14:53, 3.10s/it]
4%|███████ | 13/300 [00:36<15:18, 3.20s/it]
5%|███████▋ | 14/300 [00:40<15:45, 3.31s/it]
5%|████████▏ | 15/300 [00:44<16:39, 3.51s/it]
5%|████████▋ | 16/300 [00:48<17:01, 3.60s/it]
6%|█████████▎ | 17/300 [00:51<17:03, 3.62s/it]
6%|█████████▊ | 18/300 [00:55<16:51, 3.59s/it]
6%|██████████▍ | 19/300 [00:59<17:05, 3.65s/it]
7%|██████████▉ | 20/300 [01:02<16:58, 3.64s/it]
7%|███████████▍ | 21/300 [01:05<16:30, 3.55s/it]
7%|████████████ | 22/300 [01:09<16:15, 3.51s/it]
8%|████████████▌ | 23/300 [01:12<16:16, 3.53s/it]
8%|█████████████ | 24/300 [01:16<16:15, 3.53s/it]
8%|█████████████▋ | 25/300 [01:20<16:21, 3.57s/it]
9%|██████████████▏ | 26/300 [01:23<16:32, 3.62s/it]
9%|██████████████▊ | 27/300 [01:27<16:58, 3.73s/it]
9%|███████████████▎ | 28/300 [01:31<17:25, 3.85s/it]
10%|███████████████▊ | 29/300 [01:35<17:18, 3.83s/it]
10%|████████████████▍ | 30/300 [01:39<17:19, 3.85s/it]
10%|████████████████▉ | 31/300 [01:43<17:34, 3.92s/it]
11%|█████████████████▍ | 32/300 [01:48<18:00, 4.03s/it]
11%|██████████████████ | 33/300 [01:52<18:13, 4.09s/it]
11%|██████████████████▌ | 34/300 [01:56<17:54, 4.04s/it]
12%|███████████████████▏ | 35/300 [02:00<17:52, 4.05s/it]
12%|███████████████████▋ | 36/300 [02:04<17:31, 3.98s/it]
12%|████████████████████▏ | 37/300 [02:07<16:52, 3.85s/it]
13%|████████████████████▊ | 38/300 [02:11<16:38, 3.81s/it]
13%|█████████████████████▎ | 39/300 [02:14<16:18, 3.75s/it]
13%|█████████████████████▊ | 40/300 [02:18<16:19, 3.77s/it]
14%|██████████████████████▍ | 41/300 [02:22<16:33, 3.84s/it]
14%|██████████████████████▉ | 42/300 [02:27<17:03, 3.97s/it]
14%|███████████████████████▌ | 43/300 [02:32<18:35, 4.34s/it]
15%|████████████████████████ | 44/300 [02:36<18:06, 4.25s/it]
15%|████████████████████████▌ | 45/300 [02:40<17:44, 4.17s/it]
15%|█████████████████████████▏ | 46/300 [02:44<17:54, 4.23s/it]
16%|█████████████████████████▍ | 47/300 [03:53<1:39:12, 23.53s/it]
16%|█████████████████████████▉ | 48/300 [04:01<1:19:33, 18.94s/it]
16%|██████████████████████████▍ | 49/300 [04:30<1:32:15, 22.05s/it]
17%|███████████████████████████ | 50/300 [04:35<1:09:57, 16.79s/it]
17%|███████████████████████████▉ | 51/300 [04:39<53:55, 13.00s/it]
17%|████████████████████████████▍ | 52/300 [04:43<42:41, 10.33s/it]
18%|████████████████████████████▌ | 53/300 [05:51<1:53:36, 27.60s/it]
18%|█████████████████████████████▏ | 54/300 [06:02<1:32:26, 22.55s/it]
18%|█████████████████████████████▋ | 55/300 [06:06<1:09:26, 17.01s/it]
19%|██████████████████████████████▌ | 56/300 [06:10<53:11, 13.08s/it]
19%|███████████████████████████████▏ | 57/300 [06:14<42:15, 10.43s/it]
19%|███████████████████████████████▋ | 58/300 [06:28<46:40, 11.57s/it]
20%|████████████████████████████████▎ | 59/300 [06:41<48:27, 12.06s/it]
20%|████████████████████████████████▊ | 60/300 [06:46<39:00, 9.75s/it]
20%|█████████████████████████████████▎ | 61/300 [06:50<32:05, 8.06s/it]
21%|█████████████████████████████████▉ | 62/300 [06:54<27:41, 6.98s/it]
21%|██████████████████████████████████▍ | 63/300 [07:25<55:38, 14.09s/it]
21%|██████████████████████████████████▉ | 64/300 [07:38<53:41, 13.65s/it]
22%|███████████████████████████████████▌ | 65/300 [07:42<42:47, 10.93s/it]
22%|████████████████████████████████████ | 66/300 [07:46<34:31, 8.85s/it]
22%|████████████████████████████████████▋ | 67/300 [07:50<29:02, 7.48s/it]
23%|█████████████████████████████████████▏ | 68/300 [08:04<36:21, 9.40s/it]
23%|█████████████████████████████████████▋ | 69/300 [08:17<39:38, 10.29s/it]
23%|██████████████████████████████████████▎ | 70/300 [08:21<32:57, 8.60s/it]
24%|██████████████████████████████████████▊ | 71/300 [08:26<27:53, 7.31s/it]
24%|███████████████████████████████████████▎ | 72/300 [08:30<24:50, 6.54s/it]
24%|███████████████████████████████████████▉ | 73/300 [08:39<27:37, 7.30s/it]
25%|████████████████████████████████████████▍ | 74/300 [08:50<31:10, 8.28s/it]
25%|█████████████████████████████████████████ | 75/300 [08:56<28:04, 7.49s/it]
25%|█████████████████████████████████████████▌ | 76/300 [09:01<25:12, 6.75s/it]
26%|██████████████████████████████████████████ | 77/300 [09:06<23:07, 6.22s/it]
26%|██████████████████████████████████████████▋ | 78/300 [09:11<21:47, 5.89s/it]
26%|███████████████████████████████████████████▏ | 79/300 [09:16<20:36, 5.59s/it]
27%|███████████████████████████████████████████▋ | 80/300 [09:20<19:20, 5.28s/it]
27%|████████████████████████████████████████████▎ | 81/300 [09:25<18:26, 5.05s/it]
27%|████████████████████████████████████████████▊ | 82/300 [09:29<17:26, 4.80s/it]
28%|█████████████████████████████████████████████▎ | 83/300 [09:34<17:16, 4.78s/it]
28%|█████████████████████████████████████████████▉ | 84/300 [09:39<17:47, 4.94s/it]
28%|██████████████████████████████████████████████▍ | 85/300 [09:47<21:12, 5.92s/it]
29%|███████████████████████████████████████████████ | 86/300 [09:53<20:52, 5.85s/it]
29%|███████████████████████████████████████████████▌ | 87/300 [09:59<20:43, 5.84s/it]
29%|████████████████████████████████████████████████ | 88/300 [10:04<19:59, 5.66s/it]
30%|████████████████████████████████████████████████▋ | 89/300 [10:09<19:26, 5.53s/it]
30%|█████████████████████████████████████████████████▏ | 90/300 [10:15<19:15, 5.50s/it]
30%|█████████████████████████████████████████████████▋ | 91/300 [10:20<18:52, 5.42s/it]
31%|██████████████████████████████████████████████████▎ | 92/300 [10:25<18:36, 5.37s/it]
31%|██████████████████████████████████████████████████▊ | 93/300 [10:30<18:14, 5.29s/it]
31%|███████████████████████████████████████████████████▍ | 94/300 [10:35<17:52, 5.21s/it]
32%|███████████████████████████████████████████████████▉ | 95/300 [10:40<17:28, 5.11s/it]
32%|████████████████████████████████████████████████████▍ | 96/300 [10:45<17:08, 5.04s/it]
32%|█████████████████████████████████████████████████████ | 97/300 [10:50<16:48, 4.97s/it]
33%|█████████████████████████████████████████████████████▌ | 98/300 [10:55<16:29, 4.90s/it]
33%|██████████████████████████████████████████████████████ | 99/300 [10:59<16:08, 4.82s/it]
33%|██████████████████████████████████████████████████████▎ | 100/300 [11:04<15:52, 4.76s/it]
34%|██████████████████████████████████████████████████████▉ | 101/300 [11:09<15:51, 4.78s/it]
34%|███████████████████████████████████████████████████████▍ | 102/300 [11:13<15:49, 4.80s/it]
34%|███████████████████████████████████████████████████████▉ | 103/300 [11:18<15:53, 4.84s/it]
35%|████████████████████████████████████████████████████████▌ | 104/300 [11:23<15:50, 4.85s/it]
35%|█████████████████████████████████████████████████████████ | 105/300 [11:29<16:23, 5.04s/it]
35%|█████████████████████████████████████████████████████████▌ | 106/300 [11:34<16:14, 5.02s/it]
36%|██████████████████████████████████████████████████████████▏ | 107/300 [11:39<16:10, 5.03s/it]
36%|██████████████████████████████████████████████████████████▋ | 108/300 [11:44<15:53, 4.97s/it]
36%|███████████████████████████████████████████████████████████▏ | 109/300 [11:49<15:55, 5.00s/it]
37%|███████████████████████████████████████████████████████████▊ | 110/300 [11:54<15:52, 5.01s/it]
37%|████████████████████████████████████████████████████████████▎ | 111/300 [11:59<15:53, 5.04s/it]
37%|████████████████████████████████████████████████████████████▊ | 112/300 [12:04<15:33, 4.96s/it]
38%|█████████████████████████████████████████████████████████████▍ | 113/300 [12:09<15:30, 4.98s/it]
38%|█████████████████████████████████████████████████████████████▉ | 114/300 [12:13<15:08, 4.89s/it]
38%|██████████████████████████████████████████████████████████████▍ | 115/300 [12:18<15:04, 4.89s/it]
39%|███████████████████████████████████████████████████████████████ | 116/300 [12:23<15:05, 4.92s/it]
39%|███████████████████████████████████████████████████████████████▌ | 117/300 [12:28<15:05, 4.95s/it]
39%|████████████████████████████████████████████████████████████████ | 118/300 [12:33<14:54, 4.92s/it]
40%|████████████████████████████████████████████████████████████████▋ | 119/300 [12:38<14:48, 4.91s/it]
40%|█████████████████████████████████████████████████████████████████▏ | 120/300 [12:43<14:48, 4.94s/it]
40%|█████████████████████████████████████████████████████████████████▋ | 121/300 [12:48<14:31, 4.87s/it]
41%|██████████████████████████████████████████████████████████████████▎ | 122/300 [12:52<14:16, 4.81s/it]
41%|██████████████████████████████████████████████████████████████████▊ | 123/300 [12:57<14:09, 4.80s/it]
41%|███████████████████████████████████████████████████████████████████▎ | 124/300 [13:01<13:41, 4.67s/it]
42%|███████████████████████████████████████████████████████████████████▉ | 125/300 [13:06<13:33, 4.65s/it]
42%|████████████████████████████████████████████████████████████████████▍ | 126/300 [13:11<13:18, 4.59s/it]
42%|█████████████████████████████████████████████████████████████████████ | 127/300 [13:15<13:18, 4.61s/it]
43%|█████████████████████████████████████████████████████████████████████▌ | 128/300 [13:20<13:12, 4.61s/it]
43%|██████████████████████████████████████████████████████████████████████ | 129/300 [13:25<13:34, 4.76s/it]
43%|██████████████████████████████████████████████████████████████████████▋ | 130/300 [13:30<13:34, 4.79s/it]
44%|███████████████████████████████████████████████████████████████████████▏ | 131/300 [13:35<13:37, 4.84s/it]
44%|███████████████████████████████████████████████████████████████████████▋ | 132/300 [13:40<13:36, 4.86s/it]
44%|████████████████████████████████████████████████████████████████████████▎ | 133/300 [13:45<13:32, 4.86s/it]
45%|████████████████████████████████████████████████████████████████████████▊ | 134/300 [13:49<13:21, 4.83s/it]
45%|█████████████████████████████████████████████████████████████████████████▎ | 135/300 [13:54<13:05, 4.76s/it]
45%|█████████████████████████████████████████████████████████████████████████▉ | 136/300 [13:59<12:58, 4.75s/it]
46%|██████████████████████████████████████████████████████████████████████████▍ | 137/300 [14:03<12:50, 4.73s/it]
46%|██████████████████████████████████████████████████████████████████████████▉ | 138/300 [14:08<12:51, 4.76s/it]
46%|███████████████████████████████████████████████████████████████████████████▌ | 139/300 [14:13<12:46, 4.76s/it]
47%|████████████████████████████████████████████████████████████████████████████ | 140/300 [14:17<12:28, 4.68s/it]
47%|████████████████████████████████████████████████████████████████████████████▌ | 141/300 [14:22<12:18, 4.64s/it]
47%|█████████████████████████████████████████████████████████████████████████████▏ | 142/300 [14:27<12:25, 4.72s/it]
48%|█████████████████████████████████████████████████████████████████████████████▋ | 143/300 [14:31<12:17, 4.70s/it]
48%|██████████████████████████████████████████████████████████████████████████████▏ | 144/300 [14:36<11:59, 4.62s/it]
48%|██████████████████████████████████████████████████████████████████████████████▊ | 145/300 [14:40<11:54, 4.61s/it]
49%|███████████████████████████████████████████████████████████████████████████████▎ | 146/300 [14:45<12:01, 4.69s/it]
49%|███████████████████████████████████████████████████████████████████████████████▊ | 147/300 [14:50<12:03, 4.73s/it]
49%|████████████████████████████████████████████████████████████████████████████████▍ | 148/300 [14:55<11:57, 4.72s/it]
50%|████████████████████████████████████████████████████████████████████████████████▉ | 149/300 [15:00<11:57, 4.75s/it]
50%|█████████████████████████████████████████████████████████████████████████████████▌ | 150/300 [15:05<11:59, 4.80s/it]
50%|██████████████████████████████████████████████████████████████████████████████████ | 151/300 [15:09<11:51, 4.77s/it]
51%|██████████████████████████████████████████████████████████████████████████████████▌ | 152/300 [15:14<11:41, 4.74s/it]
51%|███████████████████████████████████████████████████████████████████████████████████▏ | 153/300 [15:18<11:26, 4.67s/it]
51%|███████████████████████████████████████████████████████████████████████████████████▋ | 154/300 [15:23<11:28, 4.71s/it]
52%|████████████████████████████████████████████████████████████████████████████████████▏ | 155/300 [15:28<11:29, 4.76s/it]
52%|████████████████████████████████████████████████████████████████████████████████████▊ | 156/300 [15:33<11:29, 4.79s/it]
52%|█████████████████████████████████████████████████████████████████████████████████████▎ | 157/300 [15:38<11:23, 4.78s/it]
53%|█████████████████████████████████████████████████████████████████████████████████████▊ | 158/300 [15:42<11:05, 4.69s/it]
53%|██████████████████████████████████████████████████████████████████████████████████████▍ | 159/300 [15:47<11:14, 4.78s/it]
53%|██████████████████████████████████████████████████████████████████████████████████████▉ | 160/300 [15:52<11:11, 4.80s/it]
54%|███████████████████████████████████████████████████████████████████████████████████████▍ | 161/300 [15:57<11:05, 4.78s/it]
54%|████████████████████████████████████████████████████████████████████████████████████████ | 162/300 [16:02<10:59, 4.78s/it]
54%|████████████████████████████████████████████████████████████████████████████████████████▌ | 163/300 [16:06<10:56, 4.79s/it]
55%|█████████████████████████████████████████████████████████████████████████████████████████ | 164/300 [16:11<10:47, 4.76s/it]
55%|█████████████████████████████████████████████████████████████████████████████████████████▋ | 165/300 [16:16<10:49, 4.81s/it]
55%|██████████████████████████████████████████████████████████████████████████████████████████▏ | 166/300 [16:21<10:52, 4.87s/it]
56%|██████████████████████████████████████████████████████████████████████████████████████████▋ | 167/300 [16:26<10:54, 4.92s/it]
56%|███████████████████████████████████████████████████████████████████████████████████████████▎ | 168/300 [16:31<11:00, 5.00s/it]
56%|███████████████████████████████████████████████████████████████████████████████████████████▊ | 169/300 [16:36<10:58, 5.03s/it]
57%|████████████████████████████████████████████████████████████████████████████████████████████▎ | 170/300 [16:42<11:05, 5.12s/it]
57%|████████████████████████████████████████████████████████████████████████████████████████████▉ | 171/300 [16:47<11:01, 5.13s/it]
57%|█████████████████████████████████████████████████████████████████████████████████████████████▍ | 172/300 [16:52<10:37, 4.98s/it]
58%|█████████████████████████████████████████████████████████████████████████████████████████████▉ | 173/300 [16:56<10:22, 4.90s/it]
58%|██████████████████████████████████████████████████████████████████████████████████████████████▌ | 174/300 [17:01<10:12, 4.86s/it]
58%|███████████████████████████████████████████████████████████████████████████████████████████████ | 175/300 [17:06<10:17, 4.94s/it]
59%|███████████████████████████████████████████████████████████████████████████████████████████████▋ | 176/300 [17:11<10:16, 4.97s/it]
59%|████████████████████████████████████████████████████████████████████████████████████████████████▏ | 177/300 [17:16<10:07, 4.94s/it]
59%|████████████████████████████████████████████████████████████████████████████████████████████████▋ | 178/300 [17:21<09:57, 4.90s/it]
60%|█████████████████████████████████████████████████████████████████████████████████████████████████▎ | 179/300 [17:26<09:57, 4.94s/it]
60%|█████████████████████████████████████████████████████████████████████████████████████████████████▊ | 180/300 [17:31<09:59, 5.00s/it]
60%|██████████████████████████████████████████████████████████████████████████████████████████████████▎ | 181/300 [17:36<09:56, 5.02s/it]
61%|██████████████████████████████████████████████████████████████████████████████████████████████████▉ | 182/300 [17:41<09:43, 4.95s/it]
61%|███████████████████████████████████████████████████████████████████████████████████████████████████▍ | 183/300 [17:46<09:36, 4.93s/it]
61%|███████████████████████████████████████████████████████████████████████████████████████████████████▉ | 184/300 [17:51<09:29, 4.91s/it]
62%|████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 185/300 [17:55<09:22, 4.89s/it]
62%|█████████████████████████████████████████████████████████████████████████████████████████████████████ | 186/300 [18:00<09:14, 4.86s/it]
62%|█████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 187/300 [18:05<09:11, 4.88s/it]
63%|██████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 188/300 [18:10<09:11, 4.92s/it]
63%|██████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 189/300 [18:15<09:12, 4.98s/it]
63%|███████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 190/300 [18:21<09:17, 5.06s/it]
64%|███████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 191/300 [18:26<09:08, 5.03s/it]
64%|████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 192/300 [18:31<09:05, 5.05s/it]
64%|████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 193/300 [18:35<08:52, 4.98s/it]
65%|█████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 194/300 [18:40<08:34, 4.86s/it]
65%|█████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 195/300 [18:45<08:22, 4.79s/it]
65%|██████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 196/300 [18:49<08:16, 4.77s/it]
66%|███████████████████████████████████████████████████████████████████████████████████████████████████████████ | 197/300 [18:54<08:11, 4.77s/it]
66%|███████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 198/300 [18:59<08:06, 4.77s/it]
66%|████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 199/300 [19:04<07:59, 4.75s/it]
67%|████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 200/300 [19:08<07:52, 4.72s/it]
67%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 201/300 [19:13<07:47, 4.73s/it]
67%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 202/300 [19:18<07:45, 4.75s/it]
68%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 203/300 [19:23<07:47, 4.82s/it]
68%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 204/300 [19:28<07:46, 4.86s/it]
68%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 205/300 [19:33<07:47, 4.92s/it]
69%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 206/300 [19:38<07:39, 4.89s/it]
69%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 207/300 [19:42<07:32, 4.86s/it]
69%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 208/300 [19:47<07:24, 4.83s/it]
70%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 209/300 [19:52<07:20, 4.84s/it]
70%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 210/300 [19:57<07:16, 4.85s/it]
70%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 211/300 [20:02<07:06, 4.80s/it]
71%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 212/300 [20:06<07:04, 4.83s/it]
71%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 213/300 [20:11<06:53, 4.75s/it]
71%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 214/300 [20:16<06:48, 4.75s/it]
72%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 215/300 [20:21<06:44, 4.76s/it]
72%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 216/300 [20:25<06:43, 4.81s/it]
72%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 217/300 [20:30<06:41, 4.84s/it]
73%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 218/300 [20:36<06:43, 4.92s/it]
73%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 219/300 [20:41<06:41, 4.95s/it]
73%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 220/300 [20:46<06:37, 4.97s/it]
74%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 221/300 [20:51<06:34, 5.00s/it]
74%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 222/300 [20:56<06:30, 5.01s/it]
74%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 223/300 [21:01<06:26, 5.02s/it]
75%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 224/300 [21:06<06:23, 5.04s/it]
75%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 225/300 [21:11<06:21, 5.09s/it]
75%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 226/300 [21:16<06:14, 5.05s/it]
76%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 227/300 [21:21<06:09, 5.06s/it]
76%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 228/300 [21:26<06:06, 5.10s/it]
76%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 229/300 [21:31<05:59, 5.06s/it]
77%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 230/300 [21:36<05:45, 4.94s/it]
77%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 231/300 [21:41<05:40, 4.94s/it]
77%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 232/300 [21:46<05:34, 4.92s/it]
78%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 233/300 [21:50<05:26, 4.88s/it]
78%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 234/300 [21:55<05:20, 4.85s/it]
78%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 235/300 [22:00<05:13, 4.82s/it]
79%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 236/300 [22:05<05:08, 4.83s/it]
79%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 237/300 [22:10<05:05, 4.85s/it]
79%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 238/300 [22:15<05:06, 4.94s/it]
80%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 239/300 [22:20<05:06, 5.02s/it]
80%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 240/300 [22:25<05:04, 5.07s/it]
80%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 241/300 [22:31<05:02, 5.13s/it]
81%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 242/300 [22:36<04:59, 5.16s/it]
81%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 243/300 [22:41<04:48, 5.06s/it]
81%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 244/300 [22:45<04:40, 5.00s/it]
82%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 245/300 [22:50<04:31, 4.95s/it]
82%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 246/300 [22:55<04:24, 4.90s/it]
82%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 247/300 [23:00<04:21, 4.93s/it]
83%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 248/300 [23:05<04:20, 5.01s/it]
83%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 249/300 [23:10<04:13, 4.97s/it]
83%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 250/300 [23:15<04:09, 4.99s/it]
84%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 251/300 [23:20<04:01, 4.93s/it]
84%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 252/300 [23:25<03:59, 4.99s/it]
84%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 253/300 [23:30<03:50, 4.90s/it]
85%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 254/300 [23:35<03:44, 4.88s/it]
85%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 255/300 [23:40<03:42, 4.93s/it]
85%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 256/300 [23:45<03:40, 5.00s/it]
86%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 257/300 [23:50<03:36, 5.04s/it]
86%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 258/300 [23:55<03:34, 5.10s/it]
86%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 259/300 [24:00<03:27, 5.05s/it]
87%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 260/300 [24:05<03:19, 4.98s/it]
87%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 261/300 [24:10<03:11, 4.91s/it]
87%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 262/300 [24:15<03:06, 4.90s/it]
88%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 263/300 [24:19<02:58, 4.81s/it]
88%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 264/300 [24:24<02:49, 4.72s/it]
88%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 265/300 [24:28<02:43, 4.68s/it]
89%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 266/300 [24:33<02:38, 4.66s/it]
89%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 267/300 [24:38<02:34, 4.68s/it]
89%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 268/300 [24:42<02:28, 4.65s/it]
90%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 269/300 [24:47<02:22, 4.58s/it]
90%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 270/300 [24:51<02:15, 4.50s/it]
90%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 271/300 [24:56<02:12, 4.57s/it]
91%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 272/300 [25:00<02:09, 4.61s/it]
91%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 273/300 [25:05<02:04, 4.62s/it]
91%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 274/300 [25:10<02:01, 4.66s/it]
92%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 275/300 [25:15<01:57, 4.69s/it]
92%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 276/300 [25:19<01:52, 4.71s/it]
92%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 277/300 [25:24<01:48, 4.74s/it]
93%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 278/300 [25:29<01:44, 4.77s/it]
93%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 279/300 [25:34<01:40, 4.78s/it]
93%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 280/300 [25:39<01:36, 4.81s/it]
94%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 281/300 [25:43<01:29, 4.71s/it]
94%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 282/300 [25:48<01:25, 4.77s/it]
94%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 283/300 [25:53<01:22, 4.85s/it]
95%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 284/300 [25:58<01:19, 4.99s/it]
95%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 285/300 [26:03<01:14, 4.98s/it]
95%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 286/300 [26:08<01:09, 4.95s/it]
96%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 287/300 [26:13<01:03, 4.92s/it]
96%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍ | 288/300 [26:18<00:58, 4.87s/it]
96%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 289/300 [26:22<00:52, 4.82s/it]
97%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 290/300 [26:27<00:48, 4.81s/it]
97%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | 291/300 [26:32<00:42, 4.75s/it]
97%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 292/300 [26:37<00:38, 4.75s/it]
98%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 293/300 [26:41<00:33, 4.72s/it]
98%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 294/300 [26:46<00:28, 4.75s/it]
98%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 295/300 [26:51<00:24, 4.82s/it]
99%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 296/300 [26:56<00:19, 4.92s/it]
99%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 297/300 [27:01<00:14, 4.98s/it]
99%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉ | 298/300 [27:06<00:10, 5.02s/it]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▍| 299/300 [27:11<00:05, 5.02s/it]
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 300/300 [27:17<00:00, 5.07s/it]
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 300/300 [27:17<00:00, 5.46s/it]
Text(0.5, 0, 'Epoch')
About the same performance (though definitely becoming overtrained). Bu there are other benefits....
class ShiftedFashionMNIST2D(Dataset):
def __init__(self, n=0, m=0):
self.n = n # Shift right
self.m = m # Shift down
self.data = torchvision.datasets.FashionMNIST(
root='./',
download=True,
train=True,
transform=transforms.ToTensor()
)
def __len__(self):
return len(self.data)
def __getitem__(self, idx): #Doing a zero-padded shift
image, label = self.data[idx] # image: [1, 28, 28]
_, H, W = image.shape
# Create a zero image
shifted_image = torch.zeros_like(image)
# Compute new ranges based on shift
y_start = self.m
x_start = self.n
y_end = H
x_end = W
# Fill the new image with shifted values from the original image
shifted_image[:, y_start:y_end, x_start:x_end] = image[:, 0:H - self.m, 0:W - self.n]
return shifted_image, label
shifted2D_dataset = ShiftedFashionMNIST2D(2, 0)
shifted2D_train_loader = DataLoader(shifted2D_dataset, batch_size=batch_size, sampler=SubsetRandomSampler(train_indices))
shifted2D_val_loader = DataLoader(shifted2D_dataset, batch_size=batch_size, sampler=SubsetRandomSampler(val_indices))
shifted2D_test_loader = DataLoader(shifted2D_dataset, batch_size=N_test, sampler=SubsetRandomSampler(test_indices))
shifted_FashionMNIST2D_test_inputs, shifted_FashionMNIST2D_test_labels = next(iter(shifted2D_test_loader))
print("CNN model trained on standard dataset evaluating the shifted dataset: " + str(multiclass_model_accuracy(model, shifted_FashionMNIST2D_test_inputs, shifted_FashionMNIST2D_test_labels).data.item()) + "%")
CNN model trained on standard dataset evaluating the shifted dataset: 70%
That's it for today¶
- Midterm grades will be posted later today.
- My office hours will be online instead of in-person.
- Project descriptions will be posted early next week.
- HW7 will be posted tomorrow.
- Have a good weekend!
References¶
[1] Roger Grosse CSC321 lectures - https://www.cs.toronto.edu/~rgrosse/courses/csc321_2018/
[2] Wikpedia - Convolution - https://en.wikipedia.org/wiki/Convolution