MLPs

O que é uma MLP?

Um perceptron multicamadas (multilayer perceptron, MLP) é a rede neural totalmente conectada (fully-connected), também chamada de densa (dense) canônica: uma pilha de camadas em que cada neurônio se conecta a todas as saídas da camada anterior. MLPs são uma das arquiteturas neurais mais antigas e mais utilizadas, e continuam sendo uma linha de base para aproximação de funções (baseline for function approximation) essencial — um primeiro modelo que você testa para responder “uma rede neural consegue aprender este mapeamento, pelo menos em princípio?”

No aprendizado profundo (deep learning) moderno, MLPs aparecem em dois papéis:

  1. Modelos independentes (standalone models) para regressão (regression) e classificação (classification) — especialmente em dados tabulares (tabular data).
  2. Submódulos (submodules) dentro de arquiteturas maiores, por exemplo, o bloco de “rede de propagação direta (feed-forward network)” dentro de Transformers, roteando “especialistas” em Mistura de Especialistas (Mixture-of-Experts, MoE), e cabeças de predição (prediction heads) sobre CNNs ou GNNs.

Em alto nível, uma MLP aprende uma função ( f_\theta: \mathbb{R}^d \to \mathbb{R}^k ) compondo transformações afins (affine transformations) e não linearidades (nonlinearities).

Arquitetura central e notação

Camadas: transformação afim + não linearidade

Uma MLP típica com (L) camadas (contando apenas camadas afins (affine layers)) computa:

[ \begin{aligned} h_0 &= x \ z_\ell &= W_\ell h_{\ell-1} + b_\ell \ h_\ell &= \phi_\ell(z_\ell), \quad \ell=1,\dots,L-1 \ \hat{y} &= W_L h_{L-1} + b_L \quad (\text{optionally followed by output activation}) \end{aligned} ]

Onde:

  • (x \in \mathbb{R}^d) é o vetor de entrada
  • (W_\ell) e (b_\ell) são pesos (weights) e vieses (biases) treináveis
  • (\phi_\ell) é uma função de ativação (activation function) não linear (por exemplo, ReLU)
  • (\hat{y}) é a saída do modelo

Sem não linearidades, toda a rede colapsa em um único mapa linear. A não linearidade é o que torna as MLPs capazes de aproximar funções complexas.

Escolhas da camada de saída (dependentes da tarefa)

  • Regressão: saída linear, perda como MSE.
  • Classificação binária: um logit (logit) + sigmoide (sigmoid) (ou use diretamente logits com BCEWithLogitsLoss).
  • Classificação multiclasse: (k) logits + softmax (softmax) para probabilidades (use CrossEntropyLoss com logits).

Essas escolhas estão ligadas à função de perda e ao modelo de verossimilhança (likelihood model), e afetam fortemente a estabilidade (stability) e a calibração (calibration).

MLPs como aproximadores de funções (a teoria)

Aproximação universal (o que diz — e o que não diz)

Um resultado clássico, frequentemente chamado de teorema da aproximação universal (universal approximation theorem), afirma que uma MLP com pelo menos uma camada oculta (hidden layer) e uma não linearidade adequada pode aproximar qualquer função contínua em um domínio compacto de forma arbitrariamente precisa, dado um número suficiente de unidades ocultas (hidden units).

Isso motiva MLPs como linha de base: em princípio, elas podem aprender quase qualquer mapeamento.

No entanto, há ressalvas importantes:

  • O teorema é existencial (existential), não construtivo: ele não diz quantas unidades você precisa, como treiná-las, ou se a otimização baseada em gradientes (gradient-based optimization) encontrará a solução.
  • A aproximação pode exigir uma rede impraticavelmente grande para certas funções.
  • A generalização (generalization) depende de dados, viés indutivo (inductive bias) e regularização (regularization) — não apenas da capacidade representacional.

Profundidade vs. largura

  • Largura (width) (mais neurônios por camada) aumenta a capacidade; redes muito largas podem aproximar funções complexas, mas podem ser ineficientes em termos de parâmetros.
  • Profundidade (depth) (mais camadas) permite composição hierárquica (hierarchical composition), frequentemente representando algumas funções de forma exponencialmente mais eficiente do que redes rasas.

Na prática, MLPs mais profundas podem ser mais difíceis de treinar sem inicialização (initialization) cuidadosa, normalização (normalization) e/ou conexões residuais (residual connections).

Viés indutivo (por que MLPs são uma “linha de base”)

MLPs assumem quase nada sobre a estrutura da entrada. Isso é força e fraqueza ao mesmo tempo:

  • Força: funciona em qualquer entrada vetorial; excelente linha de base de uso geral.
  • Fraqueza: para dados estruturados (imagens, sequências, grafos), MLPs ignoram localidade, ordem e simetrias — vieses que CNNs, RNNs/LSTMs, Transformers e GNNs exploram.

Funções de ativação (padrões práticos)

Ativações comuns (ver Funções de Ativação):

  • ReLU: rápida, forte padrão para MLPs; pode “morrer” se muitas ativações ficarem negativas.
  • GELU: alternativa suave popular em Transformers; muitas vezes competitiva para blocos MLP profundos.
  • tanh: limitada; historicamente comum, mas mais propensa a gradientes que desaparecem (vanishing gradients) em redes profundas.
  • SiLU/Swish: suave; às vezes melhora o desempenho em relação à ReLU.

Regra prática:

  • Para a maioria das linhas de base com MLP: ReLU ou GELU.
  • Se o treinamento estiver instável ou você quiser saídas limitadas dentro da rede: tente tanh, mas monitore problemas de gradiente.

Treinando MLPs: otimização e regularização

MLPs normalmente são treinadas com Retropropagação e otimizadores baseados em gradientes (ver Descida do Gradiente).

Inicialização

Uma boa inicialização evita explosão/desaparecimento de ativações:

  • Inicialização Xavier/Glorot: comum para ativações do tipo tanh.
  • Inicialização He/Kaiming: comum para ativações do tipo ReLU.

A maioria das bibliotecas de aprendizado profundo seleciona padrões sensatos, mas isso importa quando você aumenta a profundidade ou usa ativações incomuns.

Otimizadores

  • Adam/AdamW: forte padrão; AdamW desacopla decaimento de pesos (weight decay) e frequentemente se comporta melhor para generalização.
  • SGD + momentum: pode generalizar bem, mas pode exigir mais ajustes.

Normalização

A normalização pode fazer MLPs mais profundas treinarem de forma confiável:

Para MLPs em dados tabulares, a normalização pode ajudar, mas nem sempre é necessária; depende do escalonamento dos atributos e da profundidade.

Regularização

Para reduzir sobreajuste (overfitting):

  • Decaimento de pesos (L2): comum, especialmente com AdamW.
  • Dropout (dropout) (Dropout): útil para MLPs, especialmente em conjuntos de dados menores.
  • Parada antecipada (early stopping): monitore a perda/métrica de validação.
  • Pré-processamento de dados (data preprocessing): escalonar/padronizar atributos numéricos geralmente é mais importante do que ajustes arquiteturais para problemas tabulares.

Exemplos práticos

Exemplo 1: Regressão como aproximação de função (ajustar uma curva seno)

Este exemplo mostra o papel de “aproximador de funções de linha de base”: aprender (y=\sin(x)) a partir de amostras.

import torch
import torch.nn as nn
import torch.optim as optim

# Data: y = sin(x)
torch.manual_seed(0)
x = torch.linspace(-6.28, 6.28, steps=512).unsqueeze(1)
y = torch.sin(x)

# Simple MLP
model = nn.Sequential(
    nn.Linear(1, 128),
    nn.ReLU(),
    nn.Linear(128, 128),
    nn.ReLU(),
    nn.Linear(128, 1),
)

loss_fn = nn.MSELoss()
opt = optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-4)

for step in range(2000):
    pred = model(x)
    loss = loss_fn(pred, y)
    opt.zero_grad()
    loss.backward()
    opt.step()

    if step % 200 == 0:
        print(step, float(loss))

Principais aprendizados:

  • Mesmo uma MLP pequena consegue aprender bem funções não lineares suaves.
  • Se a função tiver componentes de alta frequência, você pode precisar de mais capacidade, melhores atributos, ou parametrizações alternativas.

Exemplo 2: Classificação binária tabular (linha de base com MLP)

MLPs costumam ser linhas de base competitivas para conjuntos de dados tabulares quando combinadas com bom pré-processamento.

Receita típica:

  1. Padronize atributos contínuos (média zero, variância unitária).
  2. Use incorporações (embeddings) para atributos categóricos (opcional, mas poderoso).
  3. Concatene os atributos e alimente uma MLP.
  4. Use uma saída logística (um logit) com uma perda estável.

Esboço (estilo PyTorch):

import torch
import torch.nn as nn

class TabularMLP(nn.Module):
    def __init__(self, num_cont, cat_cardinalities=None, emb_dim=16, hidden=256):
        super().__init__()
        self.cat_cardinalities = cat_cardinalities or []
        self.embs = nn.ModuleList([
            nn.Embedding(card, emb_dim) for card in self.cat_cardinalities
        ])
        in_dim = num_cont + emb_dim * len(self.cat_cardinalities)

        self.net = nn.Sequential(
            nn.Linear(in_dim, hidden),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.Linear(hidden, hidden),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.Linear(hidden, 1)  # one logit
        )

    def forward(self, x_cont, x_cat=None):
        parts = [x_cont]
        if x_cat is not None and len(self.embs) > 0:
            embs = [emb(x_cat[:, i]) for i, emb in enumerate(self.embs)]
            parts.append(torch.cat(embs, dim=1))
        x = torch.cat(parts, dim=1)
        return self.net(x)

# Use BCEWithLogitsLoss for numerical stability
loss_fn = nn.BCEWithLogitsLoss()

Por que isso funciona bem:

  • Embeddings permitem que o modelo aprenda representações densas de categorias em vez de vetores one-hot (one-hot).
  • MLPs são flexíveis o suficiente para capturar interações não lineares entre atributos.

Onde as MLPs se encaixam entre outras arquiteturas

MLPs são melhor entendidas como uma linha de base de propósito geral com premissas mínimas.

Em comparação com CNNs

  • CNNs exploram localidade espacial (spatial locality) e equivariança a translação (translation equivariance).
  • Uma MLP em pixels brutos ignora essa estrutura, frequentemente exigindo mais parâmetros e dados para igualar o desempenho de CNNs.

Use uma MLP como linha de base para imagens apenas quando:

  • as entradas já forem embeddings/atributos compactos, ou
  • você quiser explicitamente uma comparação “sem viés indutivo”.

Em comparação com RNNs/LSTMs e Transformers

  • RNNs/LSTMs e Transformers lidam com estrutura de sequência (ordem, contexto).
  • Uma MLP simples exige vetores de comprimento fixo; se você “achatar” uma sequência, perde a noção de posição a menos que adicione atributos manualmente.

Dito isso, MLPs estão dentro de Transformers: cada bloco Transformer contém uma MLP por posição (o “feed-forward network”), frequentemente com GELU e às vezes variantes com portas (por exemplo, SwiGLU).

Em comparação com GNNs

  • GNNs respeitam conectividade de grafos via passagem de mensagens (message passing).
  • Uma MLP pode ser aplicada a atributos de nós, mas sem agregação ela não consegue propagar informação pelas arestas. Na prática, MLPs frequentemente servem como funções de atualização (update functions) dentro de camadas de GNN.

Variantes modernas de MLP e padrões de design

Embora “MLP” sugira algo simples, muitos modelos de alto desempenho usam componentes do tipo MLP com estrutura adicional.

MLPs residuais

MLPs profundas frequentemente treinam melhor com conexões residuais:

[ h_{\ell} = h_{\ell-1} + \text{MLPBlock}(h_{\ell-1}) ]

Isso melhora o fluxo de gradientes e permite maior profundidade, de forma semelhante às ResNets em visão.

MLPs com portas (GLU / estilo SwiGLU)

Uma MLP com portas usa um ramo para modular outro, melhorando a expressividade (expressivity):

  • Calcule duas projeções: (a = W_a x), (b = W_b x)
  • Saída: (\phi(a) \odot b)

Isso aparece com frequência nas camadas feed-forward de modelos modernos de linguagem.

MLP-Mixer e MLPs que misturam tokens

Arquiteturas como MLP-Mixer substituem atenção (attention)/convoluções (convolutions) por MLPs que misturam informação entre tokens (tokens) e canais (channels). Embora não sejam tão dominantes quanto Transformers/CNNs, elas ilustram que projetos “somente MLP” podem funcionar quando combinados com configurações fortes de dados/otimização e mistura adequada.

Orientação prática: construindo uma linha de base forte com MLP

1) Faça um pré-processamento cuidadoso das entradas

  • Padronize atributos numéricos.
  • Trate valores ausentes (imputar + adicionar indicadores de ausência).
  • Considere transformações log para distribuições de cauda pesada.
  • Para variáveis categóricas: embeddings frequentemente superam one-hot em cardinalidade moderada/alta.

2) Escolha uma arquitetura sensata

Bons pontos de partida:

  • 2–4 camadas ocultas
  • 128–1024 unidades ocultas (depende do tamanho dos dados)
  • ReLU ou GELU
  • Dropout 0.0–0.3 (tabular frequentemente se beneficia)
  • Decaimento de pesos (10^{-6}) a (10^{-3})

3) Combine perda e saídas corretamente

  • Regressão: MSE / MAE; considere Huber para robustez.
  • Classificação: use logits + perda estável (CrossEntropyLoss, BCEWithLogitsLoss).

4) Monitore a generalização

  • Use um conjunto de validação, parada antecipada e agendamento da taxa de aprendizado (learning-rate scheduling).
  • Se a perda de treino cair, mas a validação estagnar: adicione regularização, reduza a largura, ou melhore o pré-processamento.

Armadilhas comuns

  • Atributos sem escalonamento: MLPs podem ter dificuldade quando as entradas têm magnitudes muito diferentes.
  • Sobreajuste em pequenos conjuntos tabulares: MLPs grandes memorizam com facilidade; prefira redes menores, dropout e parada antecipada.
  • ReLUs mortas (dead ReLUs): se muitos neurônios passam a emitir zero constantemente, tente reduzir a taxa de aprendizado, usar LeakyReLU/GELU, ou melhorar a inicialização.
  • Tratar MLPs como “modelos de conjunto/sequência” sem cuidado: achatar dados estruturados frequentemente destrói viés indutivo útil.

Quando usar uma MLP (e quando não usar)

Use uma MLP quando:

  • Você precisa de uma linha de base forte para um mapeamento supervisionado de vetores para alvos.
  • Seus dados são tabulares ou já estão featurizados (embeddings, estatísticas, resumos de sensores).
  • Você quer um modelo simples para validar que a tarefa é aprendível.

Considere outras arquiteturas quando:

  • A entrada tem forte estrutura: imagens → CNNs, sequências/texto → Transformers ou RNNs/LSTMs, grafos → GNNs.
  • Você precisa de eficiência em parâmetros (parameter efficiency) e generalização com poucos dados, aproveitando simetrias (symmetries) conhecidas.

Resumo

Uma MLP é a rede neural totalmente conectada padrão e uma ferramenta fundamental para aprendizado profundo. Ela é:

  • Expressiva (aproximação universal de funções em teoria),
  • Flexível (funciona em qualquer entrada vetorial),
  • Simples e eficaz como linha de base para regressão/classificação e como bloco de construção dentro de modelos maiores.

Na prática, um bom desempenho de MLP vem menos de truques exóticos e mais de: bom pré-processamento, capacidade apropriada, otimização estável e regularização sólida.