No description has been provided for this image

Lecture 15 - Convolutional neural networks¶

ECE364 - Programming Methods for Machine Learning¶

Nickvash Kani¶

Slides based off prior lectures by Alex Schwing, Aigou Han, Farzad Kamalabadi, Corey Snyder. All mistakes are my own!¶

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.

In [1]:
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()
In [2]:
# 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))
Out[2]:
Text(0.5, 1.0, 'Image of class 1')
No description has been provided for this image

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.

In [3]:
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
In [4]:
# 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]

Out[4]:
Text(0.5, 0, 'Epoch')
No description has been provided for this image
No description has been provided for this image

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:

In [5]:
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.

In [6]:
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))
In [7]:
# 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))
Out[7]:
Text(0.5, 1.0, 'Image of class 1')
No description has been provided for this image
In [8]:
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.

Fully connected layers:¶

No description has been provided for this image

Each hidden unit looks at entire image.

Locally connected layers:¶

No description has been provided for this image

Each hidden unit(s) looks at a small region of the image.

Convolutional layers:¶

No description has been provided for this image

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.

No description has been provided for this image

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\}$.

No description has been provided for this image

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} $$

No description has been provided for this image

Convolutional neural networks¶

In the above depiction of 2D convolution, we observe two things:

  1. The size of the filter $H$ does not need to scale with the size of the input image $X$.
  2. 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.

No description has been provided for this image

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¶

In [9]:
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()
No description has been provided for this image

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:

  1. Stride/padding helps reduce the size of the network, but there is a more direct way to reduce the feature map:
  2. 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.

No description has been provided for this image

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:

No description has been provided for this image

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} $$
In [10]:
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.

In [11]:
# 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 
In [12]:
# 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
In [13]:
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]

Out[13]:
Text(0.5, 0, 'Epoch')
No description has been provided for this image

About the same performance (though definitely becoming overtrained). Bu there are other benefits....

In [14]:
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))    
In [15]:
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