PDI+VC · Exercício de Programação

EP09_02 — 🟢 Pooling Manual (Máximo e Média)

9.10.2 EP09_02 🟢 Pooling Manual (Máximo e Média)

Entre blocos convolucionais, a arquitetura típica de uma CNN intercala camadas de pooling, que reduzem a resolução espacial do mapa de características sem introduzir novos parâmetros treináveis — ao contrário da convolução, o pooling não tem pesos: ele apenas resume cada janela da entrada a um único valor, por um máximo ou por uma média, exatamente como formalizado na Seção “Pooling”.

Você foi encarregado de implementar essa operação a partir de uma janela deslizante quadrada, sem sobreposição parcial nas bordas (apenas janelas completas), suportando os dois tipos mais comuns: max (preserva o valor mais saliente, tipicamente usado para reter bordas e texturas fortes) e avg (suaviza a região, preservando informação de intensidade média).

9.10.2.1 📋 Diretrizes de Implementação

  1. Entrada: Ler as dimensões \(H \times W\) do mapa de características de entrada e seus \(H \times W\) valores reais.
  2. Janela: Ler os inteiros \(k\) (tamanho da janela quadrada \(k \times k\)) e \(s\) (stride).
  3. Tipo: Ler uma string, max ou avg, indicando o tipo de pooling.
  4. Sem preenchimento: Esta operação não utiliza padding; janelas que ultrapassariam a borda da entrada são descartadas.
  5. Cálculo: Para cada posição de saída \((i,j)\), calcular o máximo ou a média dos \(k \times k\) valores da janela correspondente, iniciando em \((i \cdot s,\, j \cdot s)\).
  6. Dimensões de saída: \(O_h = \lfloor (H - k)/s \rfloor + 1\) e \(O_w = \lfloor (W - k)/s \rfloor + 1\).
  7. Saída: Imprimir \(O_h\) e \(O_w\) na primeira linha, seguidos de \(O_h\) linhas com \(O_w\) valores reais cada, formatados com 4 casas decimais.

9.10.2.2 📌 Restrições Computacionais

  • Janela quadrada: \(k \times k\), sem suporte a janelas retangulares nesta versão.
  • Sem padding: apenas janelas inteiramente contidas na entrada são consideradas — dimensões que “sobram” são simplesmente descartadas.
  • avg usa divisão real: a média é sempre \(\text{soma}/k^2\), mesmo quando o resultado tem muitas casas decimais — arredonde apenas na formatação final, conforme a diretriz geral do capítulo.
  • Formatação: todos os valores de saída com exatamente 4 casas decimais.

9.10.2.3 🧠 Fundamentação Teórica

Elemento Papel na arquitetura
Pooling máximo Preserva a ativação mais forte da janela; comum após camadas convolucionais para reter bordas e texturas salientes
Pooling médio Suaviza a região, preservando a intensidade média; comum em camadas finais (global average pooling)
Ausência de parâmetros Diferencia o pooling da convolução: reduz resolução espacial sem custo adicional de treinamento
Redução de resolução Contribui para a invariância a pequenas translações e para a redução do custo computacional das camadas seguintes

9.10.2.4 🧩 Métodos do morph.py que podem ajudar

O morph.py não implementa pooling com subamostragem diretamente, mas duas famílias de operações mostram a mesma ideia sob outra ótica, útil para checar sua intuição:

  • mm.dil(f, Bc) / mm.dil0(f, B) — dilatação morfológica: substitui cada pixel pelo máximo de sua vizinhança definida pelo elemento estruturante \(B\) (ex.: mm.sebox(n) para uma janela \((2n+1)\times(2n+1)\)). É, conceitualmente, um “max-pooling sem subamostragem” (produz uma imagem do mesmo tamanho, em vez de reduzida).
  • mm.blur(f, N) — suavização por média em uma janela \(N \times N\), análoga ao avg-pooling, também sem redução de resolução.
  • mm.readImg(h, w, dtype='float') — útil para ler o mapa de entrada em ponto flutuante.

9.10.2.5 📦 Especificação de Entrada e Saída (VPL)

Entrada:

  • Linha 1: Inteiros \(H\) e \(W\).
  • Próximas \(H\) linhas: \(W\) valores reais cada.
  • Próxima linha: Inteiros \(k\) e \(s\).
  • Próxima linha: max ou avg.

Saída:

  • Linha 1: Inteiros \(O_h\) e \(O_w\).
  • Próximas \(O_h\) linhas: \(O_w\) valores reais cada, com 4 casas decimais.

9.10.2.6 📌 Exemplos

Entrada Saída Observação
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, janela \(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 médio sobre as mesmas janelas.
🎮 Simulador: Pooling Manual 🟢 sem padding, janelas completas

Entrada 4×4 fixa — ajuste o tamanho da janela (k), o stride (s) e o tipo, exatamente os parâmetros que o EP09_02 lê na entrada, e veja como eles mudam o tamanho e os valores da saída.

Janela (k)
Stride (s)
Tipo
(0,0)
Entrada X (4×4)
fora da janela janela atual descartado (sobra)
Saída Y (pooling)

💡 Cada posição do slider revela uma célula da matriz de saída. Células cinza-tracejadas na entrada são "sobras" que nenhuma janela alcança — note como isso acontece quando (H−k) não é múltiplo de s. Trocar k, s ou o tipo reinicia a exploração.

Figura 9.44: Simulador EP09_02: Pooling Manual (máximo vs. média, com janela k e stride s ajustáveis)
%%writefile EP09_02.py
# Código Python
Writing EP09_02.py
TestSuite("EP09_02.py").run()
✔️ EP09_02.cases já existe em casos/
📋 4 caso(s) carregado(s) de casos/EP09_02.cases

🔍 Testando Python: EP09_02.py
⚠️ EP09_02.py: Arquivo sem conteúdo (menos de 3 linhas). Testes ignorados.