Visualización y Ajuste de Hiperparámetros (Keras Tuner)¶
Actividad Semana 5 | Deep Learning - Especialización en Inteligencia Artificial¶
Autor: Alexander Oviedo Fadul
Planteamiento y Contexto Aplicado (Caso Real): La Rama Judicial enfrenta severos cuellos de botella procesales por la manipulación de expedientes físicos y radicados manuales. Esta actividad simula la creación del núcleo de un Sistema Híbrido de Reconocimiento Óptico de Caracteres (OCR). Emplearemos un subconjunto estandarizado de dígitos numéricos (MNIST) para modelar la lectura de códigos de radicación manuscritos en juzgados civiles.
El objetivo central es automatizar procesos de validación hiperparamétrica —Grid Search y Random Search— para hallar la topología óptima y mitigar riesgos constitucionales como el sobredimensionamiento (overfitting).
1. Configuración de Entorno e Importación de Librerías¶
!pip install keras-tuner -q
import numpy as np
import keras_tuner
import keras
from keras import layers
import os
print("✅ Entorno preparado exitosamente.")
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/129.4 kB ? eta -:--:-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸━━ 122.9/129.4 kB 10.1 MB/s eta 0:00:01 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 129.4/129.4 kB 1.1 MB/s eta 0:00:00 ✅ Entorno preparado exitosamente.
2. Preparación de los Datos (Extracción y Normalización)¶
Cargamos la base de datos simulando el lote de registros judiciales. Las imágenes ingresan en un rango de 0 a 255 (píxeles), requiriendo su escalado entre [0, 1] para evitar una explosión de gradientes.
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# Normalizamos para reducir ruido (Overfitting)
x_train = x_train.astype("float32") / 255.0
x_test = x_test.astype("float32") / 255.0
# Dimensionamos las matrices simulando canal de color 1 (escala de grises en documentos scaneados)
x_train = np.expand_dims(x_train, -1)
x_test = np.expand_dims(x_test, -1)
print(f"Volumen OCR Entrenamiento: {x_train.shape[0]} folios simulados.")
print(f"Volumen OCR Validación: {x_test.shape[0]} folios simulados.")
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz 11490434/11490434 ━━━━━━━━━━━━━━━━━━━━ 0s 0us/step Volumen OCR Entrenamiento: 60000 folios simulados. Volumen OCR Validación: 10000 folios simulados.
3. Función Constructora del Modelo Parametrizado¶
Implementamos una topología convolucional build_model(hp) para capturar la estructura espacial de los dígitos escritos. Aquí, KerasTuner iterará automáticamente valores dinámicos para buscar la arquitectura ideal:
filters: [32, 64, 128]cnn_layers: [1 a 3]learning_rate: Opciones de [1e-2, 1e-3, 1e-4]dropout: Opción booleana [True/False] para controlar el ruido.
def build_model(hp):
inputs = keras.Input(shape=(28, 28, 1))
x = inputs
# Definimos como Hiperparámetro la cantidad de redes Convolucionales
for i in range(hp.Int("cnn_layers", 1, 3)):
x = layers.Conv2D(
hp.Int(f"filters_{i}", 32, 128, step=32),
kernel_size=(3, 3),
activation="relu",
padding="same"
)(x)
x = layers.MaxPooling2D(pool_size=(2, 2))(x)
x = layers.Flatten()(x)
# Hiperparámetro Dropout para regularización judicial (Evitar Memorización)
if hp.Boolean("dropout"):
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(10, activation="softmax")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
# Definimos el Learning Rate evaluando distintas magnitudes
learning_rate = hp.Choice("learning_rate", values=[1e-2, 1e-3, 1e-4])
model.compile(
loss="sparse_categorical_crossentropy",
metrics=["accuracy"],
optimizer=keras.optimizers.Adam(learning_rate=learning_rate),
)
return model
4. Ejecución de Búsqueda Aleatoria (Random Search)¶
A diferencia del barrido sistemático (Grid Search), la búsqueda aleatoria selecciona hiperparámetros de manera no-lineal, lo cual a menudo resulta mucho más eficiente para espacios de parámetros enormes.
import shutil
if os.path.exists("/tmp/tb_rs"):
shutil.rmtree("/tmp/tb_rs")
tuner_rs = keras_tuner.RandomSearch(
build_model,
max_trials=4, # Agilizado para viabilidad de la demostración (4 iteraciones aleatorias)
objective="val_accuracy",
directory="/tmp/tb_rs",
project_name="OCR_Judicial_RandomSearch",
overwrite=True
)
print("🚀 Iniciando Afinación Aleatoria (Random Search)...")
tuner_rs.search(
x_train,
y_train,
validation_split=0.2,
epochs=2,
callbacks=[keras.callbacks.TensorBoard("/tmp/tb_rs/logs")],
)
Trial 4 Complete [00h 02m 34s] val_accuracy: 0.9612500071525574 Best val_accuracy So Far: 0.9789166450500488 Total elapsed time: 00h 07m 46s
5. Ejecución en Búsqueda Cuadriculada (Grid Search)¶
La Búsqueda de Cuadrícula garantiza que se visite todas las combinaciones posibles indicadas en el bloque maestro, resultando más preciso pero extremadamente lento en ecosistemas complejos con muchas capas.
if os.path.exists("/tmp/tb_gs"):
shutil.rmtree("/tmp/tb_gs")
tuner_gs = keras_tuner.GridSearch(
build_model,
max_trials=4, # Restringido para fines de esta práctica académica
objective="val_accuracy",
directory="/tmp/tb_gs",
project_name="OCR_Judicial_GridSearch",
overwrite=True
)
print("🚀 Iniciando Afinación de Cuadrícula (Grid Search)...")
tuner_gs.search(
x_train,
y_train,
validation_split=0.2,
epochs=2,
callbacks=[keras.callbacks.TensorBoard("/tmp/tb_gs/logs")],
)
Trial 4 Complete [00h 01m 10s] val_accuracy: 0.9803333282470703 Best val_accuracy So Far: 0.9803333282470703 Total elapsed time: 00h 04m 17s
6. Monitoreo Integral mediante TensorBoard¶
Ejecutamos la extensión de TensorBoard en bloque directo dentro del ecosistema colab para comparar el impacto del overfitting.
%load_ext tensorboard
%tensorboard --logdir /tmp/tb_rs/logs
Output hidden; open in https://colab.research.google.com to view.
7. Mejor Configuración Hallada (Conclusiones del Modelo)¶
Identificamos la métrica biológica final recomendada por el algoritmo optimizador para proceder a la certificación.
best_hp_rs = tuner_rs.get_best_hyperparameters()[0]
best_hp_gs = tuner_gs.get_best_hyperparameters()[0]
print("--- RESULTADOS OCR --- \n")
print("🏆 Mejores Parámetros - Random Search:")
print(f"-> Capas Convolucionales: {best_hp_rs.get('cnn_layers')}")
print(f"-> Learning Rate: {best_hp_rs.get('learning_rate')}")
print(f"-> Aplicó Dropout: {best_hp_rs.get('dropout')}\n")
print("🏆 Mejores Parámetros - Grid Search:")
print(f"-> Capas Convolucionales: {best_hp_gs.get('cnn_layers')}")
print(f"-> Learning Rate: {best_hp_gs.get('learning_rate')}")
print(f"-> Aplicó Dropout: {best_hp_gs.get('dropout')}")
--- RESULTADOS OCR --- 🏆 Mejores Parámetros - Random Search: -> Capas Convolucionales: 1 -> Learning Rate: 0.01 -> Aplicó Dropout: True 🏆 Mejores Parámetros - Grid Search: -> Capas Convolucionales: 1 -> Learning Rate: 0.01 -> Aplicó Dropout: True