def generator(self, inputs, reuse=False, is_training=True): ''' inputs.shape = (?, 1, 1, 100) convt1.shape = (?, 4, 4, 512) convt2.shape = (?, 8, 8, 256) convt3.shape = (?, 16, 16, 128) convt4.shape = (?, 32, 32, 64) convt5.shape = (?, 64, 64, 3) ''' ''' inputs.shape = (?, 64, 64, 3) c7s1_32.shape = (?, 64, 64, 64) d64.shape = (?, 32, 32, 128) d128.shape = (?, 16, 16, 256) ''' with tf.variable_scope('gen', reuse=reuse): # conv layers print('inputs.shape = {}'.format(inputs.shape)) # (?, 64, 64, 3) c7s1_32 = ops.c7s1_k(inputs, self.ngf, is_training=self.is_training, norm=self.norm, reuse=self.gen_reuse, name='c7s1_32') print('c7s1_32.shape = {}'.format( c7s1_32.shape)) # (?, 64, 64, 64) d64 = ops.dk(c7s1_32, 2 * self.ngf, is_training=self.is_training, norm=self.norm, reuse=self.gen_reuse, name='d64') print('d64.shape = {}'.format(d64.shape)) # (?, 32, 32, 128) d128 = ops.dk(d64, 4 * self.ngf, is_training=self.is_training, norm=self.norm, reuse=self.gen_reuse, name='d128') print('d128.shape = {}'.format(d128.shape)) # (?, 16, 16, 256) if self.image_size <= 128: # use 6 residual blocks for 128x128 images res_output = ops.n_res_blocks(d128, reuse=self.gen_reuse, n=6) else: # 9 blocks for higher resolution res_output = ops.n_res_blocks(d128, reuse=self.gen_reuse, n=9) print('res_output.shape = {}'.format( res_output.shape)) # res_output.shape = (?, 16, 16, 256) convt1 = convt2d(res_output, (None, self.image_size // 2, self.image_size // 2, 2 * self.ngf), kernal=(5, 5), strides=(2, 2), padding="SAME", name="convt1") convt1 = tf.contrib.layers.batch_norm(convt1, is_training=is_training) convt1 = leaky_relu(convt1) print('convt1.shape = {}'.format(convt1.shape) ) # convt1.shape = (?, 4, 4, 512) -> (?, 32, 32, 128) convt2 = convt2d( convt1, (None, self.image_size, self.image_size, self.ngf), kernal=(5, 5), strides=(2, 2), padding="SAME", name="convt2") convt2 = tf.contrib.layers.batch_norm(convt2, is_training=is_training) convt2 = leaky_relu(convt2) print('convt2.shape = {}'.format( convt2.shape)) # convt1.shape = (?, 64, 64, 64) # conv layer # Note: the paper said that ReLU and _norm were used # but actually tanh was used and no _norm here output = ops.c7s1_k(convt2, 3, norm=None, activation='tanh', reuse=self.gen_reuse, name='output') print('output.shape = {}'.format( output.shape)) # output.shape = (?, 64, 64, 64) ''' def c7s1_k(input, k, reuse=False, norm='instance', activation='relu', is_training=True, name='c7s1_k'): """ A 7x7 Convolution-BatchNorm-ReLU layer with k filters and stride 1 Args: input: 4D tensor k: integer, number of filters (output depth) norm: 'instance' or 'batch' or None activation: 'relu' or 'tanh' name: string, e.g. 'c7sk-32' is_training: boolean or BoolTensor name: string reuse: boolean Returns: 4D tensor conv1 = conv2d(inputs, 64, kernal=(5, 5), strides=(2, 2), padding="SAME", activate_fn=leaky_relu, name="conv1") """ with tf.variable_scope(name, reuse=reuse): weights = _weights("weights", shape=[7, 7, input.get_shape()[3], k]) padded = tf.pad(input, [[0,0],[3,3],[3,3],[0,0]], 'REFLECT') conv = tf.nn.conv2d(padded, weights, strides=[1, 1, 1, 1], padding='VALID') normalized = _norm(conv, is_training, norm) if activation == 'relu': output = tf.nn.relu(normalized) if activation == 'tanh': output = tf.nn.tanh(normalized) return output ''' # set reuse=True for next call self.gen_reuse = True # self.variables = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope=self.name) return output
def generator(self, inputs, reuse=False, is_training=True): ''' inputs.shape = (?, 1, 1, 100) convt1.shape = (?, 4, 4, 512) convt2.shape = (?, 8, 8, 256) convt3.shape = (?, 16, 16, 128) convt4.shape = (?, 32, 32, 64) convt5.shape = (?, 64, 64, 3) ''' ''' inputs.shape = (?, 64, 64, 3) c7s1_32.shape = (?, 64, 64, 64) d64.shape = (?, 32, 32, 128) d128.shape = (?, 16, 16, 256) ''' with tf.variable_scope('gen', reuse=reuse): # conv layers print('inputs.shape = {}'.format(inputs.shape)) # (?, 64, 64, 3) c7s1_32 = ops.c7s1_k(inputs, self.ngf, is_training=self.is_training, norm=self.norm, reuse=self.reuse, name='c7s1_32') print('c7s1_32.shape = {}'.format( c7s1_32.shape)) # (?, 64, 64, 64) d64 = ops.dk(c7s1_32, 2 * self.ngf, is_training=self.is_training, norm=self.norm, reuse=self.reuse, name='d64') print('d64.shape = {}'.format(d64.shape)) # (?, 32, 32, 128) d128 = ops.dk(d64, 4 * self.ngf, is_training=self.is_training, norm=self.norm, reuse=self.reuse, name='d128') print('d128.shape = {}'.format(d128.shape)) # (?, 16, 16, 256) if self.image_size <= 128: # use 6 residual blocks for 128x128 images res_output = ops.n_res_blocks(d128, reuse=self.reuse, n=6) else: # 9 blocks for higher resolution res_output = ops.n_res_blocks(d128, reuse=self.reuse, n=9) print('res_output.shape = {}'.format( res_output.shape)) # res_output.shape = (?, 16, 16, 256) convt1 = convt2d(res_output, (None, self.image_size // 2, self.image_size // 2, 2 * self.ngf), kernal=(5, 5), strides=(2, 2), padding="SAME", name="convt1") convt1 = tf.contrib.layers.batch_norm(convt1, is_training=is_training) convt1 = leaky_relu(convt1) print('convt1.shape = {}'.format(convt1.shape) ) # convt1.shape = (?, 4, 4, 512) -> (?, 32, 32, 128) convt2 = convt2d( convt1, (None, self.image_size, self.image_size, self.ngf), kernal=(5, 5), strides=(2, 2), padding="SAME", name="convt2") convt2 = tf.contrib.layers.batch_norm(convt2, is_training=is_training) convt2 = leaky_relu(convt2) print('convt2.shape = {}'.format( convt2.shape)) # convt1.shape = (?, 64, 64, 64) # conv layer # Note: the paper said that ReLU and _norm were used # but actually tanh was used and no _norm here output = ops.c7s1_k(convt2, 3, norm=None, activation='tanh', reuse=self.reuse, name='output') print('output.shape = {}'.format( output.shape)) # output.shape = (?, 64, 64, 64) # set reuse=True for next call self.reuse = True # self.variables = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope=self.name) return output