Pytorch: Размеры для кросс-энтропии верны, но почему-то неправильны для MSE? - PullRequest
0 голосов
/ 17 июня 2020

Я создавал программу, которая будет принимать в качестве входных данных набор Fashion MNIST, и я настраивал свою модель, чтобы увидеть, как различные параметры изменят точность.

Одна из настроек, которые я внес в свою Модель заключалась в изменении функции потерь моей модели с перекрестной энтропии на MSE.

# The code above is miscellaneous training data import code

trainloader = torch.utils.data.DataLoader(trainset, batch_size = 64, shuffle = True, num_workers=4)
testloader = torch.utils.data.DataLoader(testset, batch_size = 64, shuffle = True, num_workers=4)

dataiter = iter(trainloader)
images, labels = dataiter.next()
from torch import nn, optim
import torch.nn.functional as F

model = nn.Sequential(nn.Linear(784, 128),
                      nn.ReLU(),
                      nn.Linear(128, 10),
                      nn.LogSoftmax(dim = 1)
                     )
model.to(device)

# Define the loss
criterion = nn.MSELoss()

# Define the optimizer
optimizer = optim.Adam(model.parameters(), lr = 0.001)

# Define the epochs
epochs = 5

train_losses, test_losses = [], []

for e in range(epochs):
  running_loss = 0
  for images, labels in trainloader:
    # Flatten Fashion-MNIST images into a 784 long vector
    images = images.to(device)
    labels = labels.to(device)
    images = images.view(images.shape[0], -1)

    # Training pass
    optimizer.zero_grad()

    output = model.forward(images)

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

Моя модель работала без каких-либо проблем при использовании потери перекрестной энтропии, но когда я перешел на потерю MSE, интерпретатор пожаловался и сказал, тензоры были разных размеров и поэтому не могли быть вычислены.

<class 'torch.Tensor'>
torch.Size([64, 1, 28, 28])
torch.Size([64])
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-62-ec6942122f02> in <module>
     44     output = model.forward(images)
     45 
---> 46     loss = criterion(output, labels)
     47     loss.backward()
     48     optimizer.step()

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in __call__(self, *input, **kwargs)
    530             result = self._slow_forward(*input, **kwargs)
    531         else:
--> 532             result = self.forward(*input, **kwargs)
    533         for hook in self._forward_hooks.values():
    534             hook_result = hook(self, input, result)

/opt/conda/lib/python3.7/site-packages/torch/nn/modules/loss.py in forward(self, input, target)
    429 
    430     def forward(self, input, target):
--> 431         return F.mse_loss(input, target, reduction=self.reduction)
    432 
    433 

/opt/conda/lib/python3.7/site-packages/torch/nn/functional.py in mse_loss(input, target, size_average, reduce, reduction)
   2213             ret = torch.mean(ret) if reduction == 'mean' else torch.sum(ret)
   2214     else:
-> 2215         expanded_input, expanded_target = torch.broadcast_tensors(input, target)
   2216         ret = torch._C._nn.mse_loss(expanded_input, expanded_target, _Reduction.get_enum(reduction))
   2217     return ret

/opt/conda/lib/python3.7/site-packages/torch/functional.py in broadcast_tensors(*tensors)
     50                 [0, 1, 2]])
     51     """
---> 52     return torch._C._VariableFunctions.broadcast_tensors(tensors)
     53 
     54 

RuntimeError: The size of tensor a (10) must match the size of tensor b (64) at non-singleton dimension 1

Я попытался изменить форму своих тензоров и создать новые массивы в качестве заполнителей для моего выходного массива, но, похоже, ничего не добился. потеря перекрестной энтропии работает без ошибок, а MSE - нет?

1 Ответ

1 голос
/ 17 июня 2020

nn.CrossEntropyLoss и nn.MSELoss - это совершенно разные функции потерь с принципиально разным обоснованием.

nn.CrossEntropyLoss is функция потерь для дискретных разметок задач. Следовательно, он ожидает в качестве входных данных прогноз метки вероятности и целей как базовую дискретные метки : x форма n x c (где c - это количество меток) и y имеет форму n типа целое число , каждая цель принимает значения в диапазоне {0,...,c-1}.

Напротив, nn.MSELoss - функция потерь для задач регрессии . Следовательно, ожидается, что и прогнозы, и цели будут иметь одинаковую форму и тип данных. То есть, если ваш прогноз имеет форму n x c, цель также должна иметь форму n x c (а не только n, как в случае кросс-энтропии).

Если вы настаиваете на использовании потерь MSE вместо перекрестной энтропии, вам нужно будет преобразовать целевые целые метки, которые у вас есть в настоящее время (формы n), в 1-горячие векторы формы n x c и только потом вычислить потерю MSE между вашими прогнозами и сгенерированными одними горячими целями.

...