Pytorch сверточные автоэнкодеры - PullRequest
0 голосов
/ 19 декабря 2018

Как сконструировать декодер, часть сверточного автоэнкодера?Предположим, у меня есть

(input -> conv2d -> maxpool2d -> maxunpool2d -> convTranspose2d -> output):

# CIFAR images shape = 3 x 32 x 32

class ConvDAE(nn.Module):
    def __init__(self):
        super().__init__()

        # input: batch x 3 x 32 x 32 -> output: batch x 16 x 16 x 16
        self.encoder = nn.Sequential(
            nn.Conv2d(3, 16, 3, stride=1, padding=1), # batch x 16 x 32 x 32
            nn.ReLU(),
            nn.BatchNorm2d(16),
            nn.MaxPool2d(2, stride=2) # batch x 16 x 16 x 16
        )

        # input: batch x 16 x 16 x 16 -> output: batch x 3 x 32 x 32
        self.decoder = nn.Sequential(
            # this line does not work
            # nn.MaxUnpool2d(2, stride=2, padding=0), # batch x 16 x 32 x 32
            nn.ConvTranspose2d(16, 16, 3, stride=2, padding=1, output_padding=1), # batch x 16 x 32 x 32
            nn.ReLU(),
            nn.BatchNorm2d(16),
            nn.ConvTranspose2d(16, 3, 3, stride=1, padding=1, output_padding=0), # batch x 3 x 32 x 32
            nn.ReLU()
        )

    def forward(self, x):
        print(x.size())
        out = self.encoder(x)
        print(out.size())
        out = self.decoder(out)
        print(out.size())
        return out

Вопрос, специфичный для Pytorch: почему я не могу использовать MaxUnpool2d в части декодера.Это дает мне следующую ошибку:

TypeError: forward() missing 1 required positional argument: 'indices'

И концептуальный вопрос: Разве мы не должны делать в декодере обратное тому, что мы делали в кодере?Я видел некоторые реализации, и кажется, что они заботятся только о размерах ввода и вывода декодера. Здесь и здесь - некоторые примеры.

1 Ответ

0 голосов
/ 15 января 2019

Для части вопроса с факелом в качестве обязательного позиционного аргумента unpool модули имеют индексы, возвращаемые из модулей пула, которые будут возвращены с return_indices=True.Таким образом, вы могли бы сделать

class ConvDAE(nn.Module):
    def __init__(self):
        super().__init__()

        # input: batch x 3 x 32 x 32 -> output: batch x 16 x 16 x 16
        self.encoder = nn.Sequential(
            nn.Conv2d(3, 16, 3, stride=1, padding=1), # batch x 16 x 32 x 32
            nn.ReLU(),
            nn.BatchNorm2d(16),
            nn.MaxPool2d(2, stride=2, return_indices=True)
        )

        self.unpool = nn.MaxUnpool2d(2, stride=2, padding=0)

        self.decoder = nn.Sequential( 
            nn.ConvTranspose2d(16, 16, 3, stride=2, padding=1, output_padding=1), 
            nn.ReLU(),
            nn.BatchNorm2d(16),
            nn.ConvTranspose2d(16, 3, 3, stride=1, padding=1, output_padding=0), 
            nn.ReLU()
        )

    def forward(self, x):
        print(x.size())
        out, indices = self.encoder(x)
        out = self.unpool(out, indices)
        out = self.decoder(out)
        print(out.size())
        return out

Что касается общей части вопроса, я не думаю, что в данной области техники используется симметричная часть декодера, поскольку было показано, что девонволюция / транспонированная свертка производитэффекты шахматной доски и многие подходы, как правило, используют вместо этого модули повышающей дискретизации.Вы найдете больше информации быстрее через каналы PyTorch.

...