<jupyter_start><jupyter_text>Imports<jupyter_code>import torch
import torch.nn as nn #All neural network layers definitions are present
import torch.nn.functional as F #functional api for NN layers, used to adding activations
import torch.optim as optim #Optimizers are defined here
from torch.utils.data import DataLoader #Data management for NN
import torchvision.datasets as datasets #Datasets for the NN
import torchvision.transforms as transforms #Data transform for augmentation<jupyter_output><empty_output><jupyter_text>Create Convolutional Neural NetworkHow to calculate the output channels at each layer: $$ n_{out}= [\frac{n_{in} + 2p - k}{s}] + 1  $$$n_{in}:$ no of input features $n_{out}:$ no of output features $k:$ convolutional kernel size $p:$ convolutional padding size $s:$ convolutional stride size<jupyter_code>class CNN(nn.Module):  #subclassing/inheriting from nn.Module
  def __init__(self,in_channels= 1,num_classes= 10):  #input_size= 28x28 = 784
    super(CNN,self).__init__() #calls the init function of the parent class(nn.Module)
    self.conv1= nn.Conv2d(in_channels=1,out_channels=8,kernel_size=(3,3),stride=(1,1),padding=(1,1))
    self.pool= nn.MaxPool2d(kernel_size=(2,2),stride=(2,2))
    self.conv2= nn.Conv2d(in_channels=8,out_channels=16,kernel_size=(3,3),stride=(1,1),padding=(1,1))
    self.fc1= nn.Linear(16*7*7,num_classes)

  def forward(self,x):
    x= F.relu(self.conv1(x))
    x= self.pool(x)
    x= F.relu(self.conv2(x))
    x= self.pool(x)
    x= x.reshape(x.shape[0],-1)
    x= self.fc1(x)
    return x

# Testing the class with some random generated values
# model= CNN()
# x= torch.randn((64,1,28,28))
# print(model(x).shape)<jupyter_output><empty_output><jupyter_text>Set Device<jupyter_code>device= torch.device('cuda' if torch.cuda.is_available() else 'cpu')<jupyter_output><empty_output><jupyter_text>Hyperparameters<jupyter_code>in_channel= 1
num_classes= 10
learning_rate= 0.001
batch_size= 64
num_epochs= 1<jupyter_output><empty_output><jupyter_text>Load Data<jupyter_code>train_dataset= datasets.MNIST(root='datasets/',train=True,transform=transforms.ToTensor(),download=True)
train_loader= DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)

test_dataset= datasets.MNIST(root='datasets/',train=False,transform=transforms.ToTensor(),download=True)
test_loader= DataLoader(dataset=test_dataset,batch_size=batch_size,shuffle=True)<jupyter_output>Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to datasets/MNIST/raw/train-images-idx3-ubyte.gz<jupyter_text>Initialize network<jupyter_code>model= CNN(in_channels=1,num_classes=num_classes).to(device)<jupyter_output><empty_output><jupyter_text>Loss & Optimizers<jupyter_code>criterion= nn.CrossEntropyLoss()
optimizer= optim.Adam(model.parameters(),lr=learning_rate)<jupyter_output><empty_output><jupyter_text>Train Network<jupyter_code>for epoch in range(num_epochs):
    for batch_idx,(data,targets) in enumerate(train_loader):
        data= data.to(device)
        targets= targets.to(device)
        # print(data.shape) #here we have to reshape the input from (64x1x28x28) to (64x764) which is basically unrolling
        # data= data.reshape(data.shape[0],-1)

        #forward propagation
        scores= model(data)
        loss= criterion(scores,targets)

        #backward propagation
        optimizer.zero_grad()
        loss.backward()

        #gradient descent
        optimizer.step()<jupyter_output><empty_output><jupyter_text>Check accuracy on training & test to see how good our model is<jupyter_code>def check_accuracy(loader,model):
    num_correct= 0
    num_samples= 0
    model.eval()

    with torch.no_grad():
        if loader.dataset.train:
            print("Checking accuracy on Training data")
        else:
            print("Checking accuracy on Testing data")

        for x,y in loader:
            x= x.to(device)
            y= y.to(device)
            # print('y: ',y)
            # x= x.reshape(x.shape[0],-1)
            scores= model(x)  #batch x num_classes   Here 'model' is the trained
            # print('scores: ',scores)
            _,predictions= scores.max(1)
            # print('vals: ',_,predictions)
            # break
            num_correct += (predictions == y).sum()
            num_samples += predictions.size(0)
        print(f'Got {num_correct}/{num_samples} with accuracy {float(num_correct)/float(num_samples)*100:.2f} %')

    model.train()

check_accuracy(train_loader,model)
check_accuracy(test_loader,model)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1251921809795739, 'fraction_numerical': 0.020206457280913682, 'mean_word_length': 4.75, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '172622', 'license': 'MIT', 'n_tokens_mistral': 1616, 'n_tokens_neox': 1534, 'n_words': 302, 'path': 'new/1002_Pytorch_CNN.ipynb', 'repo_name': 'novoforce/Exploring-Pytorch', 'size': '4553'}