Training resnet18 - output of resnet18(images)

Sorry, for bothering you again.

I am trying to train a resnet18 model to classify images into three different classes. Therefore, I wrote a class train_one_epoch. I would like to calculate the accuracy of the training during one epoch, so I wrote a class accuracy, too. I know, that this kind of accuracy class only siuts binary classifications. The images I feed the netowrk with are in RGB and 350x350. However, I was wondering, why the size of my outputs is [8, 1000] after passing the images to the network. Shouldn’t it be [8, 3]. Afterwards I could
use the maximum as predicted class or am I missing something essential?

Any help is appreciated.

# device configuration, use cuda if possible
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# define hyper-parameters
num_epochs = 10
learning_rate = 0.001
batchsize = 8

resnet18 = models.resnet18()
resnet18.fc.out_features = 3
# print(resnet18)
resnet18.to(device)

...

def accuracy(outputs, trues):
    
    ### Converting preds to 0 or 1
    outputs = [1 if outputs[i] >= 0.5 else 0 for i in range(len(outputs))]
    print(outputs)
    
    ### Calculating accuracy by comparing predictions with true labels
    acc = [1 if outputs[i] == trues[i] else 0 for i in range(len(outputs))]
    
    ### Summing over all correct predictions
    acc = np.sum(acc) / len(outputs)
    
    return (acc * 100)


# train the model with the help of a for-loop
total_step = len(train_data_loader)
curr_lr = learning_rate

def train_one_epoch(train_data_loader):
    epoch_loss = []
    epoch_acc = []
    start_time = time.time()
    
    for images, labels in train_data_loader:
        images = images.to(device)
        labels = labels.to(device)

        # forward pass
        optimizer.zero_grad()
        outputs = resnet18(images)
        print(outputs.size())
        print(labels.size())
        
        # calculating accuracy and loss
        _loss = criterion(outputs, labels)
        loss = _loss.item()
        epoch_loss.append(loss)
        acc = accuracy(outputs, labels)
        epoch_acc.append(acc)

        # backward and optimize
        _loss.backward()
        optimizer.step()
        
    end_time = time.time()
    total_time = end_time - start_time
    
    ###Acc and Loss
    epoch_loss = np.mean(epoch_loss)
    epoch_acc = np.mean(epoch_acc)
    
    ###Storing results to logs
    train_logs["loss"].append(epoch_loss)
    train_logs["accuracy"].append(epoch_acc)
    train_logs["time"].append(total_time)
    
    return epoch_loss, epoch_acc, total_time

Changing the out_features of an already initialized module won’t work:

resnet18.fc.out_features = 3

since the internal parameters were already created.
You should create a new nn.Linear module and assign it to the .fc attribute:

model = models.resnet18()
mdoel.fc = nn.Linear(512, 3)

Thanks ptrblack, but when I add the lines you proposed, I get another error message during the calculation of the loss and backwarding it:

RuntimeError: cuda runtime error (710) : device-side assert triggered at C:/cb/pytorch_1000000000000/work/aten/src\THC/generic/THCTensorMath.cu:29

After that, if I try to run the code again, I alawys get the following error message:

RuntimeError: CUDA error: device-side assert triggered

This one is raised with passing the model to cuda, quiet in the beginning of the code.

EDIT:

I solved this error by substracting 1 to each label:
labels = labels - 1
The indexing of the labels should start with 0 and end with the number of classes - 1. Is this correct?

Yes, nn.CrossEntropyLoss as well as nn.NLLLoss expects the target tensor to be a LongTensor containing the class indices in the range [0, nb_classes-1]. :slight_smile: