# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import paddle import paddle.nn as nn import paddle.nn.functional as F from .builder import GENERATORS @GENERATORS.register() class DeepConvGenerator(nn.Layer): """Create a Deep Convolutional generator""" def __init__(self, latent_dim, output_nc, size=64, ngf=64): """Construct a Deep Convolutional generator Args: latent_dim (int) -- the number of latent dimension output_nc (int) -- the number of channels in output images size (int) -- size of output tensor ngf (int) -- the number of filters in the last conv layer Refer to https://arxiv.org/abs/1511.06434 """ super(DeepConvGenerator, self).__init__() self.latent_dim = latent_dim self.ngf = ngf self.init_size = size // 4 self.l1 = nn.Sequential(nn.Linear(latent_dim, ngf*2 * self.init_size ** 2)) self.conv_blocks = nn.Sequential( nn.BatchNorm2D(ngf*2), nn.Upsample(scale_factor=2), nn.Conv2D(ngf*2, ngf*2, 3, stride=1, padding=1), nn.BatchNorm2D(ngf*2, 0.2), nn.LeakyReLU(0.2), nn.Upsample(scale_factor=2), nn.Conv2D(ngf*2, ngf, 3, stride=1, padding=1), nn.BatchNorm2D(ngf, 0.2), nn.LeakyReLU(0.2), nn.Conv2D(ngf, output_nc, 3, stride=1, padding=1), nn.Tanh(), ) def random_inputs(self, batch_size): return paddle.randn([batch_size, self.latent_dim]) def forward(self, z): out = self.l1(z) out = out.reshape([out.shape[0], self.ngf * 2, self.init_size, self.init_size]) img = self.conv_blocks(out) return img @GENERATORS.register() class ConditionalDeepConvGenerator(DeepConvGenerator): def __init__(self, latent_dim, output_nc, n_class=10, **kwargs): super(ConditionalDeepConvGenerator, self).__init__(latent_dim + n_class, output_nc, **kwargs) self.n_class = n_class self.latent_dim = latent_dim def random_inputs(self, batch_size): return_list = [super(ConditionalDeepConvGenerator, self).random_inputs(batch_size)] class_id = paddle.randint(0, self.n_class, [batch_size]) return return_list + [class_id] def forward(self, x, class_id=None): if self.n_class > 0: class_id = (class_id % self.n_class).detach() class_id = F.one_hot(class_id, self.n_class).astype('float32') class_id = class_id.reshape([x.shape[0], -1]) x = paddle.concat([x, class_id], 1) return super(ConditionalDeepConvGenerator, self).forward(x)