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.
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.
Pour effectuer une régression logistique dans PyTorch, vous avez besoin de 3 choses:
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())