PDI+VC · Ejercicio de Programación

EP09_02 — 🟢 Pooling Manual (Máximo y Media)

9.10.2 EP09_02 🟢 Pooling Manual (Máximo y Media)

Entre bloques convolucionales, la arquitectura típica de una CNN intercala capas de pooling, que reducen la resolución espacial del mapa de características sin introducir nuevos parámetros entrenables — a diferencia de la convolución, el pooling no tiene pesos: solo resume cada ventana de la entrada a un único valor, mediante un máximo o una media, exactamente como se formalizó en la Sección “Pooling”.

Se le ha encargado implementar esta operación a partir de una ventana deslizante cuadrada, sin superposición parcial en los bordes (solo ventanas completas), soportando los dos tipos más comunes: max (preserva el valor más sobresaliente, típicamente usado para retener bordes y texturas fuertes) y avg (suaviza la región, preservando información de intensidad media).

9.10.2.1 📋 Directrices de Implementación

  1. Entrada: Leer las dimensiones \(H \times W\) del mapa de características de entrada y sus \(H \times W\) valores reales.
  2. Ventana: Leer los enteros \(k\) (tamaño de la ventana cuadrada \(k \times k\)) y \(s\) (stride).
  3. Tipo: Leer una string, max o avg, indicando el tipo de pooling.
  4. Sin relleno: Esta operación no utiliza padding; las ventanas que sobrepasarían el borde de la entrada se descartan.
  5. Cálculo: Para cada posición de salida \((i,j)\), calcular el máximo o la media de los \(k \times k\) valores de la ventana correspondiente, comenzando en \((i \cdot s,\, j \cdot s)\).
  6. Dimensiones de salida: \(O_h = \lfloor (H - k)/s \rfloor + 1\) y \(O_w = \lfloor (W - k)/s \rfloor + 1\).
  7. Salida: Imprimir \(O_h\) y \(O_w\) en la primera línea, seguidos de \(O_h\) líneas con \(O_w\) valores reales cada una, formateados con 4 decimales.

9.10.2.2 📌 Restricciones Computacionales

  • Ventana cuadrada: \(k \times k\), sin soporte para ventanas rectangulares en esta versión.
  • Sin padding: solo se consideran ventanas completamente contenidas en la entrada — las dimensiones que “sobran” simplemente se descartan.
  • avg usa división real: la media es siempre \(\text{suma}/k^2\), incluso cuando el resultado tiene muchos decimales — redondee solo en el formato final, conforme a la directriz general del capítulo.
  • Formato: todos los valores de salida con exactamente 4 decimales.

9.10.2.3 🧠 Fundamentación Teórica

Elemento Rol en la arquitectura
Pooling máximo Preserva la activación más fuerte de la ventana; común después de capas convolucionales para retener bordes y texturas sobresalientes
Pooling medio Suaviza la región, preservando la intensidad media; común en capas finales (global average pooling)
Ausencia de parámetros Diferencia el pooling de la convolución: reduce la resolución espacial sin costo adicional de entrenamiento
Reducción de resolución Contribuye a la invariancia a pequeñas traslaciones y a la reducción del costo computacional de las capas siguientes

9.10.2.4 🧩 Métodos de morph.py que pueden ayudar

El morph.py no implementa pooling con submuestreo directamente, pero dos familias de operaciones muestran la misma idea desde otra óptica, útil para verificar su intuición:

  • mm.dil(f, Bc) / mm.dil0(f, B) — dilatación morfológica: reemplaza cada píxel por el máximo de su vecindad definida por el elemento estructurante \(B\) (ej.: mm.sebox(n) para una ventana \((2n+1)\times(2n+1)\)). Es, conceptualmente, un “max-pooling sin submuestreo” (produce una imagen del mismo tamaño, en lugar de reducida).
  • mm.blur(f, N) — suavizado por media en una ventana \(N \times N\), análoga al avg-pooling, también sin reducción de resolución.
  • mm.readImg(h, w, dtype='float') — útil para leer el mapa de entrada en punto flotante.

9.10.2.5 📦 Especificación de Entrada y Salida (VPL)

Entrada:

  • Línea 1: Enteros \(H\) y \(W\).
  • Siguientes \(H\) líneas: \(W\) valores reales cada una.
  • Siguiente línea: Enteros \(k\) y \(s\).
  • Siguiente línea: max o avg.

Salida:

  • Línea 1: Enteros \(O_h\) y \(O_w\).
  • Siguientes \(O_h\) líneas: \(O_w\) valores reales cada una, con 4 decimales.

9.10.2.6 📌 Ejemplos

Entrada Salida Observación
4 4
1 3 2 4
5 6 1 2
2 1 0 3
4 2 5 1
2 2
max
2 2
6.0000 4.0000
4.0000 5.0000
Pooling máximo, ventana \(2\times2\), stride 2.
4 4
1 3 2 4
5 6 1 2
2 1 0 3
4 2 5 1
2 2
avg
2 2
3.7500 2.2500
2.2500 2.2500
Pooling medio sobre las mismas ventanas.
🎮 Simulador: Pooling Manual 🟢 senza padding, finestre complete

Ingresso 4×4 fisso — regola la dimensione della finestra (k), lo stride (s) e il tipo, esattamente i parametri che EP09_02 legge in ingresso, e osserva come cambiano la dimensione e i valori dell'uscita.

Finestra (k)
Stride (s)
Tipo
(0,0)
Ingresso X (4×4)
fuori dalla finestra finestra attuale scartato (avanzo)
Uscita Y (pooling)

💡 Ogni posizione dello slider rivela una cella della matrice di uscita. Le celle grigio-tratteggiate nell'ingresso sono "avanzi" che nessuna finestra raggiunge — nota come ciò accade quando (H−k) non è multiplo di s. Cambiare k, s o il tipo riavvia l'esplorazione.

Figura 9.44: Simulador EP09_02: Pooling Manual (máximo vs. média, con ventana k y stride s ajustables)
%%writefile EP09_02.py
# Código Python
Overwriting EP09_02.py
TestSuite("EP09_02.py").run()
✔️ EP09_02.cases ya existe en casos/
📋 4 caso(s) cargado(s) de casos/EP09_02.cases

🔍 Probando Python: EP09_02.py
⚠️ EP09_02.py: archivo vacío (menos de 3 líneas). Pruebas omitidas.