
Proyecto Fei-Fei — Sesión 2: la primera CNN de Fashion-MNIST
En la Sesión 1 cargamos las 70.000 imágenes de ropa sin ninguna carpeta que organizar. Hoy construimos y entrenamos nuestra primera red neuronal convolucional para clasificarlas — con una diferencia importante respecto a Proyecto Asadi: allí solo había dos categorías (benigno/maligno), aquí hay diez.
Un pequeño ajuste antes de empezar: el canal de color
Las capas Conv2D de Keras esperan que cada imagen tenga tres dimensiones: alto, ancho y canal de color — en una imagen a todo color serían 3 canales (rojo, verde, azul), pero en escala de grises es solo 1. Nuestras imágenes vienen con forma (28, 28), sin ese tercer número, así que hay que añadirlo:
import numpy as np
x_entrenamiento_cnn = x_entrenamiento[..., np.newaxis]
x_prueba_cnn = x_prueba[..., np.newaxis]
print(x_entrenamiento_cnn.shape) # (60000, 28, 28, 1)

[..., np.newaxis] añade esa dimensión extra de tamaño 1 al final, sin tocar ni un solo número de las imágenes.
Construyendo la red
from tensorflow import keras
modelo = keras.Sequential([
keras.layers.Input(shape=(28, 28, 1)),
keras.layers.Rescaling(1./255),
keras.layers.Conv2D(32, 3, activation="relu"),
keras.layers.MaxPooling2D(),
keras.layers.Conv2D(64, 3, activation="relu"),
keras.layers.MaxPooling2D(),
keras.layers.Flatten(),
keras.layers.Dense(128, activation="relu"),
keras.layers.Dropout(0.5),
keras.layers.Dense(10, activation="softmax"),
])
modelo.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
modelo.summary()

Dos capas convolucionales (32 y 64 filtros) con su agrupación, igual que en Asadi. Dos cosas nuevas:
Dropout(0.5): durante el entrenamiento, esta capa “apaga” aleatoriamente la mitad de las neuronas de la capa anterior en cada pasada. Suena contraproducente, pero no lo es: obliga a la red a no depender demasiado de ninguna neurona concreta, así que aprende patrones más generales en vez de memorizar el conjunto de entrenamiento al detalle. Es una de las formas más simples y más usadas de evitar que una red “se aprenda de memoria” los datos en vez de aprender de verdad.Dense(10, activation="softmax"): en Asadi, con solo 2 categorías, la última capa daba un único número entre 0 y 1 (sigmoid). Aquí hay 10 categorías, así que necesitamos 10 números — uno por categoría — que además sumen entre todos 1, como un reparto de probabilidad. Eso es justo lo que hacesoftmax.
Ese cambio de sigmoid a softmax obliga también a cambiar la función de pérdida: en vez de binary_crossentropy usamos sparse_categorical_crossentropy. El porqué del “sparse”: nuestras etiquetas siguen siendo números sueltos (0 para camiseta, 1 para pantalón…), no hace falta convertirlas a ningún formato especial — si tuviéramos que convertirlas antes a vectores de diez posiciones, usaríamos la versión sin “sparse”.
Entrenando
historial = modelo.fit(
x_entrenamiento_cnn, y_entrenamiento,
validation_data=(x_prueba_cnn, y_prueba),
epochs=8,
)
Fijaos que aquí no usamos image_dataset_from_directory como en Asadi — al venir los datos ya como arrays de NumPy, se los pasamos directamente a fit() junto con sus etiquetas.
Al ser imágenes mucho más pequeñas que las de Asadi (28×28 frente a 224×224) y no haber que leerlas una a una desde el disco, el entrenamiento es bastante más rápido: en nuestra prueba, 8 épocas completas tardaron poco más de 2 minutos en un ordenador normal, con una exactitud final en el conjunto de examen en torno al 90%. En el vuestro puede variar un poco por las inicializaciones aleatorias, pero debería estar en ese entorno.

Próximo paso
90% de exactitud está bien, pero un 10% de error reparte sus fallos de forma muy desigual entre las diez categorías — hay prendas que hasta a una persona le costaría distinguir en 28×28 píxeles (¿un jersey o un abrigo? ¿una camisa o una camiseta?). En la próxima sesión sacamos la matriz de confusión — ya sabéis hacerla desde Javierre y Asadi — para ver exactamente qué prendas confunde más el modelo.
Etiqueta:AIDARAC, clasificacion multiclase, cnn, dropout, fashion mnist, keras, montesteam, proyecto fei-fei, softmax



