Discriminator

Now, it's time to build the second core piece of the GAN network, which is the discriminator. In previous implementations, we said that the discriminator will produce a binary output that represents whether the input image is from the real dataset (1) or it's generated by the generator (0). The scenario is different here, so the discriminator will now be a multi-class classifier.

Now, let's go ahead and build up the discriminator part of the architecture:

# Defining the discriminator part of the network
def discriminator(input_x, reuse_vars=False, leaky_alpha=0.2, drop_out_rate=0., num_classes=10, size_mult=64):
with tf.variable_scope('discriminator', reuse=reuse_vars):

# defining a dropout layer
drop_out_output = tf.layers.dropout(input_x, rate=drop_out_rate / 2.5)

# Defining the input layer for the discriminator which is 32x32x3
conv_layer_3 = tf.layers.conv2d(input_x, size_mult, 3, strides=2, padding='same')
leaky_output_4 = tf.maximum(leaky_alpha * conv_layer_3, conv_layer_3)
leaky_output_4 = tf.layers.dropout(leaky_output_4, rate=drop_out_rate)

conv_layer_4 = tf.layers.conv2d(leaky_output_4, size_mult, 3, strides=2, padding='same')
batch_normalization_4 = tf.layers.batch_normalization(conv_layer_4, training=True)
leaky_output_5 = tf.maximum(leaky_alpha * batch_normalization_4, batch_normalization_4)

conv_layer_5 = tf.layers.conv2d(leaky_output_5, size_mult, 3, strides=2, padding='same')
batch_normalization_5 = tf.layers.batch_normalization(conv_layer_5, training=True)
leaky_output_6 = tf.maximum(leaky_alpha * batch_normalization_5, batch_normalization_5)
leaky_output_6 = tf.layers.dropout(leaky_output_6, rate=drop_out_rate)

conv_layer_6 = tf.layers.conv2d(leaky_output_6, 2 * size_mult, 3, strides=1, padding='same')
batch_normalization_6 = tf.layers.batch_normalization(conv_layer_6, training=True)
leaky_output_7 = tf.maximum(leaky_alpha * batch_normalization_6, batch_normalization_6)

conv_layer_7 = tf.layers.conv2d(leaky_output_7, 2 * size_mult, 3, strides=1, padding='same')
batch_normalization_7 = tf.layers.batch_normalization(conv_layer_7, training=True)
leaky_output_8 = tf.maximum(leaky_alpha * batch_normalization_7, batch_normalization_7)

conv_layer_8 = tf.layers.conv2d(leaky_output_8, 2 * size_mult, 3, strides=2, padding='same')
batch_normalization_8 = tf.layers.batch_normalization(conv_layer_8, training=True)
leaky_output_9 = tf.maximum(leaky_alpha * batch_normalization_8, batch_normalization_8)
leaky_output_9 = tf.layers.dropout(leaky_output_9, rate=drop_out_rate)

conv_layer_9 = tf.layers.conv2d(leaky_output_9, 2 * size_mult, 3, strides=1, padding='valid')

leaky_output_10 = tf.maximum(leaky_alpha * conv_layer_9, conv_layer_9)
...

Instead of applying a fully connected layer at the end, we are going to perform so-called global average pooling (GAP), which takes the average over the spatial dimensions of a feature vector; this will produce a squashed tensor to only a single value:

...
# Flatten it by global average pooling
leaky_output_features = tf.reduce_mean(leaky_output_10, (1, 2))
...

For example, suppose that after a stack of convolutions, we get an output tensor of shape:

[BATCH_SIZE, 8, 8, NUM_CHANNELS] 

To apply global average pooling, we calculate the average value on the [8x8] tensor slice. This operation will result in a tensor which is the following shape:

 [BATCH_SIZE, 1, 1, NUM_CHANNELS] 

That can be reshaped to:

[BATCH_SIZE, NUM_CHANNELS].

After applying the global average pooling, we add a fully connected layer that will output the final logits. These have the shape of:

[BATCH_SIZE, NUM_CLASSES]

which will represent the scores for each class. To get these scores for probability, we are going to use the softmax activation function:

...
# Get the probability that the input is real rather than fake
softmax_output = tf.nn.softmax(classes_logits)s
...

And finally the discriminator function will look like this,

# Defining the discriminator part of the network
def discriminator(input_x, reuse_vars=False, leaky_alpha=0.2, drop_out_rate=0., num_classes=10, size_mult=64):
with tf.variable_scope('discriminator', reuse=reuse_vars):

# defining a dropout layer
drop_out_output = tf.layers.dropout(input_x, rate=drop_out_rate / 2.5)

# Defining the input layer for the discrminator which is 32x32x3
conv_layer_3 = tf.layers.conv2d(input_x, size_mult, 3, strides=2, padding='same')
leaky_output_4 = tf.maximum(leaky_alpha * conv_layer_3, conv_layer_3)
leaky_output_4 = tf.layers.dropout(leaky_output_4, rate=drop_out_rate)

conv_layer_4 = tf.layers.conv2d(leaky_output_4, size_mult, 3, strides=2, padding='same')
batch_normalization_4 = tf.layers.batch_normalization(conv_layer_4, training=True)
leaky_output_5 = tf.maximum(leaky_alpha * batch_normalization_4, batch_normalization_4)

conv_layer_5 = tf.layers.conv2d(leaky_output_5, size_mult, 3, strides=2, padding='same')
batch_normalization_5 = tf.layers.batch_normalization(conv_layer_5, training=True)
leaky_output_6 = tf.maximum(leaky_alpha * batch_normalization_5, batch_normalization_5)
leaky_output_6 = tf.layers.dropout(leaky_output_6, rate=drop_out_rate)

conv_layer_6 = tf.layers.conv2d(leaky_output_6, 2 * size_mult, 3, strides=1, padding='same')
batch_normalization_6 = tf.layers.batch_normalization(conv_layer_6, training=True)
leaky_output_7 = tf.maximum(leaky_alpha * batch_normalization_6, batch_normalization_6)

conv_layer_7 = tf.layers.conv2d(leaky_output_7, 2 * size_mult, 3, strides=1, padding='same')
batch_normalization_7 = tf.layers.batch_normalization(conv_layer_7, training=True)
leaky_output_8 = tf.maximum(leaky_alpha * batch_normalization_7, batch_normalization_7)

conv_layer_8 = tf.layers.conv2d(leaky_output_8, 2 * size_mult, 3, strides=2, padding='same')
batch_normalization_8 = tf.layers.batch_normalization(conv_layer_8, training=True)
leaky_output_9 = tf.maximum(leaky_alpha * batch_normalization_8, batch_normalization_8)
leaky_output_9 = tf.layers.dropout(leaky_output_9, rate=drop_out_rate)

conv_layer_9 = tf.layers.conv2d(leaky_output_9, 2 * size_mult, 3, strides=1, padding='valid')

leaky_output_10 = tf.maximum(leaky_alpha * conv_layer_9, conv_layer_9)

# Flatten it by global average pooling
leaky_output_features = tf.reduce_mean(leaky_output_10, (1, 2))

# Set class_logits to be the inputs to a softmax distribution over the different classes
classes_logits = tf.layers.dense(leaky_output_features, num_classes + extra_class)

if extra_class:
actual_class_logits, fake_class_logits = tf.split(classes_logits, [num_classes, 1], 1)
assert fake_class_logits.get_shape()[1] == 1, fake_class_logits.get_shape()
fake_class_logits = tf.squeeze(fake_class_logits)
else:
actual_class_logits = classes_logits
fake_class_logits = 0.

max_reduced = tf.reduce_max(actual_class_logits, 1, keep_dims=True)
stable_actual_class_logits = actual_class_logits - max_reduced

gan_logits = tf.log(tf.reduce_sum(tf.exp(stable_actual_class_logits), 1)) + tf.squeeze(
max_reduced) - fake_class_logits

softmax_output = tf.nn.softmax(classes_logits)

return softmax_output, classes_logits, gan_logits, leaky_output_features
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset