Comment mettre en œuvre une fonction de perte personnalisée? L'utilisation du code ci-dessous provoque une erreur:
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import numpy as np
import matplotlib.pyplot as plt
import torch.utils.data as data_utils
import torch.nn as nn
import torch.nn.functional as F
num_epochs = 20
x1 = np.array([0,0])
x2 = np.array([0,1])
x3 = np.array([1,0])
x4 = np.array([1,1])
num_epochs = 200
class cus2(torch.nn.Module):
def __init__(self):
super(cus2,self).__init__()
def forward(self, outputs, labels):
# reshape labels to give a flat vector of length batch_size*seq_len
labels = labels.view(-1)
# mask out 'PAD' tokens
mask = (labels >= 0).float()
# the number of tokens is the sum of elements in mask
num_tokens = int(torch.sum(mask).data[0])
# pick the values corresponding to labels and multiply by mask
outputs = outputs[range(outputs.shape[0]), labels]*mask
# cross entropy loss for all non 'PAD' tokens
return -torch.sum(outputs)/num_tokens
x = torch.tensor([x1,x2,x3,x4]).float()
y = torch.tensor([0,1,1,0]).long()
train = data_utils.TensorDataset(x,y)
train_loader = data_utils.DataLoader(train , batch_size=2 , shuffle=True)
device = 'cpu'
input_size = 2
hidden_size = 100
num_classes = 2
learning_rate = .0001
class NeuralNet(nn.Module) :
def __init__(self, input_size, hidden_size, num_classes) :
super(NeuralNet, self).__init__()
self.fc1 = nn.Linear(input_size , hidden_size)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_size , num_classes)
def forward(self, x) :
out = self.fc1(x)
out = self.relu(out)
out = self.fc2(out)
return out
for i in range(0 , 1) :
model = NeuralNet(input_size, hidden_size, num_classes).to(device)
criterion = nn.CrossEntropyLoss()
# criterion = Regress_Loss()
# criterion = cus2()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
total_step = len(train_loader)
for Epoch in range(num_epochs) :
for i,(images , labels) in enumerate(train_loader) :
images = images.reshape(-1 , 2).to(device)
labels = labels.to(device)
outputs = model(images)
loss = criterion(outputs , labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# print(loss)
outputs = model(x)
print(outputs.data.max(1)[1])
fait des prédictions parfaites sur les données d'entraînement:
tensor([0, 1, 1, 0])
Utiliser une fonction de perte personnalisée de https://cs230-stanford.github.io/pytorch-nlp.html#writing-a-custom-loss-function :
est implémenté dans le code ci-dessus comme cus2
Le code sans commentaire # criterion = cus2()
pour utiliser cette fonction de perte renvoie:
tensor([0, 0, 0, 0])
Un avertissement est également renvoyé:
UserWarning: index non valide d'un tenseur de 0 dim. Ce sera une erreur dans PyTorch 0.5. Utilisez tensor.item () pour convertir un tenseur de 0 dim en un nombre Python
Je n'ai pas implémenté correctement la fonction de perte personnalisée?
Votre fonction de perte est correcte par programme, à l'exception de ce qui suit:
# the number of tokens is the sum of elements in mask
num_tokens = int(torch.sum(mask).data[0])
Lorsque vous faites torch.sum
, Il renvoie un tenseur à 0 dimension et donc l'avertissement qu'il ne peut pas être indexé. Pour résoudre ce problème, faites int(torch.sum(mask).item())
comme suggéré ou int(torch.sum(mask))
fonctionnera également.
Maintenant, essayez-vous d'émuler la perte CE en utilisant la perte personnalisée? Si oui, il vous manque le log_softmax
Pour résoudre ce problème, ajoutez outputs = torch.nn.functional.log_softmax(outputs, dim=1)
avant l'instruction 4. Notez que dans le cas du didacticiel que vous avez joint, log_softmax
Est déjà effectué dans l'appel de transfert. Vous pouvez faire cela aussi.
De plus, j'ai remarqué que le taux d'apprentissage est lent et même avec une perte de CE, les résultats ne sont pas cohérents. Augmenter le taux d'apprentissage à 1e-3 fonctionne bien pour moi en cas de perte de coutume et de CE.