{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# David Leonardo Ramírez Parada","metadata":{}},{"cell_type":"markdown","source":"# Carga de imágenes","metadata":{}},{"cell_type":"code","source":"!unzip  /kaggle/input/dogs-vs-cats/train.zip | tqdm > /dev/null\n!unzip  /kaggle/input/dogs-vs-cats/test1.zip | tqdm > /dev/null\n!mkdir bw","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:11:39.852712Z","iopub.execute_input":"2022-12-10T00:11:39.853026Z","iopub.status.idle":"2022-12-10T00:11:59.288828Z","shell.execute_reply.started":"2022-12-10T00:11:39.852953Z","shell.execute_reply":"2022-12-10T00:11:59.287534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Carga de paqueterias","metadata":{}},{"cell_type":"code","source":"from keras.preprocessing.image import img_to_array\nimport matplotlib.pyplot as plt\nfrom keras import layers\nimport tensorflow as tf\nfrom tqdm import tqdm\nimport numpy as np\nimport keras \nimport cv2\nimport os\nimport re","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:12:13.573957Z","iopub.execute_input":"2022-12-10T00:12:13.575202Z","iopub.status.idle":"2022-12-10T00:12:13.580939Z","shell.execute_reply.started":"2022-12-10T00:12:13.575154Z","shell.execute_reply":"2022-12-10T00:12:13.579904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# TAMAÑO DE LAS IMAGENES\nSIZE = 256\n\n# VECTORES VACÍOS PARA LAS IMÁGENES A COLOR Y, A BLANCO Y NEGRO\ncolor_img = []\ngray_img = []\n\n# RUTAS DE LOS ARCHIVOS A COLOR Y, BLANCO Y NEGRO\npath = '/kaggle/working/train'\npathbw = '/kaggle/working/bw'\n\n# LISTA DE IMÁGENES Y ORDENAMIENTO ALEATORIO\nfiles = os.listdir(path)\nnp.random.shuffle(files)\n\nfor num, i in enumerate(tqdm(files)): \n    \n    # SI LA IMAGEN ES LA NÚMERO 2250 SE DETIENE\n    # ESTO ES PARA TOMAR SOLO LAS PIMERAS IMÁGENES\n    # DEBIDO A PROBLEMAS CON LA CANTIDAD DE MEMORIA RAM\n    if num == 2250: break\n        \n    ORG = cv2.imread(path + '/' + i, 1)        # LECTURA DE LA IMAGEN\n    img = cv2.cvtColor(ORG, cv2.COLOR_BGR2RGB) # CONVERSIÓN DE BGR A RGB\n    img = cv2.resize(img, (SIZE, SIZE))        # REDIMENSIONAMIENTO DE IMÁGENES A 256x256\n    img = img.astype('float32') / 255.0        # CONVERSIÓN A FLOAT32 Y NORMALIZACIÓN\n    color_img.append(img_to_array(img))        # AÑADIR IMÁGEN AL VECTOR DE IMÁGENES A COLOR\n    cv2.imwrite(pathbw + \"/\" + i, cv2.cvtColor(ORG, cv2.COLOR_BGR2GRAY)) # GUARDAR LA IMAGEN CONVERTIDA A BLANCO Y NEGRO\n    del ORG\n    \n    ORG = cv2.imread(pathbw + '/' + i, 1)\n    img = cv2.cvtColor(ORG, cv2.COLOR_BGR2RGB)\n    img = cv2.resize(img, (SIZE, SIZE))\n    img = img.astype('float32') / 255.0\n    gray_img.append(img_to_array(img))\n    del ORG","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:12:15.302486Z","iopub.execute_input":"2022-12-10T00:12:15.303014Z","iopub.status.idle":"2022-12-10T00:12:36.331524Z","shell.execute_reply.started":"2022-12-10T00:12:15.302967Z","shell.execute_reply":"2022-12-10T00:12:36.330459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# PARTICIONAMIENTO DE LOS DATOS PARA COMPROBACIÓN\ncolor_dataset = tf.data.Dataset.from_tensor_slices(np.array(color_img[:2000])).batch(64)\ngray_dataset = tf.data.Dataset.from_tensor_slices(np.array(gray_img[:2000])).batch(64)\ncolor_dataset_t=tf.data.Dataset.from_tensor_slices(np.array(color_img[2000:])).batch(8)\ngray_dataset_t=tf.data.Dataset.from_tensor_slices(np.array(gray_img[2000:])).batch(8)\n\n# OBTENCIÓN DE IMÁGENES PARA PLOTEARLAS\nexample_color = next(iter(color_dataset))\nexample_gray = next(iter(gray_dataset))","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:13:02.817129Z","iopub.execute_input":"2022-12-10T00:13:02.817813Z","iopub.status.idle":"2022-12-10T00:13:20.293630Z","shell.execute_reply.started":"2022-12-10T00:13:02.817777Z","shell.execute_reply":"2022-12-10T00:13:20.284549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_images(a = 4):\n    for i in range(a):\n        index = np.random.randint(0, len(example_color))\n        plt.figure(figsize = (10,10))\n        plt.subplot(121)\n        plt.title('color')\n        plt.imshow(example_color[index])\n\n        plt.subplot(122)\n        plt.title('gray')\n        plt.imshow(example_gray[index], cmap=\"gray\")\n        plt.show()\n\nplot_images(3)","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:13:20.301653Z","iopub.execute_input":"2022-12-10T00:13:20.302045Z","iopub.status.idle":"2022-12-10T00:13:21.754959Z","shell.execute_reply.started":"2022-12-10T00:13:20.302005Z","shell.execute_reply":"2022-12-10T00:13:21.754053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Definición del Discriminador y el Generador","metadata":{}},{"cell_type":"code","source":"def downsample(filters, size, apply_batchnorm = True):\n    result = tf.keras.Sequential()\n    result.add(\n        tf.keras.layers.Conv2D(filters, \n                               size,\n                               strides = 2, \n                               padding = 'same',\n                               kernel_initializer = 'he_normal', \n                               use_bias = True\n                            ))\n\n    if apply_batchnorm: result.add(tf.keras.layers.BatchNormalization())\n    result.add(tf.keras.layers.LeakyReLU())\n    return result\n\ndef upsample(filters, size, apply_dropout=False):\n    result = tf.keras.Sequential()\n    result.add(\n        tf.keras.layers.Conv2DTranspose(filters, \n                                        size, \n                                        strides = 2,\n                                        padding = 'same',\n                                        kernel_initializer = 'he_normal',\n                                        use_bias = True\n                                    ))\n\n    result.add(tf.keras.layers.BatchNormalization())\n    if apply_dropout: result.add(tf.keras.layers.Dropout(0.5))\n    result.add(tf.keras.layers.ReLU())\n\n    return result  ","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:13:40.468691Z","iopub.execute_input":"2022-12-10T00:13:40.469062Z","iopub.status.idle":"2022-12-10T00:13:40.479797Z","shell.execute_reply.started":"2022-12-10T00:13:40.469028Z","shell.execute_reply":"2022-12-10T00:13:40.478869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Generator():\n    inputs = tf.keras.layers.Input(shape=[256,256,3])\n\n    down_stack = [\n        downsample(64, 4, apply_batchnorm=False), # (bs, 128, 128, 64)\n        downsample(128, 4),                       # (bs, 64, 64, 128)\n        downsample(256, 4),                       # (bs, 32, 32, 256)\n        downsample(512, 4),                       # (bs, 16, 16, 512)\n        downsample(512, 4),                       # (bs, 8, 8, 512)\n        downsample(512, 4),                       # (bs, 4, 4, 512)\n        downsample(512, 4),                       # (bs, 2, 2, 512)\n        downsample(512, 4),                       # (bs, 1, 1, 512)\n    ]\n\n    up_stack = [\n        upsample(512, 4, apply_dropout=True), # (bs, 2, 2, 1024)\n        upsample(512, 4, apply_dropout=True), # (bs, 4, 4, 1024)\n        upsample(512, 4, apply_dropout=True), # (bs, 8, 8, 1024)\n        upsample(512, 4),                     # (bs, 16, 16, 1024)\n        upsample(256, 4),                     # (bs, 32, 32, 512)\n        upsample(128, 4),                     # (bs, 64, 64, 256)\n        upsample(64, 4),                      # (bs, 128, 128, 128)\n    ]\n\n    initializer = tf.random_normal_initializer(0., 0.02)\n    last = tf.keras.layers.Conv2DTranspose(3, \n                                           4,\n                                           strides = 2,\n                                           padding = 'same',\n                                           kernel_initializer = initializer,\n                                           activation = 'tanh'\n                                          )\n\n    x = inputs\n    skips = []\n    for down in down_stack:\n        x = down(x)\n        skips.append(x)\n\n    skips = reversed(skips[:-1])\n    for up, skip in zip(up_stack, skips):\n        x = up(x)\n        x = tf.keras.layers.Concatenate()([x, skip])\n\n    x = last(x)\n    return tf.keras.Model(inputs=inputs, outputs=x)","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:13:49.131206Z","iopub.execute_input":"2022-12-10T00:13:49.131993Z","iopub.status.idle":"2022-12-10T00:13:49.141950Z","shell.execute_reply.started":"2022-12-10T00:13:49.131957Z","shell.execute_reply":"2022-12-10T00:13:49.140813Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Discriminator():\n    initializer = tf.random_normal_initializer(0., 0.02)\n\n    inp = tf.keras.layers.Input(shape = [256, 256, 3], name = 'input_image')\n    tar = tf.keras.layers.Input(shape = [256, 256, 3], name = 'target_image')\n\n    x = tf.keras.layers.concatenate([inp, tar]) # (bs, 256, 256, channels*2)\n\n    down1 = downsample(64, 4, False)(x) # (bs, 128, 128, 64)\n    down2 = downsample(128, 4)(down1)   # (bs, 64, 64, 128)\n    down3 = downsample(256, 4)(down2)   # (bs, 32, 32, 256)\n\n    zero_pad1 = tf.keras.layers.ZeroPadding2D()(down3)       # (bs, 34, 34, 256)\n    conv = tf.keras.layers.Conv2D(512, \n                                  4, \n                                  strides = 1,\n                                  kernel_initializer = initializer,\n                                  use_bias = True\n                                 )(zero_pad1) # (bs, 31, 31, 512)\n\n    batchnorm1 = tf.keras.layers.BatchNormalization()(conv)\n\n    leaky_relu = tf.keras.layers.LeakyReLU()(batchnorm1)\n\n    zero_pad2 = tf.keras.layers.ZeroPadding2D()(leaky_relu) # (bs, 33, 33, 512)\n\n    last = tf.keras.layers.Conv2D(1, \n                                  4, \n                                  strides = 1,\n                                  kernel_initializer = initializer\n                                )(zero_pad2) \n\n    return tf.keras.Model(inputs=[inp, tar], outputs=last)","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:13:53.255969Z","iopub.execute_input":"2022-12-10T00:13:53.256956Z","iopub.status.idle":"2022-12-10T00:13:53.266633Z","shell.execute_reply.started":"2022-12-10T00:13:53.256919Z","shell.execute_reply":"2022-12-10T00:13:53.265573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Presentación de los modelos","metadata":{}},{"cell_type":"code","source":"generator = Generator()\ngenerator.summary()","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:13:56.988137Z","iopub.execute_input":"2022-12-10T00:13:56.989222Z","iopub.status.idle":"2022-12-10T00:13:58.013884Z","shell.execute_reply.started":"2022-12-10T00:13:56.989158Z","shell.execute_reply":"2022-12-10T00:13:58.012552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"discriminator = Discriminator()\ndiscriminator.summary()","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:14:00.835355Z","iopub.execute_input":"2022-12-10T00:14:00.835731Z","iopub.status.idle":"2022-12-10T00:14:00.958482Z","shell.execute_reply.started":"2022-12-10T00:14:00.835697Z","shell.execute_reply":"2022-12-10T00:14:00.957440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Configuraciones del modelo, compilación y fit","metadata":{}},{"cell_type":"code","source":"# FUNCIONES DE PÉRDIDA, OPTIMIZADOR DEL GENERADOR Y DEL DISCRIMINADOR\nloss_object = tf.keras.losses.BinaryCrossentropy(from_logits=True)\ngenerator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\ndiscriminator_optimizer = tf.keras.optimizers.Adam(2e-4, beta_1=0.5)\n\nLAMBDA = 100\n\ndef generator_loss(disc_generated_output, gen_output, target):\n    gan_loss = loss_object(tf.ones_like(disc_generated_output), disc_generated_output)\n\n    # PROMEDIO DEL ERROR ABSOLUTO\n    l1_loss = tf.reduce_mean(tf.abs(target - gen_output))\n    total_gen_loss = gan_loss + (LAMBDA * l1_loss)\n    return total_gen_loss, gan_loss, l1_loss\n\ndef discriminator_loss(disc_real_output, disc_generated_output):\n    real_loss = loss_object(tf.ones_like(disc_real_output), disc_real_output)\n    generated_loss = loss_object(tf.zeros_like(disc_generated_output), disc_generated_output)\n    total_disc_loss = real_loss + generated_loss\n\n    return total_disc_loss","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:14:03.487460Z","iopub.execute_input":"2022-12-10T00:14:03.487824Z","iopub.status.idle":"2022-12-10T00:14:03.496776Z","shell.execute_reply.started":"2022-12-10T00:14:03.487792Z","shell.execute_reply":"2022-12-10T00:14:03.495679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_step(input_image, target, epoch):\n    with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:\n        gen_output = generator(input_image, training=True)\n        disc_real_output = discriminator([input_image, target], training=True)\n        disc_generated_output = discriminator([input_image, gen_output], training=True)\n        gen_total_loss, gen_gan_loss, gen_l1_loss = generator_loss(disc_generated_output, gen_output, target)\n        disc_loss = discriminator_loss(disc_real_output, disc_generated_output)\n\n    generator_gradients = gen_tape.gradient(gen_total_loss, generator.trainable_variables)\n    discriminator_gradients = disc_tape.gradient(disc_loss, discriminator.trainable_variables)\n\n    generator_optimizer.apply_gradients(zip(generator_gradients, generator.trainable_variables))\n    discriminator_optimizer.apply_gradients(zip(discriminator_gradients, discriminator.trainable_variables))","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:14:09.445781Z","iopub.execute_input":"2022-12-10T00:14:09.446185Z","iopub.status.idle":"2022-12-10T00:14:09.456455Z","shell.execute_reply.started":"2022-12-10T00:14:09.446150Z","shell.execute_reply":"2022-12-10T00:14:09.455349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import time\ndef fit(train_ds, epochs,):\n    for epoch in range(epochs):\n        start = time.time()\n\n        print(\"Epoch: \", epoch+1)\n\n        # Train\n        for n, (input_image, target) in train_ds.enumerate():\n              train_step(input_image, target, epoch)\n        print()\n        print ('Time taken for epoch {} is {} sec\\n'.format(epoch + 1,\n                                                            time.time()-start))\n","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:14:12.754669Z","iopub.execute_input":"2022-12-10T00:14:12.755046Z","iopub.status.idle":"2022-12-10T00:14:12.761141Z","shell.execute_reply.started":"2022-12-10T00:14:12.755014Z","shell.execute_reply":"2022-12-10T00:14:12.760104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prueba del modelo sin entrenamiento","metadata":{}},{"cell_type":"code","source":"def generate_images(model, test_input, tar):\n    prediction = model(test_input, training=True)\n    plt.figure(figsize=(15,15))\n\n    display_list = [test_input[0], tar[0], prediction[0]]\n    title = ['Input Image', 'Ground Truth', 'Predicted Image']\n\n    for i in range(3):\n        plt.subplot(1, 3, i+1)\n        plt.title(title[i])\n        # getting the pixel values between [0, 1] to plot it.\n        plt.imshow(display_list[i])\n        plt.axis('off')\n    plt.show()\n\nfor example_input, example_target in tf.data.Dataset.zip((gray_dataset,color_dataset)).take(2):\n    generate_images(generator, example_input, example_target)\n","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:14:29.688788Z","iopub.execute_input":"2022-12-10T00:14:29.689201Z","iopub.status.idle":"2022-12-10T00:14:41.949721Z","shell.execute_reply.started":"2022-12-10T00:14:29.689165Z","shell.execute_reply":"2022-12-10T00:14:41.948668Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fit(tf.data.Dataset.zip((gray_dataset, color_dataset)), epochs = 35)","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:17:05.544646Z","iopub.execute_input":"2022-12-10T00:17:05.545063Z","iopub.status.idle":"2022-12-10T00:42:49.086244Z","shell.execute_reply.started":"2022-12-10T00:17:05.545025Z","shell.execute_reply":"2022-12-10T00:42:49.085031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def generate_images(model, test_input, tar):\n    plt.figure(figsize=(15,15))\n    prediction = model(test_input, training=True)\n    display_list = [test_input[0], tar[0], prediction[0]]\n    title = ['Input Image', 'Ground Truth', 'Predicted Image']\n\n    for i in range(3):\n        plt.subplot(1, 3, i+1)\n        plt.title(title[i])\n        # getting the pixel values between [0, 1] to plot it.\n        plt.imshow(display_list[i])\n        plt.axis('off')\n    plt.show()\n  \nfor example_input, example_target in tf.data.Dataset.zip((gray_dataset_t,color_dataset_t)).take(11):\n    generate_images(generator, example_input, example_target)\n","metadata":{"execution":{"iopub.status.busy":"2022-12-10T00:48:05.470597Z","iopub.execute_input":"2022-12-10T00:48:05.470958Z","iopub.status.idle":"2022-12-10T00:48:10.597038Z","shell.execute_reply.started":"2022-12-10T00:48:05.470925Z","shell.execute_reply":"2022-12-10T00:48:10.596212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Conclusión\n\nComo vimos, se entrenó un modelo Pix2Pix GAN de tal forma que pudiera transformar una fotografía de blanco y negro y, la coloreara de tal forma que tuviera sentido.\n\nTal como se puede ver en la última imagen, las coloraciones tienen defectos sin embargo, los colores son parecidos en cuanto a tono, pero le hace falta un poco más para que funcione mucho mejor.\n\nCabe mencionar que por ejemplo, en la 8va imagen se ve que la foto original posee los ojos en una tonalidad rojiza debido a la exposición de la cámara, sin embargo, en la colorización esta tonalidad cambia a amarillo; un poco más de acuerdo al color de su pelaje.\n\n\nEste trabajo fue un poco menos complicado que la versión de Seq2Seq anterior, pero mucho más complejas que el resto de las tareas.\n\nNo entendí muy bien, con qué red neuronal debía compararlo por tanto:\n\nEn este caso se usó tanto para el discriminador como para el generador un modelo secuencial convolucional, usando funciones de activación Leaky-ReLU y Tanh.\n\nLos resultados tal como se vieron no están mal, pero podrían mejorar jugando con los valores de $\\beta$ de los optimizadores y cambiando los learning-rates de los mismos.","metadata":{}}]}