Está en la página 1de 17

11/22/23, 7:31 AM TallerFinalIA.

ipynb - Colaboratory

INTEGRANTES

Camilo Ule Trujillo

CC 1004492644

Nicolas Lopez Duque

C.C.1110286638

Link al notebook de Colab:


https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7#scrollTo=kzP0_mlq3khY

Introducción y Definición del Problema:


1. Presente un breve repaso de los fundamentos de una CNN.
2. Identificación y justificación un problema del entorno que pueda abordarse mediante el uso de CNN.

RTA: 1. Las redes neuronales convolucionales (CNN) son un tipo de red neuronal artificial que se utiliza para el procesamiento de imágenes y
datos similares a imágenes. Son muy eficientes para el aprendizaje de características locales, lo que las hace ideales para tareas como el
reconocimiento de objetos, la clasificación de imágenes y la segmentación de imágenes.

Los fundamentos de una CNN se pueden dividir en tres partes principales:

La capa de convolución: es la capa más básica de una CNN. Se utiliza para aprender características locales de una imagen. La capa de
convolución consta de un conjunto de filtros, cada uno de los cuales es una matriz pequeña de números. Los filtros se pasan por la imagen, y la
salida de cada filtro es una representación de la imagen que resalta las características que el filtro está diseñado para detectar.

La capa de agrupación: se utiliza para reducir la dimensionalidad de la salida de la capa de convolución. Esto se hace combinando las salidas
de varios filtros en una sola salida. La capa de agrupación puede utilizar diferentes funciones de agrupación, como la suma, la media o la
mediana.

La capa de fully connected: es una capa de red neuronal tradicional. Se utiliza para tomar la salida de la capa de agrupación y generar una
salida final. La capa de fully connected consta de un conjunto de neuronas, cada una de las cuales está conectada a todas las neuronas de la
capa anterior.

Las CNN se han utilizado con éxito en una amplia gama de aplicaciones, incluyendo:

Reconocimiento de objetos: Las CNN se utilizan para identificar objetos en imágenes. Por ejemplo, se pueden utilizar para identificar caras,
personas, coches o animales.

Clasificación de imágenes: Las CNN se utilizan para clasificar imágenes en categorías. Por ejemplo, se pueden utilizar para clasificar imágenes
de perros y gatos, o imágenes de flores y árboles.

Segmentación de imágenes: Las CNN se utilizan para segmentar imágenes en regiones. Por ejemplo, se pueden utilizar para segmentar
imágenes de personas en sus partes individuales, o imágenes de objetos en sus componentes individuales.

2.
Identifiacion de un problema:
Para este CNN se me ocurrio una red neuronal que fuese capaz de predecir tipo de color de pelaje de los gatos, tal vez se podria explorar mas a
profundidad este CNN y construirlo para ayudar a indentificar mascotas perdidas de las personas, con el reconocimiento de imagenes que la
red sea capaz de predecir si una imagen de un gato se parece a la de su dueno, por ahora me gustaria explorar el hecho de que nuestro CNN
sea capaz de indentificar el tipo de color de pelaje en estos felinos.

Definición y preprocesamiento de datos:


1 Cree su propio Dataset (Original)
https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 1/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory
1. Cree su propio Dataset (Original).
2. Descripción y justificación de las técnicas de preprocesamiento aplicadas al Dataset

1 import matplotlib.pyplot as plt


2 import numpy as np
3 import os
4 import PIL
5 import tensorflow as tf
6 import glob
7
8 from tensorflow import keras
9 from tensorflow.keras import layers
10 from tensorflow.keras.models import Sequential
11 from sklearn.metrics import confusion_matrix, classification_report
12 import matplotlib.pyplot as plt
13 import seaborn as sns
14 from sklearn.metrics import ConfusionMatrixDisplay
15 from sklearn.metrics import roc_curve, auc
16
17 from google.colab import files
18 #uploaded = files.upload()

1 import zipfile
2 import io
3 data = zipfile.ZipFile(io.BytesIO(uploaded['Entrenamiento.zip']), 'r')
4 data.extractall()
5
6 import pathlib
7 data_dir = tf.keras.utils.get_file('/content/Entrenamiento/Base','/content/Entrenamiento/Base',)
8 data_dir = pathlib.Path(data_dir)
9 print(data_dir)

/content/Entrenamiento/Base

1 image_count = len(list(data_dir.glob('*/*')))
2 print(image_count)
3
4 ermita = list(data_dir.glob('GatoGris/*'))
5 PIL.Image.open(str(ermita[0]))

532

Justificacion
Hemos cargado un dataset con una libreria de 4 clases, cada clase contien al menos unas 120 imagenes de gatos con determinado color, para
este ejemplo he tomado muestras de gatos de Color Gris, Naranja, Negro y gatos Pelones.

1 ermita = list(data_dir.glob('GatoGris/*'))
2 PIL.Image.open(str(ermita[0]))
3
4 batch_size = 32
5 img_height = 180
6 img_width = 180
7
8 train_ds = tf.keras.preprocessing.image_dataset_from_directory(
9 data_dir,
10 validation_split=0.2,
11 subset="training",
12 seed=123,
13 image_size=(img_height, img_width),
14 batch_size=batch_size)

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 2/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

15 class_names = train_ds.class_names
16 print(class_names)

1 ermita = list(data_dir.glob('GatoGris/*'))
2 PIL.Image.open(str(ermita[-1]))

1 val_ds = tf.keras.preprocessing.image_dataset_from_directory(
2 data_dir,
3 validation_split=0.2,
4 subset="validation",
5 seed=123,
6 image_size=(img_height, img_width),
7 batch_size=batch_size)

1 plt.figure(figsize=(10, 10))
2 for images, labels in train_ds.take(1):
3 for i in range(9):
4 ax = plt.subplot(3, 3, i + 1)
5 plt.imshow(images[i].numpy().astype("uint8"))
6 plt.title(class_names[labels[i]])
7 plt.axis("off")

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 3/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

1 AUTOTUNE = tf.data.AUTOTUNE
2 train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
3 val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

Justificacion
Trabajamos con TensorFlow y aplicamos una tecnica de optimizacion para el procesamiento de nuestro CNN.

Arquitectura e Implementación de la CNN.


Describa y justifique la arquitectura diseñada para solucionar el problema, teniendo en cuenta la biblioteca utilizada, en nuestro caso, Keras,
pero también puede explorar PyTorch, por ejemplo

Justificacion
La arquitectura utilizada para resolver el problema de reconocimiento de imágenes de gatos utilizando Keras se basa en redes neuronales
convolucionales (CNN), una opción común y eficiente para tareas de visión por computadora como la clasificación de imágenes.

La elección de Keras como biblioteca diria que es la mas acertada, ya que proporciona una interfaz sencilla y poderosa para construir y
entrenar modelos de redes neuronales. Keras nos facilita la implementación de arquitecturas complejas de manera intuitiva.

La arquitectura propuesta es razonable para el problema de reconocimiento de imágenes de gatos. Sin embargo, debemos tener en cuenta que
la efectividad del modelo también depende de la cantidad y calidad del conjunto de datos, así como de otros factores como la elección de
hiperparámetros y el ajuste fino del modelo. De hecho, este fue un problema que nos sucedio durante el desarrollo del problema.

El DataSet originalmente contien aproximadamente 450 imagenes y ademas, el conjunto en total pesaba aproximadamente 10 MB.

A traves de un software para la reduccon del tamano de las imagenes, logre que el dataset pera esas MB's, al inicion el datasdet pesaba unas
200 MB, lo cual fue un problema, primero para subir los archivos a Google Colab, y segundo para entrenar el modelo, ya que cada epoca se
demoraba unos 50 segundos en ser entrenada.

1 num_classes = 4
2
3 model = Sequential([
4 layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
5 layers.Conv2D(16, 3, padding='same', activation='relu'),
6 layers.MaxPooling2D(),
7 layers.Conv2D(32, 3, padding='same', activation='relu'),
8 layers.MaxPooling2D(),
9 layers.Conv2D(64, 3, padding='same', activation='relu'),
10 layers.MaxPooling2D(),
11 layers.Flatten(),
12 layers.Dense(128, activation='relu'),
13 layers.Dense(num_classes)
14 ])
15 model.summary()

Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
rescaling (Rescaling) (None, 180, 180, 3) 0

conv2d (Conv2D) (None, 180, 180, 16) 448

max_pooling2d (MaxPooling2 (None, 90, 90, 16) 0


D)

conv2d_1 (Conv2D) (None, 90, 90, 32) 4640

max_pooling2d_1 (MaxPoolin (None, 45, 45, 32) 0


g2D)

conv2d_2 (Conv2D) (None, 45, 45, 64) 18496

max_pooling2d_2 (MaxPoolin (None, 22, 22, 64) 0


g2D)

flatten (Flatten) (None, 30976) 0

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 4/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

dense (Dense) (None, 128) 3965056

dense_1 (Dense) (None, 4) 516

=================================================================
Total params: 3989156 (15.22 MB)
Trainable params: 3989156 (15.22 MB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________

Justificacion
Definimos un modelo de red neuronal convolucional secuencial para la clasificación de imágenes binarias.

El modelo nos muestra que el modelo tiene un total de 3,989,156 parámetros, todos los cuales son entrenables. Esto significa que todos los
parámetros del modelo se actualizarán durante el proceso de entrenamiento.

1 model.compile(optimizer='adam',loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics = ["accuracy"])


2
3 model.summary()

Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
rescaling (Rescaling) (None, 180, 180, 3) 0

conv2d (Conv2D) (None, 180, 180, 16) 448

max_pooling2d (MaxPooling2 (None, 90, 90, 16) 0


D)

conv2d_1 (Conv2D) (None, 90, 90, 32) 4640

max_pooling2d_1 (MaxPoolin (None, 45, 45, 32) 0


g2D)

conv2d_2 (Conv2D) (None, 45, 45, 64) 18496

max_pooling2d_2 (MaxPoolin (None, 22, 22, 64) 0


g2D)

flatten (Flatten) (None, 30976) 0

dense (Dense) (None, 128) 3965056

dense_1 (Dense) (None, 4) 516

=================================================================
Total params: 3989156 (15.22 MB)
Trainable params: 3989156 (15.22 MB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________

Justificacion
Hemos configurado el modelo para el entrenamiento y la evaluación. Especificamente el optimizador(optimizer='adam), la función de
pérdida(loss='binary_crossentropy') y las métricas que se utilizarán durante el proceso de entrenamiento(metrics=['accuracy']).

La salida del metodo Summary nos da un modelo compilado que tiene un total de 3,989,156 parámetros, todos los cuales son entrenables.
Esto significa que todos los parámetros del modelo se actualizarán durante el proceso de entrenamiento para optimizar su rendimiento en la
tarea de clasificación.

1 epochs=20
2 history = model.fit(
3 train_ds,
4 validation_data=val_ds,
5 epochs=epochs
6 )

Epoch 1/20
14/14 [==============================] - 17s 1s/step - loss: 1.5333 - accuracy: 0.4859 - val_loss: 0.5873 - val_accuracy: 0.9434
Epoch 2/20
14/14 [==============================] - 15s 1s/step - loss: 0.1654 - accuracy: 0.9836 - val_loss: 0.0044 - val_accuracy: 1.0000

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 5/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory
Epoch 3/20
14/14 [==============================] - 16s 1s/step - loss: 0.0272 - accuracy: 0.9859 - val_loss: 0.0030 - val_accuracy: 1.0000
Epoch 4/20
14/14 [==============================] - 16s 1s/step - loss: 9.9302e-04 - accuracy: 1.0000 - val_loss: 0.0036 - val_accuracy: 1.0000
Epoch 5/20
14/14 [==============================] - 15s 1s/step - loss: 7.2501e-04 - accuracy: 1.0000 - val_loss: 1.4113e-04 - val_accuracy: 1.0000
Epoch 6/20
14/14 [==============================] - 15s 1s/step - loss: 2.0815e-04 - accuracy: 1.0000 - val_loss: 5.8410e-05 - val_accuracy: 1.0000
Epoch 7/20
14/14 [==============================] - 15s 1s/step - loss: 1.5146e-04 - accuracy: 1.0000 - val_loss: 6.4894e-05 - val_accuracy: 1.0000
Epoch 8/20
14/14 [==============================] - 16s 1s/step - loss: 9.5164e-05 - accuracy: 1.0000 - val_loss: 8.8925e-05 - val_accuracy: 1.0000
Epoch 9/20
14/14 [==============================] - 15s 1s/step - loss: 7.1773e-05 - accuracy: 1.0000 - val_loss: 4.7353e-05 - val_accuracy: 1.0000
Epoch 10/20
14/14 [==============================] - 15s 1s/step - loss: 5.2479e-05 - accuracy: 1.0000 - val_loss: 3.1292e-05 - val_accuracy: 1.0000
Epoch 11/20
14/14 [==============================] - 15s 1s/step - loss: 4.6206e-05 - accuracy: 1.0000 - val_loss: 2.7449e-05 - val_accuracy: 1.0000
Epoch 12/20
14/14 [==============================] - 15s 1s/step - loss: 3.8818e-05 - accuracy: 1.0000 - val_loss: 2.6320e-05 - val_accuracy: 1.0000
Epoch 13/20
14/14 [==============================] - 15s 1s/step - loss: 3.3743e-05 - accuracy: 1.0000 - val_loss: 2.3123e-05 - val_accuracy: 1.0000
Epoch 14/20
14/14 [==============================] - 15s 1s/step - loss: 2.9559e-05 - accuracy: 1.0000 - val_loss: 2.0387e-05 - val_accuracy: 1.0000
Epoch 15/20
14/14 [==============================] - 15s 1s/step - loss: 2.6253e-05 - accuracy: 1.0000 - val_loss: 1.8637e-05 - val_accuracy: 1.0000
Epoch 16/20
14/14 [==============================] - 15s 1s/step - loss: 2.2819e-05 - accuracy: 1.0000 - val_loss: 1.5587e-05 - val_accuracy: 1.0000
Epoch 17/20
14/14 [==============================] - 16s 1s/step - loss: 2.0147e-05 - accuracy: 1.0000 - val_loss: 1.4463e-05 - val_accuracy: 1.0000
Epoch 18/20
14/14 [==============================] - 15s 1s/step - loss: 1.7314e-05 - accuracy: 1.0000 - val_loss: 1.2373e-05 - val_accuracy: 1.0000
Epoch 19/20
14/14 [==============================] - 15s 1s/step - loss: 1.4967e-05 - accuracy: 1.0000 - val_loss: 1.2280e-05 - val_accuracy: 1.0000
Epoch 20/20
14/14 [==============================] - 15s 1s/step - loss: 1.2023e-05 - accuracy: 1.0000 - val_loss: 9.4409e-06 - val_accuracy: 1.0000

Justificacion
El modelo se está entrenando durante 20 épocas, lo que significa que pasará por todo el conjunto de datos de entrenamiento 20 veces, creo
que con esa cantidad de epocas el modelo deberia ser fuciente para entrenarse, si colocamos mas epocas es posible que causemos un
overfiting en modelo.

1 data_augmentation = keras.Sequential(
2 [
3 layers.experimental.preprocessing.RandomFlip("horizontal",
4 input_shape=(img_height,
5 img_width,
6 3)),
7 layers.experimental.preprocessing.RandomRotation(0.1),
8 layers.experimental.preprocessing.RandomZoom(0.1),])

Justificacion
Definimos la entrada de datos utilizando el modelo tf.keras.Sequential. El aumento de datos es una técnica que implica modificar
artificialmente los datos de entrenamiento para aumentar el tamaño y la diversidad del conjunto de datos. Esto nos ayuda a evitar algun tipo de
sobreajuste de los datos de entrenamiento del modelo y mejoramos su generalización en datos invisibles.

Volteado horizontal aleatorio: este paso voltea las imágenes horizontalmente con un 50% de probabilidad. Esto aumenta la cantidad de
imágenes únicas en el conjunto de datos de entrenamiento y hace que el modelo sea más robusto ante las variaciones de orientación de la
imagen.

Rotación aleatoria: este paso rota aleatoriamente las imágenes en un ángulo de hasta 0,1 radianes. Esto aumenta aún más la variabilidad de la
imagen y hace que el modelo sea más invariante a la rotación de la imagen.

Zoom aleatorio: este paso amplía las imágenes aleatoriamente 0,1x. Esto ayuda al modelo a aprender características a diferentes escalas y lo
hace más robusto ante las variaciones del tamaño de la imagen.

1 plt.figure(figsize=(10,10))
2 for images, labels in train_ds.take(1):
3 for i in range(9):
4 ax = plt.subplot(3, 3, i + 1)

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 6/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

5 plt.imshow(images[i].numpy().astype("uint8"))
6 plt.title(class_names[labels[i]])
7 plt.axis("off")

Valoración del modelo:


1. Mediante métodos de predicción demuestre que la arquitectura implementada permite llegar o tener un acercamiento a la solución del
problema planteado. Concluya al respecto.

1 ColorPelo= {'GatoGris' : 'gris' ,'GatoNaranja' : 'naranja','GatoNegro' : 'negro','GatoPelon': 'pelon'}


2
3 #sunflower_url = "/content/PruebaGato.jpg"
4 sunflower_path = tf.keras.utils.get_file('/content/Entrenamiento/Base/GatoNaranja/download (1).jpeg','/content/base/')
5 img = keras.preprocessing.image.load_img(sunflower_path, target_size=(img_height, img_width))
6 img_array = keras.preprocessing.image.img_to_array(img)
7 img_array = tf.expand_dims(img_array,0)
8 predictions = model.predict(img_array)
9 score = tf.nn.softmax(predictions[0])
10 print(" La probabilidad del acierto del pelaje {} del gato es de: {:.2f}% \n".format(ColorPelo[class_names[np.argmax(score)]],100*np.max(

1/1 [==============================] - 0s 31ms/step


La probabilidad del acierto del pelaje naranja del gato es de: 100.00%

justificacion:

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 7/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory
Parace ser quer nuestro modelo ha alcanzado una precision de un 100%, lo que nos permite decir que nuestro modolo es capaz de detectar
exactamente el color de pelo de cada una de nuestras clases entrenadas.

2. Utilice los métodos que considere convenientes para para evaluar el rendimiento del modelo. Concluya al respecto.

3. Utilice, en especial gráficas, para soportar sus respuestas.

1 evaluation = model.evaluate(val_ds)
2 print("Validation Accuracy: {:.2f}%".format(evaluation[1] * 100))
3 print("Validation Loss: {:.4f}".format(evaluation[0]))

4/4 [==============================] - 3s 704ms/step - loss: 9.4409e-06 - accuracy: 1.0000


Validation Accuracy: 100.00%
Validation Loss: 0.0000

1 y_true = []
2 y_pred = []
3
4 for images, labels in val_ds:
5 y_true.extend(labels.numpy())
6 predictions = model.predict(images)
7 y_pred.extend(np.argmax(predictions, axis=1))
8
9 # Matriz de Confusión
10 cm = confusion_matrix(y_true, y_pred, labels=range(num_classes))
11 plt.figure(figsize=(8, 8))
12 sns.heatmap(cm, annot=True, fmt='g', cmap='Blues', xticklabels=class_names, yticklabels=class_names)
13 plt.figure(figsize=(12, 4))
14 plt.xlabel('Predicted')
15 plt.ylabel('True')
16 plt.title('Confusion Matrix')
17 plt.show()

1/1 [==============================] - 0s 464ms/step


1/1 [==============================] - 0s 498ms/step
1/1 [==============================] - 0s 426ms/step
1/1 [==============================] - 0s 155ms/step

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 8/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

Justificacion
Con respecto a la Matriz de confucion podemos deducir que nuestro modelo es capaz de predecir bastante bien el color de pelo para cada
clase o cada gato, ya que nos muestra unos valores en la diagonal principal bastante buenos y ademas por fuera de la diagonal no tenemos
ningun valor, esto nos quiere decir que nuestro modelo es capaz de predecir bastante bien o perfectamente el colo de pelo de los gatos.

1 plt.figure(figsize=(12, 4))
2 plt.subplot(1, 2, 1)
3 plt.plot(history.history['loss'], label='Training Loss')
4 plt.plot(history.history['val_loss'], label='Validation Loss')
5 plt.xlabel('Epochs')
6 plt.ylabel('Loss')
7 plt.legend()
8
9 plt.subplot(1, 2, 2)
10 plt.plot(history.history['accuracy'], label='Training Accuracy')
11 plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
12 plt.xlabel('Epochs')
13 plt.ylabel('Accuracy')
14 plt.legend()
15
16 plt.show()

Justificacion
1. Pérdida de entrenamiento: La pérdida de entrenamiento disminuye a medida que la red se entrena. Esto indica que la red neuronal está
aprendiendo a representar las características de las imágenes de gatos de manera más precisa.

2. Pérdida de validación: La pérdida de validación también disminuye a medida que la red se entrena. Sin embargo, la pérdida de validación
no es tan baja como la pérdida de entrenamiento. Esto indica que la red neuronal está comenzando a sobreajustarse a los datos de
entrenamiento.

3. Precisión de entrenamiento: La precisión de entrenamiento aumenta a medida que la red se entrena. Esto indica que la red neuronal está
aprendiendo a clasificar correctamente las imágenes de gatos.

4. Precisión de validación: La precisión de validación también aumenta a medida que la red se entrena. Sin embargo, la precisión de
validación no es tan alta como la precisión de entrenamiento. Esto indica que la red neuronal podría no ser tan precisa en imágenes
nuevas como lo es en imágenes que ya ha visto.

En general, las curvas de aprendizaje nos indican que la red neuronal está aprendiendo de manera efectiva. Sin embargo, hay algunas áreas en
las que la red neuronal podría mejorar para aumentar su precisión y evitar el sobreajuste. Se podria evitar este sobreajuste ajustand los
parámetros de la red neuronal o proporcionar más datos de entrenamiento.

1 from sklearn.metrics import roc_auc_score


2
3 y_true_val = []
4 y_pred_val = []
5
6 for images labels in val ds:
https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 9/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory
6 for images, labels in val_ds:
7 y_true_val.extend(labels.numpy())
8 predictions = model.predict(images)
9 y_pred_val.extend(predictions)
10
11 y_true_val = np.array(y_true_val)
12 y_pred_val = np.array(y_pred_val)
13
14 y_true_one_hot_val = tf.keras.utils.to_categorical(y_true_val, num_classes=num_classes)
15
16 plt.figure(figsize=(12, 8))
17
18 for i in range(num_classes):
19 fpr, tpr, _ = roc_curve(y_true_one_hot_val[:, i], y_pred_val[:, i])
20 roc_auc = auc(fpr, tpr)
21
22 plt.plot(fpr, tpr, label=f'Class {i} (AUC = {roc_auc:.2f})')
23
24 plt.plot([0, 1], [0, 1], linestyle='--', color='gray', label='Random')
25 plt.xlabel('False Positive Rate')
26 plt.ylabel('True Positive Rate')
27 plt.title('ROC Curve for Each Class on Validation Set')
28 plt.legend()
29 plt.show()

1/1 [==============================] - 1s 974ms/step


1/1 [==============================] - 1s 722ms/step
1/1 [==============================] - 1s 882ms/step
1/1 [==============================] - 0s 328ms/step

Justificacion
La curva ROC para la clase de gatos grises tiene un AUC (área bajo la curva) de 1.00. Esto significa que la red neuronal es perfecta para
clasificar gatos grises. Las curvas ROC para las otras tres clases de gatos también tienen AUC muy altos, lo que indica que la red neuronal
también es muy buena para clasificar gatos negros, gatos naranjas y gatos pelados.

En general, la gráfica ROC indica que la red neuronal tiene un buen desempeño en la clasificación de los cuatro colores de pelo de gato. La red
neuronal tiene una alta sensibilidad y una alta especificidad, lo que significa que puede clasificar correctamente los gatos con una alta tasa de

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 10/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory
aciertos y una baja tasa de errores.

Parte II Deep Learnig – RNN – LSTM

Fundamentos de una RNN:


1. Presente un breve repaso de los fundamentos y los aspectos más importantes de las redes neuronales secuenciales

Las redes neuronales secuenciales, como las Redes Neuronales Recurrentes (RNN), están diseñadas para trabajar con datos secuenciales o
datos que tienen una estructura temporal. Estas redes son poderosas en el procesamiento de datos que tienen una dependencia temporal,
como el lenguaje natural, series temporales, música, entre otros. Aquí tienes un breve repaso de los fundamentos y aspectos clave:

Estructura básica:

Las RNN tienen una estructura recurrente que les permite mantener y utilizar estados anteriores mientras procesan nueva información. Cada
neurona en una capa recibe entradas no solo de la capa anterior, sino también de su propia salida anterior (estado oculto).

Celdas recurrentes:

Las unidades básicas de una RNN son las celdas recurrentes. Estas celdas tienen la capacidad de mantener información a lo largo del tiempo y
actualizarla con nuevas entradas.

Tipos de celdas:

LSTM (Long Short-Term Memory) y GRU (Gated Recurrent Unit) son variantes populares de celdas recurrentes. Ambas abordan el problema del
"olvido a largo plazo" en las RNN estándar y ayudan a mantener y utilizar información relevante a lo largo de secuencias largas.

Procesamiento secuencial:

Las RNN son aptas para procesar secuencias de longitud variable. Pueden trabajar con entrada y salida secuenciales, lo que las hace útiles en
tareas como la traducción automática, el análisis de sentimientos, la generación de texto, entre otros.

Problemas comunes:

Las RNN pueden enfrentar problemas de desvanecimiento del gradiente (cuando los gradientes se vuelven demasiado pequeños o grandes
durante el entrenamiento) o explosión del gradiente (cuando los gradientes crecen exponencialmente). Las variantes como LSTM y GRU
abordan estos problemas en cierta medida.

Aplicaciones:

Se utilizan ampliamente en el procesamiento de lenguaje natural (NLP), reconocimiento de voz, generación de texto, predicción de series
temporales, entre otras aplicaciones donde la secuencialidad de los datos es fundamental. Las redes neuronales secuenciales, a pesar de sus
desafíos, han revolucionado el procesamiento de datos secuenciales y continúan siendo objeto de investigación y desarrollo debido a su
versatilidad en una amplia gama de campos.

Arquitectura e Implementación de la RNN.


1. Diseñe y estructure una arquitectura de redes neuronales recurrentes que permita solucionar un problema de traducción español – ingles

2. Describa con comentarios la estructura de la red y específique claramente los beneficios de la red que se utilizó para crear la red
recurrente o secuencia, por ejemplo: keras.layers.RNN, keras.layers.LSTM, keras.layers.GRU

3. Justifique las características de la estructura

1 import pathlib
2 import random
3 import string
4 import re
5 import numpy as np
6 import tensorflow as tf
7 import spacy
8 from tensorflow import keras
9 from tensorflow.keras import layers
10 from tensorflow.keras.layers import TextVectorization

Descargamos las traducciones

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 11/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

1 text_file = keras.utils.get_file(
2 fname="spa-eng.zip",
3 origin="http://storage.googleapis.com/download.tensorflow.org/data/spa-eng.zip",
4 extract=True,
5 )
6 text_file = pathlib.Path(text_file).parent / "spa-eng" / "spa.txt"

Downloading data from http://storage.googleapis.com/download.tensorflow.org/data/spa-eng.zip


2638744/2638744 [==============================] - 1s 0us/step

Analizamos la información
Cada línea contiene una oración en inglés y su correspondiente oración en español. La oración en inglés es la secuencia fuente y la en español
es la secuencia objetivo. Anteponemos el token "[start]" y agregamos el token "[end]" a la oración en español.

1 with open(text_file) as f:
2 lines = f.read().split("\n")[:-1]
3 text_pairs = []
4 for line in lines:
5 eng, spa = line.split("\t")
6 spa = "[start] " + spa + " [end]"
7 text_pairs.append((eng, spa))

Aqui tenemos cinco ejemplos del resultado:

1 for _ in range(5):
2 print(random.choice(text_pairs))

('Harshness should be avoided in those cases.', '[start] Debe evitarse la dureza en esos casos. [end]')
('I like the way you talk.', '[start] Me gusta la forma que tienes de hablar. [end]')
("Tom should've trusted me.", '[start] Tom debió haber confiado en mí. [end]')
('They ate supper.', '[start] Ellos cenaron. [end]')
("It looks as if you're right.", '[start] Parece que tienes razón. [end]')

Ahora, dividiremos los pares de oraciones en un conjunto de entrenamiento, un conjunto de validación, y un equipo de prueba.

1 random.shuffle(text_pairs)
2 num_val_samples = int(0.15 * len(text_pairs))
3 num_train_samples = len(text_pairs) - 2 * num_val_samples
4 train_pairs = text_pairs[:num_train_samples]
5 val_pairs = text_pairs[num_train_samples : num_train_samples + num_val_samples]
6 test_pairs = text_pairs[num_train_samples + num_val_samples :]
7
8 print(f"{len(text_pairs)} total pairs")
9 print(f"{len(train_pairs)} training pairs")
10 print(f"{len(val_pairs)} validation pairs")
11 print(f"{len(test_pairs)} test pairs")

118964 total pairs


83276 training pairs
17844 validation pairs
17844 test pairs

Vectorizamos los datos del texto


Usaremos dos instancias de la capa TextVectorization para vectorizar el datos de texto (uno para inglés y otro para español), es decir,
convertir las cadenas originales en secuencias enteras donde cada número entero representa el índice de una palabra en un vocabulario.

La capa en inglés utilizará la estandarización de cadenas predeterminada (eliminar caracteres de puntuación) y esquema de división (dividido
en espacios en blanco), mientras que la capa en español usará una estandarización personalizada, donde agregamos el carácter "¿" al
conjunto de caracteres de puntuación que se eliminarán.

1 strip_chars = string.punctuation + "¿"


2 strip_chars = strip_chars.replace("[", "")
3 strip_chars = strip_chars.replace("]", "")
4
5 vocab_size = 15000
6 sequence_length = 20

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 12/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

7 batch_size = 64
8
9
10 def custom_standardization(input_string):
11 lowercase = tf.strings.lower(input_string)
12 return tf.strings.regex_replace(lowercase, "[%s]" % re.escape(strip_chars), "")
13
14
15 eng_vectorization = TextVectorization(
16 max_tokens=vocab_size,
17 output_mode="int",
18 output_sequence_length=sequence_length,
19 )
20 spa_vectorization = TextVectorization(
21 max_tokens=vocab_size,
22 output_mode="int",
23 output_sequence_length=sequence_length + 1,
24 standardize=custom_standardization,
25 )
26 train_eng_texts = [pair[0] for pair in train_pairs]
27 train_spa_texts = [pair[1] for pair in train_pairs]
28 eng_vectorization.adapt(train_eng_texts)
29 spa_vectorization.adapt(train_spa_texts)

A continuación, formatearemos nuestros datasets.

En cada paso de entrenamiento, el modelo buscará predecir las palabras objetivo N+1 (y más allá) usando la oración fuente y las palabras
objetivo 0 a N.

Como tal, el conjunto de datos de entrenamiento producirá una tupla (inputs, targets) , donde:

inputs es un diccionario con las claves encoder_inputs y decoder_inputs . encoder_inputs es la oración fuente vectorizada y
decoder_inputs es la oración objetivo "hasta ahora", es decir, las palabras 0 a N utilizadas para predecir la palabra N+1 (y más allá) en la
oración objetivo.
target es la frase objetivo desplazada en un paso: proporciona las siguientes palabras en la oración objetivo: lo que el modelo intentará
predecir.

1 def format_dataset(eng, spa):


2 eng = eng_vectorization(eng)
3 spa = spa_vectorization(spa)
4 return (
5 {
6 "encoder_inputs": eng,
7 "decoder_inputs": spa[:, :-1],
8 },
9 spa[:, 1:],
10 )
11
12
13 def make_dataset(pairs):
14 eng_texts, spa_texts = zip(*pairs)
15 eng_texts = list(eng_texts)
16 spa_texts = list(spa_texts)
17 dataset = tf.data.Dataset.from_tensor_slices((eng_texts, spa_texts))
18 dataset = dataset.batch(batch_size)
19 dataset = dataset.map(format_dataset)
20 return dataset.shuffle(2048).prefetch(16).cache()
21
22
23 train_ds = make_dataset(train_pairs)
24 val_ds = make_dataset(val_pairs)

Let's take a quick look at the sequence shapes (we have batches of 64 pairs, and all sequences are 20 steps long):

1 for inputs, targets in train_ds.take(1):


2 print(f'inputs["encoder_inputs"].shape: {inputs["encoder_inputs"].shape}')
3 print(f'inputs["decoder_inputs"].shape: {inputs["decoder_inputs"].shape}')
4 print(f"targets.shape: {targets.shape}")

inputs["encoder_inputs"].shape: (64, 20)


inputs["decoder_inputs"].shape: (64, 20)
targets.shape: (64, 20)

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 13/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

Construcción del modelo


Nuestro transformador de secuencia a secuencia consta de un TransformerEncoder y un TransformerDecoder encadenados. Para que el
modelo sea consciente del orden de las palabras, También utilizamos una capa PositionalEmbedding .

La secuencia fuente se pasará al TransformerEncoder , lo que producirá una nueva representación del mismo. Esta nueva representación será
entonces aprobada al TransformerDecoder , junto con la secuencia objetivo hasta el momento (palabras objetivo 0 a N). El TransformerDecoder
buscará entonces predecir las siguientes palabras en la secuencia objetivo (N+1 y más).

Un detalle clave que hace esto posible es el enmascaramiento causal. ( use_causal_mask=True en la primera capa de atención del
TransformerDecoder ). El TransformerDecoder ve las secuencias completas a la vez y, por lo tanto, debemos hacer asegúrese de que solo
utilice información de los tokens objetivo 0 a N al predecir el token N+1 (de lo contrario, podría utilizar información del futuro, lo que dar como
resultado un modelo que no se puede utilizar en el momento de la inferencia).

1 class TransformerEncoder(layers.Layer):
2 def __init__(self, embed_dim, dense_dim, num_heads, **kwargs):
3 super().__init__(**kwargs)
4 self.embed_dim = embed_dim
5 self.dense_dim = dense_dim
6 self.num_heads = num_heads
7 self.attention = layers.MultiHeadAttention(
8 num_heads=num_heads, key_dim=embed_dim
9 )
10 self.dense_proj = keras.Sequential(
11 [
12 layers.Dense(dense_dim, activation="relu"),
13 layers.Dense(embed_dim),
14 ]
15 )
16 self.layernorm_1 = layers.LayerNormalization()
17 self.layernorm_2 = layers.LayerNormalization()
18 self.supports_masking = True
19
20 def call(self, inputs, mask=None):
21 attention_output = self.attention(query=inputs, value=inputs, key=inputs)
22 proj_input = self.layernorm_1(inputs + attention_output)
23 proj_output = self.dense_proj(proj_input)
24 return self.layernorm_2(proj_input + proj_output)
25
26 def get_config(self):
27 config = super().get_config()
28 config.update(
29 {
30 "embed_dim": self.embed_dim,
31 "dense_dim": self.dense_dim,
32 "num_heads": self.num_heads,
33 }
34 )
35 return config
36
37
38 class PositionalEmbedding(layers.Layer):
39 def __init__(self, sequence_length, vocab_size, embed_dim, **kwargs):
40 super().__init__(**kwargs)
41 self.token_embeddings = layers.Embedding(
42 input_dim=vocab_size, output_dim=embed_dim
43 )
44 self.position_embeddings = layers.Embedding(
45 input_dim=sequence_length, output_dim=embed_dim
46 )
47 self.sequence_length = sequence_length
48 self.vocab_size = vocab_size
49 self.embed_dim = embed_dim
50
51 def call(self, inputs):
52 length = tf.shape(inputs)[-1]
53 positions = tf.range(start=0, limit=length, delta=1)
54 embedded_tokens = self.token_embeddings(inputs)
55 embedded_positions = self.position_embeddings(positions)
56 return embedded_tokens + embedded_positions
57
58 def compute_mask(self, inputs, mask=None):
59 return tf.math.not_equal(inputs, 0)

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 14/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

60
61 def get_config(self):
62 config = super().get_config()
63 config.update(
64 {
65 "sequence_length": self.sequence_length,
66 "vocab_size": self.vocab_size,
67 "embed_dim": self.embed_dim,
68 }
69 )
70 return config
71
72
73 class TransformerDecoder(layers.Layer):
74 def __init__(self, embed_dim, latent_dim, num_heads, **kwargs):
75 super().__init__(**kwargs)
76 self.embed_dim = embed_dim
77 self.latent_dim = latent_dim
78 self.num_heads = num_heads
79 self.attention_1 = layers.MultiHeadAttention(
80 num_heads=num_heads, key_dim=embed_dim
81 )
82 self.attention_2 = layers.MultiHeadAttention(
83 num_heads=num_heads, key_dim=embed_dim
84 )
85 self.dense_proj = keras.Sequential(
86 [
87 layers.Dense(latent_dim, activation="relu"),
88 layers.Dense(embed_dim),
89 ]
90 )
91 self.layernorm_1 = layers.LayerNormalization()
92 self.layernorm_2 = layers.LayerNormalization()
93 self.layernorm_3 = layers.LayerNormalization()
94 self.add = layers.Add() # instead of `+` to preserve mask
95 self.supports_masking = True
96
97 def call(self, inputs, encoder_outputs, mask=None):
98 attention_output_1 = self.attention_1(
99 query=inputs, value=inputs, key=inputs, use_causal_mask=True
100 )
101 out_1 = self.layernorm_1(self.add([inputs, attention_output_1]))
102
103 attention_output_2 = self.attention_2(
104 query=out_1,
105 value=encoder_outputs,
106 key=encoder_outputs,
107 )
108 out_2 = self.layernorm_2(self.add([out_1, attention_output_2]))
109
110 proj_output = self.dense_proj(out_2)
111 return self.layernorm_3(self.add([out_2, proj_output]))
112
113 def get_config(self):
114 config = super().get_config()
115 config.update(
116 {
117 "embed_dim": self.embed_dim,
118 "latent_dim": self.latent_dim,
119 "num_heads": self.num_heads,
120 }
121 )
122 return config
123

A continuación, ensamblamos el modelo de secuencia a secuencia.

1 embed_dim = 256
2 latent_dim = 2048
3 num_heads = 8
4
5 encoder_inputs = keras.Input(shape=(None,), dtype="int64", name="encoder_inputs")
6 x = PositionalEmbedding(sequence_length, vocab_size, embed_dim)(encoder_inputs)
7 encoder_outputs = TransformerEncoder(embed_dim, latent_dim, num_heads)(x)
8 encoder = keras.Model(encoder_inputs, encoder_outputs)

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 15/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

9
10 decoder_inputs = keras.Input(shape=(None,), dtype="int64", name="decoder_inputs")
11 encoded_seq_inputs = keras.Input(shape=(None, embed_dim), name="decoder_state_inputs")
12 x = PositionalEmbedding(sequence_length, vocab_size, embed_dim)(decoder_inputs)
13 x = TransformerDecoder(embed_dim, latent_dim, num_heads)(x, encoded_seq_inputs)
14 x = layers.Dropout(0.5)(x)
15 decoder_outputs = layers.Dense(vocab_size, activation="softmax")(x)
16 decoder = keras.Model([decoder_inputs, encoded_seq_inputs], decoder_outputs)
17
18 decoder_outputs = decoder([decoder_inputs, encoder_outputs])
19 transformer = keras.Model(
20 [encoder_inputs, decoder_inputs], decoder_outputs, name="transformer")

Entrenamos nuestro modelo


Usaremos la precisión como una forma rápida de monitorear el progreso del entrenamiento en los datos de validación. Tenga en cuenta que la
traducción automática suele utilizar puntuaciones BLEU, así como otras métricas, en lugar de precisión.

Aquí solo entrenamos durante 1 época, pero para que el modelo realmente converja es recomendable el entrenar durante al menos 30 épocas.

1 epochs = 1 # This should be at least 30 for convergence


2
3 transformer.summary()
4 transformer.compile(
5 "rmsprop", loss="sparse_categorical_crossentropy", metrics=["accuracy"]
6 )
7 transformer.fit(train_ds, epochs=epochs, validation_data=val_ds)

Model: "transformer"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
encoder_inputs (InputLayer [(None, None)] 0 []
)

positional_embedding (Posi (None, None, 256) 3845120 ['encoder_inputs[0][0]']


tionalEmbedding)

decoder_inputs (InputLayer [(None, None)] 0 []


)

transformer_encoder (Trans (None, None, 256) 3155456 ['positional_embedding[0][0]']


formerEncoder)

model_1 (Functional) (None, None, 15000) 1295964 ['decoder_inputs[0][0]',


0 'transformer_encoder[0][0]']

==================================================================================================
Total params: 19960216 (76.14 MB)
Trainable params: 19960216 (76.14 MB)
Non-trainable params: 0 (0.00 Byte)
__________________________________________________________________________________________________
1302/1302 [==============================] - 4279s 3s/step - loss: 3.6447 - accuracy: 0.4683 - val_loss: 2.5259 - val_accuracy: 0.6047
<keras.src.callbacks.History at 0x7c717d075570>

Decodificamos oraciones de prueba


Finalmente, demostremos cómo traducir oraciones nuevas en inglés. Simplemente introducimos en el modelo la frase en inglés vectorizada.
así como el token de destino "[start]" , luego generamos repetidamente el siguiente token, hastallegamos al token "[end]" .

1 pa_vocab = spa_vectorization.get_vocabulary()
2 spa_index_lookup = dict(zip(range(len(spa_vocab)), spa_vocab))
3 max_decoded_sentence_length = 20
4
5
6 def decode_sequence(input_sentence):
7 tokenized_input_sentence = eng_vectorization([input_sentence])
8 decoded_sentence = "[start]"
9 for i in range(max_decoded_sentence_length):
10 tokenized_target_sentence = spa_vectorization([decoded_sentence])[:, :-1]
11 predictions = transformer([tokenized_input_sentence, tokenized_target_sentence])
12
13 sampled_token_index = np.argmax(predictions[0, i, :])
14 sampled_token = spa_index_lookup[sampled_token_index]

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 16/17
11/22/23, 7:31 AM TallerFinalIA.ipynb - Colaboratory

15 decoded_sentence += " " + sampled_token


16
17 if sampled_token == "[end]":
18 break
19 return decoded_sentence
20
21
22 test_eng_texts = [pair[0] for pair in test_pairs]
23 for _ in range(30):
24 input_sentence = random.choice(test_eng_texts)
25 translated = decode_sequence(input_sentence)

Obtenemos resultados como:

Hello, how are you?. [start] ¿Hola cómo está usted? [end]

Tom has never heard Mary sing. [start] tom nunca ha oído cantar a mary [end]

Perhaps she will come tomorrow. [start] tal vez ella vendrá mañana [end]

I love to write. [start] me encanta escribir [end]

His French is improving little by little. [start] su francés va a [UNK] sólo un poco [end]

My hotel told me to call you. [start] mi hotel me dijo que te [UNK] [end]

https://colab.research.google.com/drive/1KBvgfvCg_Yv9r5EzhLgxkgLFloLbcOK7?usp=sharing#scrollTo=EQCGEOZ9ie6i&printMode=true 17/17

También podría gustarte