web-dev-qa-db-fra.com

Manque de mémoire pendant l'évaluation dans Pytorch

Je forme un mannequin en pytorch. Toutes les 10 époques, j'évalue le train et l'erreur de test sur l'ensemble du train et du jeu de données de test. Pour une raison quelconque, la fonction d'évaluation provoque une mémoire insuffisante sur mon GPU. C'est étrange car j'ai la même taille de lot pour la formation et l'évaluation. Je crois que cela est dû au fait que la méthode net.forward () est appelée répétée et que toutes les valeurs cachées sont stockées en mémoire, mais je ne sais pas comment contourner cela?

def evaluate(self, data):
    correct = 0
    total = 0
    loader = self.train_loader if data == "train" else self.test_loader
    for step, (story, question, answer) in enumerate(loader):
        story = Variable(story)
        question = Variable(question)
        answer = Variable(answer)
        _, answer = torch.max(answer, 1)

        if self.config.cuda:
            story = story.cuda()
            question = question.cuda()
            answer = answer.cuda()

        pred_prob = self.mem_n2n(story, question)[0]
        _, output_max_index = torch.max(pred_prob, 1)
        toadd = (answer == output_max_index).float().sum().data[0]
        correct = correct + toadd
        total = total + captions.size(0)

    acc = correct / total
    return acc
10
user3768533

Je pense que cela échoue pendant la validation parce que vous n'utilisez pas optimizer.zero_grad(). Le zero_grad exécute detach, faisant du tenseur une feuille. Il est couramment utilisé à chaque époque de la partie formation.

L'utilisation de l'indicateur volatile dans Variable de PyTorch 0.4.0 a été supprimée. Réf - migration_guide_to_0.4.

À partir de 0.4.0, pour éviter le calcul du gradient lors de la validation, utilisez torch.no_grad ()

Exemple de code du guide de migration.

# evaluate
with torch.no_grad():                   # operations inside don't track history
  for input, target in test_loader:
      ...

Pour 0.3.X, l'utilisation de volatile devrait fonctionner.

14
MonsieurBeilto

Je suggère d'utiliser volatile indicateur défini sur True pour toutes les variables utilisées lors de l'évaluation,

    story = Variable(story, volatile=True)
    question = Variable(question, volatile=True)
    answer = Variable(answer, volatile=True)

Ainsi, les gradients et l'historique des opérations ne sont pas stockés et vous économiserez beaucoup de mémoire. Vous pouvez également supprimer les références à ces variables à la fin du traitement par lots:

del story, question, answer, pred_prob

N'oubliez pas de mettre le modèle en mode évaluation (et de revenir en mode train après avoir terminé l'évaluation). Par exemple, comme ça

model.eval()
11
Egor Lakomkin