Как подключить вход к выходу напрямую, используя один полностью подключенный слой в PyTorch? - PullRequest
0 голосов
/ 03 декабря 2018

Я новичок в области глубокого изучения и cnn и пытаюсь ознакомиться с этим полем, используя учебный код CIFAR10 с веб-сайта PyTorch.Итак, в этом коде я играл с удалением / добавлением слоев, чтобы лучше понять их эффект, и я попытался подключить вход (который является исходными данными с пакетом из 4 изображений) к выходу напрямую, используя только один полностью подключенныйслой.Я знаю, что в этом нет особого смысла, но я делаю это только ради эксперимента.Итак, когда я попытался это сделать, я столкнулся с некоторыми ошибками, а именно:

Во-первых, вот фрагмент кода:

########################################################################
# 2. Define a Convolution Neural Network
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Copy the neural network from the Neural Networks section before and modify it to
# take 3-channel images (instead of 1-channel images as it was defined).

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


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        #self.conv1 = nn.Conv2d(3, 6, 5)
        #self.pool = nn.MaxPool2d(2, 2)
        #self.conv2 = nn.Conv2d(6, 16, 5)
        #self.fc1 = nn.Linear(16 * 5 * 5, 120)
        #self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(768 * 4 * 4, 10)

    def forward(self, x):
        #x = self.pool(F.relu(self.conv1(x)))
        #x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 768 * 4 * 4)
        #x = F.relu(self.fc1(x))
        #x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


net = Net()

#######################################################################
# 3. Define a Loss function and optimizer
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Let's use a Classification Cross-Entropy loss and SGD with momentum.

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

########################################################################
# 4. Train the network
# ^^^^^^^^^^^^^^^^^^^^
#
# This is when things start to get interesting.
# We simply have to loop over our data iterator, and feed the inputs to the
# network and optimize.

for epoch in range(4):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # get the inputs
        inputs, labels = data

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        print(len(outputs))
        print(len(labels))
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

Итак, когда я запускаю код, Я получаю следующую ошибку:

Traceback (most recent call last):
      File "C:\Users\Andrey\Desktop\Machine_learning_Danila\Homework 3\cifar10_tutorial1.py", line 180, in <module>
        loss = criterion(outputs, labels)
      File "C:\Program Files\Python36\lib\site-packages\torch\nn\modules\module.py", line 477, in __call__
        result = self.forward(*input, **kwargs)
      File "C:\Program Files\Python36\lib\site-packages\torch\nn\modules\loss.py", line 862, in forward
        ignore_index=self.ignore_index, reduction=self.reduction)
      File "C:\Program Files\Python36\lib\site-packages\torch\nn\functional.py", line 1550, in cross_entropy
        return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
      File "C:\Program Files\Python36\lib\site-packages\torch\nn\functional.py", line 1405, in nll_loss
        .format(input.size(0), target.size(0)))
    ValueError: Expected input batch_size (1) to match target batch_size (4).

Я пытался проверить длину x, и оказалось, что изначально это 4, но становится 1 после строки

x = x.view(-1, 768 * 4 * 4)

Я думаю, что мои цифры верны, но, похоже, у меня есть только 1 тензор вместо 4, как я и предполагал, и я чувствую, что именно это и вызывает эту ошибку.Мне интересно, почему это так и как лучше это исправить?Кроме того, что будет лучшим оптимальным числом для выходного размерного вывода в nn.Linear (Полностью подключенный слой) в этом случае?

1 Ответ

0 голосов
/ 03 декабря 2018

В вашем модифицированном коде есть две очевидные ошибки (из официальных с веб-страницы PyTorch).Во-первых,

torch.nn.Linear(in_features, out_features)

- правильный синтаксис.Но вы передаете 768 * 4 * 4 как in_features.Это в 4 раза больше действительного количества нейронов (пикселей) в одном изображении CIFAR10 (32 * 32 * 3 = 3072).

Вторая ошибка связана с первой.Когда вы готовите свой тензор inputs,

# forward + backward + optimize;
# `inputs` should be a tensor of shape [batch_size, input_shape]
        outputs = net(inputs)

, вы должны передать его как тензор формы [batch_size, input_size], который по вашему требованию равен [4, 3072], так как вы хотите использовать размер партии 4Здесь вы должны указать размер партии;Не в nn.Linear, что вы сейчас делаете, и это вызывает ошибку.

Наконец, вы также должны исправить строку в методе forward.Измените следующую строку

x = x.view(-1, 768 * 4 * 4)   

на

x = x.view(-1, 32*32*3)

Исправление этих ошибок должно исправить ваши ошибки.


Сказав, что я не уверен, будет ли этона самом деле работа, в концептуальном смысле.Потому что это простое линейное преобразование (т.е. аффинное преобразование без какой-либо нелинейности).Точки данных (которые соответствуют изображениям в CIFAR10), скорее всего, не будут линейно разделимы в этом 3072-мерном пространстве (многообразии).Следовательно, точность была бы крайне плохой.Поэтому желательно добавить хотя бы скрытый слой с нелинейностью, такой как ReLU.

...