En 07-01 dejamos una cifra sobre la mesa — 82-85 % de exactitud del clasificador de categorías — y una promesa: batirla sin escribir apenas más código. Este proyecto final la cumple con el transfer learning de 05-03: en lugar de entrenar una CNN desde cero, tomaremos MobileNetV2 preentrenada en ImageNet y la adaptaremos a nuestro problema en dos fases (extracción de características y fine-tuning). Al terminar compararás ambos enfoques con números en la mano, decidirás cuál despliega TecnoMarket y cerrarás el módulo con los cinco proyectos entregados.
Contenido
- Enunciado: rehacer 07-01 y batirlo
- Fase 1: datos — redimensionado y
preprocess_inputcorrecto - Fase 2: el modelo con MobileNetV2 congelada
- Fase 3: entrenamiento en dos fases (extracción → fine-tuning)
- Fase 4: comparación de curvas entre fases
- Fase 5: comparación final honesta contra la CNN de 07-01
- Fase 6: cuándo compensa el transfer learning (la tabla 2×2, revisada)
- Fase 7: empaquetado final y decisión de negocio
- Cierre del módulo: el portfolio de TecnoMarket
Enunciado: rehacer 07-01 y batirlo
Mismo problema, mismos datos, misma vara de medir: CIFAR-10 como stand-in de las categorías de producto de TecnoMarket, el mismo conjunto de test congelado de 07-01 y la misma partición train/validación. Solo cambia la estrategia: en vez de aprender a ver desde cero con 45 000 imágenes, partimos de una red que ya aprendió a ver con 1.4 millones (ImageNet) y le enseñamos únicamente nuestras categorías. Es la apuesta central de 05-03; hoy la medimos contra una alternativa real construida por nosotros mismos — la comparación más honesta posible.
Objetivo cuantitativo: superar claramente el 85 % de 07-01. Resultado típico esperable: 90-93 %.
Fase 1: datos — redimensionado y preprocess_input correcto
MobileNetV2 no acepta 32×32: fue preentrenada con imágenes grandes y su cascada de reducciones dejaría mapas vacíos. Redimensionamos a 160×160 (compromiso entre fidelidad y coste; 05-03). Y el punto que más proyectos rompe: cada red preentrenada exige su propio preprocesado. MobileNetV2 espera píxeles en [-1, 1], no el /255 que usamos en 07-01:
import tensorflow as tf
import numpy as np
tf.random.set_seed(42)
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
x_val, y_val = x_train[45000:], y_train[45000:] # misma particion que 07-01
x_train, y_train = x_train[:45000], y_train[:45000]
TAM = 160
BATCH = 64
AUTOTUNE = tf.data.AUTOTUNE
aumento = tf.keras.Sequential([ # mismo aumento que 07-01 (05-04)
tf.keras.layers.RandomFlip("horizontal"),
tf.keras.layers.RandomTranslation(0.1, 0.1),
tf.keras.layers.RandomZoom(0.1),
])
def preparar(x, y):
x = tf.image.resize(tf.cast(x, tf.float32), (TAM, TAM))
x = tf.keras.applications.mobilenet_v2.preprocess_input(x) # -> [-1, 1]
return x, y
def dataset(x, y, entrenar=False):
ds = tf.data.Dataset.from_tensor_slices((x, y)).map(preparar, AUTOTUNE)
if entrenar:
ds = ds.shuffle(10_000).batch(BATCH).map(
lambda a, b: (aumento(a, training=True), b), AUTOTUNE)
else:
ds = ds.batch(BATCH)
return ds.prefetch(AUTOTUNE)
train_ds = dataset(x_train, y_train, entrenar=True)
val_ds = dataset(x_val, y_val)
test_ds = dataset(x_test, y_test)Usar preprocess_input de la misma familia de modelo no es opcional: con el /255 de 07-01, MobileNetV2 recibiría entradas fuera de la distribución con la que se preentrenó y rendiría varios puntos por debajo sin dar ningún error visible.
Fase 2: el modelo con MobileNetV2 congelada
La receta de 05-03: base preentrenada sin cabeza (include_top=False), congelada, más una cabeza nueva mínima:
from tensorflow.keras import layers, models
base = tf.keras.applications.MobileNetV2(
input_shape=(TAM, TAM, 3),
include_top=False, # sin la cabeza de las 1000 clases de ImageNet
weights="imagenet",
)
base.trainable = False # fase 1: congelada por completo
entradas = layers.Input(shape=(TAM, TAM, 3))
x = base(entradas, training=False) # training=False: BN en modo inferencia (05-03)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.3)(x)
salidas = layers.Dense(10, activation="softmax")(x)
modelo = models.Model(entradas, salidas, name="tecnomarket_tl")
modelo.summary()
# Total: ~2.3 M de parametros; entrenables: ~13 000 (solo la cabeza)Fíjate en la desproporción: la base aporta ~2.26 M de parámetros ya aprendidos; nosotros solo entrenamos ~13 000. El training=False en la llamada a la base es el detalle sutil de 05-03: mantiene las BatchNormalization en modo inferencia incluso durante el fine-tuning posterior, protegiendo las estadísticas de ImageNet.
Fase 3: entrenamiento en dos fases (extracción → fine-tuning)
Fase de extracción de características — solo la cabeza, lr normal:
modelo.compile(optimizer=tf.keras.optimizers.Adam(1e-3),
loss="sparse_categorical_crossentropy", metrics=["accuracy"])
callbacks = [
tf.keras.callbacks.EarlyStopping(monitor="val_accuracy", patience=5,
restore_best_weights=True),
tf.keras.callbacks.ModelCheckpoint("models/tl_extraccion.keras",
monitor="val_accuracy", save_best_only=True),
tf.keras.callbacks.TensorBoard(log_dir="logs/tl_fase1"),
]
hist1 = modelo.fit(train_ds, validation_data=val_ds, epochs=15,
callbacks=callbacks)
# Resultado tipico: val_accuracy ~86-88 % en 8-12 epocasYa en esta fase — entrenando el 0.6 % de los parámetros — se supera a la CNN de 07-01. Las características de ImageNet (bordes, texturas, formas de objetos) transfieren bien a CIFAR-10.
Fase de fine-tuning — descongelar el bloque final, lr bajo:
base.trainable = True
for capa in base.layers[:100]: # MobileNetV2 tiene 154 capas: liberamos ~1/3 final
capa.trainable = False
modelo.compile(optimizer=tf.keras.optimizers.Adam(1e-5), # lr 100x mas bajo
loss="sparse_categorical_crossentropy", metrics=["accuracy"])
callbacks[1] = tf.keras.callbacks.ModelCheckpoint("models/tl_finetuning.keras",
monitor="val_accuracy", save_best_only=True)
callbacks[2] = tf.keras.callbacks.TensorBoard(log_dir="logs/tl_fase2")
hist2 = modelo.fit(train_ds, validation_data=val_ds, epochs=15,
callbacks=callbacks)
# Resultado tipico: val_accuracy ~90-93 %Las dos reglas de oro de 05-03, aplicadas: recompilar tras cambiar trainable (si no, el cambio no surte efecto) y learning rate muy bajo (1e-5): las capas descongeladas ya contienen conocimiento valioso; un lr alto lo destruiría en las primeras iteraciones (el llamado catastrophic forgetting). Descongelamos solo el bloque final porque las capas tempranas (bordes, colores) son universales y las tardías son las que conviene especializar en nuestras categorías.
Fase 4: comparación de curvas entre fases
Concatena ambos historiales y pinta la exactitud de validación con una línea vertical en el cambio de fase:
import matplotlib.pyplot as plt
acc = hist1.history["val_accuracy"] + hist2.history["val_accuracy"]
plt.plot(acc, label="val_accuracy")
plt.axvline(len(hist1.history["val_accuracy"]) - 1, ls="--", c="gray",
label="inicio fine-tuning")
plt.xlabel("epoca"); plt.legend(); plt.grid(True)Lectura típica de la curva:
- Fase 1: subida rápida las primeras épocas y meseta en ~87 % — la cabeza exprime todo lo que dan unas características genéricas congeladas.
- Cambio de fase: un salto visible de 2-4 puntos en las primeras épocas de fine-tuning — las capas finales se adaptan a texturas de CIFAR — y meseta nueva en ~91-92 %.
- Si en la fase 2 la exactitud cae de golpe, el lr era demasiado alto: es el síntoma clásico.
Fase 5: comparación final honesta contra la CNN de 07-01
Evalúa sobre el mismo test congelado de 07-01 y pon las cifras frente a frente. Valores típicos (los tuyos variarán algo; usa los que obtengas de verdad):
test_loss, test_acc = modelo.evaluate(test_ds)
print(f"Exactitud test transfer learning: {test_acc:.3f}")| Criterio | CNN propia (07-01) | MobileNetV2 + fine-tuning |
|---|---|---|
| Exactitud en test | ~83 % | ~91 % |
| Parámetros totales | ~1.2 M | ~2.3 M |
| Parámetros entrenados | ~1.2 M (todos) | ~13 K + ~0.9 M (fase 2) |
| Épocas hasta el mejor modelo | 40-50 | 10 + 8 |
| Tiempo de entrenamiento (GPU) | ~20 min | ~25-35 min* |
| Tamaño en disco | ~14 MB | ~28 MB |
| Coste de inferencia | Menor (entrada 32×32) | Mayor (entrada 160×160) |
* Cada época del transfer learning es más cara (imágenes 160×160), pero necesita muchas menos.
Conclusiones honestas: +8 puntos de exactitud es una mejora enorme (los errores bajan de ~17 % a ~9 %: casi la mitad); el precio es un modelo mayor y una inferencia más cara. Repite también la matriz de confusión de 07-01: verás que las parejas conflictivas (gato↔perro) siguen siendo las peores, pero con la mitad de confusiones — con el umbral de 0.80 de 03-04, la cobertura automática típica sube del ~70 % al ~85 %.
Fase 6: cuándo compensa el transfer learning (la tabla 2×2, revisada)
Retomamos la tabla 2×2 de 05-03 y situamos este proyecto en ella:
| Datos parecidos a ImageNet | Datos muy distintos | |
|---|---|---|
| Pocos datos | Extracción de características (solo cabeza) | Fine-tuning profundo con cuidado, o buscar otra base |
| Muchos datos | Fine-tuning parcial ← nuestro caso | Considerar entrenar desde cero |
CIFAR-10 cae en «muchos datos (45 K), parecidos a ImageNet (objetos naturales)»: la casilla del fine-tuning parcial, y los resultados lo confirman. La CNN desde cero de 07-01 solo habría sido competitiva en la casilla inferior derecha — por ejemplo, imágenes médicas o espectrogramas con millones de ejemplos. Para las fotos de producto reales de TecnoMarket (objetos cotidianos, decenas de miles de fotos), la receta de hoy es la correcta casi con seguridad.
Fase 7: empaquetado final y decisión de negocio
Decisión: TecnoMarket despliega el modelo de transfer learning. La mejora de exactitud reduce a la mitad la carga de la cola de revisión (03-04), lo que compensa con creces el mayor coste de inferencia. La CNN de 07-01 queda documentada como baseline en el repositorio (git, 06-04) — todo modelo en producción necesita un baseline contra el que justificarse.
Empaquetado según 06-05, con el preprocesado dentro del modelo:
entrada = tf.keras.layers.Input(shape=(32, 32, 3), dtype=tf.uint8) # imagen cruda
x = tf.cast(entrada, tf.float32)
x = tf.keras.layers.Resizing(TAM, TAM)(x)
x = tf.keras.applications.mobilenet_v2.preprocess_input(x)
prob = modelo(x, training=False)
modelo_servicio = tf.keras.Model(entrada, prob)
modelo_servicio.save("models/clasificador_categorias_v2.keras")Redimensionado y preprocess_input viajan dentro del .keras: la API de FastAPI de 06-05 recibe la imagen cruda y no puede equivocarse de preprocesado. Antes de sustituir a v1, el protocolo de 06-05: validar v2 sobre el conjunto congelado, comparar contra v1 con las mismas imágenes, desplegar con posibilidad de vuelta atrás y recalibrar el umbral de confianza sobre validación.
Cierre del módulo: el portfolio de TecnoMarket
Con este quinto proyecto, el equipo de TecnoMarket (es decir, tú) entrega su portfolio completo:
| Proyecto | Problema de negocio | Técnica principal | Estado |
|---|---|---|---|
| 07-01 | Alta automática de artículos | CNN propia + umbral y cola de revisión | Baseline documentado |
| 07-02 | Borradores de descripciones | LSTM carácter a carácter + temperatura | Prototipo con revisión humana |
| 07-03 | Detección de fraude | Autoencoder + error de reconstrucción | En producción con recalibrado periódico |
| 07-04 | Creatividades generativas | DCGAN con bucle GradientTape | Prototipo educativo; producción requiere difusión |
| 07-05 | Alta automática, v2 | Transfer learning MobileNetV2 | Desplegado, sustituye a 07-01 |
Cinco proyectos, cuatro modalidades (imágenes, texto, datos tabulares, generación) y un método común: fases claras, particiones honestas, métricas adecuadas al problema, humanos en el circuito y entrega empaquetada.
Errores Comunes y Consejos
- Usar
/255en lugar delpreprocess_inputde la familia del modelo: el error silencioso más común del transfer learning; cuesta varios puntos de exactitud sin lanzar ninguna excepción. - Olvidar recompilar tras cambiar
trainable: Keras fija qué variables se entrenan al compilar; sin recompilar, tu «fine-tuning» sigue entrenando solo la cabeza. - Fine-tuning con el mismo lr de la fase 1: destruye los pesos preentrenados en pocas iteraciones y la exactitud se desploma. Baja el lr dos órdenes de magnitud.
- Descongelar toda la base con pocos datos: más parámetros libres de los que tus datos pueden gobernar; sobreajuste casi garantizado. Descongela por bloques, del final hacia atrás.
- Comparar modelos con particiones distintas: la comparación de la fase 5 solo vale porque el test congelado y la partición train/val son idénticos a los de 07-01. Cambiar los datos entre comparaciones invalida la tabla.
Ejercicios
- Repite el proyecto entrenando solo la fase de extracción (sin fine-tuning) y compara la tabla de la fase 5 con tres columnas: CNN propia, extracción sola, extracción + fine-tuning. ¿Cuánto aporta cada escalón?
- Prueba
TAM = 96en lugar de 160 y mide exactitud y tiempo por época. ¿Dónde queda en la comparación coste/beneficio? - Descongela solo las últimas 20 capas (en vez de ~54) y, por separado, la base entera. Compara la exactitud final y el comportamiento de las curvas en los tres escenarios de descongelación.
Soluciones
- Basta saltarse la fase 2. Tabla típica: CNN propia ~83 %, extracción ~87 %, extracción+fine-tuning ~91 %. Lectura: el grueso del salto lo da el preentrenamiento (características de ImageNet); el fine-tuning añade el refinamiento final. Si el presupuesto de cómputo es mínimo, la extracción sola ya bate al modelo propio.
- Con 96×96 el tiempo por época cae aproximadamente a la mitad y la exactitud típica baja 1-2 puntos (~89-90 %): menos resolución, menos detalle para las capas profundas. Es un punto intermedio razonable para iterar rápido y entrenar la versión final a 160.
- Con 20 capas el resultado se queda ~1 punto por debajo del escenario base (menos capacidad de adaptación); con la base entera y lr=1e-5 puede igualar o mejorar décimas, pero las curvas son más frágiles (más riesgo de sobreajuste y de caída inicial) y el entrenamiento es más lento. El tercio final es el compromiso robusto: suficiente adaptación sin poner en riesgo las capas universales.
Conclusión
Proyecto final entregado y promesa cumplida: el clasificador v2 con MobileNetV2 bate a la CNN propia de 07-01 por unos 8 puntos, con una comparación honesta de costes y una decisión de despliegue justificada. Más importante que la cifra es el criterio que te llevas: la tabla 2×2 para decidir cuándo transferir, las dos fases con sus dos learning rates, y la disciplina de comparar siempre contra un baseline sobre el mismo test congelado. Con esto se cierra el módulo 7: cinco proyectos de principio a fin en el portfolio de TecnoMarket, integrando todo lo aprendido desde la primera red densa de 02-05 hasta el despliegue de 06-05. Pero un profesional no termina cuando el modelo funciona: lo que hemos construido — modelos que clasifican productos, generan textos e imágenes y señalan clientes como sospechosos — tiene consecuencias sobre personas reales. El módulo 8 aborda exactamente eso: la ética, el impacto y el futuro del Deep Learning que todo practicante debe dominar.
Curso de Deep Learning
Módulo 1: Introducción a Deep Learning
- ¿Qué es Deep Learning?
- Historia y evolución del Deep Learning
- Aplicaciones de Deep Learning
- Conceptos básicos de redes neuronales
- Preparación del entorno de trabajo
Módulo 2: Fundamentos de Redes Neuronales
- Perceptrón y Perceptrón Multicapa
- Función de activación
- Propagación hacia adelante y hacia atrás
- Optimización y función de pérdida
- Tu primera red neuronal completa
Módulo 3: Redes Neuronales Convolucionales (CNN)
- Introducción a las CNN
- Capas convolucionales y de pooling
- Arquitecturas populares de CNN
- Aplicaciones de CNN en reconocimiento de imágenes
Módulo 4: Redes Neuronales Recurrentes (RNN)
- Introducción a las RNN
- LSTM y GRU
- Aplicaciones de RNN en procesamiento del lenguaje natural
- Secuencias y series temporales
Módulo 5: Técnicas Avanzadas en Deep Learning
- Redes Generativas Adversariales (GAN)
- Autoencoders
- Transfer Learning
- Regularización y técnicas de mejora
- Mecanismos de atención y Transformers
Módulo 6: Herramientas y Frameworks
- Introducción a TensorFlow
- Introducción a PyTorch
- Comparación de frameworks
- Entornos de desarrollo y recursos adicionales
- Guardar, cargar y desplegar modelos
Módulo 7: Proyectos Prácticos
- Clasificación de imágenes con CNN
- Generación de texto con RNN
- Detección de anomalías con Autoencoders
- Creación de una GAN para generación de imágenes
- Fine-tuning de un modelo preentrenado
