How to predict a label in MultiClass classification model in pytorch?
I am currently working on my  mini-project, where I predict movie genres based on their posters. So in the dataset that I have, each movie can have from 1 to 3 genres, therefore each instance can belong to multiple classes. I have total of 15 classes(15 genres). So now I am facing with the problem of how to do predictions  using pytorch for this particular problem.

In pytorch CIFAR-tutorial, where each instance can have only one class ( for example, if image is a car it should belong to class of cars) and there are 10 classes in total. So in this case, model prediction is defined in the following way(copying code snippet from pytorch website):

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

for epoch in range(2):  # loop over the dataset multiple times

running_loss = 0.0
for i, data in enumerate(trainloader, 0):
    # get the inputs
    inputs, labels = data

    # zero the parameter gradients
    optimizer.zero_grad()

    # forward + backward + optimize
    outputs = net(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()

    # print statistics
    running_loss += loss.item()
    if i % 2000 == 1999:    # print every 2000 mini-batches
        print('[%d, %5d] loss: %.3f' %
              (epoch + 1, i + 1, running_loss / 2000))
        running_loss = 0.0


print('Finished Training')

Question 1(for training part). What could you suggest to use  as an activation function. I was thinking about BCEWithLogitsLoss() but I am not sure how good it will be.

and then the accuracy of prediction for testset is defined in the following way:
for the entire network:

correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))


and for each class:

class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()
            class_total[label] += 1


for i in range(10):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i]))


where the output is as follows:

Accuracy of plane : 36 % 
Accuracy of   car : 40 % 
Accuracy of  bird : 30 % 
Accuracy of   cat : 19 % 
Accuracy of  deer : 28 % 
Accuracy of   dog : 17 % 
Accuracy of  frog : 34 % 
Accuracy of horse : 43 % 
Accuracy of  ship : 57 % 
Accuracy of truck : 35 % 


Now here is question 2:
How can I determine the accuracy so it would look in the following way:

For example:

The Matrix (1999)                ['Action: 91%', 'Drama: 25%', 'Adventure: 13%']
The Others (2001)                ['Drama: 76%', 'Horror: 65%', 'Action: 41%']
Alien: Resurrection (1997)       ['Horror: 67%', 'Action: 64%', 'Drama: 43%']
The Martian (2015)               ['Drama: 95%', 'Adventure: 81%']


Considering that every movie does not always have 3 genres, sometimes is 2 and sometimes is 1. So  as I see it, I should find 3 maximum values, 2 maximum values or 1 maximum value of my output list , which is list of 15 genres so, for example, if 

my predicted genres are [Movie, Adventure] then 

some_kind_of_function(outputs) should give me output of 

[1 0 0 0 0 0 0 0 0 0 0 1 0 0 0] , 

which I can compare afterwards with ground_truth.
 I don't think torchmax will work in this case, cause it gives only one max value from [weigts array], so

What's the best way to implement it?

Thank you in advance, appreciate any help or suggestion:)


You're right, you're looking to perform binary classification (is poster X a drama movie or not? Is it an action movie or not?) for each poster-genre pair. BinaryCrossEntropy(WithLogits) is the way to go.
Regarding the best metric to evaluate your resulting algorithm, it's up to you, what are you looking for. But you may want to investigate ideas like precision and recall or f1 score. Personally, I would probably pick the top 3 for each genre (since that's at max number of genres assigned to each poster) and look if the ones to be expected show up with high probability and if the unexpected ones (in case of a movie with 2 "ground truth" genres) show at the last places, with significantly less probability assigned.

