Por qué las computadoras ven mejor con las CNN: una guía intuitiva para el reconocimiento de imágenes
En las partes anteriores de esta serie, Lina vio cómo una sola neurona puede predecir si un cliente comprará un libro y cómo la retropropagación permite que una red aprenda de sus errores. Esos ejemplos eran simples. Solo un puñado de números — tiempo en la página, artículos en el carrito.
¿Qué sucede cuando Lina quiere que una computadora vea una imagen? Una imagen no es un puñado de números. Es una cuadrícula de miles, o millones, de píxeles. Al introducir esto en las redes neuronales planas que hemos analizado hasta ahora, nos topamos con un problema real.
El problema de la ‘linterna’: por qué las redes estándar fallan en visión
Imagina a Lina construyendo un sistema para BookSight que verifique automáticamente la foto de la publicación de un vendedor: confirmando que muestra el libro físico real, no una imagen de stock, y señalando daños como manchas de agua en la portada.
La red que construimos en la Parte 1 le dio a cada entrada su propio peso—weight_time para el tiempo en la página, weight_cart para los artículos en el carrito. Apila capas como esa y obtendrás una red Densa (o Completamente Conectada), donde cada entrada se conecta a cada neurona. Si lo escalas a una imagen, trata cada píxel como su propia entrada independiente, tal como trató el tiempo en la página y los artículos en el carrito. Excepto que ahora hay miles, no dos. La red no tiene idea de que el píxel #10 está justo al lado del píxel #11.
Para una red estándar, la portada de un libro desplazada dos píxeles a la izquierda es un conjunto de entradas completamente diferente. No tiene contexto espacial. No puede ver que los píxeles vecinos forman figuras.
Luego está la Explosión de Parámetros. Una pequeña foto a color de 100x100 píxeles son 30,000 entradas (100 de ancho × 100 de alto × 3 canales de color). Dale a tu primera capa oculta solo 512 neuronas y una red Densa necesitará más de 15 millones de conexiones solo para ese primer paso.
Una Red Neuronal Convolucional (CNN) evita esto cambiando las capas Densas por una capa Conv2D (abreviatura de “capa convolucional 2D”). En lugar de asignarle a cada píxel su propio peso, una capa Conv2D desliza un pequeño conjunto de pesos compartido a través de toda la imagen. Entraremos en la mecánica de ese deslizamiento en la siguiente sección—por ahora, “Conv2D” es simplemente el tipo de capa que hace posible esta eficiencia.
Entonces, ¿cómo se compara una CNN en cuanto a la cantidad de parámetros?
# Comparing a Dense layer to a Convolutional layer
# Imagine a 100x100 RGB image (30,000 values)
dense_params = (100 * 100 * 3) * 512 + 512
print(f"Dense Layer Parameters: {dense_params:,}")
# Output: 15,360,512
# A Conv2D layer with 32 filters of size 3x3
conv_params = (3 * 3 * 3) * 32 + 32
print(f"Conv2D Layer Parameters: {896:,}")
# Output: 896
dense_params = (100 * 100 * 3) * 512 + 512— Cada uno de los 30,000 valores de entrada tiene su propio peso conectado a cada una de las 512 neuronas, más 512 términos de sesgo. El resultado: más de 15 millones de parámetros para una sola capa.conv_params = (3 * 3 * 3) * 32 + 32— 32 filtros, cada uno de 3×3 a lo largo de 3 canales de color, más 32 sesgos. Los mismos filtros se reutilizan en toda la imagen, por lo que el total es de apenas 896, aproximadamente 17,000× menos que en la capa Dense.print(f"Conv2D Layer Parameters: {896:,}")— La cadena de formato fija el valor 896 en lugar de usar la variableconv_params, pero el valor impreso coincide de ambas formas.
Qué significa esto: La capa Dense tiene más de 15 millones de parámetros. La capa Conv2D tiene menos de 1,000. Esto es aproximadamente 17,000× más eficiente, lo cual se logra reutilizando los mismos filtros pequeños en toda la imagen en lugar de aprender un peso único para cada píxel.
Conteo de parámetros en una capa densa
Cada píxel de entrada (altura × ancho × canales ) tiene su propio peso para cada una de las neuronas, más términos de sesgo.
Conteo de parámetros en una capa Conv2D
Cada filtro es píxeles a través de canales, y hay filtros. Cada filtro es pequeño (por ej., 3×3×3 = 27 pesos) y se reutiliza en toda la imagen.
Operación de convolución
En cada posición , el filtro se multiplica elemento por elemento con el parche superpuesto y los resultados se suman — una puntuación de similitud local.
| Lenguaje sencillo | Símbolo estadístico | Equivalente en Python |
|---|---|---|
| Altura de la imagen de entrada | 100 | |
| Ancho de la imagen de entrada | 100 | |
| Número de canales de color | / | 3 |
| Número de neuronas (Dense) | 512 | |
| Número de filtros (Conv2D) | 32 | |
| Altura del filtro | 3 | |
| Ancho del filtro | 3 | |
| Cantidad de parámetros de Dense | dense_params | |
| Cantidad de parámetros de Conv2D | conv_params |
Capas densas vs. capas Conv2D: ¿cuándo gana la convolución?
| Enfoque | Qué hace | Ideal para | Compromiso |
|---|---|---|---|
| Densa (Totalmente Conectada) | Cada entrada se conecta a cada neurona | Datos tabulares (tiempo en la página, artículos en el carrito), decisiones finales de clasificación | Explosión de parámetros en imágenes — 15M+ pesos para una foto de 100×100. Sin conocimiento espacial. |
| Conv2D | Pequeños filtros compartidos se deslizan por la imagen | Datos de imagen, entradas en forma de cuadrícula, cualquier cosa con estructura espacial | Asume que los patrones pueden aparecer en cualquier lugar (invariancia de traslación) — no es ideal si la posición absoluta importa. Menos flexibilidad por píxel. |
Regla general: Usa Conv2D cuando tus datos tengan estructura espacial o de cuadrícula (imágenes, mapas de calor, espectrogramas). Usa Densa cuando tus características sean atributos independientes (precio, recuento de clics, tiempo en la página) o al final de una red para producir una predicción final.
La ventana deslizante: pensar en patrones, no en píxeles
Entonces, ¿cómo logra una CNN ser tan eficiente? Utiliza un Filtro (también llamado ‘Kernel’). Piensa en un filtro como una pequeña lupa de 3x3 que se desliza sobre la imagen.
En lugar de escanear toda la imagen de una vez, el filtro busca un patrón específico —digamos, un borde vertical— en cada posición. Esa es la operación de Convolución. Es esencialmente una puntuación de similitud. Cuando un parche de 3x3 de la imagen coincide con el filtro de 3x3, la salida es alta. Una falta de coincidencia produce un número bajo.
Construyamos un detector de bordes verticales manual con NumPy para ver esto en acción.
import numpy as np
# A simple 6x6 'image' with a vertical line in the middle
# 0 is dark, 10 is bright
image = np.array([
[0, 0, 10, 10, 0, 0],
[0, 0, 10, 10, 0, 0],
[0, 0, 10, 10, 0, 0],
[0, 0, 10, 10, 0, 0],
[0, 0, 10, 10, 0, 0],
[0, 0, 10, 10, 0, 0]
])
# A 3x3 Vertical Edge Filter (Sobel-style)
# It looks for a change from dark to bright
filter_vertical = np.array([
[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]
])
# Let's apply it to one 3x3 patch (the top left)
patch = image[0:3, 0:3]
# Multiply the patch by the filter and sum it up
score = np.sum(patch * filter_vertical)
print(f"Similarity score for top-left patch: {score}")
# Output: 30.0 (It found a hint of an edge!)
image = np.array([...])— Una cuadrícula de 6×6 que simula una imagen diminuta. Los valores 0 (oscuro) y 10 (brillante) crean una franja brillante vertical en el medio, imitando un borde que podrías encontrar en la portada de un libro.filter_vertical = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])— Un detector de bordes verticales estilo Sobel de 3×3. La columna de la izquierda se multiplica por −1, la de la derecha por +1, por lo que una transición de oscuro a brillante de izquierda a derecha produce una puntuación alta y positiva.patch = image[0:3, 0:3]— Extrae la región superior izquierda de 3×3. Este parche contiene la mitad izquierda de la franja brillante: valores[[0, 0, 10], [0, 0, 10], [0, 0, 10]].score = np.sum(patch * filter_vertical)— Multiplica elemento por elemento el parche por el filtro y lo suma. La columna de −1 encuentra ceros, la columna de +1 encuentra dieces, dando como resultado 0 + 0 + 30 = 30 — una fuerte señal de borde.
Intuición antes del formalismo: Si el filtro tiene forma de ‘L’, ‘grita’ (devuelve un número alto) cuando se desliza sobre una ‘L’ en la foto. ‘Susurra’ (devuelve un número bajo) sobre un círculo. La red encuentra patrones sin importar dónde se encuentren en el encuadre.
La parte más difícil: entendiendo los ‘mapas de características’
Una vez que deslizamos el filtro por toda la imagen, terminamos con una nueva cuadrícula de números. Eso es un Mapa de Características.
Aquí viene la parte complicada. La salida de una capa CNN ya no es realmente una imagen — es un mapa de calor que muestra dónde aparecieron ciertas características. Usa 32 filtros y obtienes 32 mapas de características. Uno podría resaltar líneas verticales. Otro detecta círculos, otro texturas.
En la terminología de las CNN, el número de filtros que usas es la Profundidad. No profundidad como una caja 3D — más bien como tener 32 versiones diferentes de la imagen, cada una resaltando un patrón diferente.
Submuestreo: por qué reducimos la imagen con pooling
Las imágenes están llenas de detalles que no importan. ¿Una mancha de agua en (50, 50) o (51, 51)? En realidad no importa.
Por eso usamos Max Pooling. Deslizamos una pequeña ventana—generalmente de 2x2—a lo largo del mapa de características y conservamos solo el valor más grande en esa ventana.
# A 4x4 feature map
feature_map = np.array([
[1, 5, 2, 3],
[4, 0, 1, 2],
[1, 2, 8, 4],
[0, 1, 3, 2]
])
# Max Pooling (2x2 window, stride of 2)
# We look at the top-left 2x2 square: [1, 5, 4, 0]. Max is 5.
top_left_max = np.max(feature_map[0:2, 0:2])
print(f"Summarized 2x2 area: {top_left_max}") # Output: 5
feature_map = np.array([...])— Una cuadrícula de 4×4 de números que representa un pequeño mapa de características — el tipo de resultado que obtendrías después de deslizar un filtro sobre una imagen de portada de un libro.feature_map[0:2, 0:2]— Extrae el bloque superior izquierdo de 2×2: valores[[1, 5], [4, 0]]. El max pooling conserva solo el valor más grande de este bloque.np.max(...)— Devuelve 5, el máximo de los cuatro valores. Los otros tres números (1, 4, 0) se descartan. Así es como el pooling reduce el mapa de características mientras retiene las señales más fuertes.
Lo que esto significa en realidad: El pooling dice: “Encontré la característica en algún lugar de esta área general, y eso es suficiente”. La red se vuelve invariante a la traslación—los pequeños desplazamientos no importan. También reduce los datos, por lo que la siguiente capa obtiene una vista más limpia de la imagen general.
Poniéndolo todo junto: la jerarquía de la visión
Apila estas capas y obtendrás lo que se conoce como la Jerarquía de Visión:
- Capas iniciales: Usan filtros pequeños para encontrar cosas simples como líneas y bordes.
- Capas intermedias: Combinan esas líneas para encontrar formas como círculos o cuadrados.
- Capas finales: Combinan esas formas para encontrar objetos complejos como ‘esquinas’, ‘portadas’ o ‘daños por agua’.
Una capa Flatten luego convierte estos mapas 2D de nuevo en una larga lista de números para que una neurona estándar (de la Parte 1) pueda hacer la conjetura final: “Este es un listado de libro genuino.”
from tensorflow.keras import layers, models
model = models.Sequential([
# 32 filters, each 3x3 pixels
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)),
layers.MaxPooling2D((2, 2)),
layers.Flatten(),
layers.Dense(1, activation='sigmoid')
])
model.summary()
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3))— La primera capa: 32 filtros de tamaño 3×3, cada uno escaneando la imagen de entrada de 100×100×3.activation='relu'pone a cero las puntuaciones de similitud negativas, conservando solo las coincidencias positivas.layers.MaxPooling2D((2, 2))— Reduce cada mapa de características tomando el valor máximo en cada ventana de 2×2. Las dimensiones espaciales se reducen a la mitad, pero las señales más fuertes sobreviven.layers.Flatten()— Convierte los mapas de características 2D en un vector plano 1D para que la capa Dense pueda leerlo.layers.Dense(1, activation='sigmoid')— Una sola neurona de salida con activación sigmoide, que produce una probabilidad entre 0 y 1 — la predicción final de Lina de “¿es este un listado de libro genuino?”.
Revisemos los datos: Ejecuta model.summary() y verás cambiar el ‘Output Shape’. Comienza como una cuadrícula de 100x100 y se hace más pequeña y ‘más profunda’ a medida que pasa por las capas.
Resumen de lo que hemos aprendido:
- Las redes estándar son ciegas a la ubicación y explotan en tamaño con las imágenes.
- La convolución usa filtros deslizantes para encontrar patrones de manera eficiente.
- Los mapas de características son mapas de calor de dónde se encuentran los patrones.
- El Pooling resume los datos e ignora movimientos diminutos y sin importancia.
Las CNN manejan bien los datos de imágenes en forma de cuadrícula, pero el problema real de Lina no son las imágenes, sino las secuencias. La sesión de navegación de un lector se desarrolla página por página, y lo que vieron antes importa tanto como lo que están viendo ahora. En la Parte 5, veremos por qué las redes estándar tienen dificultades para recordar lo que ocurrió antes en una secuencia.
Comprueba tu comprensión
Las preguntas a continuación van desde el recuerdo simple hasta el diseño de preguntas abiertas, siguiendo aproximadamente la Taxonomía de Bloom.
Recordar ¿Qué es un “Filtro” (también llamado “Kernel”) en una CNN y sobre qué se desliza?
Comprender Con tus propias palabras, explica por qué una capa Conv2D tiene muchos menos parámetros que una capa Dense, utilizando la idea de los “pesos compartidos”.
Aplicar
Usando la fórmula de parámetros de Conv2D del artículo ((kernel_height * kernel_width * channels) * num_filters + num_filters), calcula la cantidad de parámetros para una capa Conv2D con 16 filtros de tamaño 5x5 en una imagen de 3 canales.
Analizar El filtro detector de bordes del artículo produjo una puntuación de similitud de 30.0 para un parche con una fuerte transición de oscuro a brillante. Explica paso a paso por qué el mismo filtro produciría una puntuación exactamente de 0 si se aplicara a un parche que es uniformemente brillante (todos 10s) en lugar de ser mitad oscuro, mitad brillante.
Evaluar El Max Pooling conserva solo el valor más grande en cada ventana y descarta el resto. Critica esto: describe un escenario realista en la clasificación de fotos de productos donde descartar todo excepto el valor máximo podría provocar la pérdida de información que la red realmente necesitaba.
Crear Diseña un filtro 3x3 (con números específicos, como el filtro de bordes verticales del artículo) que detecte un borde horizontal en su lugar. Explica por qué los números de tu filtro funcionan.
Artículos relacionados
- Por qué mueren las redes profundas: Resolviendo el problema del gradiente desvanecido
- Por qué las RNN olvidan: La intuición detrás del gradiente desvanecido
Referencias y lecturas adicionales
- LeCun, Y., Bottou, L., Bengio, Y., & Haffner, P. (1998). “Gradient-Based Learning Applied to Document Recognition.” Proceedings of the IEEE, 86(11), 2278–2324. — El artículo fundacional que introdujo LeNet-5, la primera red neuronal convolucional exitosa para el reconocimiento de dígitos manuscritos, y el esquema base para las arquitecturas modernas de CNN.
Esta traducción fue generada automáticamente y puede contener errores. Si el idioma inglés es tu preferencia, puedes leer el artículo original en inglés .
«Aplica lo que aprendiste» es para suscriptores Supporter e Insider.
Suscríbete para desbloquear los ejercicios de este artículo.
Ver planesArtículos relacionados
- Aprendizaje Profundo En revisión
Retropropagación intuitiva: cómo las redes aprenden de sus errores
Aprende cómo funciona la retropropagación de forma intuitiva, sin necesidad de cálculo. Descubre cómo las redes neuronales asignan la culpa a los pesos mediante la regla de la cadena y aprenden de sus errores.
- Aprendizaje Profundo En revisión
¿Por qué mi modelo no aprende? Guía amigable para diagnosticar callejones sin salida en el deep learning
Aprende una lista de verificación práctica de 4 pasos para diagnosticar modelos de deep learning estancados: sobreajustar un lote, revisar los gradientes, escalar los datos y hacer un barrido de las tasas de aprendizaje.
- Aprendizaje Profundo En revisión
LSTMs y GRUs: Dándole memoria a las redes
Aprende cómo las LSTMs y GRUs usan memoria con compuertas para superar el gradiente desvaneciente, reteniendo señales tempranas a lo largo de secuencias largas para lograr mejores predicciones de secuencias.
- Aprendizaje Profundo En revisión
Referencia: Optimizadores
Una referencia que cubre los optimizadores de redes neuronales desde GD hasta AdamW, con programación de la tasa de aprendizaje, árboles de decisión y guía práctica para cada arquitectura.
¿Buscas otra cosa?
Busca en todos los artículos por título, resumen o tema.