#pytorch #conv-neural-network
#pytorch #conv-нейронная сеть
Вопрос:
def __init__(self):
super().__init__()
self.conv = nn.Sequential(
nn.Conv2d(1, 64, kernel_size=5, stride=2, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.Conv2d(64, 64, kernel_size=3, stride=2, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.Conv2d(64, 64, kernel_size=3, stride=2, bias=False),
nn.BatchNorm2d(64),
)
Как я могу справиться с этой ошибкой? Я думаю, что ошибка связана с self.fc, но я не могу сказать, как это исправить.
Ответ №1:
Результат self.conv(x)
имеет форму torch.Size([32, 64, 2, 2])
: 32*64*2*2= 8192
(это эквивалентно ( self.conv_out_size
) . Ввод в полностью подключенный слой ожидает одномерный вектор, т.Е. Вам нужно сгладить его перед переходом к полностью подключенному слою в прямой функции.
т. е.
class Network():
...
def foward():
...
conv_out = self.conv(x)
print(conv_out.shape)
conv_out = conv_out.view(-1, 32*64*2*2)
print(conv_out.shape)
x = self.fc(conv_out)
return x
вывод
torch.Size([32, 64, 2, 2])
torch.Size([1, 8192])
Редактировать:
Я думаю, вы неправильно используете self._get_conv_out
функцию.
Это должно быть
def _get_conv_out(self, shape):
output = self.conv(torch.zeros(1, *shape)) # not (32, *size)
return int(numpy.prod(output.size()))
затем, в прямом проходе, вы можете использовать
conv_out = self.conv(x)
# flatten the output of conv layers
conv_out = conv_out.view(conv_out.size(0), -1)
x = self.fc(conv_out)
Для ввода (32, 1, 110, 110)
вывода должно быть torch.Size([32, 2])
.
Комментарии:
1. после выравнивания он должен работать нормально, каков размер ввода (я предположил, что это 32, 1, 110, 110)?
2. он работает в Google colab (torch 1.7.0), я не уверен, почему он не работает в вашей системе.
3. Хорошо, теперь я понял!
4. входная форма (32, 1, 110, 110) имеет тензор, который вы передаете модели, верно? соответствует (batch_size, канал, высота, ширина)
5. редактирование, которое я сделал, может обрабатывать любой размер пакета: 1) измените функцию _get_conv_out и 2) сгладьте в прямой функции с помощью
(conv_out.size(0), -1)
.
Ответ №2:
У меня была такая же проблема, однако я решил ее, используя пакет из 32 и размер тензора [3, 32, 32] для моих изображений и следующих конфигураций в моей модели. Я использую ResNet с 9 CNN и ищу 4 выхода.
transform = transforms.Compose([transforms.Resize((32, 32)), transforms.ToTensor()])
def conv_block(in_channels, out_channels, pool=False):
layers = [nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
nn.BatchNorm2d(out_channels),
nn.ReLU(inplace=True)]
if pool: layers.append(nn.MaxPool2d(2))
return nn.Sequential(*layers)
class ResNet9(ImageClassificationBase):
def __init__(self, in_channels, num_classes):
super().__init__()
self.conv1 = conv_block(in_channels, 64)
self.conv2 = conv_block(64, 128, pool=True)
self.res1 = nn.Sequential(conv_block(128, 128), conv_block(128, 128))
self.conv3 = conv_block(128, 256, pool=True)
self.conv4 = conv_block(256, 512, pool=True)
self.res2 = nn.Sequential(conv_block(512, 512), conv_block(512, 512))
self.classifier = nn.Sequential(nn.MaxPool2d(4),
nn.Flatten(),
nn.Dropout(0.2),
nn.Linear(512, num_classes))
def forward(self, xb):
out = self.conv1(xb)
out = self.conv2(out)
out = self.res1(out) out
out = self.conv3(out)
out = self.conv4(out)
out = self.res2(out) out
out = self.classifier(out)
return out