web-dev-qa-db-fra.com

Entrées Pytorch pour nn.CrossEntropyLoss ()

J'essaie d'effectuer une régression logistique dans PyTorch sur un simple ensemble de données étiqueté 0,1. Le critère ou la perte est défini comme: criterion = nn.CrossEntropyLoss(). Le modèle est: model = LogisticRegression(1,2)

J'ai un point de données qui est une paire: dat = (-3.5, 0), le premier élément est le point de données et le second est l'étiquette correspondante.
Ensuite, je convertis le premier élément de l'entrée en un tenseur: tensor_input = torch.Tensor([dat[0]]).
Puis j'applique le modèle au tensor_input: outputs = model(tensor_input).
Ensuite, je convertis l'étiquette en un tenseur: tensor_label = torch.Tensor([dat[1]]).
Maintenant, quand j'essaye de faire ça, la chose se brise: loss = criterion(outputs, tensor_label). Il donne et erreur: RuntimeError: Dimension out of range (expected to be in range of [-1, 0], but got 1)

import torch
import torch.nn as nn

class LogisticRegression(nn.Module):
    def __init__(self, input_size, num_classes):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(input_size, num_classes) 

    def forward(self, x):
        out = self.linear(x)
        return out

model = LogisticRegression(1,2)
criterion = nn.CrossEntropyLoss()
dat = (-3.5,0)
tensor_input = torch.Tensor([dat[0]])
outputs = binary_model(tensor_input)
tensor_label = torch.Tensor([dat[1]])
loss = criterion(outputs, tensor_label)

Je ne peux pas pour la vie de moi comprendre.

6

Pour la plupart, la documentation de PyTorch fait un travail incroyable pour expliquer les différentes fonctions; ils incluent généralement les dimensions d'entrée attendues, ainsi que quelques exemples simples.
Vous pouvez trouver la description de nn.CrossEntropyLoss()ici .

Pour parcourir votre exemple spécifique, commençons par examiner la dimension d'entrée attendue:

Entrée: (N, C) où C = nombre de classes. [...]

Pour ajouter à cela, [~ # ~] n [~ # ~] fait généralement référence à la taille du lot (nombre d'échantillons). Pour comparer cela à ce que vous avez actuellement:

outputs.shape
>>> torch.Size([2])

C'est à dire. actuellement, nous n'avons qu'une dimension d'entrée de (2,), et non de (1,2), comme le prévoit PyTorch. Nous pouvons remédier à cela en ajoutant une "fausse" dimension à notre tenseur actuel, en utilisant simplement .unsqueeze() comme ceci:

outputs = binary_model(tensor_input).unsqueeze(dim=0)
outputs.shape
>>> torch.Size([1,2])

Maintenant que nous avons obtenu cela, regardons l'entrée attendue pour les cibles:

Cible: (N) [...]

Nous avons donc déjà la bonne forme pour cela. Cependant, si nous essayons ceci, nous rencontrerons toujours une erreur:

RuntimeError: Expected object of scalar type Long but got scalar type Float 
              for argument #2 'target'.

Encore une fois, le message d'erreur est plutôt expressif. Le problème ici est que les tenseurs PyTorch (par défaut) sont interprétés comme torch.FloatTensors, Mais l'entrée doit être des entiers (ou Long) à la place. Nous pouvons simplement le faire en spécifiant le type exact lors des créations de tenseurs:

tensor_label = torch.LongTensor([dat[1]])

J'utilise PyTorch 1.0 sous Linux fyi.

3
dennlinger

Pour effectuer une régression logistique dans PyTorch, vous avez besoin de 3 choses:

  • Étiquettes (cibles) codées en 0 ou 1;
  • Activation sigmoïde sur la dernière couche, donc le nombre de sorties sera 1;
  • Entropie croisée binaire comme fonction de perte.

Voici un exemple minimal:

import torch
import torch.nn as nn


class LogisticRegression(nn.Module):
    def __init__(self, n_inputs, n_outputs):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(n_inputs, n_outputs)
        self.sigmoid = nn.Sigmoid()


    def forward(self, x):
        x = self.linear(x)
        return self.sigmoid(x)


# Init your model
# Attention!!! your num_output will be 1, because logistic function returns one value in range (0, 1) 
model = LogisticRegression(n_inputs=1, n_outputs=1)
# Define Binary Cross Entropy Loss:
criterion = nn.BCELoss()

# dummy data
data = (42.0, 0)
tensor_input = torch.Tensor([data[0]])
tensor_label = torch.Tensor([data[1]])

outputs = model(tensor_input)

loss = criterion(outputs, tensor_label)

print(loss.item())
0
trsvchn