Generator of handwritten digits similar to the ones in the MNIST dataset.
| 92 | |
| 93 | |
| 94 | class Generator(tf.keras.Model): |
| 95 | """Generator of handwritten digits similar to the ones in the MNIST dataset. |
| 96 | """ |
| 97 | |
| 98 | def __init__(self, data_format): |
| 99 | """Creates a model for discriminating between real and generated digits. |
| 100 | |
| 101 | Args: |
| 102 | data_format: Either 'channels_first' or 'channels_last'. |
| 103 | 'channels_first' is typically faster on GPUs while 'channels_last' is |
| 104 | typically faster on CPUs. See |
| 105 | https://www.tensorflow.org/performance/performance_guide#data_formats |
| 106 | """ |
| 107 | super(Generator, self).__init__(name='') |
| 108 | self.data_format = data_format |
| 109 | # We are using 128 6x6 channels as input to the first deconvolution layer |
| 110 | if data_format == 'channels_first': |
| 111 | self._pre_conv_shape = [-1, 128, 6, 6] |
| 112 | else: |
| 113 | assert data_format == 'channels_last' |
| 114 | self._pre_conv_shape = [-1, 6, 6, 128] |
| 115 | self.fc1 = layers.Dense(6 * 6 * 128, activation=tf.tanh) |
| 116 | |
| 117 | # In call(), we reshape the output of fc1 to _pre_conv_shape |
| 118 | |
| 119 | # Deconvolution layer. Resulting image shape: (batch, 14, 14, 64) |
| 120 | self.conv1 = layers.Conv2DTranspose( |
| 121 | 64, 4, strides=2, activation=None, data_format=data_format) |
| 122 | |
| 123 | # Deconvolution layer. Resulting image shape: (batch, 28, 28, 1) |
| 124 | self.conv2 = layers.Conv2DTranspose( |
| 125 | 1, 2, strides=2, activation=tf.nn.sigmoid, data_format=data_format) |
| 126 | |
| 127 | def call(self, inputs): |
| 128 | """Return a batch of generated images. |
| 129 | |
| 130 | Users should invoke __call__ to run the network, which delegates to this |
| 131 | method (and not call this method directly). |
| 132 | |
| 133 | Args: |
| 134 | inputs: A batch of noise vectors as a Tensor with shape |
| 135 | [batch_size, length of noise vectors]. |
| 136 | |
| 137 | Returns: |
| 138 | A Tensor containing generated images. If data_format is 'channels_last', |
| 139 | the shape of returned images is [batch_size, 28, 28, 1], else |
| 140 | [batch_size, 1, 28, 28] |
| 141 | """ |
| 142 | |
| 143 | x = self.fc1(inputs) |
| 144 | x = tf.reshape(x, shape=self._pre_conv_shape) |
| 145 | x = self.conv1(x) |
| 146 | x = self.conv2(x) |
| 147 | return x |
| 148 | |
| 149 | |
| 150 | def discriminator_loss(discriminator_real_outputs, discriminator_gen_outputs): |