{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# Input data files are available in the \"../input/\" directory.\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nfrom glob import glob\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport xml.etree.ElementTree as ET # for parsing XML\nimport gc\nimport math\nimport shutil\nimport random\nimport os","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"%load_ext tensorboard.notebook\n%tensorboard --logdir logs\nos.mkdir(\"/kaggle/working/logs\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"NUM_EPOCHS = 130\nBATCH_SIZE = 32\nDIM_X = 64\nDIM_Y = 64\nDIM_Z = 3\nD_LEARNING_RATE = 0.0015\nG_LEARNING_RATE = 0.0015\nBETA1 = 0.5\nZ_NOISE_DIM = 128\nF_DIM = 128\nFULL_OUTPUT_PATH = \"../output_dir/\"\nos.mkdir(FULL_OUTPUT_PATH)\n\ndef image_from_array(image_arr):\n    return np.reshape(image_arr, (DIM_X, DIM_Y, DIM_Z))\n\ndef transform_image(image):\n    # back from -1,1 to 0,1\n    image = image / 2 + 0.5\n    # from 0,1 to 0,255\n    image = image * 255\n    return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def random_crop_inside_bbox(image,bbox):\n    img = tf.image.crop_to_bounding_box(image, bbox[1], bbox[0], bbox[3]-bbox[1], bbox[2]-bbox[0])\n    img = tf.image.central_crop(img,0.5)\n    imgs = tf.image.resize_bilinear(tf.expand_dims(img, 0),[64,64])\n    return tf.squeeze(imgs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def read_image(filename, bbox):\n    \"\"\"\n    This function does blah blah.\n    \"\"\"\n    image_string = tf.read_file(filename)\n    image = tf.image.decode_jpeg(image_string, channels=3)\n    image = tf.image.convert_image_dtype(image, tf.float32)\n    \n    \n    # image = tf.image.random_flip_up_down(image)\n    # image = random_rotation(image)\n    \n    #image = tf.image.crop_to_bounding_box(image, bbox[1], bbox[0], bbox[3]-bbox[1], bbox[2]-bbox[0])\n    #image = tf.image.resize_image_with_pad(image,DIM_X,DIM_Y)\n    height = tf.shape(image)[1]\n    width = tf.shape(image)[0]\n    image = tf.image.crop_and_resize(tf.expand_dims(image, 0), [[bbox[1]/width, bbox[0]/height, bbox[3]/width, bbox[2]/height]],box_ind = [0], crop_size = [64,64])\n    image = tf.squeeze(image)\n    image = tf.image.random_flip_left_right(image)\n    image = tf.subtract(image, 0.5)\n    image = tf.multiply(image, 2.0)\n    return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def prepare_data():\n    filenames = []\n    labels = []\n    bboxes = []\n    breeds = os.listdir('../input/annotation/Annotation/')\n    for breed in breeds:\n        dogs = os.listdir('../input/annotation/Annotation/' + breed + \"/\")\n        for dog in dogs:\n            if os.path.exists('../input/all-dogs/all-dogs/' + dog + '.jpg'):\n                tree = ET.parse('../input/annotation/Annotation/' + breed + '/' + dog)\n                root = tree.getroot()\n                objects = root.findall('object')\n                for o in objects:\n                    bndbox = o.find('bndbox') # reading bound box\n                    xmin = int(bndbox.find('xmin').text)\n                    ymin = int(bndbox.find('ymin').text)\n                    xmax = int(bndbox.find('xmax').text)\n                    ymax = int(bndbox.find('ymax').text)\n                    label = o.find('name').text\n                filenames.append('../input/all-dogs/all-dogs/' + dog + '.jpg')\n                bboxes.append([xmin, ymin, xmax, ymax])\n    return filenames, bboxes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_dataset(filenames, b_boxes):\n    \"\"\"\n    This function creates a tf.data.Dataset from a folder containing images\n    \"\"\"   \n    dataset = (tf.data.Dataset.from_tensor_slices((filenames, b_boxes))\n                .apply(tf.data.experimental.shuffle_and_repeat(buffer_size=len(filenames), count=NUM_EPOCHS))\n                .map(lambda filename, b_box: read_image(\n                    filename,b_box), num_parallel_calls=8)\n                .batch(BATCH_SIZE)\n                .prefetch(1))\n\n    return dataset, len(filenames)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class batch_norm(object):\n    def __init__(self, epsilon=1e-5, momentum=0.9, name=\"batch_norm\"):\n        with tf.variable_scope(name):\n            self.epsilon = epsilon\n            self.momentum = momentum\n            self.name = name\n\n    def __call__(self, x, train=True):\n        return tf.contrib.layers.batch_norm(x, decay=self.momentum, updates_collections=None, epsilon=self.epsilon, scale=True, is_training=train, scope=self.name)\n\nd_bn1 = batch_norm(name='d_bn1')\nd_bn2 = batch_norm(name='d_bn2')\nd_bn3 = batch_norm(name='d_bn3')\n\ng_bn0 = batch_norm(name='g_bn0')\ng_bn1 = batch_norm(name='g_bn1')\ng_bn2 = batch_norm(name='g_bn2')\ng_bn3 = batch_norm(name='g_bn3')\n\ndef conv2d(input_, output_dim,\n           k_h=5, k_w=5, d_h=2, d_w=2, stddev=0.02,\n           name=\"conv2d\"):\n    with tf.variable_scope(name):\n        w = tf.get_variable('w', [k_h, k_w, input_.get_shape()[-1], output_dim],\n                            initializer=tf.truncated_normal_initializer(stddev=stddev))\n        conv = tf.nn.conv2d(input_, w, strides=[\n            1, d_h, d_w, 1], padding='SAME')\n        biases = tf.get_variable(\n            'biases', [output_dim], initializer=tf.constant_initializer(0.0))\n        conv = tf.reshape(tf.nn.bias_add(conv, biases), conv.get_shape())\n\n        return conv\n\n\ndef deconv2d(input_, output_shape,\n             k_h=5, k_w=5, d_h=2, d_w=2, stddev=0.02,\n             name=\"deconv2d\", with_w=False):\n    with tf.variable_scope(name):\n        w = tf.get_variable('w', [k_h, k_w, output_shape[-1], input_.get_shape()[-1]],\n                            initializer=tf.random_normal_initializer(stddev=stddev))\n\n        deconv = tf.nn.conv2d_transpose(input_, w, output_shape=output_shape,\n                                        strides=[1, d_h, d_w, 1])\n        biases = tf.get_variable(\n            'biases', [output_shape[-1]], initializer=tf.constant_initializer(0.0))\n        deconv = tf.reshape(tf.nn.bias_add(deconv, biases), deconv.get_shape())\n        if with_w:\n            return deconv, w, biases\n        else:\n            return deconv\n\n\ndef lrelu(x, leak=0.2, name=\"lrelu\"):\n    return tf.maximum(x, leak*x)\n\n\ndef linear(input_, output_size, scope=None, stddev=0.02, bias_start=0.0, with_w=False):\n    shape = input_.get_shape().as_list()\n\n    with tf.variable_scope(scope or \"Linear\"):\n        try:\n            matrix = tf.get_variable(\"Matrix\", [shape[1], output_size], tf.float32,\n                                     tf.random_normal_initializer(stddev=stddev))\n        except ValueError as err:\n            msg = \"NOTE: Usually, this is due to an issue with the image dimensions.  Did you correctly set '--crop' or '--input_height' or '--output_height'?\"\n            err.args = err.args + (msg,)\n            raise\n        bias = tf.get_variable(\"bias\", [output_size],\n                               initializer=tf.constant_initializer(bias_start))\n        if with_w:\n            return tf.matmul(input_, matrix) + bias, matrix, bias\n        else:\n            return tf.matmul(input_, matrix) + bias\n\n\ndef conv_out_size_same(size, stride):\n    return int(math.ceil(float(size) / float(stride)))\n\n\ndef discriminator(x, reuse=False,  decaying_noise=None):\n    df_dim = F_DIM\n    with tf.variable_scope(\"discriminator\") as scope:\n        if reuse:\n            scope.reuse_variables()\n        x0 = x + decaying_noise\n        conv_1 = conv2d(x0, df_dim, name='d_h0_conv')\n        \n        h0 = lrelu(conv_1)\n        h1 = lrelu(d_bn1(conv2d(h0, df_dim*2, name='d_h1_conv')))\n        h2 = lrelu(d_bn2(conv2d(h1, df_dim*4, name='d_h2_conv')))\n        h3 = lrelu(d_bn3(conv2d(h2, df_dim*8, name='d_h3_conv')))\n        h4 = linear(tf.reshape(h3, [BATCH_SIZE, -1]), 1, 'd_h4_lin')\n\n        return tf.nn.sigmoid(h4), h4\n\n\ndef generator(z):\n    gf_dim = F_DIM\n    with tf.variable_scope(\"generator\") as scope:\n        \n        s_h, s_w = DIM_X, DIM_Y\n        s_h2, s_w2 = conv_out_size_same(s_h, 2), conv_out_size_same(s_w, 2)\n        s_h4, s_w4 = conv_out_size_same(s_h2, 2), conv_out_size_same(s_w2, 2)\n        s_h8, s_w8 = conv_out_size_same(s_h4, 2), conv_out_size_same(s_w4, 2)\n        s_h16, s_w16 = conv_out_size_same(s_h8, 2), conv_out_size_same(s_w8, 2)\n\n        z_, h0_w, h0_b = linear(z, gf_dim*8*s_h16*s_w16,\n                                'g_h0_lin', with_w=True)\n        h0 = tf.reshape(z_, [-1, s_h16, s_w16, gf_dim * 8])\n        h0 = tf.nn.relu(g_bn0(h0))\n        h1, h1_w, h1_b = deconv2d(\n            h0, [BATCH_SIZE, s_h8, s_w8, gf_dim*4], name='g_h1', with_w=True)\n        h1 = tf.nn.relu(g_bn1(h1))\n        h2, h2_w, h2_b = deconv2d(\n            h1, [BATCH_SIZE, s_h4, s_w4, gf_dim*2], name='g_h2', with_w=True)\n        h2 = tf.nn.relu(g_bn2(h2))\n        h3, h3_w, h3_b = deconv2d(\n            h2, [BATCH_SIZE, s_h2, s_w2, gf_dim*1], name='g_h3', with_w=True)\n        h3 = tf.nn.relu(g_bn3(h3))\n        h4, h4_w, h4_b = deconv2d(\n            h3, [BATCH_SIZE, s_h, s_w, DIM_Z], name='g_h4', with_w=True)\n\n        return tf.nn.tanh(h4)\n\n\ndef sampler(z, batch_size=BATCH_SIZE):\n    gf_dim = F_DIM\n    with tf.variable_scope(\"generator\") as scope:\n        scope.reuse_variables()\n\n        s_h, s_w = DIM_X, DIM_Y\n        s_h2, s_w2 = conv_out_size_same(s_h, 2), conv_out_size_same(s_w, 2)\n        s_h4, s_w4 = conv_out_size_same(s_h2, 2), conv_out_size_same(s_w2, 2)\n        s_h8, s_w8 = conv_out_size_same(s_h4, 2), conv_out_size_same(s_w4, 2)\n        s_h16, s_w16 = conv_out_size_same(s_h8, 2), conv_out_size_same(s_w8, 2)\n\n        h0 = tf.reshape(\n            linear(z, gf_dim*8*s_h16*s_w16, 'g_h0_lin'),\n            [-1, s_h16, s_w16, gf_dim * 8])\n        h0 = tf.nn.relu(g_bn0(h0, train=False))\n\n        h1 = deconv2d(h0, [batch_size, s_h8, s_w8, gf_dim*4], name='g_h1')\n        h1 = tf.nn.relu(g_bn1(h1, train=False))\n\n        h2 = deconv2d(h1, [batch_size, s_h4, s_w4, gf_dim*2], name='g_h2')\n        h2 = tf.nn.relu(g_bn2(h2, train=False))\n\n        h3 = deconv2d(h2, [batch_size, s_h2, s_w2, gf_dim*1], name='g_h3')\n        h3 = tf.nn.relu(g_bn3(h3, train=False))\n\n        h4 = deconv2d(h3, [batch_size, s_h, s_w, DIM_Z], name='g_h4')\n\n    return tf.nn.tanh(h4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def model_inputs(image_width, image_height, image_channels, z_dim, batch_size = BATCH_SIZE):\n    \"\"\"\n    Create the model inputs\n    :param image_width: The input image width\n    :param image_height: The input image height\n    :param image_channels: The number of image channels\n    :param z_dim: The dimension of Z\n    :return: Tuple of (tensor of real input images, tensor of z data, learning rate)\n    \"\"\"\n    real_input_images = tf.placeholder(tf.float32, [BATCH_SIZE] + [image_width, image_height, image_channels], name='real_images')\n    input_z = tf.placeholder(tf.float32, [None, z_dim], name='input_z')\n\n    return real_input_images, input_z\n\ndef model_loss(input_real, input_z, smooth_factor=0.1, decaying_noise=None):\n    \"\"\"\n    Get the loss for the discriminator and generator\n    :param input_real: Images from the real dataset\n    :param input_z: Z input\n    :param out_channel_dim: The number of channels in the output image\n    :return: A tuple of (discriminator loss, generator loss)\n    \"\"\"\n    fake_samples = generator(input_z)\n    tf.summary.image(\"G\", fake_samples, max_outputs=5, collections=[\"g_imgs\"])\n    tf.summary.image(\"D\", input_real, max_outputs=5, collections=[\"d_imgs\"])\n    d_model_real, d_logits_real = discriminator(input_real, reuse=False, decaying_noise=decaying_noise)\n    d_model_fake, d_logits_fake = discriminator(fake_samples, reuse=True, decaying_noise=decaying_noise)\n        \n    d_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_real, labels=tf.ones_like(d_model_real) * (1 - smooth_factor)))\n    d_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake, labels=tf.zeros_like(d_model_fake)))    \n    d_loss = d_loss_real + d_loss_fake\n    \n\n    g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake, labels=tf.ones_like(d_model_fake)))\n    \n    \n    return d_loss, g_loss\n\ndef model_opt(d_loss, g_loss, d_learning_rate, g_learning_rate, beta1):\n    \"\"\"\n    Get optimization operations\n    :param d_loss: Discriminator loss Tensor\n    :param g_loss: Generator loss Tensor\n    :param learning_rate: Learning Rate Placeholder\n    :param beta1: The exponential decay rate for the 1st moment in the optimizer\n    :return: A tuple of (discriminator training operation, generator training operation)\n    \"\"\"\n    t_vars = tf.trainable_variables()\n    d_vars = [var for var in t_vars if var.name.startswith('discriminator')]\n    g_vars = [var for var in t_vars if var.name.startswith('generator')]\n\n    # Optimize\n    with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)):\n        d_train_opt = tf.train.AdamOptimizer(d_learning_rate, beta1=beta1).minimize(d_loss, var_list=d_vars)\n        g_train_opt = tf.train.AdamOptimizer(g_learning_rate, beta1=beta1).minimize(g_loss, var_list=g_vars)\n\n    tf.summary.scalar(\"g_loss\", g_loss, collections=[\"g_summ\"])\n    tf.summary.scalar(\"d_loss\", d_loss, collections=[\"d_summ\"])\n    return d_train_opt, g_train_opt","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"filenames, b_boxes = prepare_data()\ndataset, dataset_len = create_dataset(filenames, b_boxes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"iterator = dataset.make_initializable_iterator()\nglobal_step = tf.Variable(0, trainable=False, name='global_step')\nincrement_global_step = tf.assign_add(global_step, 1, name='increment_global_step')\n\n# Model\ninput_real, input_z = model_inputs(DIM_X, DIM_Y, DIM_Z, Z_NOISE_DIM)\ntotal_steps = (dataset_len / BATCH_SIZE) * NUM_EPOCHS\nstarter_stdev = 0.1\n\n##decayed_learning_rate = learning_rate * decay_rate ^ (global_step / decay_steps)\ndecaying_stdev = tf.train.exponential_decay(starter_stdev, global_step, total_steps * 10, 0.0001)\n\ndecaying_noise = tf.random_normal(shape=tf.shape(input_real), mean=0.0, stddev=decaying_stdev, dtype=tf.float32)\ntf.summary.scalar(\"stdev\", tf.keras.backend.std(decaying_noise), collections=[\"d_summ\"])\nd_loss, g_loss = model_loss(input_real, input_z, decaying_noise=decaying_noise)\nd_train_opt, g_train_opt = model_opt(d_loss, g_loss, D_LEARNING_RATE, G_LEARNING_RATE, BETA1)\n\nz_batch_tensor = tf.random.uniform((BATCH_SIZE, Z_NOISE_DIM), dtype=tf.float32, minval=-1, maxval=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sess = tf.Session()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"steps = 0\nsess.run(tf.global_variables_initializer())\nsess.run(iterator.initializer)\nnext_batch = iterator.get_next()\n\nwriter = tf.summary.FileWriter(\"/kaggle/working/logs/\", sess.graph)\ng_imgs = tf.summary.merge_all(key=\"g_imgs\")\nd_imgs = tf.summary.merge_all(key=\"d_imgs\")\ng_summ = tf.summary.merge_all(key=\"g_summ\")\nd_summ = tf.summary.merge_all(key=\"d_summ\")\n\nwhile True:\n    try:\n        steps = sess.run(increment_global_step)\n        try:\n            batch_imgs = sess.run(next_batch)\n        except Exception as e:\n            print(e)\n            continue\n        else:\n            if len(batch_imgs) != BATCH_SIZE:\n                break\n        batch_z = sess.run(z_batch_tensor)\n\n        _, d_loss_sum_str = sess.run([d_train_opt, d_summ], feed_dict={\n                                     input_real: batch_imgs, input_z: batch_z})\n        writer.add_summary(d_loss_sum_str, steps)\n\n        _, g_sum_str = sess.run([g_train_opt, g_summ], feed_dict={\n            input_real: batch_imgs, input_z: batch_z})\n        writer.add_summary(g_sum_str, steps)\n\n        _, g_sum_str = sess.run([g_train_opt, g_summ], feed_dict={\n            input_real: batch_imgs, input_z: batch_z})\n\n        writer.add_summary(g_sum_str, steps)\n\n        if steps % 20 == 0:\n            g_imgs_summ, d_imgs_summ = sess.run([g_imgs,d_imgs], feed_dict={\n                               input_z: batch_z, input_real : batch_imgs})\n            writer.add_summary(g_imgs_summ, steps)\n            writer.add_summary(d_imgs_summ, steps)\n            \n        if steps % 100 == 0:\n            train_loss_d, train_loss_g = sess.run([d_loss, g_loss], feed_dict={\n                                                  input_real: batch_imgs, input_z: batch_z})\n\n            print(\"Step {} de {}\".format(steps % int(dataset_len/BATCH_SIZE)+1, int(dataset_len/BATCH_SIZE)+1),\n                  \"-- Epoch [{} de {}]\".format(int(steps *\n                                                   BATCH_SIZE/dataset_len), NUM_EPOCHS),\n                  \"-- Global step {}\".format(steps),\n                  \"-- Discriminator Loss: {:.4f}\".format(train_loss_d),\n                  \"-- Generator Loss: {:.4f}\".format(train_loss_g))\n        gc.collect()\n\n    except tf.errors.OutOfRangeError:\n        print(\"End\")\n        break\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def save_images(imgs_batch, curr_batch=1):\n    for i, image in enumerate(imgs_batch):\n        filepath = FULL_OUTPUT_PATH + \"_\" + str(curr_batch) + \"_\" + str(i) + \"_\" + \".png\"\n        output_image = Image.fromarray(transform_image(\n            image_from_array(image)).astype(np.uint8))\n        output_image.save(filepath)\n\ndef generate_samples(sess, z_batch_tensor, input_z, num_samples):\n    \"\"\"\n    This function does blah blah.\n    \"\"\"    \n    num_batches = (num_samples // BATCH_SIZE) + 1\n    for batch_count in range(num_batches):\n        example_z = sess.run(z_batch_tensor)\n        samples = sess.run(sampler(input_z),\n                       feed_dict={input_z: example_z})\n        imgs = [img[:, :, :] for img in samples]\n        save_images(imgs, batch_count)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"generate_samples(sess,z_batch_tensor, input_z, 10000)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path, dirs, files = next(os.walk(FULL_OUTPUT_PATH))\nexceed = len(files) - 10000\ni = 0\nfor file in os.listdir(FULL_OUTPUT_PATH):\n    if i < exceed:\n        os.remove(FULL_OUTPUT_PATH + file)\n        i += 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path, dirs, files = next(os.walk(FULL_OUTPUT_PATH))\nexceed = len(files) - 10000\nprint(exceed)\nshutil.make_archive('images', 'zip', FULL_OUTPUT_PATH)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}