diff --git a/WIP/4 - Gated_PixelCNN/gated_pixelcnn.ipynb b/WIP/4 - Gated_PixelCNN/gated_pixelcnn.ipynb index 8fedab5..1114ac6 100644 --- a/WIP/4 - Gated_PixelCNN/gated_pixelcnn.ipynb +++ b/WIP/4 - Gated_PixelCNN/gated_pixelcnn.ipynb @@ -1,602 +1,678 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "accelerator": "GPU", + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "k1uZnxh4Xz9Z" + }, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "gpu_devices = tf.config.experimental.list_physical_devices('GPU')\n", + "for device in gpu_devices: tf.config.experimental.set_memory_growth(device, True)\n", + "\n", + "import random as rn\n", + "import time\n", + "\n", + "import matplotlib\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import tensorflow as tf\n", + "from tensorflow.keras.utils import Progbar\n", + "from tensorflow import keras\n", + "from tensorflow.keras import initializers\n", + "from tensorflow import nn" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "NN6vJl7eVnZ4" + }, + "outputs": [], + "source": [ + "# Defining random seeds\n", + "random_seed = 42\n", + "tf.random.set_seed(random_seed)\n", + "np.random.seed(random_seed)\n", + "rn.seed(random_seed)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "8BnkhgCjVpJu" + }, + "outputs": [], + "source": [ + "# Loading data\n", + "(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()\n", + "\n", + "height = 28\n", + "width = 28\n", + "n_channel = 1\n", + "\n", + "x_train = x_train.astype('float32') / 255.\n", + "x_test = x_test.astype('float32') / 255.\n", + "\n", + "x_train = x_train.reshape(x_train.shape[0], height, width, n_channel)\n", + "x_test = x_test.reshape(x_test.shape[0], height, width, n_channel)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "3ne-qY7JVZaB" + }, + "outputs": [], + "source": [ + "def quantise(images, q_levels):\n", + " \"\"\"Quantise image into q levels\"\"\"\n", + " return (np.digitize(images, np.arange(q_levels) / q_levels) - 1).astype('float32')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "3QVhnMymVrzc" + }, + "outputs": [], + "source": [ + "# Quantise the input data in q levels\n", + "q_levels = 2\n", + "x_train_quantised = quantise(x_train, q_levels)\n", + "x_test_quantised = quantise(x_test, q_levels)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "ZObIXqzNGwmo" + }, + "outputs": [], + "source": [ + "# Creating input stream using tf.data API\n", + "batch_size = 192\n", + "train_buf = 10000\n", + "\n", + "train_dataset = tf.data.Dataset.from_tensor_slices((x_train_quantised / (q_levels - 1),\n", + " x_train_quantised.astype('int32')))\n", + "train_dataset = train_dataset.shuffle(buffer_size=train_buf)\n", + "train_dataset = train_dataset.batch(batch_size)\n", + "\n", + "test_dataset = tf.data.Dataset.from_tensor_slices((x_test_quantised / (q_levels - 1),\n", + " x_test_quantised.astype('int32')))\n", + "test_dataset = test_dataset.batch(batch_size)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "75VTDkK8VZLA" + }, + "outputs": [], + "source": [ + "class MaskedConv2D(keras.layers.Layer):\n", + " \"\"\"Convolutional layers with masks for Gated PixelCNN.\n", + "\n", + " Masked convolutional layers used to implement Vertical and Horizontal\n", + " stacks of the Gated PixelCNN.\n", + "\n", + " Note: This implementation is different from the normal PixelCNN.\n", + "\n", + " Arguments:\n", + " mask_type: one of `\"V\"`, `\"A\"` or `\"B\".`\n", + " filters: Integer, the dimensionality of the output space\n", + " (i.e. the number of output filters in the convolution).\n", + " kernel_size: An integer or tuple/list of 2 integers, specifying the\n", + " height and width of the 2D convolution window.\n", + " Can be a single integer to specify the same value for\n", + " all spatial dimensions.\n", + " strides: An integer or tuple/list of 2 integers,\n", + " specifying the strides of the convolution along the height and width.\n", + " Can be a single integer to specify the same value for\n", + " all spatial dimensions.\n", + " Specifying any stride value != 1 is incompatible with specifying\n", + " any `dilation_rate` value != 1.\n", + " padding: one of `\"valid\"` or `\"same\"` (case-insensitive).\n", + " kernel_initializer: Initializer for the `kernel` weights matrix.\n", + " bias_initializer: Initializer for the bias vector.\n", + " \"\"\"\n", + "\n", + " def __init__(self,\n", + " mask_type,\n", + " filters,\n", + " kernel_size,\n", + " strides=1,\n", + " padding='same',\n", + " kernel_initializer='glorot_uniform',\n", + " bias_initializer='zeros'):\n", + " super(MaskedConv2D, self).__init__()\n", + "\n", + " assert mask_type in {'A', 'B', 'V'}\n", + " self.mask_type = mask_type\n", + "\n", + " self.filters = filters\n", + "\n", + " if isinstance(kernel_size, int):\n", + " kernel_size = (kernel_size, kernel_size)\n", + " self.kernel_size = kernel_size\n", + "\n", + " self.strides = strides\n", + " self.padding = padding.upper()\n", + " self.kernel_initializer = initializers.get(kernel_initializer)\n", + " self.bias_initializer = initializers.get(bias_initializer)\n", + "\n", + " def build(self, input_shape):\n", + " kernel_h, kernel_w = self.kernel_size\n", + "\n", + " self.kernel = self.add_weight('kernel',\n", + " shape=(kernel_h,\n", + " kernel_w,\n", + " int(input_shape[-1]),\n", + " self.filters),\n", + " initializer=self.kernel_initializer,\n", + " trainable=True)\n", + "\n", + " self.bias = self.add_weight('bias',\n", + " shape=(self.filters,),\n", + " initializer=self.bias_initializer,\n", + " trainable=True)\n", + "\n", + " mask = np.ones(self.kernel.shape, dtype=np.float32)\n", + "\n", + " if kernel_h % 2 != 0: \n", + " center_h = kernel_h // 2\n", + " else:\n", + " center_h = (kernel_h - 1) // 2\n", + "\n", + " if kernel_w % 2 != 0: \n", + " center_w = kernel_w // 2\n", + " else:\n", + " center_w = (kernel_w - 1) // 2\n", + "\n", + " if self.mask_type == 'V':\n", + " mask[center_h + 1:, :, :, :] = 0.\n", + " else:\n", + " mask[:center_h, :, :] = 0.\n", + " mask[center_h, center_w + (self.mask_type == 'B'):, :, :] = 0.\n", + " mask[center_h + 1:, :, :] = 0. \n", + "\n", + " self.mask = tf.constant(mask, dtype=tf.float32, name='mask')\n", + "\n", + " def call(self, input):\n", + " masked_kernel = tf.math.multiply(self.mask, self.kernel)\n", + " x = nn.conv2d(input,\n", + " masked_kernel,\n", + " strides=[1, self.strides, self.strides, 1],\n", + " padding=self.padding)\n", + " x = nn.bias_add(x, self.bias)\n", + " return x" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "PTUN4s52Nu3w" + }, + "outputs": [], + "source": [ + "class GatedBlock(tf.keras.Model):\n", + " \"\"\" Gated block of the Gated PixelCNN.\"\"\"\n", + "\n", + " def __init__(self, mask_type, filters, kernel_size):\n", + " super(GatedBlock, self).__init__(name='')\n", + "\n", + " self.mask_type = mask_type\n", + " self.vertical_conv = MaskedConv2D(mask_type='V',\n", + " filters=2 * filters,\n", + " kernel_size=kernel_size)\n", + " \n", + " self.horizontal_conv = MaskedConv2D(mask_type=mask_type,\n", + " filters=2 * filters,\n", + " kernel_size=kernel_size)\n", + "\n", + " self.padding = keras.layers.ZeroPadding2D(padding=((1,0),0))\n", + " self.cropping = keras.layers.Cropping2D(cropping=((0, 1), 0))\n", + "\n", + " self.v_to_h_conv = keras.layers.Conv2D(filters=2 * filters, kernel_size=1)\n", + "\n", + " self.horizontal_output = keras.layers.Conv2D(filters=filters, kernel_size=1)\n", + "\n", + " def _gate(self, x):\n", + " tanh_preactivation, sigmoid_preactivation = tf.split(x, 2, axis=-1)\n", + " return tf.nn.tanh(tanh_preactivation) * tf.nn.sigmoid(sigmoid_preactivation)\n", + "\n", + " def call(self, input_tensor):\n", + " v = input_tensor[0]\n", + " h = input_tensor[1]\n", + "\n", + " vertical_preactivation = self.vertical_conv(v) # NxN\n", + "\n", + " # Shifting feature map down to ensure causality\n", + " v_to_h = self.padding(vertical_preactivation)\n", + " v_to_h = self.cropping(v_to_h)\n", + " v_to_h = self.v_to_h_conv(v_to_h) # 1x1\n", + "\n", + " horizontal_preactivation = self.horizontal_conv(h) # 1xN\n", + " \n", + " v_out = self._gate(vertical_preactivation)\n", + "\n", + " horizontal_preactivation = horizontal_preactivation + v_to_h\n", + " h_activated = self._gate(horizontal_preactivation)\n", + " h_activated = self.horizontal_output(h_activated)\n", + "\n", + " if self.mask_type == 'A':\n", + " h_out = h_activated\n", + " elif self.mask_type == 'B':\n", + " h_out = h + h_activated\n", + "\n", + " return v_out, h_out" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "WB57YufrVxn2" + }, + "outputs": [], + "source": [ + "# Create Gated PixelCNN model\n", + "inputs = keras.layers.Input(shape=(height, width, n_channel))\n", + "v, h = GatedBlock(mask_type='A', filters=64, kernel_size=3)([inputs, inputs])\n", + "\n", + "for i in range(7):\n", + " v, h = GatedBlock(mask_type='B', filters=64, kernel_size=3)([v, h])\n", + "\n", + "x = keras.layers.Activation(activation='relu')(h)\n", + "x = keras.layers.Conv2D(filters=128, kernel_size=1, strides=1)(x)\n", + "\n", + "x = keras.layers.Activation(activation='relu')(x)\n", + "x = keras.layers.Conv2D(filters=q_levels, kernel_size=1, strides=1)(x)\n", + "\n", + "gated_pixelcnn = tf.keras.Model(inputs=inputs, outputs=x)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "_LnzHUaqV77d" + }, + "outputs": [], + "source": [ + "# Prepare optimizer and loss function\n", + "lr_decay = 0.999995\n", + "learning_rate = 1e-3\n", + "optimizer = keras.optimizers.Adam(lr=learning_rate)\n", + "\n", + "compute_loss = keras.losses.CategoricalCrossentropy(from_logits=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "CsAgEKVzLCJD" + }, + "outputs": [], + "source": [ + "@tf.function\n", + "def train_step(batch_x, batch_y):\n", + " with tf.GradientTape() as ae_tape:\n", + " logits = gated_pixelcnn(batch_x, training=True)\n", + "\n", + " loss = compute_loss(tf.squeeze(tf.one_hot(batch_y, q_levels)), logits)\n", + "\n", + " gradients = ae_tape.gradient(loss, gated_pixelcnn.trainable_variables)\n", + " gradients, _ = tf.clip_by_global_norm(gradients, 1.0)\n", + " optimizer.apply_gradients(zip(gradients, gated_pixelcnn.trainable_variables))\n", + "\n", + " return loss" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { "colab": { - "name": "gated_pixelcnn.ipynb", - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" + "base_uri": "https://localhost:8080/", + "height": 591 }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.8" + "colab_type": "code", + "id": "NoEPrfwQNM-s", + "outputId": "52dae9be-4f84-4b91-c5ba-e2369259478e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/50\n", + "313/313 [==============================] - 205s 655ms/step - loss: 0.1192\n", + "Epoch 2/50\n", + "313/313 [==============================] - 107s 343ms/step - loss: 0.0913\n", + "Epoch 3/50\n", + "313/313 [==============================] - 108s 344ms/step - loss: 0.0872\n", + "Epoch 4/50\n", + "313/313 [==============================] - 107s 341ms/step - loss: 0.0854\n", + "Epoch 5/50\n", + "313/313 [==============================] - 107s 341ms/step - loss: 0.0843\n", + "Epoch 6/50\n", + "313/313 [==============================] - 105s 336ms/step - loss: 0.0835\n", + "Epoch 7/50\n", + "313/313 [==============================] - 108s 344ms/step - loss: 0.0830\n", + "Epoch 8/50\n", + "313/313 [==============================] - 107s 342ms/step - loss: 0.0824\n", + "Epoch 9/50\n", + "313/313 [==============================] - 104s 333ms/step - loss: 0.0820\n", + "Epoch 10/50\n", + "313/313 [==============================] - 106s 340ms/step - loss: 0.0816\n", + "Epoch 11/50\n", + "313/313 [==============================] - 105s 335ms/step - loss: 0.0814\n", + "Epoch 12/50\n", + "313/313 [==============================] - 105s 336ms/step - loss: 0.0810\n", + "Epoch 13/50\n", + "313/313 [==============================] - 105s 336ms/step - loss: 0.0808\n", + "Epoch 14/50\n", + "313/313 [==============================] - 106s 337ms/step - loss: 0.0806\n", + "Epoch 15/50\n", + "313/313 [==============================] - 107s 340ms/step - loss: 0.0803\n", + "Epoch 16/50\n", + "313/313 [==============================] - 106s 338ms/step - loss: 0.0802\n", + "Epoch 17/50\n", + "313/313 [==============================] - 104s 332ms/step - loss: 0.0800\n", + "Epoch 18/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0798\n", + "Epoch 19/50\n", + "313/313 [==============================] - 104s 333ms/step - loss: 0.0796\n", + "Epoch 20/50\n", + "313/313 [==============================] - 106s 338ms/step - loss: 0.0795\n", + "Epoch 21/50\n", + "313/313 [==============================] - 103s 330ms/step - loss: 0.0793\n", + "Epoch 22/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0792\n", + "Epoch 23/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0791\n", + "Epoch 24/50\n", + "313/313 [==============================] - 103s 330ms/step - loss: 0.0789\n", + "Epoch 25/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0788\n", + "Epoch 26/50\n", + "313/313 [==============================] - 103s 330ms/step - loss: 0.0787\n", + "Epoch 27/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0786\n", + "Epoch 28/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0784\n", + "Epoch 29/50\n", + "313/313 [==============================] - 103s 329ms/step - loss: 0.0783\n", + "Epoch 30/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0782\n", + "Epoch 31/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0781\n", + "Epoch 32/50\n", + "313/313 [==============================] - 103s 329ms/step - loss: 0.0780\n", + "Epoch 33/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0779\n", + "Epoch 34/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0778\n", + "Epoch 35/50\n", + "313/313 [==============================] - 105s 335ms/step - loss: 0.0776\n", + "Epoch 36/50\n", + "313/313 [==============================] - 106s 339ms/step - loss: 0.0775\n", + "Epoch 37/50\n", + "313/313 [==============================] - 106s 340ms/step - loss: 0.0774\n", + "Epoch 38/50\n", + "313/313 [==============================] - 107s 342ms/step - loss: 0.0773\n", + "Epoch 39/50\n", + "313/313 [==============================] - 107s 342ms/step - loss: 0.0772\n", + "Epoch 40/50\n", + "313/313 [==============================] - 107s 342ms/step - loss: 0.0771\n", + "Epoch 41/50\n", + "313/313 [==============================] - 106s 338ms/step - loss: 0.0770\n", + "Epoch 42/50\n", + "313/313 [==============================] - 105s 337ms/step - loss: 0.0769\n", + "Epoch 43/50\n", + "313/313 [==============================] - 104s 331ms/step - loss: 0.0768\n", + "Epoch 44/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0767\n", + "Epoch 45/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0766\n", + "Epoch 46/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0765\n", + "Epoch 47/50\n", + "313/313 [==============================] - 103s 329ms/step - loss: 0.0764\n", + "Epoch 48/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0763\n", + "Epoch 49/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0762\n", + "Epoch 50/50\n", + "313/313 [==============================] - 103s 328ms/step - loss: 0.0761\n" + ] } + ], + "source": [ + "# Training loop\n", + "n_epochs = 50\n", + "n_iter = int(np.ceil(x_train_quantised.shape[0] / batch_size))\n", + "for epoch in range(n_epochs):\n", + " progbar = Progbar(n_iter)\n", + " print('Epoch {:}/{:}'.format(epoch + 1, n_epochs))\n", + "\n", + " for i_iter, (batch_x, batch_y) in enumerate(train_dataset):\n", + " optimizer.lr = optimizer.lr * lr_decay\n", + " loss = train_step(batch_x, batch_y)\n", + "\n", + " progbar.add(1, values=[('loss', loss)])" + ] }, - "cells": [ - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "k1uZnxh4Xz9Z", - "colab": {} - }, - "source": [ - "import random as rn\n", - "import time\n", - "\n", - "import matplotlib\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import tensorflow as tf\n", - "from tensorflow.keras.utils import Progbar\n", - "from tensorflow import keras\n", - "from tensorflow.keras import initializers\n", - "from tensorflow import nn" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "NN6vJl7eVnZ4", - "colab": {} - }, - "source": [ - "# Defining random seeds\n", - "random_seed = 42\n", - "tf.random.set_seed(random_seed)\n", - "np.random.seed(random_seed)\n", - "rn.seed(random_seed)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "8BnkhgCjVpJu", - "colab": {} - }, - "source": [ - "# Loading data\n", - "(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()\n", - "\n", - "height = 28\n", - "width = 28\n", - "n_channel = 1\n", - "\n", - "x_train = x_train.astype('float32') / 255.\n", - "x_test = x_test.astype('float32') / 255.\n", - "\n", - "x_train = x_train.reshape(x_train.shape[0], height, width, n_channel)\n", - "x_test = x_test.reshape(x_test.shape[0], height, width, n_channel)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "3ne-qY7JVZaB", - "colab": {} - }, - "source": [ - "def quantise(images, q_levels):\n", - " \"\"\"Quantise image into q levels\"\"\"\n", - " return (np.digitize(images, np.arange(q_levels) / q_levels) - 1).astype('float32')" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "3QVhnMymVrzc", - "colab": {} - }, - "source": [ - "# Quantise the input data in q levels\n", - "q_levels = 2\n", - "x_train_quantised = quantise(x_train, q_levels)\n", - "x_test_quantised = quantise(x_test, q_levels)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "ZObIXqzNGwmo", - "colab": {} - }, - "source": [ - "# Creating input stream using tf.data API\n", - "batch_size = 128\n", - "train_buf = 60000\n", - "\n", - "train_dataset = tf.data.Dataset.from_tensor_slices((x_train_quantised / (q_levels - 1),\n", - " x_train_quantised.astype('int32')))\n", - "train_dataset = train_dataset.shuffle(buffer_size=train_buf)\n", - "train_dataset = train_dataset.batch(batch_size)\n", - "\n", - "test_dataset = tf.data.Dataset.from_tensor_slices((x_test_quantised / (q_levels - 1),\n", - " x_test_quantised.astype('int32')))\n", - "test_dataset = test_dataset.batch(batch_size)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "75VTDkK8VZLA", - "colab": {} - }, - "source": [ - "class MaskedConv2D(keras.layers.Layer):\n", - " \"\"\"Convolutional layers with masks for Gated PixelCNN.\n", - "\n", - " Masked convolutional layers used to implement Vertical and Horizontal\n", - " stacks of the Gated PixelCNN.\n", - "\n", - " Note: This implementation is different from the normal PixelCNN.\n", - "\n", - " Arguments:\n", - " mask_type: one of `\"V\"`, `\"A\"` or `\"B\".`\n", - " filters: Integer, the dimensionality of the output space\n", - " (i.e. the number of output filters in the convolution).\n", - " kernel_size: An integer or tuple/list of 2 integers, specifying the\n", - " height and width of the 2D convolution window.\n", - " Can be a single integer to specify the same value for\n", - " all spatial dimensions.\n", - " strides: An integer or tuple/list of 2 integers,\n", - " specifying the strides of the convolution along the height and width.\n", - " Can be a single integer to specify the same value for\n", - " all spatial dimensions.\n", - " Specifying any stride value != 1 is incompatible with specifying\n", - " any `dilation_rate` value != 1.\n", - " padding: one of `\"valid\"` or `\"same\"` (case-insensitive).\n", - " kernel_initializer: Initializer for the `kernel` weights matrix.\n", - " bias_initializer: Initializer for the bias vector.\n", - " \"\"\"\n", - "\n", - " def __init__(self,\n", - " mask_type,\n", - " filters,\n", - " kernel_size,\n", - " strides=1,\n", - " padding='same',\n", - " kernel_initializer='glorot_uniform',\n", - " bias_initializer='zeros'):\n", - " super(MaskedConv2D, self).__init__()\n", - "\n", - " assert mask_type in {'A', 'B', 'V'}\n", - " self.mask_type = mask_type\n", - "\n", - " self.filters = filters\n", - "\n", - " if isinstance(kernel_size, int):\n", - " kernel_size = (kernel_size, kernel_size)\n", - " self.kernel_size = kernel_size\n", - "\n", - " self.strides = strides\n", - " self.padding = padding.upper()\n", - " self.kernel_initializer = initializers.get(kernel_initializer)\n", - " self.bias_initializer = initializers.get(bias_initializer)\n", - "\n", - " def build(self, input_shape):\n", - " kernel_h, kernel_w = self.kernel_size\n", - "\n", - " self.kernel = self.add_weight('kernel',\n", - " shape=(kernel_h,\n", - " kernel_w,\n", - " int(input_shape[-1]),\n", - " self.filters),\n", - " initializer=self.kernel_initializer,\n", - " trainable=True)\n", - "\n", - " self.bias = self.add_weight('bias',\n", - " shape=(self.filters,),\n", - " initializer=self.bias_initializer,\n", - " trainable=True)\n", - "\n", - " mask = np.ones(self.kernel.shape, dtype=np.float32)\n", - "\n", - " if kernel_h % 2 != 0: \n", - " center_h = kernel_h // 2\n", - " else:\n", - " center_h = (kernel_h - 1) // 2\n", - "\n", - " if kernel_w % 2 != 0: \n", - " center_w = kernel_w // 2\n", - " else:\n", - " center_w = (kernel_w - 1) // 2\n", - "\n", - " if self.mask_type == 'V':\n", - " mask[center_h + 1:, :, :, :] = 0.\n", - " else:\n", - " mask[:center_h, :, :] = 0.\n", - " mask[center_h, center_w + (self.mask_type == 'B'):, :, :] = 0.\n", - " mask[center_h + 1:, :, :] = 0. \n", - "\n", - " self.mask = tf.constant(mask, dtype=tf.float32, name='mask')\n", - "\n", - " def call(self, input):\n", - " masked_kernel = tf.math.multiply(self.mask, self.kernel)\n", - " x = nn.conv2d(input,\n", - " masked_kernel,\n", - " strides=[1, self.strides, self.strides, 1],\n", - " padding=self.padding)\n", - " x = nn.bias_add(x, self.bias)\n", - " return x" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "PTUN4s52Nu3w", - "colab": {} - }, - "source": [ - "class GatedBlock(tf.keras.Model):\n", - " \"\"\" Gated block of the Gated PixelCNN.\"\"\"\n", - "\n", - " def __init__(self, mask_type, filters, kernel_size):\n", - " super(GatedBlock, self).__init__(name='')\n", - "\n", - " self.mask_type = mask_type\n", - " self.vertical_conv = MaskedConv2D(mask_type='V',\n", - " filters=2 * filters,\n", - " kernel_size=kernel_size)\n", - " \n", - " self.horizontal_conv = MaskedConv2D(mask_type=mask_type,\n", - " filters=2 * filters,\n", - " kernel_size=kernel_size)\n", - "\n", - " self.padding = keras.layers.ZeroPadding2D(padding=((1,0),0))\n", - " self.cropping = keras.layers.Cropping2D(cropping=((0, 1), 0))\n", - "\n", - " self.v_to_h_conv = keras.layers.Conv2D(filters=2 * filters, kernel_size=1)\n", - "\n", - " self.horizontal_output = keras.layers.Conv2D(filters=filters, kernel_size=1)\n", - "\n", - " def _gate(self, x):\n", - " tanh_preactivation, sigmoid_preactivation = tf.split(x, 2, axis=-1)\n", - " return tf.nn.tanh(tanh_preactivation) * tf.nn.sigmoid(sigmoid_preactivation)\n", - "\n", - " def call(self, input_tensor):\n", - " v = input_tensor[0]\n", - " h = input_tensor[1]\n", - "\n", - " vertical_preactivation = self.vertical_conv(v) # NxN\n", - "\n", - " # Shifting feature map down to ensure causality\n", - " v_to_h = self.padding(vertical_preactivation)\n", - " v_to_h = self.cropping(v_to_h)\n", - " v_to_h = self.v_to_h_conv(v_to_h) # 1x1\n", - "\n", - " horizontal_preactivation = self.horizontal_conv(h) # 1xN\n", - " \n", - " v_out = self._gate(vertical_preactivation)\n", - "\n", - " horizontal_preactivation = horizontal_preactivation + v_to_h\n", - " h_activated = self._gate(horizontal_preactivation)\n", - " h_activated = self.horizontal_output(h_activated)\n", - "\n", - " if self.mask_type == 'A':\n", - " h_out = h_activated\n", - " elif self.mask_type == 'B':\n", - " h_out = h + h_activated\n", - "\n", - " return v_out, h_out" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "WB57YufrVxn2", - "colab": {} - }, - "source": [ - "# Create Gated PixelCNN model\n", - "inputs = keras.layers.Input(shape=(height, width, n_channel))\n", - "v, h = GatedBlock(mask_type='A', filters=64, kernel_size=3)([inputs, inputs])\n", - "\n", - "for i in range(7):\n", - " v, h = GatedBlock(mask_type='B', filters=64, kernel_size=3)([v, h])\n", - "\n", - "x = keras.layers.Activation(activation='relu')(h)\n", - "x = keras.layers.Conv2D(filters=128, kernel_size=1, strides=1)(x)\n", - "\n", - "x = keras.layers.Activation(activation='relu')(x)\n", - "x = keras.layers.Conv2D(filters=q_levels, kernel_size=1, strides=1)(x)\n", - "\n", - "gated_pixelcnn = tf.keras.Model(inputs=inputs, outputs=x)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "_LnzHUaqV77d", - "colab": {} - }, - "source": [ - "# Prepare optimizer and loss function\n", - "lr_decay = 0.999995\n", - "learning_rate = 1e-3\n", - "optimizer = keras.optimizers.Adam(lr=learning_rate)\n", - "\n", - "compute_loss = keras.losses.CategoricalCrossentropy(from_logits=True)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "CsAgEKVzLCJD", - "colab": {} - }, - "source": [ - "@tf.function\n", - "def train_step(batch_x, batch_y):\n", - " with tf.GradientTape() as ae_tape:\n", - " logits = gated_pixelcnn(batch_x, training=True)\n", - "\n", - " loss = compute_loss(tf.squeeze(tf.one_hot(batch_y, q_levels)), logits)\n", - "\n", - " gradients = ae_tape.gradient(loss, gated_pixelcnn.trainable_variables)\n", - " gradients, _ = tf.clip_by_global_norm(gradients, 1.0)\n", - " optimizer.apply_gradients(zip(gradients, gated_pixelcnn.trainable_variables))\n", - "\n", - " return loss" - ], - "execution_count": 0, - "outputs": [] + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 52 }, + "colab_type": "code", + "id": "ue0vZbitSNmz", + "outputId": "b4be6fad-6f16-4380-8dbd-2e01bc3e1af1" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "NoEPrfwQNM-s", - "outputId": "52dae9be-4f84-4b91-c5ba-e2369259478e", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 591 - } - }, - "source": [ - "# Training loop\n", - "n_epochs = 100\n", - "n_iter = int(np.ceil(x_train_quantised.shape[0] / batch_size))\n", - "for epoch in range(n_epochs):\n", - " progbar = Progbar(n_iter)\n", - " print('Epoch {:}/{:}'.format(epoch + 1, n_epochs))\n", - "\n", - " for i_iter, (batch_x, batch_y) in enumerate(train_dataset):\n", - " optimizer.lr = optimizer.lr * lr_decay\n", - " loss = train_step(batch_x, batch_y)\n", - "\n", - " progbar.add(1, values=[('loss', loss)])" - ], - "execution_count": 12, - "outputs": [ - { - "output_type": "stream", - "text": [ - "Epoch 1/100\n", - "469/469 [==============================] - 176s 376ms/step - loss: 0.1096\n", - "Epoch 2/100\n", - "469/469 [==============================] - 171s 366ms/step - loss: 0.0892\n", - "Epoch 3/100\n", - "469/469 [==============================] - 171s 365ms/step - loss: 0.0864\n", - "Epoch 4/100\n", - "469/469 [==============================] - 171s 365ms/step - loss: 0.0848\n", - "Epoch 5/100\n", - "469/469 [==============================] - 171s 365ms/step - loss: 0.0837\n", - "Epoch 6/100\n", - "469/469 [==============================] - 171s 365ms/step - loss: 0.0829\n", - "Epoch 7/100\n", - " 92/469 [====>.........................] - ETA: 2:18 - loss: 0.0824" - ], - "name": "stdout" - }, - { - "output_type": "error", - "ename": "KeyboardInterrupt", - "evalue": "ignored", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mloss\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtrain_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbatch_x\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbatch_y\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0mprogbar\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'loss'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mloss\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/utils/generic_utils.py\u001b[0m in \u001b[0;36madd\u001b[0;34m(self, n, values)\u001b[0m\n\u001b[1;32m 595\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 596\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 597\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mupdate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_seen_so_far\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 598\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 599\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/utils/generic_utils.py\u001b[0m in \u001b[0;36mupdate\u001b[0;34m(self, current, values)\u001b[0m\n\u001b[1;32m 488\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_values\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mv\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mvalue_base\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue_base\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 489\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 490\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_values\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mv\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mvalue_base\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 491\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_values\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mvalue_base\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 492\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/ops/math_ops.py\u001b[0m in \u001b[0;36mbinary_op_wrapper\u001b[0;34m(x, y)\u001b[0m\n\u001b[1;32m 913\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 914\u001b[0m \u001b[0;32mraise\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 915\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 916\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 917\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mbinary_op_wrapper_sparse\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msp_x\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/ops/math_ops.py\u001b[0m in \u001b[0;36m_mul_dispatch\u001b[0;34m(x, y, name)\u001b[0m\n\u001b[1;32m 1199\u001b[0m \u001b[0mis_tensor_y\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mops\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTensor\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1200\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_tensor_y\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1201\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mgen_math_ops\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmul\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1202\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1203\u001b[0m \u001b[0;32massert\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msparse_tensor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSparseTensor\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# Case: Dense * Sparse.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/ops/gen_math_ops.py\u001b[0m in \u001b[0;36mmul\u001b[0;34m(x, y, name)\u001b[0m\n\u001b[1;32m 6111\u001b[0m _result = _pywrap_tensorflow.TFE_Py_FastPathExecute(\n\u001b[1;32m 6112\u001b[0m \u001b[0m_ctx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_context_handle\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtld\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdevice_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"Mul\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtld\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mop_callbacks\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 6113\u001b[0;31m x, y)\n\u001b[0m\u001b[1;32m 6114\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0m_result\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6115\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0m_core\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_FallbackException\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mKeyboardInterrupt\u001b[0m: " - ] - } - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "nll : 0.08091852068901062 nats\n", + "bits/dim : 0.11674074851410661\n" + ] + } + ], + "source": [ + "# Test set performance\n", + "test_loss = []\n", + "for batch_x, batch_y in test_dataset:\n", + " logits = gated_pixelcnn(batch_x, training=False)\n", + "\n", + " # Calculate cross-entropy (= negative log-likelihood)\n", + " loss = compute_loss(tf.one_hot(batch_y, q_levels), logits)\n", + "\n", + " test_loss.append(loss)\n", + "print('nll : {:} nats'.format(np.array(test_loss).mean()))\n", + "print('bits/dim : {:}'.format(np.array(test_loss).mean() / np.log(2)))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 581 }, + "colab_type": "code", + "id": "-Ia9VXYySkuW", + "outputId": "924010f4-0dcb-4a82-bd1d-75c6091cadc6" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "ue0vZbitSNmz", - "outputId": "b4be6fad-6f16-4380-8dbd-2e01bc3e1af1", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 52 - } - }, - "source": [ - "# Test set performance\n", - "test_loss = []\n", - "for batch_x, batch_y in test_dataset:\n", - " logits = gated_pixelcnn(batch_x, training=False)\n", - "\n", - " # Calculate cross-entropy (= negative log-likelihood)\n", - " loss = compute_loss(tf.one_hot(batch_y, q_levels), logits)\n", - "\n", - " test_loss.append(loss)\n", - "print('nll : {:} nats'.format(np.array(test_loss).mean()))\n", - "print('bits/dim : {:}'.format(np.array(test_loss).mean() / np.log(2)))" - ], - "execution_count": 13, - "outputs": [ - { - "output_type": "stream", - "text": [ - "nll : 0.08227105438709259 nats\n", - "bits/dim : 0.11869204217296468\n" - ], - "name": "stdout" - } + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAj4AAAI0CAYAAAAdqSPKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAgAElEQVR4nO3dXXbjttIoUOiuO4TOczwIz38E9hw6z/Ec9D2knaNWKAqk+FOF2vvlnJWWbRQBUEABBC/X67UBAFTw/84uAADAUQx8AIAyDHwAgDIMfACAMgx8AIAyDHwAgDIMfACAMgx8AIAyDHwAgDL+/5IP//jx4/r29rZTUfbz8+fP9vX1dXn2uazxtdba5+fn1/V6/ePZ57LG2FuHrYkxstH7ojr8nRjjqtwXFw183t7e2sfHxzalOtD7+3vX57LG11prl8vlr57PZY2xtw5bE2Nko/dFdfg7McZVuS9a6gIAyjDwAQDKMPABAMow8AEAyli0uXkrl0vXZvl/Xa/XnUoCj021U20ROIt70jYOG/gsHezM/Wykiu6JK1J5t/JKfT4S6To9iu/7v0cqK48taafqlKjm2rF70nKWugCAMnbP+OyRGYiiN7bL5ZJ2NH5k/WW+TsQx8j2HOpa24yj3zwzLcTI+AEAZu2Z89pp5RRnZjubsmXKEOl2SxWstRpnPcHudIl+DyGWDKWffhyvYZeBTseKmbrC31yHyF+UZT9ll+eJ8JnK9virbILDifYc+o9xvMnzPXK/X8H3RUhcAUMYp5/iMYsmoOvIs46yyRbomr85QMs0oo8/GttJbD5nqjmUytfW1m4K/PxMp1j3KtGU/lfEBAMrYNOMTacR5JtfhuUgz663rK8I6+70922SkOJfQT2vJ2k7XiHYPWvNA0p6HNlrq2oibaD69dfZsQ+Hc749y41niUZmjn89xn15/dP0f1V2kWJ7Z+n6TKfYekU/775WxzI9sOejZgqUuAKCMlBmfSCPhbI/80me0enolnuiZnjmjZWK3fDfgaNcmuyx9ao1Xst+3P7dVm5XxAQDKSJHxGXkkTE73bbLK29wzxLH0UdoMMX27j21N2SNnerbYfxU5vqNkatO3jqq7sAOfLBXXeyO63XA59zlyynBaaa8RNv+Oasvzpr5lqNe1980Msb1qlPvOvbnJpXN8AAA6hcv4ZB2hZy0324l4gmpFz65/1r669QnTka7DFg+J6Hfx3N4T19bdHiery/gAAGVsmvEx453mepBF1j0grdU4WiJjmefM1VnvY8yZ2+wrssY91f+mxg57fm/K+AAAZeyyx0fmB3LonXFHt2T2W/G+lOkN9FPl630dCTFNPfW6tB9uWd+7bm4e6RHfJSrGnNHcAL3CjXWEx9ZfSfdnXPJaWubR7kVTm2Uffaaa6HFHOl/LUhcAUMbuj7NXW/aqEmcFo86uR1neupe57Ev1Hph6L9o12vL7IVpse8q0dHkvQnllfACAMkIcYBhhBPiqLLP9NZZmCCKs4S7xbC/a1OwqW4ytjZXpuY8lW/nXeLRBtCf2TNdn6UF3mWIjhsMGPqM3zqkvxArLfK/ElnlzaY9IcWVZ+mDe0vNOstTv0ee4UJulLgCgjBBLXSN5dAaF2ctjETI/W2TnIs6uR8gG3Nsiy9ha3vhbGzeb3HuvzFx3nE/GBwAoQ8aHWaPNKJ/JvHm5V8Yy37rNCmSPZS+Zr8t92UfJ0hGHgQ+bmbthLfm5CCKW6VUjxrRmYD7SdaiyjD5SnW3NJGA5S10AQBkyPsyamlHezizWzjbMTvY1+jk3U9nF0WLs9epGZ0tJ+VTJ9O1FxgcAKEPG5wDZR+Zzs8ClJzebUbIH7Wr6zeWuC/yXgc/BRr4RGfBAHpa4zrPHUnTl5d6lLHUBAGVclowQL5fL3621v/Yrzm7+vF6vfzz7UOL4Whs/xq74WhNjcNrpL2IMTYy/jBjfooEPAEBmlroAgDIMfACAMgx8AIAyDHwAgDIMfACAMgx8AIAyDHwAgDIWvbLix48f17e3t52Ksp+fP3+2r6+vpy/Myhpfa619fn5+9RxGlTXG3jpsTYyRjd4X1eHvxBhX5b64aODz9vbWPj4+tinVgd7f37s+lzW+1lq7XC5dJ2tmjbG3DlsTY2Sj90V1+DsxxlW5L1rqAgDKMPABAMow8GGxy6Vr6RsAwjHwAQDKWLS5mdpketabunbX6/WEkkBtt31RH4xv7ntnbf0Z+MBODBQhjiz9saecow/YLpfLvzFOxfp9jW4/t4SlLgCgDBkfnsoyU1rr6Piiz9YeXY/o5YasRr/H9uq9Dt/3osvl8u/PLLk/yfgAAGWEz/g8GwFmn4Vm3GiXpZzPHDHLinytRtpwLUtFRmvvQWv3thxhTdnur8PesYUb+FRJ+U3FGX0QFLFMW6sQ41wfG2kw1Nr6+0nEmJfEErH8PaLfA7eytJ9F/l6c+y57VodHD3i+WeoCAMoIkfFZs5x1+zjbo89E1DtyjxJX5JnGls6+zme53ST46N8iq9A+e88xqXAtRvWsr83107OtLduZscj4AABlnJrxqXRQ05K1zNvPRsn8vCpSRmGUa7rUXBuMPKOckqWcW8qcFeB/Rt3HNNX+pu61W3wXvHoNTxn47HEEdUSvbKwc4eb1LIazBiAjtbFeo91sp26yr8YVtc/1xhW1/FFkHhhmKvPU99dWT11utRnaUhcAUMbhGZ8tRn7RZ69bZLTuZycRzm1Y+4ji1M9kmsGQgyVMItuynqK38egPTcj4AABlhHicfc0adoRRYwVL1munfnbNv7Gdin2mUuZHtiePNXuMstfvln1wy3vZ4QOfpYOcbBt999rEdaboaUvq2mLDaqS+1ivqgwMsM1dP7rf7sdQFAJQRYqnrVu+ySrQZzZaP6EedgUa51rCl26xR5Da+JJvcc7L9FkvWLLdm+0DlOtjj+1DGBwAoI/zJzUt+R/ZRcZWDHTnObTYjaiZxa6NkWL+t2esxdRzGq3/fPWg7vcd7VL7me+5xkvEBAMrYPeOzxWyqZ5R3O6M9cpT8apYm+myzmlGfpFjydOQI8Y5gi7a4xcGh2sP+XOPntrxGuw58jhr0LPncEbYc8ESKa2Rz9bH14PSsOh25LY0c27ctYnw0AK5w/chlzzZpqQsAKGPXjM+zV9Fn1xuT9HJ8W765Wd2xh60et9c+qU7GBwAo47DH2de80TujLbJcZmR5qCv2om3BPsKd3DyCpQMeN7jz3deZOoExbbmsTU6WugCAMsJkfB6NwqO/P+fb0llEhpiqMPODetyD65LxAQDKCJPxmZPhXTHeszUGdQUwthQDn6x8icZmiQsgnmf35le/Wy11AQBlhMj47D26O1q28m5lhMf4LVnW4QgDOM8rGfdXt7/I+AAAZZya8ekZ8WWchWXYjL2VpY/v337+7Ou09AiC289VqNtR2dvF2bZsg1NvC4h8f4rQ/w4b+IywDHLver2GqMSopuow8gDoEXWcnyVMotj6fjL1+86+p06J1ActdQEAZVyWjLQul8vfrbW/9ivObv68Xq9/PPtQ4vhaGz/GrvhaE2Nw2ukvYgxNjL+MGN+igQ8AQGaWugCAMgx8AIAyDHwAgDIMfACAMgx8AIAyDHwAgDIMfACAMha9suLHjx/Xt7e3nYqyn58/f7avr6+n54Rnja+11j4/P796DqPKGmNvHbYmxshG74vq8HdijKtyX1w08Hl7e2sfHx/blOpA7+/vXZ/LGl9rrV0ul66TNbPG2FuHrYkxstH7ojr8nRjjqtwXLXUBwIEul4uXH5/IwAcAKGPRUhdQ2/0s1bv+YJnbPvT9/9f0I31xPRkfAKAMAx+ApL73itgvUstUfWsD/Sx1Meu2M02lUqc6m5TrmNxY41AX3Mt43+1px3vEJeMDAJQh40O33lmmTXdjkdWLTV3ktbTu5u7Bl8slVVtY+33S2uttXsYHACgjZcbn0Ugx+2j3u/y9I+Es8UadiTy7zhHLvNZWe0KiXpMR7gk9Rt/bM3I9jl53veauw1w9b3n9Ug58pkTvGD2VtrZBsMzSFGvGa+8m+48tr8PZ7WDkOn0WW+a+eJTo1+bVJavr9frv73i1PVjqAgDKSJXxybrJMmu5l7iNZ+6MiQhx95Zh7exi1PoeIYbR3M6Cb//bqCLdR46UPdu39VL77b15TVuQ8QEAykiR8ck6g85a7lu9hxbejryXbtKOamp2cf9vt549avro57a29XXP0GanMh+j6GlX9/8tQ53d2mtTa/R7cNUMVmvbxbzmGqYY+Iwo8xNFz5a1RjM3kFuzDBa5bqdkuTkvHYyOoEJfnIrxWT+KeC167iOjup2YbHEfeXVybakLACgjfMYneqpyytLU9Nznosc6NRuLXua1ph6n/Da1DBZ9Fveonh6VO2O26tXynlmHS4+3uG13o/fF1h7fbzL0u+hl3MPebXFJm5fxAQDKCJ/xySjzLPMVc3GPPPN85NHMrsJsnH1oM+tFunZLs1TZslpHWZs9SzXwidRweUynPNerqfQsS3Wjm6oHg+Yxqc9jWeoCAMoIm/GpONt8dk5MdBXr7FakOpvL2vSWM1I8R8vYlrPfP3rIRsaS8YGH1mR8AIBCwmZ8GEfGGcGejrwern1+z7Icld7V9W3pYZUVrslZMu47k/EBAMqQ8QlghBmbNXdGd/bM9tEBmhnvF3uotP8nyiGIc4e63n9uqZ7vxbXXwMBnhS1vOtlvYNLLVKE951C1ns7aaNwz4NxikLb0rQdzLHUBAGWkyPiMOIKX6RlLxTeDj+x2FluxPcNSme6BMj4AQBnhMj5RR4i31myiG2ED87dHcWeOCaZEatNTWeIqb2LnvzJs5r5tk2vL+axdP/pufX9/f/gz4QY+2czddF45NTeSyB0rIsuA7EX7Iau92u6a32upCwAoQ8ZnB6Nkelqru5w3xXuvOIOMK3PcW5aT8QEAypDxecGep1Zmdh/vKI8E39b3CPHA2fbIZumbPGPg84KRlrQemToa/ZXjx7Nfn57yZ4+RmLK3K0t2RGGpCwAoI3zGJ+Isp0Km59bIsfE7S7b5jFQvI8VCXDI+AEAZ4TM+0ZmhPGZNfyxL6lO/2N7tQwIZ98xlKitjM/Bhc9WWAhlD1HY79XoKYD1LXQBAGZclM5rL5fJ3a+2v/Yqzmz+v1+sfzz6UOL7Wxo+xK77WxBicdvqLGEMT4y8jxrdo4AMAkJmlLgCgDAMfAKAMAx8AoAwDHwCgDAMfAKAMAx8AoAwDHwCgDAMfAKCMRe/q+vHjx/Xt7W2nouzn58+f7evr6+lLbrLG11prn5+fXz2ncGaNsbcOWxNjZKP3RXX4OzHGVbkvLhr4vL29tY+Pj21KdaD39/euz2WNr7XWLpdL15HiWWPsrcPWxBjZ6H1RHf5uaYy3L2E9860C6vF/RozP29mhsPu3fXuFDWe6Xq//tsnv/9Um2Zo9PgBAGTI+UMx9lgciuc/wXC4XWR82JeMDAJQRLuMzNxs16mdvo+4rkOUhq9H6YiWvbFbf814cYuDTe1PO9qW09ssmS3y3nqWjsw1oK6TXR4/vmZ7+Ge0aZetH1PTqRGvviZqlLgCgjFMyPluMBqPMbvYYmUaK75nb+Ndei2yZvEym6qTSdR7pXsO83rqOUJ8Zs41H2zN+GR8AoIxTMj7fI7ml69XRNmguKc/a/S9RvRp7tJj3PsivQlYrWozR2tirHsWzxfWOVndLLK3ns2JdW85bGeuntf5yH9VnT93cvLQSbwdMkTtqxDJtbW7wurZeRxTpy3ev6xylL27RFiPV11GmlqvPrstXPCt7xTo+0prre3SdWOoCAMoI8Tj7SLaYYWaYbWUtdxVHzaCizJ6rtsetY8x0zZYuT5/VVqP0kUz2bocyPgBAGWkzPmfOTF6ZXY46+l8Tf6bZ5Rqj1nVr8erx9q3e36YeRc9YJxnLHE209vrttizZD6fMlHVNNfDJvAlvpJvXmpvISPE/k+kGsET0OpzacB+9zGdybc7TOyDPet9Y+71wVLyWugCAMlJlfG5FGwlPZaAynSR6hmxZu+yWXu+sqfeec8KmPn9LNiS+nnrOXI+R+9itjNdYxgcAKCNExifjiPGRkWK5t8XJo6OKtkY/Nxt+pV4yzEJf2ciapc1mqIej9F6LSNds1H2A33r27py54fzwgU+WG8ucpan0nt+V1Qj1uYWpp4qy1+23DHGM/kXCMtn6YvTyzcm45GipCwAo47CMz9IZ2bMRYoQR/dQsf8nPZjNqpuuVeKJnGpZu3I1U9h7Rr39Eo1+zaNmFLe+bkb0SZ0+bnDqXay0ZHwCgjMP3+LwyYnu2YfOsrM99OZZ8PqPbTNfSrN0I8beWO7Ys5ZwTIeNLLL17TLSVfa15Z9rRh4/K+AAAZeye8dniEej7EeSaQwKPUmU2MVKcW7znaaTrAaOI9F0RccXibHPf7Xs69XH2ns1QFRtDdhmXgdamWqPHNaJqyxZbxpixby71KJ7ocTrJ/jiWugCAMnbP+MwtF2wx+6jyqCDHmGtPZmJkVeH+mKV/vnIMCtuQ8QEAykj1ODuxRXtf1SsylhmW0MbPU3mlIkLsIV5S+oqKDecIo53OzDgsFfRznWKbe6hi9PvnmfFZ6gIAykib8XFyK1Bldrwl14rqZHwAgDLSZnzMWvax5Z4As3H2cr83YovjB0Y6wiDDgwYZysiY0g58yKPaSbscZ+6VBFU39mYfwNnGwN4sdQEAZcj48JveMxbmZmFzP2v56zx7ZEAi1WOksrCdqi/wZD8yPgBAGTI+gSydke85C3rld0c4mZN/7F0HZuPxZK6PuT1bsBUDn4Nt/dRU5JvcVNlun8KJXPbsetvZ2jrwpcTeTKDYi6UuAKCMy5IZ3+Vy+bu19td+xdnNn9fr9Y9nH0ocX2vjx9gVX2tiDE47/UWMoYnxlxHjWzTwAQDIzFIXAFCGgQ8AUIaBDwBQhoEPAFCGgQ8AUIaBDwBQhoEPAFDGoldW/Pjx4/r29rZTUfbz8+fP9vX19fTc86zxtdba5+fnV89hVFlj7K3D1sQY2eh9UR3+ToxxVe6LiwY+b29v7ePjY5tSHej9/b3rc1nja621y+XSdbJm1hh767A1MUY2el9Uh78TY1yV+6KlLgCgDAMfAKAMAx8AoAwDHwCgjEWbm892ufx3g7a3ywMwoqnvvNZ8770q3MDnUUU/+3z0hrAkruixwKjm+ql+ydaWft9N/Zx2uZylLgCgjFMyPmtHuVVkGs1nKuurKsWazVZ18/2zU/eoLNll4tvyO9B9aTkZHwCgjHB7fHoY1Z6jaqZuLu6MG+63LPPlcjk13r3a5G1MVds9vCrqnrlTBj5z6eSlFyNLmq+nbFFvsD31NLc08Ejk+mrtv+WfKu9cW47kWfmil7/HUe3p7MEePBJhOTbDvcRSFwBQxqlLXa+MSntm45lFiac3o7ZmaSDC7OSRLJnEZ/aefZ11bTLMKs+y9Npkbt9Zrc0UT9VVlL6QadlfxgcAKCPl5uYoI9ytRIxnTcaj4iGNEeuutbjl2sso7WmpV+o54jV7tn9qlEzst6lM+dK4Iu4zXPqdcXRdphj4ZEqhLRU1tqWdKftG5ikZy9zjlSe4Xv0dI4gQe2+/jFDWHrfxrL3nZIn1kS3Lf+Y2gj0myluz1AUAlBE+4xM1I1LJq7OHrPU1F3f0drlH+jtSfGeIEP/WZzC98vNb2mLTbqR4iE3GBwAoI1zGJ+pJj0eKdEDa9Xr9t06qPiYbadPgFsyM+0Wq++hZxq3dZi17DkzlXJnaYpiBT09DjtbxH5W596mELJbGk6kDPHI74Ov9fEQ9L92c+nx1kfpp9XrqjbXSNcksQt+y1AUAlHFqxmft0snUo49HjvYrvPdojdFmXKNl7npEWmaNItL1iFQW9jfSI/uR7pkyPgBAGSnf1RVp1LvFY8OR4ukVafTOc0v3LFUV6RrtVZbMm9sj1c/enu3Ly1h/Ucj4AABlhHmqK7uMh9ytNWpca2SKO/KbnaOKVL9blCVrfWct9xpbvSYokqlM1ZnlN/B50WjvzIEMSyGRyxbdCNduxKXbpRPKDGfeRV2as9QFAJQh47PC0lRdpJHuKyxx5Uovs0zU2ekWMmTxHqnQ57a6t0ap3+h1JuMDAJQh4/OCKKPro1SLdyQjvH6jmvvM8pKM1AgH31XPMM8dJho9ozIlUpkNfGCF0W7Ao8WzVsTr0Hti/cgDhbk4Msc44hNcS5xVd5a6AIAyZHxggcyzyymjxTOyqUe4R87yzBklA/IsY9cTZ8T6nspSRiqnjA8AUIaMDxTw6NTmETbBvipT9qBi/dzqzYpkvE73Zc5wQOEzUctp4ANFjXj6LWNa2k4zn1v0LXPZo7PUBQCUIeMDhU2dFVNtplkt3iyevVS354ybETI/bE/GBwAow8AHgGHI7vCMpS4ozOZmMjK44RUyPgBAGZclI+fL5fJ3a+2v/Yqzmz+v1+sfzz6UOL7Wxo+xK77WxBicdvqLGEMT4y8jxrdo4AMAkJmlLgCgDAMfAKAMAx8AoAwDHwCgDAMfAKAMAx8AoAwDHwCgjEWvrPjx48f17e1tp6Ls5+fPn+3r6+vp2fxZ42uttc/Pz6+ew6iyxthbh62JMbLR+6I6/J0Y46rcFxcNfN7e3trHx8c2pTrQ+/t71+eyxtdaa5fLpetkzawx9tZha2KMbPS+qA5/J8a4KvdFLymFAm5fRuq0dqAye3wAgDJkfKAImR5uM3+3tA0qkfEBAMo4PONjr8EYvutRHcJxHmVsyO1yubiXHujUpS5fnjm5+cJYzr4X995T1pZv6vdH+N65LVfUMo7IUhcAUIbNzfDA/Qws8+wrc9nZzm07iJC5nSvDd1mfZUVe+dvRM1xnZ+JGJeMDAJQh4wMTpmZkNiDah5DVVB3NZVSOqNPetrSmLHNxnBXv1N//dr1eQ2Tgotuqvg4b+IxeqWfFl/lLpyfNfbSl9fjs85nrh5yytLnbL/uty5zpGkz9/2/f18eS17YDVktdAEAZlrpeMHoW694RZzBFyvTcLwUsTcNfLpchZmoRM3NHyXTu2NLyRbh/nX1Nz17i2vLzZ9vrXrfH8rqMDwBQxmEZn6mNdFmNEMPZIm2SfVaWteXKumExY5m39mhze2ux2unWv+PsDMyeIh1P8WzTdRZz/SSyEEtdoz0tM1IsW4vUKSINvrJxneLYoi5Grc+ofXzpfTBCmac8K9fW9/utroOlLgCgjBAZn2yinX4aRe/ZGd+izmIq6mnHFeorW3/urZNqG9Qj3m9G2u7R65Vrvud1kvEBAMqQ8WEzjx7/zjDDOXs2eBaZnv/J0E6/yfQsEynWqYcerCI8t2UdHj7weVbp2WT6cj9a1JvuXLm2PLclept4VL6M/bH3Wr8SW6brErXvHSHD2Uu95Ypa/r3tfe+01AUAlHHKUlfVUSwxzL2c8daSc1uiZ3duZSrr1jIfneGx9X4Z46zcL78dtSldxgcAKMPm5hcZpf9Pto2yU5mf3j1b2WJtbdu2evYpxnMilulIER/lZjl1th8ZHwCgDBkfVlmS8Yi+r+LRW9fvY8z8nqNHWYClT1hGznCuvf6Z6/VW9UxP5Lb5zNZvbh+h3veMwcCHbr3LQPcNNmMnfLbx+Vv02Lb8Mny0ATz6Nbi35EsmW2zkN9fmMg/u5hwdl6UuAKAMGZ+NVZghjhjjEQfgnW2PpaBI12Ppu+JGUX2Jq4KR2++UvduvjA8AUIaMzwuqjcJHZoa8TLTrdbtRe4t+GS0+6rjNXPa8VmaE76Gj+5uBzwojNDTG9sr78Hrad8RzfObOZZoy6hLRK0/mjRB/a2PU7QgxRGWpCwAoQ8ZnI0bijOD28fSprFHETM+9pW++njq6IHJ8t7Y4YfzZ57Nci8zmlrVuWW3YhowPAFCGjA8UsGSm+OizZps5qKecWareA2J7fgfzDhv4ZEshQ2Zb3ETnfu+oqseXedA0St0tfWJrlLiPZKkLAChj94xP5hnEPRv/yObZI94VHm1+ZKR70yO9dVjhWmR0339H6pNz36c95xe9QsYHAChj14yPWQTE8GimNNIMstfes8kj7VnmjNdjVCPVxdy44Kgxw2Gbm0eqOCAny9X/ZYJKNZa6AIAyLgvf4fN3a+2v/Yqzmz+v1+sfzz6UOL7Wxo+xK77WxBicdvqLGEMT4y8jxrdo4AMAkJmlLgCgDAMfAKAMAx8AoAwDHwCgDAMfAKAMAx8AoAwDHwCgjEWvrPjx48f17e1tp6Ls5+fPn+3r6+vpuexZ42uttc/Pz6+ew6iyxthbh62JMbLR+6I6/J0Y46rcFxcNfN7e3trHx8c2pTrQ+/t71+eyxtdaa5fLpetkzawx9tZha2KMbPS+qA5/J8a4KvfFw15Syjq3LxB0yjYAvMYeHwCgDBmfoG4zPa3J9gAsVSFjfv9d0dq5sWa45jI+AEAZ4TM+U6PZR6KOLl8xYkwAUx5lC5Z8Dzz73aPcU7e4JluaKk/Uax524BOtUo9UOXbgPJGWKfa6D0b9Ml4i+ndE9GtrqQsAKCNcxifaRi3mqS/ITwYhh2f15Dr1kfEBAMoIl/GpLNL6+rc1M8ER1tCrGjWDt0VGY4TrMEW2h2oMfAKK0NGj3wzZ1lx9Zx4MbdmOKw3oI8QYoQx72eOctpGv19YsdQEAZcj4BJAluzI3o8gSA9uIuCz7TVvskzmTB6+Q8QEAygiX8fmecdzORqqsrUeKr7csZo1jmOp3U/U4dzrr3M9F8UrZvuO8XC6hYyS2Vx4YmaItLhdu4PMt6wDITZHMnrXdqX5ZUYZ70SOR6y7j9aTPUe2upw1Z6gIAygib8Xn2eG3kmcGS2WDk2dec6ktcS+tttGszl/mJ3j/5L/V1nKmXrz7qM1mXuHruj2eWX8YHACgjRMYna9bj1iuP90Yeud/KOvt4Zk37W7r5O/OekDnX6zVV/62eqSOuTP1oyrP9f5H6UoiBz5yl6b8sRojh1ijLG1vHcH8zGOU6RbblBuwMN/Glsj44MqKpZa/sMrQhS10AQBmnZnzWLp1EGlFmOsNkb67FY2c/Bl4x07R0GS7bst2rqrWH6JyMfxwZHwCgjDB7fDLOPqo9yoz5gTwAABAkSURBVLt0Pdq+gWlHXpepfRzf9vr7kep77YMG1Y9rIJazM8ajkfEBAMoIkfHJNpN6NuqusNdl1KftRrEkI9fa+jY6ap2P2GfJK2s/i5r1DzHwybw81DMAGPX8m3v3sWTprBU2tT5bplx6g7IUBDwS/X5qqQsAKCNExqe1uCmxKb1vsL4VfQS8p8wZvVHc1sGz92x9047JaMT7TdbNzVHrQcYHACjj1IzP3NHpc5/PKOuIfY3Mm7uPyDyecT2m/mbvvp81vxvOZA9aDFFXckIsdfWeWBn1Iq6ROYbbVPKoA9Wt3LfZo67J0neELR2Yq1uievSwwgjfH1nKPnX/uf+3M1nqAgDKCJHxmTPKo8YjxHBLpue5aHX+6oxXvZLF3Mb8ETI/WTzbznJWHcj4AABlhM/4jCLz5uaeMo8yexoljm9LHyBgLPZsEcHS9zzuzcDnIBEqe4ml5c1+dsaWZY+QyqWeV+4xln+oxFIXAFCGjA+/6d20nC2Dtbfo54YsqbtI5ea5V9tehb5cIcYsXjk5fisyPgBAGTI+B8s4m5479bf6TCp6pmdK9PLRL2P7O0L1+1I2R5/2H3bgM1rDzXozylruvTi/iEhuzzlb2v6yb8Jf+h2RMcbRnfV6I0tdAEAZl4Wb4P5urf21X3F28+f1ev3j2YcSx9fa+DF2xdeaGIPTTn8RY2hi/GXE+BYNfAAAMrPUBQCUYeADAJRh4AMAlGHgAwCUYeADAJRh4AMAlGHgAwCUYeADAJSx6F1dP378uL69ve1UlP38/PmzfX19PX2xS9b4Wmvt8/Pzq+cUzqwx9tZha2KMbPS+qA5/J8a4KvfFRQOft7e39vHxsU2pDvT+/t71uazxtdba5XLpOlI8a4y9ddiaGCMbvS+qw9+JMa7KfTHs29nhDNnfWL1W1biBeuzxAQDKkPGB9nvGozVZD4BRyfgAAGXI+JzkPsNwT8bhOFX3tzxrg9lMxVOpPiGqpfeavfutgc8B1nzBfP+MG/cxKl3nufZY6Tp809diu1wu6iaRLSZUe09GLXUBAGWEz/hkXBJaMuKdKv/tz48yG42YZRhtqeeZiHWwlVeyqsDrtu5Pe96TZHwAgDLCZnx6R48RMyLfZdmibJHi6rV05H92HWa8xks9qpORYx85NogiY+Y03MCn9zyV+89F3AC3tDwZG9C3jEuSr1hbV0dfh5GXt1hu5H5a9enMyJ5t5Ziz59lqlroAgDLCZHyWju7ul5Myy3j+SNVMwgjtbcv6GSHTOqIR2um3Z/U5UqzZrFlCv/23JXW35b1GxgcAKCNExsfa7O+iX4NRNsqOvAdrjyzio/irZv+i6Wmfr+y5ONra74Wqbe6M79Hr9frSwyk9P7PH8S4hBj4VjbK8Fb3Me5uLP9IXyiv1FCkO/qtqvxypXW4dy5FPyu7xN/ZeQrfUBQCUESLjs2Zkt+ejbnsaZXaWscxrLa2zs+t4q5T32XHQZ7Q6yXpvX2OkrNUrpq7D3LV5NaMl4wMAlBEi47NUxlFy5g3BlWZgt9aeQJ1d5rba2vPZYNX2PCfbNZCNnJfhWpx5vww/8BnhpFGddHxRBwtVXpty+3QJtWRon1Xt1SdfrXNLXQBAGWEzPlkzPc82lkYtd4/b07Izx7GFyNkF2Y9/TLVTZ4blJGvOlmR8AIAyDsv49O41yDRTfVbWEWaXmepja6++Dy5SnS/Zg5T1PXhT5ZYpeCxL/arDftGuy9oDXte+z6uXjA8AUEaIPT5rRnRnPJL6ysjTI7R1RKjbub0tPf996jMR4uqRNWPFP+bqL0sbPFK2axKhXg8f+Ky5GfW8WG/vDbdblzvbl0lrOcu8hd60a+TrskXqOMINa4nIZeM59fc/2a9FtOM+LHUBAGWEWOqa8mwkGC2dnX1E/sioca01wvXoyaD2GmEDf3Xq7TyjL+tFzZDL+AAAZRyW8XmWoVk7+jtq1DjC6Bse2SILJPsD61TqL0tj3WN15/ClrkoVPMd1ILpXbjhVN8ID+z/F/Or9xVIXAFBG2M3NQAzPHoWX1cklygMhsMTtOwi9nR0AoJOMD6eQOchJHQG9tr5fbPX7DHwOIr0MQCVRH3Kw1AUAlCHjA1BItNk344u2tUHGBwAoY/eMT7SRHgBwrjNPerfUdYCpwV/UTV9ncA2Ae16BkldPfd3W79Hfh5a6AIAyLktGWJfL5e/W2l/7FWc3f16v1z+efShxfK2NH2NXfK2JMTjt9BcxhibGX0aMb9HABwAgM0tdAEAZBj4AQBkGPgBAGQY+AEAZBj4AQBkGPgBAGQY+AEAZi15Z8ePHj+vb29tORdnPz58/29fX13/fG3Ena3yttfb5+fnVcxhV1hh767A1MUY2el9Uh78TY1yV++Kigc/b21v7+PjYplQHen9/7/pc1vhaa+1yuXSdrJk1xt46bE2MkY3eF9Xh78QYV+W+aKkLACjDwAcAKCPtwOdyufz2WnsAgGfSDnwAAJZKOfC5zfTI/LAXbQtgPIue6jqLLx/O9N3+rtfroT97hjV9LUNst/XQE2OGmIB1UmZ8AADW2DXjs2T2eD/D6v1ZMzNYZvQM6lx8U/92ew/5/vfbz7nHsKVn/W/09vasDx5BxgcAKGOXjM+aGeXSnxl9VAxb2KJfZcgQbTWL/P6ZqDGvLdfctYia3YparrV66y7bvsCMUmxuvqdB7Oe+cy75IlQvvzvzy3Puby+tp7nBwNl1vnRZ65nveCIOgF4pS6Yv3UjXfAs999Spz40mUnyWugCAMnbP+PTMHLacnWa0R/p6rfuZ7l7p5tHS2I+cEVvEzAzrPbs/TmVpXp1dn9U/I2UFtla9D0bKosr4AABlhNjjU3EkHP1x/bm/+2jfT4T9ARFEmNHslZ3b4/e/Yoty3J8Ef/t7o8R577ZcU2XMto9ki3JFv6cSx+4DH6ek/qP6ct63qDfekWzVniIPeFim9+yYTEvQa+8lR0/QXt3uwfYsdQEAZYRY6so0y9jKaHH2vgMps9Hj++a4glj23hT6bNlsT0tXBLa8BpfL5fQ2XeWeEo2MDwBQxi4Zn1dG6L2HPRHL3AbRqjLGX3Ffz1RGJXob7i3fCHsLX8mKRD2JfIR6ySzEOT6tPW4IEdKRW5g7H+f+M9mNFsfadHymtjtye1wjYuxTy8mP2lilL9apF1yPFiPbstQFAJQRYnNza9Oj9hHNxRk9vT5l1Hq6lak+lpLp+Z8Mcc8ty91/Zu7nI9h6CevZv0W/V0Wqm9HJ+AAAZYTJ+FSVfW/IUpHe17K3UeuQ883t6xkti5e57FMq3Puik/EBAMoIl/GpOBrOEnNvObPEU1WlJ36qi1yfU0+p7VXeCFkw/S6OMAOfKqfFGhT8V8ZN3T0yLVlmKSf/lfmeUr3dvXIO05rfxz8sdQEAZYTI+ERIQ+5tycg9WuxHzSgzZUgyqtDP4FamNr/FfXbU7PnWZHwAgDJOzfhkGo2/atS4eiw5Un+kGUukGLbua7e/L1Kc0FqefU9ZyjmaUwY+Kjs/X3aPRbo2vQMefXIskdrgUZ614QrXpEKMW7DUBQCUEWJzM7HtMYuYOsNjr79VWc+7ncjtvo6r9aGe9hzhmqw5tX6u3PrxejI+AEAZp2R8et4zE2GEzr4qvbfrbI8ybI8++4w6i6faPTNLpufemjJljTWqsEtdBkBx7H2svDo+xhbX+ahXDMCcKq9/GD3Os2Kw1AUAlBEm42PZIw+bkoEzjJ4BuTVqrBHKLuMDAJQRJuNDbrJA45ON5QxV2t2SOJ2c/hoDnxct7ZQZG+naZUidc1zqk2gyPxDzyuAuc9xnsdQFAJRxWTJKvFwuf7fW/tqvOLv583q9/vHsQ4nja238GLvia02MwWmnv4gxNDH+MmJ8iwY+AACZWeoCAMow8AEAyjDwAQDKMPABAMow8AEAyjDwAQDKMPABAMpY9MqKHz9+XN/e3nYqyn5+/vzZvr6+np4JnjW+1lr7/Pz86jmMKmuMvXXYmhgjG70vqsPfiTGuyn1x0cDn7e2tfXx8bFOqA72/v3d9Lmt8rbV2uVy6TtbMGmNvHbYmxshG74vq8HdijKtyX7TUBQCUYeADAJRh4AMAlGHgAwCUsWhz89kul382aEd/o/x3ObcQPVZqytIXgfM8+y486/6RauDz7XK5hLvhbjnYGU3vtYlWp0vdx5k9ninZ2/lt+TPXzyhx7G2uvbpu+1hyjzirfix1AQBlpMj4RJ1lRi1XFEuvT+ZZbPS28Kh8S65z5voZRfR2dqbMmeWpskcs55w12Zu5n9lzOV3GBwAoI0XGJ5otN2xtMROPYvTZ6O3esix7B0avk0pGyArsIUtfvNXTLzNnsL49K9v9v0/FvEfmx8BngYwdbG8jf7HOdcKM1rZRS1zxqId5la7P2f1zywF5z8RyC5a6AIAyUmZ8RhjNV80eHTWiP8rIdTXq4/nZ4hilrxwlev0uqc9H98vr9apdvEDGBwAoI2XG5wxHbCyMPlO5tWbWcv/fos9YMtXHlqLXy6ucOj2G0dvprUf30NbGug5HxWLgc7ARnszY6qm2ETtudiO0z5G9WhejPEWa8Z7xbHtDxpham76P9yyTn/nUmqUuAKCM8BmfrKPge6PEMWfpyLzCNTnb7WxsbolHpieeLfqHPhbbbR9bmgHPVLdLy7r3vUfGBwAoI3zG59aZM9CpNdjet8RnGpkzptv2u+XJ48Q06j1n6rC+qfvy/WciuC3LfV+MVM61puJ75XfsKdXAJ6KphttT6SM09Hs9nXjUG3IGc6n0EdvjMyN96dxa08cyX4u5dh01rvsy906ie35nBJHKMsVSFwBQhozPAj0zi97fkdmzRy9fyeqMcH2iq3yNMz82/MyWm6EztpG5rPsWGRXGIeMDAJQh47PCmoP3Rptt3Mcz6iwazjJ3MNwWG0kzWfs49LNrd7ap4yZ6VKjzPcn4AABlyPi84NF+gUgziqM8OxTP6ylgnZ5XAmz9t6Ib7bU4U98lr7zmgXkGPi/KcqM4w9IX67mW8NieG7P1vfM5BuQ4lroAgDJkfIBSsix/TNnyoQJZntzU33oyPgBAGTI+AEk92/czalZg5AMJM2YiszHwgQ08ulmNenMewSh1M0occ9aey5NlELH2nCLWsdQFAJQh48OhRnmMvXeGFvG0WBhJ72nWWfpg5s33Wcj4AABlyPhAp94ZmBkb7OPZG9jnPh+RvT3nMPCh29QrKNb87AjcgOBcmfvg3CBttHtlRJa6AIAyZHxYZUlaOfuj3q9kugB6jH4eU6RlPRkfAKAMGR+e6l2PXvLo9ggzmGcqxAgs17ufZ5R7yKPvkEffGZfLZdejQFIMfLJV/hab0yLHfFu2uQHQiJzLAxxhhHvMsy0RZ8VoqQsAKOOyZMR1uVz+bq39tV9xdvPn9Xr949mHEsfX2vgxdsXXmhiD005/EWNoYvxlxPgWDXwAADKz1AUAlGHgAwCUYeADAJRh4AMAlGHgAwCUYeADAJRh4AMAlGHgAwCUYeADAJTxf4rkxtcxx9ImAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Generating new images\n", + "samples = np.zeros((100, height, width, n_channel), dtype='float32')\n", + "for i in range(height):\n", + " for j in range(width):\n", + " logits = gated_pixelcnn(samples)\n", + " next_sample = tf.random.categorical(logits[:, i, j, :], 1)\n", + " samples[:, i, j, 0] = (next_sample.numpy() / (q_levels - 1))[:, 0]\n", + "\n", + "fig = plt.figure(figsize=(10, 10))\n", + "for i in range(100):\n", + " ax = fig.add_subplot(10, 10, i + 1)\n", + " ax.matshow(samples[i, :, :, 0], cmap=matplotlib.cm.binary)\n", + " plt.xticks(np.array([]))\n", + " plt.yticks(np.array([]))\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 153 }, + "colab_type": "code", + "id": "KBuWx-FtSouR", + "outputId": "85fb1988-aeea-4695-f5e3-d5a57d28bed6" + }, + "outputs": [ { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "-Ia9VXYySkuW", - "outputId": "924010f4-0dcb-4a82-bd1d-75c6091cadc6", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 581 - } - }, - "source": [ - "# Generating new images\n", - "samples = np.zeros((100, height, width, n_channel), dtype='float32')\n", - "for i in range(height):\n", - " for j in range(width):\n", - " logits = gated_pixelcnn(samples)\n", - " next_sample = tf.random.categorical(logits[:, i, j, :], 1)\n", - " samples[:, i, j, 0] = (next_sample.numpy() / (q_levels - 1))[:, 0]\n", - "\n", - "fig = plt.figure(figsize=(10, 10))\n", - "for i in range(100):\n", - " ax = fig.add_subplot(10, 10, i + 1)\n", - " ax.matshow(samples[i, :, :, 0], cmap=matplotlib.cm.binary)\n", - " plt.xticks(np.array([]))\n", - " plt.yticks(np.array([]))\n", - "plt.show()" - ], - "execution_count": 14, - "outputs": [ - { - "output_type": "display_data", - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "tags": [] - } - } + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAj8AAABECAYAAABu1lQcAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAADy0lEQVR4nO3cQVLkOBAF0PTEHIFeTx2C+58A7kCvhztoFkwHBOFy2WW7UCrfW3Y4OpSWbL5Shqm1FgAAVfz10wMAAHgk4QcAKEX4AQBKEX4AgFKEHwCgFOEHAChF+AEAShF+AIBShB8AoJS/t1z89PTULpfLSUM519vbW7y/v09L12SuLyLi9fX1vbX2a+mazDWumcMINfbOs/ghc43W6afRa8xcX8T1Z3FT+LlcLvHy8nLcqB7o+fn55jWZ64uImKbp961rMte4Zg4j1Ng7z+KHzDVap59GrzFzfRHXn0XHXgBAKcIPAFDKpmMvtpum+ePU1tqDRwIAROj8AADF6Pwc5FqH59b1FTpAo9Q6N8fZawLGNE2T99MCnR8AoBSdnwNs7fpAT0bpzO2V8T58f/dkGjvb3XvC8If18Un4OcnSIvu6IDO+cNcaKRSOVMtRvt6TzOv3+9xmeCbPWI9Z5jPLOPfyzjmXYy8AoJRTOz8VPxDdWt/o9yO7W7uvDF2Ca/buLFtrdqc/4Oj3apajEWttbI/OCzo/AEApp3R+lhL6kem9lx3K2nFU3bn0Mk9b+LCwhuzd6UxjvdeanydZ78O9489a7x9r369L1+29B6eEn7Uf++6VfeGPLGvQO2rcPf+NjaOCWtY5zuqMD317/nh4y/rq+Xm75lZ92epZ0uO7wrEXAFDKw3/VfW+a7Xmnck321jrzvs5hjzubORmfnzNkma+IXGP9SVlOAqrM59o65+br+1zO/V97u306PwBAKf7I4cmqpPwR7NmpzO1QsuxEtxp1TY82T3Myd6GXOgRz/9ZbXZnv/dHu+cD76PeOzg8AUEqazk+2bxXO/BW9nmWbp7XW1tJrB+iseRlpjjPZ8ht72Tt1o66xUes6osO19K3PUboPP9kf3K9GXewjM2efRnoWM1nzg+Deuel1ffe2edjLs/Ohp7/z59gLACil+85P1rSfddx7Za575OOgI8bTW017ZKwl45jvtfWYuXdZxnmEpVp7ug86PwBAKcIPAFCK8AMAlCL8AAClCD8AQCnCDwBQivADAJQi/AAApQg/AEApwg8AUIrwAwCUIvwAAKUIPwBAKcIPAFCK8AMAlCL8AAClCD8AQCnCDwBQivADAJQi/AAApQg/AEApwg8AUIrwAwCUMrXW1l88Tf9GxO/zhnOqf1prv5YuSF5fxPg13qwvQo0JjL5OI8av0Tr93+g1Jq8v4kqNm8IPAEB2jr0AgFKEHwCgFOEHAChF+AEAShF+AIBShB8AoBThBwAoRfgBAEoRfgCAUv4Dzge+SeXbn58AAAAASUVORK5CYII=\n", + "text/plain": [ + "
" ] + }, + "metadata": {}, + "output_type": "display_data" }, { - "cell_type": "code", - "metadata": { - "colab_type": "code", - "id": "KBuWx-FtSouR", - "outputId": "85fb1988-aeea-4695-f5e3-d5a57d28bed6", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 153 - } - }, - "source": [ - "# Filling occluded images\n", - "occlude_start_row = 14\n", - "num_generated_images = 10\n", - "samples = np.copy(x_test_quantised[0:num_generated_images, :, :, :])\n", - "samples = samples / (q_levels - 1)\n", - "samples[:, occlude_start_row:, :, :] = 0\n", - "\n", - "fig = plt.figure(figsize=(10, 10))\n", - "\n", - "for i in range(10):\n", - " ax = fig.add_subplot(1, 10, i + 1)\n", - " ax.matshow(samples[i, :, :, 0], cmap=matplotlib.cm.binary)\n", - " plt.xticks(np.array([]))\n", - " plt.yticks(np.array([]))\n", - "\n", - "for i in range(occlude_start_row, height):\n", - " for j in range(width):\n", - " logits = gated_pixelcnn(samples)\n", - " next_sample = tf.random.categorical(logits[:, i, j, :], 1)\n", - " samples[:, i, j, 0] = (next_sample.numpy() / (q_levels - 1))[:, 0]\n", - "\n", - "fig = plt.figure(figsize=(10, 10))\n", - "\n", - "for i in range(10):\n", - " ax = fig.add_subplot(1, 10, i + 1)\n", - " ax.matshow(samples[i, :, :, 0], cmap=matplotlib.cm.binary)\n", - " plt.xticks(np.array([]))\n", - " plt.yticks(np.array([]))\n", - "plt.show()" - ], - "execution_count": 15, - "outputs": [ - { - "output_type": "display_data", - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAj8AAABECAYAAABu1lQcAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0\ndHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAADy0lEQVR4nO3cQVLkOBAF0PTEHIFeTx2C+58A7kCv\nhztoFkwHBOFy2WW7UCrfW3Y4OpSWbL5Shqm1FgAAVfz10wMAAHgk4QcAKEX4AQBKEX4AgFKEHwCg\nFOEHAChF+AEAShF+AIBShB8AoJS/t1z89PTULpfLSUM519vbW7y/v09L12SuLyLi9fX1vbX2a+ma\nzDWumcMINfbOs/ghc43W6afRa8xcX8T1Z3FT+LlcLvHy8nLcqB7o+fn55jWZ64uImKbp961rMte4\nZg4j1Ng7z+KHzDVap59GrzFzfRHXn0XHXgBAKcIPAFDKpmMvtpum+ePU1tqDRwIAROj8AADF6Pwc\n5FqH59b1FTpAo9Q6N8fZawLGNE2T99MCnR8AoBSdnwNs7fpAT0bpzO2V8T58f/dkGjvb3XvC8If1\n8Un4OcnSIvu6IDO+cNcaKRSOVMtRvt6TzOv3+9xmeCbPWI9Z5jPLOPfyzjmXYy8AoJRTOz8VPxDd\nWt/o9yO7W7uvDF2Ca/buLFtrdqc/4Oj3apajEWttbI/OCzo/AEApp3R+lhL6kem9lx3K2nFU3bn0\nMk9b+LCwhuzd6UxjvdeanydZ78O9489a7x9r369L1+29B6eEn7Uf++6VfeGPLGvQO2rcPf+NjaOC\nWtY5zuqMD317/nh4y/rq+Xm75lZ92epZ0uO7wrEXAFDKw3/VfW+a7Xmnck321jrzvs5hjzubORmf\nnzNkma+IXGP9SVlOAqrM59o65+br+1zO/V97u306PwBAKf7I4cmqpPwR7NmpzO1QsuxEtxp1TY82\nT3Myd6GXOgRz/9ZbXZnv/dHu+cD76PeOzg8AUEqazk+2bxXO/BW9nmWbp7XW1tJrB+iseRlpjjPZ\n8ht72Tt1o66xUes6osO19K3PUboPP9kf3K9GXewjM2efRnoWM1nzg+Deuel1ffe2edjLs/Ohp7/z\n59gLACil+85P1rSfddx7Za575OOgI8bTW017ZKwl45jvtfWYuXdZxnmEpVp7ug86PwBAKcIPAFCK\n8AMAlCL8AAClCD8AQCnCDwBQivADAJQi/AAApQg/AEApwg8AUIrwAwCUIvwAAKUIPwBAKcIPAFCK\n8AMAlCL8AAClCD8AQCnCDwBQivADAJQi/AAApQg/AEApwg8AUIrwAwCUMrXW1l88Tf9GxO/zhnOq\nf1prv5YuSF5fxPg13qwvQo0JjL5OI8av0Tr93+g1Jq8v4kqNm8IPAEB2jr0AgFKEHwCgFOEHAChF\n+AEAShF+AIBShB8AoBThBwAoRfgBAEoRfgCAUv4Dzge+SeXbn58AAAAASUVORK5CYII=\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "tags": [] - } - }, - { - "output_type": "display_data", - "data": { - "image/png": "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\n/AcUCbSNo+kQgwAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "tags": [] - } - } + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAj8AAABECAYAAABu1lQcAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAFDUlEQVR4nO3dQXLbOBAAQHArT3DOq0f4/y+w/+Cc4z9wD16XXCqKAkVCwmC6jylFhRFAeDAAyWme5wIAkMU/z24AAMAjSX4AgFQkPwBAKpIfACAVyQ8AkIrkBwBIRfIDAKQi+QEAUpH8AACp/Nry4ZeXl/l0OjVqSlsfHx/l8/NzWvtM5PhKKeX9/f1znuffa5+JHGNNH5Yixt65Fr9EjtE4PRs9xsjxlXL9WtyU/JxOp/L29nZcqx7o9fX15mcix1dKKdM0/bn1mcgx1vRhKWLsnWvxS+QYjdOz0WOMHF8p169F214AQCqSHwAglU3bXmw3TcvbqfM8P7glAEApKj8AQDIqPwe5VuG59fkMFaBRYl3q4+gxAWOapsn8tELlBwBIReXnAFurPtCTUSpze0X8HS7nnkhtZ7t7dxi+GR9nkp9G1gbZzwEZccKtNVJSOFIsR/n5m0Qev5d9G+GabDEeo/RnlHbuZc5py7YXAJBK08pPxgOiW+Mb/feI7tbqK0KV4Jq9K8t5nq1On+DoeTXK1oixNrZH5wsqPwBAKk0qP2sZ+pHZey8rlNp2ZF259NJPWzhYmEP06nSktt6r5u9J1N/h3vZHjfdb7fy69rm9v0GT5Kf2sO9e0Qf+yKImeke1u+dnbByVqEXt46haHPTt+fDwlvHV8/V2za34osWzpse5wrYXAJDKw29135vN9rxSuSZ6aZ1lP/uwx5XNkojXTwtR+quUWG19pig7AVn6szbOpf667Mul79pb7VP5AQBS8ZDDxrJk+SPYs1JZWqFEWYluNeqYHq2flkSuQq9VCJb+rbe4Iv/2R7vngPfR847KDwCQSpjKT7SzCi1v0etZtH6qVRtLrxWgVv0yUh9HsuWOveiVulHH2KhxHVHhWjvrc5Tuk5/oF+5Pow72kemzs5GuxUhq/hDc2ze9ju/eFg97uXa+9PScP9teAEAq3Vd+LkXO/rPr/cBfT21pKfPTqCOvwGsP/K79v8jxE1dPFZ9vKj8AQCrdVn5GWp1GbvseVpkxrFXkMhzcjxzHvW3vPealW5tHOPuTQYvDyi36vNvkJyp/8G8zeT3e1ruBMiQ9mYw0L0WMpcVzanp35HZri3e32fYCAFLpsvIT+Vkxj3g+QTQ99mGrMdb7oe4ltVWh3uO4xTUZqw9Hn0sjvon+XjVxPrqfVX4AgFS6rPyMIEtGf2n01do12eIljmxjs9e5N+vc2CuVHwAglS4rP71m7oxpzy20o94VNdJZn2/Z7rgZpQ8v236tDyPG6Pb95+ky+SG+3i/mteeI7P1e+mXrIb7o11ivLz9+lmddi7a9AIBUVH5I68gqwCgrtpGerM5Z5soCz3HrSMCWebfFuFX5AQBSUfkhvSwP+bsl6zmYrW9Gj+JnZTNi+0c36vvLaq6nHuYayQ+siDwJ7TF63F7cCsepvQPv3qTHu70AAHZS+QHSUhXhmY666eJZ7xTcWjnt6VETKj8AQCoqP1TZmqkvZf0R33ieib4A9qqd+7d+x9FUfgCAVFR+2KzmBH9tpj/CrZ0Az9BjNb2H8zw1JD+sqnnOzREvBPUsEoBYIj8l37YXAJDKtCXbmqbpbynlT7vmNPXvPM+/1z4QPL5Sxo/xZnyliDGA0cdpKePHaJz+b/QYg8dXypUYNyU/AADR2fYCAFKR/AAAqUh+AIBUJD8AQCqSHwAgFckPAJCK5AcASEXyAwCkIvkBAFL5D4QYq3XSuptvAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" ] + }, + "metadata": {}, + "output_type": "display_data" } - ] -} \ No newline at end of file + ], + "source": [ + "# Filling occluded images\n", + "occlude_start_row = 14\n", + "num_generated_images = 10\n", + "samples = np.copy(x_test_quantised[0:num_generated_images, :, :, :])\n", + "samples = samples / (q_levels - 1)\n", + "samples[:, occlude_start_row:, :, :] = 0\n", + "\n", + "fig = plt.figure(figsize=(10, 10))\n", + "\n", + "for i in range(10):\n", + " ax = fig.add_subplot(1, 10, i + 1)\n", + " ax.matshow(samples[i, :, :, 0], cmap=matplotlib.cm.binary)\n", + " plt.xticks(np.array([]))\n", + " plt.yticks(np.array([]))\n", + "\n", + "for i in range(occlude_start_row, height):\n", + " for j in range(width):\n", + " logits = gated_pixelcnn(samples)\n", + " next_sample = tf.random.categorical(logits[:, i, j, :], 1)\n", + " samples[:, i, j, 0] = (next_sample.numpy() / (q_levels - 1))[:, 0]\n", + "\n", + "fig = plt.figure(figsize=(10, 10))\n", + "\n", + "for i in range(10):\n", + " ax = fig.add_subplot(1, 10, i + 1)\n", + " ax.matshow(samples[i, :, :, 0], cmap=matplotlib.cm.binary)\n", + " plt.xticks(np.array([]))\n", + " plt.yticks(np.array([]))\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "name": "gated_pixelcnn.ipynb", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.9" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +}