Otimização

O que “otimização” significa no aprendizado de máquina (machine learning)

Na maior parte da IA moderna (AI), o aprendizado é enquadrado como: escolher parâmetros do modelo (model parameters) que tornem uma pontuação numérica tão boa quanto possível. Essa pontuação é chamada de função objetivo (objective function) (ou perda (loss) / custo (cost)), e o processo de melhorá-la é a otimização numérica (numerical optimization).

Um modelo (model) é tipicamente escrito como uma função (f_\theta(x)), onde:

  • (x) é uma entrada (uma imagem, uma sequência de tokens (token sequence), um vetor de características (feature vector))
  • (\theta) são parâmetros (parameters) (pesos em uma rede neural (neural network), coeficientes em regressão (regression))
  • (f_\theta(x)) produz previsões (probabilidades de classe (class probabilities), uma estimativa de valor real (real-valued estimate), uma distribuição do próximo token (next-token distribution))

O aprendizado escolhe (\theta) para minimizar uma perda sobre dados ({(x_i, y_i)}_{i=1}^n):

[ \min_\theta ;; \frac{1}{n}\sum_{i=1}^n \ell(f_\theta(x_i), y_i) ]

Esse enquadramento se conecta diretamente a:

A otimização é poderosa porque transforma “inteligência” em uma receita genérica: escolha um objetivo que corresponda a um bom comportamento, depois minimize-o.

Ela também é difícil: o objetivo frequentemente é de alta dimensionalidade (high-dimensional), ruidoso (noisy), não convexo (nonconvex), mal condicionado (ill-conditioned) e caro de avaliar.

Do “aprendizado” a um objetivo: exemplos comuns

Regressão linear (mínimos quadrados (least squares))

Para predição ( \hat{y} = w^\top x + b ), uma perda comum é o erro quadrático médio (mean squared error):

[ \min_{w,b} ;; \frac{1}{n}\sum_{i=1}^n (w^\top x_i + b - y_i)^2 ]

Este é um exemplo clássico em que a otimização é bem compreendida: o objetivo é convexo (convex) e tem um mínimo global (global minimum) (e até mesmo uma solução em forma fechada (closed-form solution) em alguns cenários).

Regressão logística (classificação (classification))

Para classificação binária (binary classification) com (p_\theta(y=1|x) = \sigma(w^\top x + b)), frequentemente usamos entropia cruzada (cross-entropy) (log-verossimilhança negativa (negative log-likelihood)):

[ \min_{w,b} ;; -\frac{1}{n}\sum_{i=1}^n \left[y_i \log p_i + (1-y_i)\log(1-p_i)\right] ]

Isso também é convexo em ((w,b)) (com parametrizações típicas), o que o torna “fácil” em relação a redes profundas.

Redes neurais (aprendizado profundo (deep learning))

Redes neurais compõem muitas camadas não lineares. Para classificação, ainda usamos frequentemente entropia cruzada, mas agora:

  • (\theta) pode ter milhões/bilhões de parâmetros
  • o objetivo é geralmente não convexo
  • a superfície de perda (loss surface) pode conter regiões planas, ravinas íngremes e muitos pontos de sela (saddle points)

O aprendizado profundo é, em grande parte, a história de tornar esse difícil problema de otimização tratável com bons algoritmos, arquiteturas e truques de treinamento (por exemplo, normalização (normalization), inicialização (initialization), otimizadores adaptativos (adaptive optimizers)).

Ingredientes da otimização: objetivo, gradientes e uma regra de atualização

A maior parte da otimização em aprendizado de máquina é iterativa (iterative): começa-se com um (\theta_0) inicial e então atualiza-se repetidamente.

Gradientes: “em que direção a perda diminui mais rápido?”

Para uma perda diferenciável (L(\theta)), o gradiente (\nabla_\theta L(\theta)) aponta na direção de maior aumento. Assim, (-\nabla_\theta L(\theta)) é uma direção natural de descida.

Isso se apoia em Cálculo. Em redes profundas, gradientes são computados de forma eficiente via Retropropagação, geralmente implementada com diferenciação automática (automatic differentiation).

Descida do gradiente (lote completo (full-batch))

A atualização básica é:

[ \theta_{t+1} = \theta_t - \eta \nabla_\theta L(\theta_t) ]

onde (\eta > 0) é a taxa de aprendizado (learning rate).

Pseudocódigo:

initialize θ
repeat:
    g = ∇θ L(θ)          # compute gradient on all data
    θ = θ - η g
until converged

A descida do gradiente em lote completo pode ser estável, mas frequentemente é cara demais para grandes conjuntos de dados.

Descida estocástica do gradiente (stochastic gradient descent, SGD)

Em vez de usar todos os dados, use um mini-lote (mini-batch) (B) e otimize uma estimativa:

[ g_t = \nabla_\theta \left(\frac{1}{|B|}\sum_{i\in B}\ell(f_\theta(x_i),y_i)\right) ]

Este é o carro-chefe (workhorse) do aprendizado profundo. O ruído ao amostrar mini-lotes não é apenas um incômodo — ele pode ajudar na exploração e na generalização (generalization).

Este tópico é expandido em Otimização Estocástica.

Por que a otimização é difícil em IA

1) Alta dimensionalidade e não convexidade

Modelos profundos criam objetivos com muitos parâmetros e não linearidades. Diferentemente de problemas convexos (veja Otimização Convexa), objetivos não convexos podem ter:

  • múltiplos mínimos locais (local minima)
  • regiões planas amplas (“platôs (plateaus)”)
  • pontos de sela (gradiente perto de zero, mas não um mínimo)

Nuance importante: em redes neurais grandes, mínimos locais nem sempre são o principal inimigo. Muitos mínimos podem ser igualmente bons, mas encontrar rapidamente uma boa bacia (basin) ainda é desafiador.

2) Má condição: ravinas e progresso lento

Mesmo para uma função suave e bem comportada, a otimização pode ser lenta se a curvatura for muito diferente em direções diferentes.

Uma figura clássica: um vale longo e estreito. O gradiente aponta através das paredes do vale, então uma descida do gradiente ingênua ziguezagueia e avança lentamente.

Isso está ligado à Hessiana (Hessian) (H = \nabla^2 L(\theta)) e ao seu número de condição (condition number) (razão entre o maior e o menor autovalor (eigenvalue)). A má condição pode vir de:

  • características correlacionadas (comum em dados reais)
  • composições profundas de transformações
  • inicialização / escala ruins

Métodos de normalização (como normalização em lote (BatchNorm), normalização por camada (LayerNorm)) e inicialização cuidadosa frequentemente ajudam ao melhorar o condicionamento.

3) Gradientes que desaparecem e que explodem

Em redes profundas, gradientes são produtos de muitos Jacobianos (Jacobians). Dependendo de suas normas, os gradientes podem:

  • desaparecer (vanish) (ir para ~0): o aprendizado trava nas camadas iniciais
  • explodir (explode) (ficar enormes): as atualizações se tornam instáveis

Mitigações práticas incluem:

  • melhores ativações (variantes de ReLU (ReLU variants) vs sigmoide/tanh em muitos cenários)
  • conexões residuais (residual connections) (comuns em arquiteturas modernas)
  • recorte de gradiente (gradient clipping) (comum em redes neurais recorrentes (RNNs, recurrent neural networks) e no treinamento de transformers (transformers) grandes)
  • camadas de normalização

Essas são escolhas arquiteturais/de design de treinamento que tornam o problema de otimização mais bem comportado.

4) Estocasticidade: gradientes ruidosos e treinamento instável

Gradientes de mini-lotes têm variância (variance). Isso introduz:

  • curvas de perda tremidas
  • sensibilidade à taxa de aprendizado e ao tamanho do lote
  • divergência ocasional se os passos forem grandes demais

Mas a estocasticidade pode ser útil:

  • Ela pode ajudar a escapar de regiões agudas/instáveis.
  • Ela pode enviesar para soluções “mais planas” que às vezes generalizam melhor (um tópico de pesquisa ativo, com muitas ressalvas).

5) Não estacionariedade em configurações modernas de treinamento

Alguns problemas de otimização mudam conforme você otimiza:

  • Em aprendizado por reforço (reinforcement learning), a distribuição dos dados depende da política (policy) atual.
  • Em redes adversariais generativas (GANs, generative adversarial networks), gerador e discriminador mudam juntos (um jogo (game), não um único objetivo).
  • Em aprendizado auto-supervisionado (self-supervised learning), o colapso de representações (representation collapse) pode acontecer sem o devido design.

Essas questões vão além de uma simples minimização, mas ainda aparecem como “dificuldades de otimização” na prática.

6) Restrições, regularização e trade-offs implícitos

Muitos problemas de aprendizado de máquina têm restrições ou preferências:

  • limitar a complexidade do modelo
  • impor esparsidade (sparsity)
  • manter restrições de equidade (fairness constraints)
  • satisfazer restrições de recursos (resource constraints) (latência, memória)

Às vezes, estas são restrições explícitas:

[ \min_\theta L(\theta) \quad \text{s.t.} \quad c(\theta)\le 0 ]

Frequentemente, elas são tratadas adicionando termos de penalidade (penalty terms):

[ \min_\theta ; L(\theta) + \lambda R(\theta) ]

onde (R(\theta)) pode ser (||\theta||_2^2) (decaimento de pesos (weight decay)) ou (||\theta||_1) (esparsidade).

Para ferramentas formais (multiplicadores de Lagrange (Lagrange multipliers), condições KKT (KKT conditions)), veja Otimização com Restrições.

7) Otimização vs generalização: “perda de treinamento não é o objetivo”

A otimização minimiza a perda de treinamento, mas nos importamos com o desempenho em dados não vistos. Muitos fenômenos vivem nessa fronteira:

  • Sobreajuste (overfitting): a perda de treinamento diminui enquanto a perda de teste aumenta
  • Regularização (regularization): explícita (decaimento de pesos, abandono aleatório (dropout)) e implícita (ruído do SGD, parada antecipada (early stopping))
  • Seleção de modelo (model selection): escolher arquiteturas (architectures) e hiperparâmetros (hyperparameters) com base em métricas de validação (validation metrics)

A otimização é necessária, mas não suficiente: é um mecanismo para ajustar parâmetros, não uma garantia de inteligência generalizável.

Interpretando perdas por meio de probabilidade e decisões

Muitas perdas padrão correspondem a princípios estatísticos:

  • Minimizar a log-verossimilhança negativa = estimação por máxima verossimilhança (maximum likelihood estimation)
  • Adicionar um termo de prior corresponde à estimação a posteriori máxima (MAP, maximum a posteriori)

Por exemplo, com verossimilhança (p(y|x,\theta)):

[ \min_\theta -\sum_i \log p(y_i|x_i,\theta) ]

Isso conecta otimização a Probabilidade e Estatística. Quando nos importamos com ações e custos (não apenas acurácia preditiva), objetivos se conectam a utilidades (utilities) e funções de perda em Teoria da Decisão Bayesiana.

Algoritmos centrais de otimização usados em aprendizado de máquina

Métodos de primeira ordem (os mais comuns)

Métodos de primeira ordem (first-order) usam gradientes, mas não segundas derivadas.

  • descida estocástica do gradiente: simples, escalável, forte baseline
  • momento (momentum): acumula uma velocidade para reduzir ziguezagueamento
  • momento de Nesterov (Nesterov momentum): uma variante com lookahead
  • Adam / AdamW: taxas de aprendizado adaptativas por parâmetro; AdamW desacopla decaimento de pesos e é amplamente usado no treinamento de transformers

Uma atualização típica “tipo momento” (conceitualmente):

v = β v + (1-β) g
θ = θ - η v

Pontos práticos:

  • Cronogramas de taxa de aprendizado (learning rate schedules) (warmup, decaimento cossenoidal (cosine decay)) importam tanto quanto a escolha do otimizador.
  • Métodos da família Adam podem convergir rápido, mas podem exigir regularização e ajuste cuidadosos para obter a melhor generalização.
  • Descida do gradiente estocástica com momento ainda é comum em visão e em cenários onde a generalização é especialmente sensível.

Métodos de segunda ordem e quase-segunda-ordem (menos comuns em escala)

Métodos de segunda ordem (second-order) usam informação de curvatura (curvature) (Hessiana). O método de Newton (Newton’s method) atualiza aproximadamente como:

[ \theta_{t+1} = \theta_t - H^{-1}\nabla L(\theta_t) ]

Isso pode ser muito rápido perto de um ótimo, mas tipicamente é impraticável para redes neurais enormes porque:

  • armazenar (H) é impossível em escala
  • resolver sistemas lineares é caro
  • a estocasticidade complica estimativas de curvatura

Métodos quase-Newton (quasi-Newton) como L-BFGS são usados em problemas menores e em alguns cenários de ML científico.

Métodos sem gradiente (úteis em nichos)

Quando gradientes não estão disponíveis ou são pouco confiáveis:

  • estratégias evolutivas (evolutionary strategies)
  • busca aleatória (random search) / otimização bayesiana (Bayesian optimization) para hiperparâmetros
  • diferenças finitas (finite differences) (caro em alta dimensionalidade)

Eles raramente são usados para treinar redes neurais diferenciáveis grandes, mas podem importar em contextos de otimização de caixa-preta (black-box optimization).

Exemplo prático: ajustando um modelo simples com descida do gradiente

Abaixo está um exemplo mínimo de descida do gradiente para regressão linear para tornar a otimização concreta:

import numpy as np

# synthetic data
rng = np.random.default_rng(0)
n, d = 200, 3
X = rng.normal(size=(n, d))
true_w = np.array([2.0, -1.0, 0.5])
y = X @ true_w + 0.1 * rng.normal(size=n)

# initialize parameters
w = np.zeros(d)
lr = 0.1

for step in range(200):
    # predictions and residuals
    yhat = X @ w
    r = yhat - y

    # MSE gradient: (2/n) X^T (Xw - y)
    grad = (2.0 / n) * X.T @ r
    w -= lr * grad

print("estimated w:", w)

Mesmo aqui, o comportamento da otimização depende da escala (scaling):

  • Se uma coluna de características em (X) for 100× maior que as outras, a descida do gradiente pode ficar lenta ou instável, a menos que você normalize características ou ajuste a taxa de aprendizado.
  • No aprendizado profundo, questões análogas de escala aparecem por toda a rede e são um grande motivo pelo qual normalização e inicialização cuidadosa importam.

Diagnosticando problemas de otimização na prática

Quando o treinamento falha ou é lento, sintomas comuns se mapeiam para questões de otimização:

  • A perda é NaN / diverge
    Frequentemente: taxa de aprendizado alta demais, gradientes que explodem, instabilidade numérica (por exemplo, precisão mista (mixed precision) sem escala de perda (loss scaling))

  • A perda diminui extremamente devagar
    Frequentemente: taxa de aprendizado baixa demais, má condição, inicialização ruim, gradientes que desaparecem

  • O treinamento é instável / muito sensível ao tamanho do lote
    Frequentemente: ruído de gradiente alto demais, taxa de aprendizado não escalada adequadamente, hiperparâmetros do otimizador incompatíveis

  • A perda de treinamento melhora, a perda de validação piora
    Frequentemente: sobreajuste; considere regularização, aumento de dados (data augmentation), parada antecipada

Intervenções úteis (dependem do problema):

  • ajustar a taxa de aprendizado (e usar um cronograma)
  • normalizar entradas; considerar camadas de normalização
  • mudar o tamanho do lote (e reajustar a taxa de aprendizado)
  • tentar recorte de gradiente
  • tentar AdamW vs SGD+momento dependendo do domínio
  • verificar o pipeline de dados e rótulos (muitas falhas de “otimização” na verdade são problemas de dados)

Um modelo mental: por que “boa otimização” importa

Otimização não é apenas um solucionador; ela molda quais soluções você obtém:

  • Com muitos graus de liberdade, múltiplas configurações de parâmetros podem ajustar os dados de treinamento.
  • O otimizador, a inicialização, o ruído do lote e a regularização enviesam quais soluções são encontradas.
  • Essas soluções podem diferir drasticamente em robustez (robustness), calibração (calibration) e comportamento fora de distribuição (out-of-distribution) — mesmo que a perda de treinamento seja similar.

Então “o aprendizado vira otimização” não é apenas um reenquadramento matemático conveniente. É uma escolha profunda de design: treinamos o que conseguimos otimizar, e frequentemente redesenhamos modelos e objetivos para tornar a otimização viável.

Para onde ir a seguir