Pytorch ValueError: цель и вход должны иметь одинаковое количество элементов после изменения размера изображения

У меня есть рабочий код, который принимает размер пакета из 32 изображений с формой 256 * 256, и я могу обучать свою нейронную сеть.

class Netz(nn.Module):
def __init__(self):
    super(Netz,self).__init__()
    self.conv1 = nn.Conv2d(3, 6, kernel_size=5)
    self.conv2 = nn.Conv2d(6, 12, kernel_size=3)
    self.conv3 = nn.Conv2d(12, 18, kernel_size=3)
    self.conv4 = nn.Conv2d(18, 24, kernel_size=3)
    self.fc1 = nn.Linear(4704, 1000)
    self.fc2 = nn.Linear(1000, 350)
    self.fc3 = nn.Linear(350,43)


def forward (self,x):
    x = F.relu(F.max_pool2d(self.conv1(x), 2))
    x = F.relu(F.max_pool2d(self.conv2(x), 2))
    x = F.relu(F.max_pool2d(self.conv3(x), 2))
    x = F.relu(F.max_pool2d(self.conv4(x), 2))
    x = x.view(-1,4704)
    x = F.relu(self.fc1(x))
    x = F.relu(self.fc2(x))
    x = self.fc3(x)
    return torch.sigmoid(x)



    # Traningsalgorithmus
optimizer = optim.Adam(model.parameters(), lr=0.001)
def train(epoch):
    model.train()
    batch_id = 0
    for data, target in train_data_set:
        data = Variable(data)
        target = torch.Tensor(target)
        target = Variable(target)
        optimizer.zero_grad()
        out = model(data)
        criterion = F.binary_cross_entropy
        loss = criterion(out,target)
        loss.backward()
        optimizer.step()
        print ('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
            epoch, batch_id * len(data), len(train_data_set)*32,
                100. * batch_id / len(train_data_set), loss.item()))
        batch_id = batch_id + 1

Когда я меняю размер изображения на 50 * 50 и меняю код Net следующим образом:

class Netz(nn.Module):
def __init__(self):
    super(Netz,self).__init__()
    self.conv1 = nn.Conv2d(3, 6, kernel_size=5)
    self.conv2 = nn.Conv2d(6, 12, kernel_size=3)
    self.conv3 = nn.Conv2d(12, 18, kernel_size=3)
    self.conv4 = nn.Conv2d(18, 24, kernel_size=3)
    self.fc1 = nn.Linear(768, 1000)
    self.fc2 = nn.Linear(1000, 350)
    self.fc3 = nn.Linear(350,43)


def forward (self,x):
    x = F.relu(F.max_pool2d(self.conv1(x), 2))
    x = F.relu(F.max_pool2d(self.conv2(x), 2))
    x = F.relu(F.max_pool2d(self.conv3(x), 2))
    x = F.relu(F.max_pool2d(self.conv4(x), 2))
    x = x.view(-1,768)
    x = F.relu(self.fc1(x))
    x = F.relu(self.fc2(x))
    x = self.fc3(x)
    return torch.sigmoid(x)

Я получаю сообщение об ошибке: ValueError: Target и input должны иметь одинаковое количество элементов. целевой элемент (1376)! = входной элемент (43)

Пока я вижу, что проблема возникает после того, как x = x.view(-1,768) он возвращает Tensor с torch.Size ([1,768]). Когда я использую размер изображения 256 * 256, он возвращает Tensor с torch.Size ([32,4704]), и я не получаю сообщение об ошибке.

Кто-нибудь знает, как я могу решить проблему?


person Sascha Steger    schedule 05.06.2020    source источник


Ответы (1)


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

При вводе размера [32, 3, 256, 256] вывод после сверток имеет размер [32, 24, 14, 14], который может быть сведен к [32, 4704], как вы и ожидали в первой версии. Когда вы изменяете входной размер на [32, 3, 50, 50], результат после сверток имеет размер [32, 24, 1, 1], который может явно не может быть преобразован в размер [32, 768], потому что его выравнивание приведет к размеру [32, 24]. Учитывая это 32 * 24 = 768, вы неправильно объединяете пакеты в один, создавая тензор размера [1, 768], и если бы вы использовали другой размер пакета, это даже не сработало бы.

Правильный размер ввода для первой строки должен быть 24:

self.fc1 = nn.Linear(24, 1000)

Чтобы поймать любую ошибку в отношении размеров в модели, вместо того, чтобы позже при вычислении потерь, вы можете установить фактический размер без какого-либо -1 в представлении или, альтернативно, сгладить его после размера партии, либо с помощью view, либо _ 6_, поэтому при несоответствии размеров в линейном слое возникнет ошибка:

# Reshape to [batch_size, 24]
x = x.view(x.size(0), 24)

# Flatten with view
x = x.view(x.size(0), -1)

# Flatten, starting from dimension 1 (after the batch dimension)
x = x.flatten(1)
person Michael Jungo    schedule 05.06.2020
comment
Большое вам спасибо. Вы могли бы решить мою проблему: D. - person Sascha Steger; 29.06.2020