Прямое распространение PyTorch возвращает разные логиты на одних и тех же образцах - PullRequest
0 голосов
/ 11 июля 2020

Рассмотрим следующую модель L eNet для MNIST

import torch
from torch import nn
import torch.nn.functional as F

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5, 1)
        self.conv2 = nn.Conv2d(20, 50, 5, 1)
        self.fc1 = nn.Linear(4*4*50, 500)
        self.fc2 = nn.Linear(500, 10)
        self.ceriation = nn.CrossEntropyLoss()
    def forward(self, x):
        x = self.conv1(x)
        x = F.max_pool2d(x, 2, 2)
        x = F.relu(x)
        x = self.conv2(x)
        x = F.max_pool2d(x, 2, 2)
        x = F.relu(x)
        x = x.view(-1, 4*4*50)
        x = self.fc1(x)
        x = self.fc2(x)
        return x

Теперь я использую эту модель, чтобы сделать один шаг вперед для пакета образцов, например

network=LeNet()
optimizer = torch.optim.SGD(self.network.parameters(), lr=0.001, momentum=0.9)
device = torch.device("cpu")
network.to(device)
network.train()
optimizer.zero_grad()
# X_batch= ... some batch of 50 samples pulled from a train_loader defined as
# torch.manual_seed(42)
# training_set = datasets.MNIST('./mnist_data', train=True, download=False, 
#                               transform=transforms.Compose([
#                                   transforms.ToTensor(),
#                                   transforms.Normalize((0.1307,), (0.3081,))]))
# train_loader = torch.utils.data.DataLoader(training_set, 
#                                            batch_size=50, 
#                                            shuffle=False)
logits = network(X_batch)

Примечание. это shuffle=False и download=False для загрузчика, поскольку набор данных уже загружен, и я не хочу перемешивать. Моя проблема в том, что если я запустил этот код дважды, я получу разные значения для logits, и я не понимаю, почему, поскольку все остальное, кажется, не изменилось. Для дополнительной проверки я также извлекаю X_batch в массив numpy и проверяю, что пакет образцов точно такой же, как и при предыдущем выполнении. Я провожу эту проверку с помощью функции numpy.array_equal().

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

1 Ответ

1 голос
/ 12 июля 2020

Причина в том, что каждый раз, когда вы запускаете этот код, вы вызываете

network = LeNet()

и в конечном итоге получаете разные случайные инициализации для весов сети. Если вы установите случайное начальное число перед этим, например, вот так:

torch.manual_seed(42)
network = LeNet()

, тогда вы должны получить те же результаты на первом шаге вперед, если вы используете те же данные, что и входные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...