Возникла эта ошибка при классификации изображений, содержащих 10 классов в pytorch, в ResNet50. Мой код: - PullRequest
0 голосов
/ 03 марта 2020

Это код, который я реализую: я использую подмножество набора данных CalTech256 для классификации изображений 10 различных видов животных. Мы go закончим подготовку набора данных, добавим данные, а затем предпримем шаги по созданию классификатора.

def train_and_validate(model, loss_criterion, optimizer, epochs=25):
    '''
    Function to train and validate
    Parameters
        :param model: Model to train and validate
        :param loss_criterion: Loss Criterion to minimize
        :param optimizer: Optimizer for computing gradients
        :param epochs: Number of epochs (default=25)

    Returns
        model: Trained Model with best validation accuracy
        history: (dict object): Having training loss, accuracy and validation loss, accuracy
    '''

    start = time.time()
    history = []
    best_acc = 0.0

    for epoch in range(epochs):
        epoch_start = time.time()
        print("Epoch: {}/{}".format(epoch+1, epochs))

        # Set to training mode
        model.train()

        # Loss and Accuracy within the epoch
        train_loss = 0.0
        train_acc = 0.0

        valid_loss = 0.0
        valid_acc = 0.0

        for i, (inputs, labels) in enumerate(train_data_loader):

            inputs = inputs.to(device)
            labels = labels.to(device)

            # Clean existing gradients
            optimizer.zero_grad()

            # Forward pass - compute outputs on input data using the model
            outputs = model(inputs)

            # Compute loss
            loss = loss_criterion(outputs, labels)

            # Backpropagate the gradients
            loss.backward()

            # Update the parameters
            optimizer.step()

            # Compute the total loss for the batch and add it to train_loss
            train_loss += loss.item() * inputs.size(0)

            # Compute the accuracy
            ret, predictions = torch.max(outputs.data, 1)
            correct_counts = predictions.eq(labels.data.view_as(predictions))

            # Convert correct_counts to float and then compute the mean
            acc = torch.mean(correct_counts.type(torch.FloatTensor))

            # Compute total accuracy in the whole batch and add to train_acc
            train_acc += acc.item() * inputs.size(0)

            #print("Batch number: {:03d}, Training: Loss: {:.4f}, Accuracy: {:.4f}".format(i, loss.item(), acc.item()))


        # Validation - No gradient tracking needed
        with torch.no_grad():

            # Set to evaluation mode
            model.eval()

            # Validation loop
            for j, (inputs, labels) in enumerate(valid_data_loader):
                inputs = inputs.to(device)
                labels = labels.to(device)

                # Forward pass - compute outputs on input data using the model
                outputs = model(inputs)

                # Compute loss
                loss = loss_criterion(outputs, labels)

                # Compute the total loss for the batch and add it to valid_loss
                valid_loss += loss.item() * inputs.size(0)

                # Calculate validation accuracy
                ret, predictions = torch.max(outputs.data, 1)
                correct_counts = predictions.eq(labels.data.view_as(predictions))

                # Convert correct_counts to float and then compute the mean
                acc = torch.mean(correct_counts.type(torch.FloatTensor))

                # Compute total accuracy in the whole batch and add to valid_acc
                valid_acc += acc.item() * inputs.size(0)

                #print("Validation Batch number: {:03d}, Validation: Loss: {:.4f}, Accuracy: {:.4f}".format(j, loss.item(), acc.item()))

        # Find average training loss and training accuracy
        avg_train_loss = train_loss/train_data_size 
        avg_train_acc = train_acc/train_data_size

        # Find average training loss and training accuracy
        avg_valid_loss = valid_loss/valid_data_size 
        avg_valid_acc = valid_acc/valid_data_size

        history.append([avg_train_loss, avg_valid_loss, avg_train_acc, avg_valid_acc])

        epoch_end = time.time()

        print("Epoch : {:03d}, Training: Loss: {:.4f}, Accuracy: {:.4f}%, \n\t\tValidation : Loss : {:.4f}, Accuracy: {:.4f}%, Time: {:.4f}s".format(epoch, avg_train_loss, avg_train_acc*100, avg_valid_loss, avg_valid_acc*100, epoch_end-epoch_start))

        # Save if the model has best accuracy till now
        torch.save(model, dataset+'_model_'+str(epoch)+'.pt')

    return model, history

# Load pretrained ResNet50 Model
resnet50 = models.resnet50(pretrained=True)
#resnet50 = resnet50.to('cuda:0')


# Freeze model parameters
for param in resnet50.parameters():
    param.requires_grad = False
# Change the final layer of ResNet50 Model for Transfer Learning
fc_inputs = resnet50.fc.in_features

resnet50.fc = nn.Sequential(
    nn.Linear(fc_inputs, 256),
    nn.ReLU(),
    nn.Dropout(0.4),
    nn.Linear(256, num_classes), # Since 10 possible outputs
    nn.LogSoftmax(dim=1) # For using NLLLoss()
)

# Convert model to be used on GPU
# resnet50 = resnet50.to('cuda:0')

# Change the final layer of ResNet50 Model for Transfer Learning
fc_inputs = resnet50.fc.in_features

resnet50.fc = nn.Sequential(
    nn.Linear(fc_inputs, 256),
    nn.ReLU(),
    nn.Dropout(0.4),
    nn.Linear(256, num_classes), # Since 10 possible outputs
    nn.LogSoftmax(dienter code herem=1) # For using NLLLoss()
)

# Convert model to be used on GPU
# resnet50 = resnet50.to('cuda:0')`enter code here`

Ошибка заключается в следующем:


RuntimeError Traceback (самое последнее последний вызов) in () 6 # Обучить модель 25 эпохам 7 num_epochs = 30 ----> 8 train_model, history = train_and_validate (resnet50, loss_fun c, оптимизатор, num_epochs) 9 10 torch.save (history, dataset + '_history.pt')

в train_and_validate (модель, loss_criterion, оптимизатор, эпохи) 43 44 # Вычислить потери ---> 45 loss = loss_criterion (выходные данные, метки) 46 47 # Обратно распространять градиенты

~ \ Anaconda3 \ lib \ site-packages \ torch \ nn \ modules \ module.py in call (self, * input, ** kwargs) 539 result = self._slow_forward (* input, ** kwargs) 540 else: -> 541 result = self.forward (* input, ** kwargs) 542 для ловушки в self._forward_hooks.values ​​(): 543 hook_result = hook (self, input, result)

~ \ Anaconda3 \ lib \ site-packages \ torch \ nn \ modules \ loss.py в forward (self, input, target) 202 203 def forward (self, input, target): -> 204 return F.nll_loss (вход, target, weight = self.weight, ignore_index = self.ignore_index, сокращение = self.reduction) 205 206

~ \ Anaconda3 \ lib \ site-packages \ torch \ nn \ functions.py в nll_loss (вход, цель, вес, size_average, ignore_index, уменьшение, уменьшение) 1836 .format (input.size (0), target. size (0))) 1837, если dim == 2: -> 1838 ret = torch ._ C ._ nn.nll_loss (вход, цель, вес, _Reduction.get_enum (сокращение), ignore_index) 1839 elif dim == 4 : 1840 ret = torch ._ C ._ nn.nll_loss2d (вход, цель, вес, _Reduction.get_enum (сокращение), ignore_index)

RuntimeError: Ошибка утверждения `cur_target> = 0 && cur_target

1 Ответ

1 голос
/ 03 марта 2020

Это происходит, когда в вашем наборе данных имеются неправильные метки, или метки индексируются 1 (вместо 0). Начиная с сообщения об ошибке, cur_target должно быть меньше, чем общее количество классов (10). Чтобы проверить проблему, проверьте максимальную и минимальную метки в вашем наборе данных. Если данные действительно индексируются 1, просто минус одна из всех аннотаций, и с вами все будет в порядке.

Обратите внимание, еще одна возможная причина заключается в том, что в данных существует несколько меток -1. Некоторые (особенно старые) наборы данных используют -1 как указание на неправильную / сомнительную метку. Если вы найдете такие ярлыки, просто отбросьте их.

...