Точность для каждой эпохи в Pytorch - PullRequest
0 голосов
/ 09 мая 2020

Я изо всех сил пытаюсь вычислить точность для каждой эпохи в моей обучающей функции для классификатора CNN в Pytorch.

После запуска этого скрипта он всегда выводит 0, 0,25 или 0,75, что, очевидно, неверно. Я предполагаю, что проблема заключается во входных данных функции get_accuracy (выходы и метки), поскольку они не накапливаются за всю эпоху, но не знаю, как это исправить.

В идеале, я хотел бы распечатать и тренировочную, и тестовую точность для каждой эпохи.

def get_accuracy(pred, actual):
  assert len(pred) == len(actual)

  total = len(actual)
  _, predicted = torch.max(pred.data, 1)
  correct = (predicted == actual).sum().item()
  return correct / total


def train_model(model):
    for epoch in range(epochs):
        running_loss = 0.00
        for i, data in enumerate(trainloader, 0):
            inputs, labels = data
            inputs, labels = inputs.to(device), labels.to(device)

            optimizer.zero_grad()

            outputs = cnn(inputs)

            loss = criterion(outputs, labels) 
            loss.backward() 
            optimizer.step() 

            running_loss += loss.item() #calculates loss of the batch in average

        running_loss /= len(trainloader)

        training_accuracy = get_accuracy(outputs, labels)
        test_accuracy = 'todo'

        print('='*10,'iteration: {0}'.format(epoch+1),'='*10,)
        print('\n Loss: {0} \n Training accuracy:{1}% \n Test accuracy: {2}%'.format(running_loss, training_accuracy, test_accuracy))

    print('Finished Training')

Ответы [ 2 ]

0 голосов
/ 09 мая 2020

Я предполагаю, что вы хотите рассчитать точность для случая мультикласса (так что ваши классы имеют форму [0, 1, 2, 3, ..., N]).

Вы используете maximum, тогда как это должно быть argmax, например:

def accuracy(predictions, labels):
    classes = torch.argmax(predictions, dim=1)
    return torch.mean((classes == labels).float())

Этот индекс возврата с максимальным значением, в то время как вы возвращаете максимальную вероятность (или ненормализованную вероятность). Поскольку вероятность почти никогда не равна 1, вы всегда должны иметь нулевую точность (до float точности, иногда она может быть действительно близкой к 0 или 1, поэтому она может "попасть").

Например, 0.9 != 2, и вы никогда не сможете предсказать класс 2, но вы можете случайно предсказать класс 1 (0.999999999 ~= 1).

Эта функция должна вызываться внутри вашего внутреннего l oop, точно так же, как вы рассчитываете потери, поэтому это будет:

for epoch in range(epochs):
    running_loss = 0.00
    running_accuracy = 0.00
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data inputs, labels = inputs.to(device), labels.to(device)
        optimizer.zero_grad() 
        outputs = cnn(inputs) 
        loss = criterion(outputs, labels)
        loss.backward() 
        optimizer.step() 
        running_loss += loss.item()
        running_accuracy += accuracy(outputs, labels)
    running_loss /= len(trainloader)
    running_accuracy /= len(trainloader)

То же самое будет go для тестирования и проверки, просто переключите вашу модель в режим оценки (через model.eval()) и отключить градиент с помощью with torch.no_grad(): диспетчера контекста).

0 голосов
/ 09 мая 2020

Ну, во-первых, ваши входные и выходные данные не накапливаются за всю эпоху, при расчете точности учитывается только последняя итерация вашего загрузчика поезда. Если вы хотите рассчитать точность, у вас есть 2 варианта:

  1. Либо накапливайте ввод и вывод вручную после каждой итерации, а затем вычисляйте точность.
  2. Рассчитывайте точность на каждой итерации и усредняйте их за один период перед печатью.
...