Получил 512 каналов вместо 64 - что я должен изменить в своем автоэнкодере? - PullRequest
0 голосов
/ 03 марта 2020
ndf = 128
z_size = 512

# define the model (a simple autoencoder)
class MyNetwork(nn.Module):
    def __init__(self):
        super(MyNetwork, self).__init__()

        self.encoder = nn.Sequential(
            nn.Conv2d(3, 6, kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),
            nn.Conv2d(6,16,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),
            nn.Conv2d(16,64,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True))

        self.decoder = nn.Sequential(       
            nn.ConvTranspose2d(64,16,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),        
            nn.ConvTranspose2d(16,6,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),
            nn.ConvTranspose2d(6,3,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True))

        self.fc1 = nn.Linear(ndf*4*8*16,z_size)
        self.fc2 = nn.Linear(ndf*4*8*16,z_size)
        self.d1 = nn.Linear(z_size, ndf*4*8*8)
        self.z_size = z_size
        self.d_max = ndf *4

    def encode(self, x):
        x = self.encoder(x) 
        x = x.view(x.shape[0], -1)  
        mu = self.fc1(x)
        log_var = self.fc2(x)
        return mu, log_var

    def decode(self,x):
        x = x.view(x.shape[0], self.z_size)
        x = self.d1(x)
        x = x.view(x.shape[0], self.d_max, 8,8)
        x = self.decoder(x)
        return x

    def reparameterize(self, mu, log_var):
        std = torch.exp(0.5 * log_var)
        eps = torch.randn_like(std)
        return eps.mul(std).add_(mu)

    def forward(self, x):
        mu, log_var = self.encode(x)
        mu = mu.squeeze()
        log_var = log_var.squeeze()
        z = self.reparameterize(mu, log_var)
        return self.decode(z.view(-1, self.z_size, 1, 1)), mu, log_var

Я адаптировал код из учебника, и в настоящее время я получаю сообщение об ошибке «Учитывая транспонированный = 1, вес размера 64 16 3 3, ожидаемый вход [16, 512, 8, 8] для 64 каналов , но получил 512 каналов вместо 'при попытке запустить мой авто-кодер.

Может кто-нибудь объяснить, как мне следует адаптировать этот код, используя набор данных CIFAR10, размер пакета которого равен 16.

Ответы [ 2 ]

0 голосов
/ 04 марта 2020

Вход для функции decoder (x = self.decoder(x) in forward) должен иметь 64 канала, как определено в nn.ConvTranspose2d(64,16,kernel_size=3, stride=1, padding=1).

Для этого вы можете сделать следующее изменение:

  • Изменить self.d1 = nn.Linear(z_size, ndf*4*8*8) на self.d1 = nn.Linear(z_size, ndf*4*8*16).
  • Изменить с x = x.view(x.shape[0], self.d_max, 8,8) в decoder метод на x = x.view(x.shape[0], 64, 32, 32)

Использовать печать операторы для анализа формы входного тензора на разных слоях:

ndf = 128
z_size = 512

# define the model (a simple autoencoder)
class MyNetwork(nn.Module):
    def __init__(self):
        super(MyNetwork, self).__init__()

        self.encoder = nn.Sequential(
            nn.Conv2d(3, 6, kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),
            nn.Conv2d(6,16,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),
            nn.Conv2d(16,64,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True))

        self.decoder = nn.Sequential(       
            nn.ConvTranspose2d(64,16,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),        
            nn.ConvTranspose2d(16,6,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),
            nn.ConvTranspose2d(6,3,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True))

        self.fc1 = nn.Linear(ndf*4*8*16,z_size)
        self.fc2 = nn.Linear(ndf*4*8*16,z_size)
        self.d1 = nn.Linear(z_size, ndf*4*8*16)
        self.z_size = z_size
        self.d_max = ndf *4

    def encode(self, x):
        print('encoder')
        print(x.shape)
        x = self.encoder(x)
        print(x.shape) 
        x = x.view(x.shape[0], -1)  
        print(x.shape)
        mu = self.fc1(x)
        print(mu.shape)
        log_var = self.fc2(x)
        print(log_var.shape)
        return mu, log_var

    def decode(self,x):
        print('decoder')
        print(x.shape)
        x = x.view(x.shape[0], self.z_size)
        print(x.shape)
        x = self.d1(x)
        print(x.shape)
        x = x.view(x.shape[0], 64, 32, 32)
        print(x.shape)
        x = self.decoder(x)
        print(x.shape)
        return x

    def reparameterize(self, mu, log_var):
        std = torch.exp(0.5 * log_var)
        eps = torch.randn_like(std)
        return eps.mul(std).add_(mu)

    def forward(self, x):
        mu, log_var = self.encode(x)
        mu = mu.squeeze()
        log_var = log_var.squeeze()
        z = self.reparameterize(mu, log_var)
        return self.decode(z.view(-1, self.z_size, 1, 1)), mu, log_var
0 голосов
/ 04 марта 2020

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

Принимая форму входного и выходного массива как 32x32x3, я отформатировал этот код.

ndf = 128
z_size = 512

# define the model (a simple autoencoder)
class MyNetwork(nn.Module):
    def __init__(self):
        super(MyNetwork, self).__init__()

        self.encoder = nn.Sequential(
            nn.Conv2d(3, 6, kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),
            nn.Conv2d(6,16,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),
            nn.Conv2d(16,64,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True))

        self.decoder = nn.Sequential(       
            nn.ConvTranspose2d(64,16,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),        
            nn.ConvTranspose2d(16,6,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True),
            nn.ConvTranspose2d(6,3,kernel_size=3, stride=1, padding=1),
            nn.ReLU(True))

        self.fc1 = nn.Linear(ndf*4*8*16,z_size)
        self.fc2 = nn.Linear(ndf*4*8*16,z_size)
        self.d1 = nn.Linear(z_size, ndf*4*8*16)
        self.z_size = z_size
        self.d_max = ndf *4

    def encode(self, x):
        x = self.encoder(x) 
        x = x.view(x.shape[0], -1)  
        mu = self.fc1(x)
        log_var = self.fc2(x)
        return mu, log_var

    def decode(self,x):
        x = x.view(x.shape[0], self.z_size)
        x = self.d1(x)
        x = x.view(x.shape[0], 64, 32, 32)
        x = self.decoder(x)
        return x

    def reparameterize(self, mu, log_var):
        std = torch.exp(0.5 * log_var)
        eps = torch.randn_like(std)
        return eps.mul(std).add_(mu)

    def forward(self, x):
        mu, log_var = self.encode(x)
        mu = mu.squeeze()
        log_var = log_var.squeeze()
        z = self.reparameterize(mu, log_var)
        return self.decode(z.view(-1, self.z_size, 1, 1)), mu, log_var

Надеюсь, что это код работает:)

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