这是一篇来自美国的关于从头开始编码一个卷积神经网络,以便使用PyTorch对图像进行分类的机器学习代写
Convolutional Neural Networks
In this assignment, you’ll be coding up a convolutional neural network from scratch to classify images using PyTorch.
Instructions
Install PyTorch following the instructions here (https://pytorch.org/).
Install the torchinfo package (https://github.com/TylerYep/torchinfo) to visualize the network architecture and the number of parameters. The maximum number of parameters you are allowed to use for your network is 100,000.
You are required to complete the functions defined in the code blocks following each question. Fill out sections of the code marked “YOUR CODE HERE” .
You’re free to add any number of methods within each class.
You may also add any number of additional code blocks that you deem necessary.
Once you’ve filled out your solutions, submit the notebook on Canvas.
Do NOT forget to type in your name and UIN at the beginning of the notebook.
Data Preparation
In [ ]:
!pip install torchinfo
In [ ]:
# Importing the libraries
import os
import torch
import torchvision
from torchvision.utils import make_grid
import numpy as np
In this assignment, we will use the Fashion-MNIST dataset. Fashion-MNIST is a dataset of Zalando’s article images—consisting of a training set of 60,000 examples and a test set of 10,000 examples. Each example is a 28×28 grayscale image, associated with a label from 10 classes.Data
Each image is 28 pixels in height and 28 pixels in width, for a total of 784 pixels in total. Each pixel has a single pixel-value associated with it, indicating the lightness or darkness of that pixel, with higher numbers meaning darker. This pixel-value is an integer between 0 and 255.
Labels
Each training and test example is assigned to one of the following labels:
Label Description
0 T-shirt/top
1 Trouser
2 Pullover
3 Dress
4 Coat
5 Sandal
6 Shirt
7 Sneaker
8 Bag
9 Ankle boot
Fashion-MNIST is included in the torchvision library.
In [ ]:
In [ ]:
Data Exploration
Let’s take a look at the classes in our dataset.
In [ ]:
from torchvision.datasets import FashionMNIST
from torchvision.transforms import Compose, ToTensor, Normalize
# Transform to normalize the data and convert to a tensor
transform = Compose([ToTensor(),
Normalize((0.5,), (0.5,))
])
# Download the data
dataset = FashionMNIST(‘MNIST_data/’, download = True, train = True, transform = transform)
print(dataset.classes)In [ ]:
import matplotlib.pyplot as plt
def show_example(img, label):
print(‘Label: {} ({})’.format(dataset.classes[label], label))
plt.imshow(img.squeeze(), cmap=’Greys_r’)
plt.axis(False)
In [ ]:
show_example(*dataset[20])
In [ ]:
show_example(*dataset[20000])
Creating Training and Validation Datasets
The split_indices function takes in the size of the entire dataset, n , the fraction of data to be used as validation set, val_frac , and the random seed and returns the indices of the data points to be added to the validation dataset.
Choose a suitable fraction for your validation set and experiment with the seed. Remember that the better your validation set, the higher the chances that your model would do well on the test set.
In [ ]:
def split_indices(n, val_frac, seed):
# Determine the size of the validation set
n_val = int(val_frac * n)
np.random.seed(seed)
# Create random permutation between 0 to n-1
idxs = np.random.permutation(n)
# Pick first n_val indices for validation set
return idxs[n_val:], idxs[:n_val]
In [ ]:
######################
# YOUR CODE BELOW #
######################
val_frac = ## Set the fraction for the validation set
rand_seed = ## Set the random seed
train_indices, val_indices = split_indices(len(dataset), val_frac, rand_seed)
print(“#samples in training set: {}”.format(len(train_indices)))
print(“#samples in validation set: {}”.format(len(val_indices)))
Next, we make use of the built-in dataloaders in PyTorch to create iterables of our our training and validation sets. This helps in avoiding fitting the whole dataset into memory and only loads a batch of the data that we can decide.Set the batch_size depending on the hardware resource (GPU/CPU RAM) you are using for the assignment
In [ ]:
from torch.utils.data.sampler import SubsetRandomSampler
from torch.utils.data.dataloader import DataLoader
In [ ]:
######################
# YOUR CODE BELOW #
######################
batch_size = ## Set the batch size
In [ ]:
# Training sampler and data loader
train_sampler = SubsetRandomSampler(train_indices)
train_dl = DataLoader(dataset,
batch_size,
sampler=train_sampler)
# Validation sampler and data loader
val_sampler = SubsetRandomSampler(val_indices)
val_dl = DataLoader(dataset,
batch_size,
sampler=val_sampler)
Plot images in a sample batch of data.
In [ ]:
def show_batch(dl):
for images, labels in dl:
fig, ax = plt.subplots(figsize=(10,10))
ax.set_xticks([]); ax.set_yticks([])
ax.imshow(make_grid(images, 8).permute(1, 2, 0), cmap=’Greys_r’)
break
In [ ]:
show_batch(train_dl)
Building the Model
Grading: 20 pts for Build the Model section
They don’t have to have the exact same model, e.g., the number of layers can be different, the parameters in the model
The very first parameter of the first layer has to be 1 nn.Conv2d(1, ….), because this is black-white dataset, otherwise -5pts
The very last parameter of the last layer has to be 10 nn.Linear(…, 10), otherwise -20pts.using nn.Conv1d (if ever happens) -20pts.
M P
l2d 10
Create your model by defining the network architecture in the ImageClassifierNet class.
NOTE: The number of parameters in your network must be ≤ 100,000.
In [ ]:
In [ ]:
In [ ]:
The following code block prints your network architecture. It also shows the total number of parameters inyour network (see Total params ).
NOTE: The total number of parameters in your model should be <= 100,000.
In [ ]:
##Check Model Requirements status
Below code cell is to check if your model meets the requirements specefied
Run the cell to check the status of your model
# Import the libraries
import torch.nn as nn
import torch.nn.functional as F
from torchinfo import summary
class ImageClassifierNet(nn.Module):
def __init__(self, n_channels=3):
super(ImageClassifierNet, self).__init__()
######################
# YOUR CODE HERE #
######################
def forward(self, X):
######################
# YOUR CODE HERE #
######################
model = ImageClassifierNet()
summary(model, input_size=(batch_size, 1, 28, 28))
In [ ]:
def check_model(model):
first_layer = list(model.children())[0]
last_layer = list(model.children())[-1]
num_params = sum(p.numel() for p in model.parameters())
has_conv1d = False
has_maxpool2d = False
first_layer_status= False
last_layer_status = False
if isinstance(first_layer, nn.Sequential):
if isinstance(first_layer[0], nn.Conv2d) and first_layer[0].in_channels == 1:
first_layer_status= True
else:
if isinstance(first_layer, nn.Conv2d) and first_layer.in_channels == 1:
first_layer_status= True
if isinstance(last_layer, nn.Sequential):
if isinstance(last_layer[-1], nn.Linear) and last_layer[-1].out_features == 10:
last_layer_status = True
else:
print(type(last_layer))
if isinstance(last_layer, nn.Linear) and last_layer.out_features == 10:
last_layer_status = True
for layer in model.modules():
if isinstance(layer, nn.Conv1d):
has_conv1d = True
if isinstance(layer, nn.MaxPool2d):
has_maxpool2d = True
flag = False
if first_layer_status == False:
print(“The very first parameter of the first layer is not 1 nn.Conv2d(1, ….)”)
flag = True
if last_layer_status == False:
print(“The very last parameter of the last layer is not 10 nn.Linear(…, 10)”)
flag = True
if has_conv1d == True:
print(“Using nn.Conv1d, which should not happen”)
flag = True
if has_maxpool2d == False:
print(“No nn.MaxPool2d”)
flag = True
if num_params > 100000:
print(“Parameters > 100000, please make the network less complex to recieve full grade”)
if flag == False:
print(“The Network looks good”)
check_model(model)
Enable training on a GPU
NOTE: This section is necessary if you’re training your model on a GPU.