11

Convoluciones y visión

¿Cómo aprende una red a ver bordes, formas y objetos?

6 min

Convoluciones y visión

Con voz. Puedes pausar y saltar a cualquier paso.

Lección completa

Subtítulos

Una imagen de cien por cien píxeles tiene diez mil valores. Conectar cada uno a mil neuronas exige diez millones de pesos, solo en la primera capa.

Voz

Sin voz: la lección avanza sola con subtítulos.

La voz de esta lección está en preparación: por ahora avanza sola con subtítulos.

0:00 / 0:00

Qué lograrás

  • Explicar qué hace un kernel de convolución y calcular a mano un valor de salida de un kernel de tres por tres.
  • Entender por qué compartir pesos hace posible procesar imágenes con muy pocos parámetros.
  • Describir cómo las capas apiladas pasan de bordes a partes y a objetos, y qué limita a estas redes.

Ideas clave

  1. Conectar cada píxel con cada neurona no escala: una imagen pequeña ya exige millones de pesos.
  2. Un kernel es una cuadrícula pequeña de pesos que recorre la imagen; en cada posición multiplica, suma y produce un píxel de salida.
  3. El mismo kernel se reutiliza en toda la imagen (pesos compartidos): pocos parámetros y el mismo detector en cualquier posición.
  4. Los valores del kernel se aprenden con retropropagación; una capa tiene muchos kernels y cada uno produce un mapa de características.
  5. Apilar capas construye una jerarquía de bordes a partes y a objetos. Las redes entrenadas con ImageNet tienden a apoyarse en texturas, y las redes de visión pueden ser frágiles ante cambios sutiles.

Lo que mucha gente cree

Creencia común Una red de visión «ve» la imagen como una persona: reconoce objetos y entiende la escena.

Lo correcto Detecta patrones estadísticos en números de píxeles. Es muy buena con lo que vio en el entrenamiento, pero tiende a apoyarse en texturas y puede equivocarse con cambios que una persona ni nota.

Compruébalo

Cuatro preguntas. Sin nota ni cuenta: sirven para ver si la idea quedó.

Concepto¿Qué ventaja principal tiene compartir el mismo kernel en toda la imagen?
CálculoUna imagen de 28 × 28 se convoluciona con un kernel de 3 × 3, sin relleno y con zancada 1. ¿Qué tamaño tiene el mapa de salida?
Concepto¿Qué hace el pooling máximo de 2 × 2?
AplicaciónUn sistema de inspección de calidad funciona en el laboratorio, pero en la fábrica, con otra iluminación, falla mucho. ¿Cuál es la explicación más probable?

Por dentroPara quien quiere las fórmulas y el código. No hace falta para seguir el curso.

La operación

Dada una imagen II y un kernel KK de tamaño k×kk\times k, la salida (sin relleno) en la posición (i,j)(i,j) es

O[i,j]=b+∑u=0k−1∑v=0k−1K[u,v]  I[i+u, j+v].O[i,j] = b + \sum_{u=0}^{k-1}\sum_{v=0}^{k-1} K[u,v]\; I[i+u,\,j+v].

Técnicamente esto es una correlación cruzada; la convolución matemática voltea el kernel, pero en deep learning el kernel se aprende y la distinción no importa (Goodfellow et al., 2016, cap. 9). Con una imagen de n×nn\times n, sin relleno (p=0p=0) y zancada 1, la salida mide n−k+1n-k+1 por lado; con zancada (stride) ss y relleno pp (filas y columnas de ceros alrededor): ⌊(n+2p−k)/s⌋+1\lfloor (n+2p-k)/s \rfloor + 1 (Dumoulin y Visin, 2016). Ejemplo del quiz: 28×2828\times28 con k=3k=3 da 26×2626\times26; con p=1p=1 el tamaño se conserva en 28×2828\times28.

Parámetros: conectado frente a convolucional

Una capa totalmente conectada de 10410^4 entradas a 10310^3 neuronas tiene 10710^7 pesos (más sesgos). Una capa convolucional con CoutC_{out} kernels de k×kk\times k sobre CinC_{in} canales tiene

Cout (k2 Cin+1)C_{out}\,(k^2\,C_{in} + 1)

parámetros, independientes del tamaño de la imagen. Con Cin=1C_{in}=1, k=3k=3 y 16 kernels: 16⋅(9+1)=16016\cdot(9+1)=160.

La comparación del gancho (10 millones frente a 10) pone un solo kernel frente a mil neuronas, y un kernel produce un solo mapa. Con 1 000 kernels de 3×33\times3 sobre la misma imagen de 100×100100\times100 (sin relleno) hay 1 000⋅(9+1)=10 0001\,000\cdot(9+1)=10\,000 parámetros, mil veces menos que 10710^7; pero la salida son 1 000 mapas de 98×9898\times98 (9 604 000 valores) y 982⋅9⋅1 000≈8698^2\cdot 9\cdot 1\,000\approx 86 millones de multiplicaciones, más que las 10 millones de la capa densa. Compartir pesos ahorra parámetros (y datos para ajustarlos), no operaciones: no cambia el orden del tiempo de cómputo de la pasada hacia delante, solo la memoria de los parámetros (Goodfellow et al., 2016, §9.2).

De dónde viene la idea

El neocognitrón de Fukushima (1980) ya combinaba capas de detectores de rasgos locales con capas tolerantes a desplazamientos, pero se entrenaba con una regla autoorganizada, sin supervisión: no tenía un algoritmo supervisado de extremo a extremo como la retropropagación (LeCun, Bengio y Hinton, 2015; Goodfellow et al., 2016, §9.10). LeCun et al. (1989) entrenaron con retropropagación una red con pesos compartidos para reconocer dígitos de códigos postales manuscritos que les dio el Servicio Postal de EE. UU.: 9 298 dígitos ya segmentados (7 291 para entrenar, 2 007 para probar) en imágenes de 16×1616\times16. Sus 64 660 conexiones se controlaban con 9 760 parámetros independientes, y el error fue 0.14 % en entrenamiento (10 errores) y 5.0 % en prueba (102 errores); una red totalmente conectada con 40 neuronas ocultas, probada como comparación, llegó a 8.1 % en prueba. Esa red no usaba pooling, sino convoluciones que saltaban de dos en dos píxeles. LeNet-5 (LeCun et al., 1998) tiene 7 capas, entrada de 32×3232\times32, kernels de 5×55\times5, 340 908 conexiones y unos 60 000 parámetros libres; su «submuestreo» promedia cada bloque de 2×22\times2 (con un coeficiente y un sesgo entrenables) en lugar de tomar el máximo.

El kernel de la lección

Los kernels de bordes de la escena son los del operador de Sobel (documentación de OpenCV, «Sobel Derivatives»). El de bordes verticales es

Kx=(−101−202−101),Ky=Kx⊤.K_x=\begin{pmatrix}-1&0&1\\-2&0&2\\-1&0&1\end{pmatrix},\qquad K_y=K_x^\top.

Su magnitud (Kx∗I)2+(Ky∗I)2\sqrt{(K_x * I)^2 + (K_y * I)^2} estima la intensidad de los bordes (la misma fuente). Aquí los kernels se eligen a mano para ver la operación; en una red entrenada los aprende el entrenamiento, y en las primeras capas suelen parecerse a detectores de bordes orientados y de manchas de color (Krizhevsky et al., 2012, fig. 3; Yosinski et al., 2014).

Campo receptivo y jerarquía

Cada capa ve una zona mayor de la imagen original. Con rL=1r_L=1 en la última capa, el campo receptivo cumple rl−1=sl rl+(kl−sl)r_{l-1}=s_l\,r_l+(k_l-s_l) (Araujo, Norris y Sim, 2019): dos convoluciones de 3×33\times3 seguidas «ven» 5×55\times5; con un pooling de 2×22\times2 en medio (3×33\times3, pooling, 3×33\times3) ven 8×88\times8, y una unidad de la red de ejemplo de la escena, tras sus dos pooling, ve 10×1010\times10 píxeles. Por eso las primeras capas detectan patrones locales (bordes, colores) y las profundas, combinaciones amplias.

En una red de tipo AlexNet, Zeiler y Fergus (2014) visualizaron qué excita a cada capa: la 2 responde a esquinas y combinaciones de borde y color; la 3, a texturas y patrones más complejos; la 4, a partes propias de una clase (caras de perro); la 5, a objetos enteros con mucha variación de pose. LeCun, Bengio y Hinton (2015) lo resumen como bordes, motivos, partes y objetos, y subrayan que esas capas de rasgos no las diseñan ingenieros: se aprenden de los datos. Lo que sí diseña una persona es la arquitectura (cuántas capas, qué tamaño de kernel, dónde va el pooling).

Pooling y desplazamientos

El pooling máximo de 2×22\times2 con paso 2 reduce el mapa a la mitad por lado y vuelve la salida aproximadamente invariante a desplazamientos pequeños (Goodfellow et al., 2016, §9.3; LeCun, Bengio y Hinton, 2015). Es solo aproximado: en la escena, desplazar la imagen un píxel cambia un 56 % el mapa de bordes (suma de diferencias absolutas entre suma de valores absolutos) y tras el pooling un 19 %; con 400 imágenes de franjas al azar, el cambio medio baja de 0.97 a 0.50 y en 50 de las 400 el pooling no lo reduce (script verify-data.ts). Azulay y Weiss (2019) muestran que en redes completas desplazar o escalar un poco la imagen puede cambiar mucho la predicción. En la escena el pooling toma el máximo del valor absoluto; en una red real la activación (por ejemplo ReLU) va antes.

Los límites, con números

  • Texturas. Geirhos et al. (2019) mostraron a redes entrenadas con ImageNet imágenes con la forma de un objeto y la textura de otro. Al elegir, ResNet-50 respondió según la textura el 77.9 % de las veces (VGG-16, 82.8 %; GoogLeNet, 68.8 %; AlexNet, 57.1 %); las personas eligieron la forma en el 95.9 % de sus decisiones correctas. Con la misma arquitectura, entrenar con una versión «estilizada» de ImageNet cambió ese sesgo: depende de los datos y de la tarea, no solo de la convolución.
  • Cambios casi invisibles. Szegedy et al. (2014) hallaron perturbaciones apenas perceptibles que cambian la clase que predice la red. Goodfellow, Shlens y Szegedy (2015) pasaron la respuesta de GoogLeNet ante la foto de un panda de «panda» (57.7 % de confianza) a «gibón» (99.3 %) sumando una perturbación de magnitud 0.007, el bit más pequeño de una imagen de 8 bits.
  • Datos distintos de los de entrenamiento. Recht et al. (2019) rehicieron con el mismo procedimiento los conjuntos de prueba de ImageNet y la exactitud de los modelos bajó entre 11 % y 14 %. Beery et al. (2018): con cámaras trampa de fauna, buen rendimiento donde se entrenó y mala generalización a lugares nuevos. Hendrycks y Dietterich (2019): ImageNet-C aplica 75 alteraciones (15 tipos en 5 intensidades, entre ellas brillo, contraste, niebla y ruido), y la robustez relativa casi no mejoró de AlexNet a ResNet.
  • Escenas. Goodfellow et al. (2016, §9.10) señalan que el sistema visual humano hace mucho más que reconocer objetos (entiende escenas completas, relaciones entre objetos y geometría 3D) y que las aplicaciones de las redes convolucionales a esos problemas estaban entonces en su infancia.

Reutilizar un modelo ya entrenado

Yosinski et al. (2014) midieron qué se puede reutilizar: los rasgos de la primera capa (como los de Gabor y las manchas de color) no dependen de la tarea ni de los datos, y los de las últimas capas sí. He, Girshick y Dollár (2018, informe técnico) compararon, en detección de objetos con COCO, partir de un modelo preentrenado en ImageNet frente a entrenar desde cero: el preentrenamiento acelera la convergencia, pero con suficientes iteraciones entrenar desde cero igualó la exactitud, incluso con el 10 % de los datos; solo con muy pocos datos (menos de unas 10 000 imágenes de COCO) el preentrenamiento mejoró claramente el resultado.

En código

import numpy as np

def conv2d(img, K, b=0.0):
    k = K.shape[0]
    h, w = img.shape[0] - k + 1, img.shape[1] - k + 1
    out = np.zeros((h, w))
    for i in range(h):
        for j in range(w):
            out[i, j] = b + np.sum(K * img[i:i + k, j:j + k])
    return out

Kx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
img = np.zeros((6, 6)); img[:, 3:] = 1          # mitad oscura, mitad clara: un borde vertical
print(conv2d(img, Kx))                           # valores 4 en las columnas del borde, 0 en el resto

Lo que viene

La retropropagación de la lección 8 entrena los kernels igual que cualquier peso. Las redes convolucionales pasaron a dominar la visión a partir de 2012 (lección 13); LeCun, Bengio y Hinton (2015) las describen como el enfoque dominante para casi todas las tareas de reconocimiento y detección. Para datos en secuencia, como el lenguaje, hace falta otra idea (lección 12).

Lente de decisión

Qué significa esta idea si tu trabajo es decidir, no programar.

  • Un sistema de visión rinde bien con imágenes parecidas a las del entrenamiento: pide que lo prueben con tus cámaras, tu iluminación y tus casos reales.
  • Si el proveedor habla de «exactitud del 99 %», pregunta en qué conjunto de imágenes y con qué variedad: el rendimiento cae cuando cambian las condiciones.
  • Estas redes pueden fallar de formas que una persona no entiende (cambios mínimos, fondos, texturas). Para decisiones críticas, diseña revisión humana y casos de prueba adversarios.
  • Partir de un modelo de visión ya entrenado suele acelerar el entrenamiento y ayuda sobre todo cuando tienes pocos datos propios; con muchos datos, entrenar desde cero puede igualarlo. Pregunta si usan uno preentrenado y cómo lo ajustaron.

Términos de la lección

Transcripción completa
ComentariosConversación pública de esta lección: dudas, datos por revisar, ideas.

Los comentarios viven en GitHub Discussions, en el repositorio público del curso; para escribir se necesita una cuenta de GitHub. Se cargan desde giscus.app al abrir esta sección. Las personas que revisan el curso los leen, y si un cambio se acepta, se aplica en los dos idiomas. Abrir el hilo en GitHub

Fuentes