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). I use mini-batch of 4.When I train my classifier, my labels is a list of 3 elements and it looks like that:
tensor([[ 2., 10., 5.],
[ 2., 5., 0.],
[14., 0., 0.],
[ 1., 0., 0.]]) , where 0 means there is no genre for that position available
and my output at the last stage is
tensor([[-0.0968, -0.0381, -0.0629, -0.0519, 0.1343, -0.0395, 0.0480, -0.0035,
0.0559, -0.0791, 0.0652, 0.0573, -0.0751, 0.0459, -0.0035],
[-0.0978, -0.0385, -0.0551, -0.0518, 0.1312, -0.0432, 0.0539, 0.0017,
0.0460, -0.0868, 0.0627, 0.0534, -0.0666, 0.0420, 0.0013],
[-0.0939, -0.0549, -0.0444, -0.0664, 0.1229, -0.0561, 0.0458, 0.0021,
0.0328, -0.0869, 0.0710, 0.0462, -0.0734, 0.0459, 0.0065],
[-0.0916, -0.0274, -0.0734, -0.0436, 0.1443, -0.0329, 0.0525, -0.0043,
0.0679, -0.0738, 0.0639, 0.0557, -0.0754, 0.0459, -0.0087]],
my total number of genres is 15 , therefore my last fully connected layer gives me the output of a list with 15 weights. But now, the problem is, I don’t know which Loss Function to choose here, so it would properly calculate loss of my problem. I tried CrossEntropy, but it does not work since it does not support multilabeling problem. ( multi-target not supported at c:\new-builder_3\win-wheel\pytorch\aten\src\thnn\generic/ClassNLLCriterion.c:21)
I also tried nn.MultiLabelSoftMarginLoss(),
but here the problem is that the numbers of elemetns in my output and target do not match t, 60 != 12… S
o I am wondering what would be the best LossFunction in this case and how to implement it…
Currently trainin part in my code looks like that:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 10, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(10, 20, 5)
self.fc1 = nn.Linear(20 * 22 * 39, 100)
self.fc2 = nn.Linear(100, 50)
self.fc3 = nn.Linear(50, 10)
self.fc4 = nn.Linear(10,3)
def forward(self, x):
x = x.view(-1, 3, 100, 170)
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 20 * 22 * 39)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = F.relu(self.fc3(x))
x = self.fc4(x)
#print(x)
return x
net = Net()
import torch.optim as optim
criterion = nn.MultiLabelSoftMarginLoss()#nn.CrossEntropyLoss()#BCEWithLogitsLoss()#
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
########################################################################
4. Train the network
^^^^^^^^^^^^^^^^^^^^
for epoch in range(4): # loop over the dataset multiple times
losses = []
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# get the inputs
inputs, labels = data
inputs = inputs.float()
labels = labels.float()
# 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 % 200 == 199: # print every 2000 mini-batches
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 200))
running_loss = 0.0
print('Finished Training')