<jupyter_start><jupyter_text>Creating a Convolutional Neural Network-Dogs-v-Cats  Imports<jupyter_code>import os
import numpy as np
import cv2
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.nn.functional as F<jupyter_output><empty_output><jupyter_text>Creating a NN<jupyter_code>class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 32, (3,3))
        self.conv2 = nn.Conv2d(32, 64, (3,3))
        self.conv3 = nn.Conv2d(64, 64, (3,3))<jupyter_output><empty_output><jupyter_text>> The layers input and output size, and a kernel size of `3x3` which is also known as the kennel window. The first `conv1` will output `32` which will be the input of `conv2` which has a kernel size of `3x3` and outputing `64`. > Now we need to flatten the output at some point to a `dense` layer with an activation function, because now if we look at the last layer it is not flat. So we need to flatten the output of the last layer before passing it to the dense layer. **How do we do that?** > We are ging to solve this by creating a fake, torch tesor and get the shape of the last `conv` by applying some max_pooling in the `conv` function.<jupyter_code>class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 32, (3,3))
        self.conv2 = nn.Conv2d(32, 64, (3,3))
        self.conv3 = nn.Conv2d(64, 128, (3,3))
        self.x = torch.randn(200,200).view(-1, 1,200,200)
        self._to_linear = None
        self.conv(self.x)
        
        self.fc1 = nn.Linear(self._to_linear, 32)
        self.fc2 = nn.Linear(32, 2)
        
    def conv(self, x):
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, kernel_size=(2, 2))
#         print()
        #print(x.shape)
        
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, kernel_size =(2, 2))
        x = F.relu(self.conv3(x))
        x = F.max_pool2d(x, kernel_size =(2, 2))
        if self._to_linear is None:
            self._to_linear = x[0].shape[0] * x[0].shape[1] * x[0].shape[2]
        return x
        
    def forward(self, x):
        x = self.conv(x)
#         print(self._to_linear)
#         type(x)
        x = x.view(-1, self._to_linear) ##
        x = F.relu(self.fc1(x))
        return F.softmax(self.fc2(x), dim=1)<jupyter_output><empty_output><jupyter_text>> **What is going on here?*** first we created a dummy torch tensor `x` with a shape of `1x1x200x200`* we created a `_to_linear` local variable that will helps us to keep tracking our shape.    * The idea here is to say, when we get the shape we want to `multiply` all dimensions and asign the value to `_to_linear`* We created our `conv` function that will help us to update the value of the `_to_linear` when it is called.* First we applied a `relu` activation function to our first `conv1` layer* We then apply `max_pool2d` with a kernel_size of `2x2`* We do this for all `layers`* Since we have assigned `_to_linear` to **None** we want to check if it is still none. If that's the case we will multiply all shapes of the element `x`.* We will create our forward function as usual and imidiately call conv function and get the shape. We will reshape `x` to the new `_to_linear` value, that is flattening it* Apply a `relu` activation function* return the output with softmax activation function applied<jupyter_code>net = Net()
net
128*23*23<jupyter_output><empty_output><jupyter_text>Model Training<jupyter_code>from torch import optim
optimizer = optim.Adam(net.parameters(), lr=1e-3)
loss_function = nn.MSELoss()<jupyter_output><empty_output><jupyter_text>> We are going to use the `Adam` optimizer* Since we have `one_hot` vectors, we're going to use `MSELoss` metric.  Data> We are now going to load our data and split it into `train` and `test`<jupyter_code>data = np.load('cats_v_dogs.npy', allow_pickle=True)
len(data)
type(data)<jupyter_output><empty_output><jupyter_text>> We want to convert this data to `toch.Tensor`<jupyter_code>X = torch.Tensor([(i[0]) for i in data]).view(-1, 200, 200)
y = torch.Tensor([i[1] for i in data])
X.view((-1, 200, 200)).shape<jupyter_output><empty_output><jupyter_text>> Split the data into `train` and `test`.<jupyter_code>X_train = X[:150]
y_train = y[:150]

X_test = X[-150:]
y_test = y[-150:]
EPOCHS = 10
BATCH_SIZE = 5
for epoch in range(EPOCHS):
    print(f'Epochs: {epoch+1}/{EPOCHS}')
    for i in range(0, len(y_train), BATCH_SIZE):
        X_batch = X_train[i: i+BATCH_SIZE].view(-1, 1, 200, 200)
        y_batch = y_train[i: i+BATCH_SIZE]
        
        net.zero_grad() ## or you can say optimizer.zero_grad()
        
        outputs = net(X_batch)
        loss = loss_function(outputs, y_batch)
        loss.backward()
        optimizer.step()
    print("Loss", loss)
total, correct = 0, 0
with torch.no_grad():
    for i in range(len(X_test)):
        correct_label = torch.argmax(y_test[i])
        prediction = torch.argmax(net(X_test[i].view(-1, 1, 200, 200))[0])
    
        if prediction == correct_label:
            correct+=1
        total +=1
        
    print(f"Accuracy: {correct/total}")<jupyter_output><empty_output><jupyter_text>Making predictions> We are going to predict one of the image that is in our `test` and visualise it. Remember `cat=0` and `dog=1`.<jupyter_code>class_names = ["cat", "dog"]
def plotImages(images, labels, cmap="gray"):
    plt.figure()
    for i in range(len(labels)):
        plt.subplot(221+i)
        plt.title(class_names[labels[i]])
        plt.imshow(images[i], cmap=cmap)
    plt.show()
images = X_test[4:6]

predictions = []
for image in images:
    prediction_index = torch.argmax(net(image.view(-1,1, 200, 200))[0])
    predictions.append(prediction_index)
plotImages(images, predictions)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1243763977292276, 'fraction_numerical': 0.0330294168243592, 'mean_word_length': 3.493044822256569, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '32670', 'license': 'MIT', 'n_tokens_mistral': 2149, 'n_tokens_neox': 2040, 'n_words': 629, 'path': '02_Neural_Nets/02_Conv_NNets/01_cats_v_dogs/02_Creating_CNNet.ipynb', 'repo_name': 'CrispenGari/pytorch-python', 'size': '5813'}