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

EP09_03 — 🟡 Contagem de Parâmetros Treináveis de uma CNN

9.10.3 EP09_03 🟡 Contagem de Parâmetros Treináveis de uma CNN

Este EP formaliza a contagem de parâmetros treináveis de uma CNN. Dada a descrição textual de uma pequena arquitetura, composta por camadas convolucionais, de pooling e totalmente conectadas, determine, para cada camada, o número de parâmetros treináveis e o total da rede.

A arquitetura deve ser interpretada sequencialmente: a saída de uma camada convolucional torna-se a entrada da próxima camada compatível. Assim, o número de canais produzidos por uma camada CONV determina o número de canais de entrada (cin) da camada convolucional seguinte.

Em uma camada convolucional, é importante distinguir canais de entrada e canais de saída:

  • \(c_{in}\) (channels in) é o número de canais que entram na camada. Uma imagem em tons de cinza possui \(c_{in}=1\), enquanto uma imagem RGB possui \(c_{in}=3\). Em uma camada convolucional intermediária, cin normalmente é igual ao número de canais produzidos pela camada CONV anterior.
  • \(c_{out}\) (channels out) é o número de canais produzidos pela camada. Ele é igual ao número de filtros utilizados. Portanto, se uma camada possui 16 filtros, ela produz \(c_{out}=16\) canais.

Por exemplo, considere a sequência:

CONV 3 3 1 8 1
POOL
CONV 3 3 8 16 1
POOL
FC 784 10 1

A primeira convolução recebe uma imagem com um canal e produz 8 canais. Depois do pooling, a segunda convolução recebe esses 8 canais e produz 16 canais. A camada POOL não altera o número de canais, apenas pode reduzir as dimensões espaciais. A camada FC recebe a quantidade de entradas informada na própria descrição.

Cada filtro convolucional possui dimensões

\[ k_h \times k_w \times c_{in}. \]

Assim, uma camada com \(c_{out}\) filtros possui

\[ k_h \cdot k_w \cdot c_{in} \cdot c_{out} \]

pesos. Se houver viés, acrescenta-se um parâmetro para cada filtro, totalizando mais \(c_{out}\) parâmetros.

O ponto central deste exercício é observar que a quantidade de parâmetros de uma camada convolucional não depende das dimensões espaciais (\(H \times W\)) do mapa de características. Isso ocorre devido ao compartilhamento de pesos: o mesmo filtro é reutilizado em diferentes posições da entrada.

9.10.3.1 📋 Diretrizes de Implementação

  1. Entrada: Ler o inteiro \(L\) (número de camadas da arquitetura, na ordem em que são aplicadas).

  2. Camadas: Ler \(L\) linhas, cada uma descrevendo uma camada em um dos três formatos:

    • CONV kh kw cin cout bias — camada convolucional com kernel \(k_h \times k_w\), \(c_{in}\) canais de entrada, \(c_{out}\) canais de saída e bias (0 ou 1), indicando se há viés por filtro;
    • POOL — camada de pooling (máximo ou médio), que não possui parâmetros treináveis e preserva o número de canais;
    • FC in out bias — camada totalmente conectada com in entradas, out saídas e bias (0 ou 1), indicando se há viés por neurônio.
  3. Consistência entre camadas CONV: em uma sequência de camadas convolucionais, o cin de uma camada deve corresponder ao cout da camada convolucional anterior. Uma camada POOL não altera esse número de canais.

    Por exemplo:

    CONV 3 3 1 8 1
    POOL
    CONV 3 3 8 16 1

    A primeira CONV produz 8 canais, que são recebidos pela segunda CONV. Portanto, na segunda camada, cin=8 e cout=16.

  4. Parâmetros de uma camada CONV:

    Cada um dos \(c_{out}\) filtros possui \(k_h \cdot k_w \cdot c_{in}\) pesos. Portanto,

    \[ P_{\mathrm{CONV}} = k_h \cdot k_w \cdot c_{in} \cdot c_{out} + c_{out}\cdot\text{bias}. \]

  5. Parâmetros de uma camada FC:

    \[ P_{\mathrm{FC}} = \text{in}\cdot\text{out} + \text{out}\cdot\text{bias}. \]

  6. Parâmetros de uma camada POOL: sempre \(0\).

  7. Total da rede: somar os parâmetros treináveis de todas as camadas.

  8. Saída: Para cada camada, na ordem de leitura, imprimir Camada i: P, em que \(i\) começa em \(1\) e \(P\) é o número de parâmetros daquela camada. Ao final, imprimir Total: T.

9.10.3.2 📐 Exemplo para entender cin e cout

Considere a sequência:

CONV 3 3 1 8 1
POOL
CONV 3 3 8 16 1

Na primeira camada:

  • cin=1: entra um canal;
  • cout=8: existem 8 filtros e, portanto, saem 8 canais.

Cada filtro possui

\[ 3\cdot3\cdot1=9 \]

pesos. Como existem 8 filtros:

\[ 9\cdot8=72 \]

pesos. Com um viés por filtro:

\[ 72+8=80. \]

Na segunda camada:

  • cin=8: entram os 8 canais produzidos pela primeira CONV;
  • cout=16: existem 16 filtros e, portanto, saem 16 canais.

Cada filtro possui

\[ 3\cdot3\cdot8=72 \]

pesos. Como existem 16 filtros:

\[ 72\cdot16=1152 \]

pesos. Com 16 vieses:

\[ 1152+16=1168. \]

Assim, as duas camadas possuem, respectivamente, 80 e 1168 parâmetros treináveis.

Observe que cout não é \(cin\) multiplicado pelo número de filtros. O número de filtros é exatamente cout: cada filtro combina todos os canais de entrada e produz um único canal de saída.

9.10.3.3 📌 Restrições Computacionais

  • Independência da dimensão espacial: a entrada não informa \(H \times W\). A contagem de uma camada CONV depende apenas de kh, kw, cin e cout.
  • Consistência dos canais: para duas camadas CONV consecutivas, o cin da segunda deve ser igual ao cout da primeira. Uma camada POOL preserva o número de canais.
  • bias sempre 0 ou 1: multiplique diretamente o termo de viés por esse valor.
  • Camadas POOL sem argumentos adicionais: a linha contém apenas a palavra POOL.
  • Camadas FC: o número de entradas in é fornecido explicitamente. Não é necessário calcular as dimensões espaciais produzidas pelas camadas anteriores.
  • Todos os valores numéricos de entrada são inteiros não negativos.

9.10.3.4 🧠 Fundamentação Teórica

Elemento Papel na contagem de parâmetros
\(c_{in}\) Número de canais recebidos pela camada
\(c_{out}\) Número de filtros e, portanto, de canais produzidos pela camada
Filtro convolucional Cada filtro possui \(k_h \cdot k_w \cdot c_{in}\) pesos e produz um canal de saída
Compartilhamento de pesos O mesmo filtro é reutilizado em diferentes posições da entrada, tornando a contagem independente de \(H \times W\)
Viés Um único parâmetro adicional por filtro (CONV) ou por neurônio (FC)
Pooling Pode alterar \(H \times W\), mas não possui parâmetros treináveis e preserva o número de canais
Camada FC Possui um peso para cada combinação entre entrada e neurônio de saída

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

Este exercício é puramente aritmético e não utiliza diretamente funções do morph.py. A contagem pode, entretanto, ser conferida em uma arquitetura real implementada em PyTorch por meio de:

sum(p.numel() for p in modelo.parameters())

Essa expressão contabiliza os parâmetros do modelo, incluindo pesos e vieses.

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

Entrada:

  • Linha 1: Inteiro \(L\).
  • Próximas \(L\) linhas: descrição de cada camada, no formato CONV kh kw cin cout bias, POOL ou FC in out bias.

Saída:

  • \(L\) linhas no formato Camada i: P.
  • Última linha: Total: T.

9.10.3.7 📌 Exemplos

Entrada Saída Observação
3
CONV 3 3 1 8 1
POOL
FC 1352 10 1
Camada 1: 80
Camada 2: 0
Camada 3: 13530
Total: 13610
Rede simples com uma convolução, pooling e camada de classificação.
5
CONV 3 3 1 8 1
POOL
CONV 3 3 8 16 1
POOL
FC 400 10 1
Camada 1: 80
Camada 2: 0
Camada 3: 1168
Camada 4: 0
Camada 5: 4010
Total: 5258
Pequena CNN com duas convoluções, dois poolings e uma camada totalmente conectada.
6
CONV 3 3 1 8 1
POOL
CONV 3 3 8 16 1
POOL
FC 256 32 1
FC 32 10 1
Camada 1: 80
Camada 2: 0
Camada 3: 1168
Camada 4: 0
Camada 5: 8224
Camada 6: 330
Total: 9802
CNN pequena com duas convoluções, pooling intermediário e duas camadas totalmente conectadas para classificação.
🎮 Simulador: Contagem de Parâmetros 🟡 compartilhamento de pesos
CONV Bloco azul POOL Cilindro verde FC Losango laranja BATCH Pilha vermelha 🖱️ Arraste para mover camadas
32×32
1
4
3
🧠 Visualização 3D
🖱️ Arraste camadas | Scroll zoom | P pausar
Figura 9.45: Simulador EP09_03: Contagem de Parâmetros — Convolução vs. Camada Totalmente Conectada
%%writefile EP09_03.py
# Código Python
Writing EP09_03.py
TestSuite("EP09_03.py").run()
✔️ EP09_03.cases já existe em casos/
📋 3 caso(s) carregado(s) de casos/EP09_03.cases

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