A genetic NN with PyTorch -- extracting output layer for the fitness function

maria.solyanik: <p>I am trying to build my first genetic NN. I have to admit that I am not that proficient in ML and I probably should have started from something more basic, but here I am…</p>
<p>I have this simple CNN for MNIST, inspired by <a href="https://medium.com/@nutanbhogendrasharma/pytorch-convolutional-neural-network-with-mnist-dataset-4e8a4265e118" rel="noopener nofollow ugc">these</a>. I want to extract weights from each forward-processed image-label pair so that then I could write a custom fitness function for the GNN.</p>
<pre><code>import torch
from pylab import *

from torchvision import datasets
from torchvision.transforms import ToTensor

train_data = datasets.MNIST(
    root = 'data',
    train = True,                         
    transform = ToTensor(), 
    download = True,            
)
test_data = datasets.MNIST(
    root = 'data', 
    train = False, 
    transform = ToTensor()
)

from torch.utils.data import DataLoader
loaders = {
    'train' : torch.utils.data.DataLoader(train_data, 
                                          batch_size=1, 
                                          shuffle=True, 
                                          num_workers=1),
    
    'test'  : torch.utils.data.DataLoader(test_data, 
                                          batch_size=1, 
                                          shuffle=True, 
                                          num_workers=1),
}
loaders

import torch.nn as nn

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Sequential(         
            nn.Conv2d(
                in_channels=1,              
                out_channels=16,            
                kernel_size=5,              
                stride=1,                   
                padding=2,                  
            ),                              
            nn.ReLU(),                      
            nn.MaxPool2d(kernel_size=2),    
        )
        self.conv2 = nn.Sequential(         
            nn.Conv2d(16, 32, 5, 1, 2),     
            nn.ReLU(),                      
            nn.MaxPool2d(2),                
        )
        self.out = nn.Linear(32 * 7 * 7, 10)
    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)
        output = self.out(x)
        return output, x

cnn = CNN()
activation = {}
def getActivation(name):
  # the hook signature
  def hook(model, input, output):
    activation[name] = output.detach()
  return hook

h = cnn.out.register_forward_hook(getActivation('out'))
from torch.autograd import Variable

num_epochs = 1
def train(num_epochs, cnn, loaders):

  cnn.train()

images, labels = next(iter(loaders['train']))

imshow(torch.squeeze(images))

print(labels)

b_x = Variable(images)   # batch x
b_y = Variable(labels)   # batch y
output = cnn(b_x)[0] 

print(activation['out'])
h.remove()
</code></pre>
<p>My question is how do the values in activation relate to the actual final accuracy, and how do one “reads” negative values? I was expecting ten tensor elements to be proportional to what the NN “thinks” of where the input image belongs to: if the largest float in activation tensor is the 4th element, then at this point CNN “thinks” that the input image is an integer “3”.</p>

eqy: <p>The logits (last layer model activations) for this kind of multiclass classification problem typically go through a softmax to convert the output to a probability distribution: <a href="https://pytorch.org/docs/stable/generated/torch.nn.Softmax.html" rel="noopener nofollow ugc">Softmax — PyTorch 1.11.0 documentation</a>.</p>
<p>In this case negative values just move the value of exp(x) closer to zero.</p>