Пользовательская функция потерь, вызывающая ошибку в индексах - PullRequest
0 голосов
/ 25 февраля 2020

Я создал пользовательские функции потерь следующим образом:

def my_loss(outputs, labels):

    """
    Args:
        outputs - output of network ([batch size, 3]) 
        labels  - desired labels  ([batch size, 3])
    """

    loss = torch.zeros(1, dtype=torch.float, requires_grad=True)
    loss = loss.to(device)

    #----------------------------------------------
    # implementation needed here 
    #----------------------------------------------
    batch_size = outputs.size()[0]            # batch_size
    outputs = F.log_softmax(outputs, dim=1)   # compute the log of softmax values
    outputs = outputs[range(batch_size), labels] # pick the values corresponding to the labels
    loss = -torch.sum(outputs)/num_examples

    # Observe: If you need to iterate and add certain values to loss defined above
    # you cannot write: loss +=... because this will raise the error: 
    # "Leaf variable was used in an inplace operation"
    # Instead, to avoid this error write: loss = loss + ...    

    return loss

Но когда я запускаю фактическое обучение NN, я получаю следующую ошибку, я искал в Интернете, но ничего не смог найти solid, которые могут мне помочь:

IndexError                                Traceback (most recent call last)
<ipython-input-31-5992a9440f01> in <module>
     18             train_losses,
     19             validation_losses,
---> 20             epochs=2)

<ipython-input-30-2fa819e6c600> in train_model(model, optimizer, train_loader, validation_loader, train_losses, validation_losses, epochs)
     29             # Forward pass
     30             outputs = model(inputs.float())
---> 31             loss = my_loss(outputs, labels)
     32 
     33             # Backward and optimize

<ipython-input-25-1e2caf3c6a5e> in my_loss(outputs, labels)
     18     batch_size = outputs.size()[0]            # batch_size
     19     outputs = F.log_softmax(outputs, dim=1)   # compute the log of softmax values
---> 20     outputs = outputs[range(batch_size), labels] # pick the values corresponding to the labels
     21     loss = -torch.sum(outputs)/num_examples
     22 

IndexError: tensors used as indices must be long, byte or bool tensors

Вот вспомогательные функции, которые используют функцию my_loss:

def validate_model(model, loader):
    """
    This function parses a given loader and returns the avergae (per image) loss 
    (as defined by "my_loss") of the entire dataset associated with the given loader.

    Args:
        model  - neural network to examine
        loader - where input data comes from (train, validation, or test)

    returns:
        average loss per image in variable named "avg_loss"
    """

    model.eval()  # eval mode (batchnorm uses moving mean/variance instead of mini-batch mean/variance)
                  # (dropout is set to zero)

    #----------------------------------------------
    # implementation needed here 
    #----------------------------------------------
    labels = next(iter(loader['labels']))
    avg_loss = my_loss(model,labels)

    model.train()  #back to default
    return avg_loss

def train_model(model,
                optimizer,
                train_loader,
                validation_loader,
                train_losses,
                validation_losses,
                epochs=1):

    """
    Trains a neural network. 
    Args:
        model               - model to be trained
        optimizer           - optimizer used for training
        train_loader        - loader from which data for training comes 
        validation_loader   - loader from which data for validation comes (maybe at the end, you use test_loader)
        train_losses        - adding train loss value to this list for future analysis
        validation_losses   - adding validation loss value to this list for future analysis
        epochs              - number of runs over the entire data set 
    """

    #----------------------------------------------
    # implementation needed here 
    #----------------------------------------------

    for epoch in range(epochs):
        for i, data in enumerate(loader, 0):
            inputs = (data['image']).to(device)
            labels = (data['labels']).to(device)
            # Forward pass
            outputs = model(inputs.float())
            loss = my_loss(outputs, labels)

            # Backward and optimize
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

    return 

Процесс, вызывающий ошибку:

# Using two lists (train_losses, validation_losses) containing history of losses 
# (i.e., loss for each training epoch) for train and validation sets. 
# If these are not defined, we define them. Otherwise, the function train_model
# updates these two lists (by adding loss values when it is called for further training) 
# in order to be able to visualize train and validation losses


if not 'train_losses' in vars():
    train_losses = []
if not 'validation_losses' in vars():
    validation_losses = []


train_model(model, 
            optimizer,
            train_loader, 
            validation_loader, 
            train_losses, 
            validation_losses,
            epochs=2)
...