Gradientes, Jacobianos (Jacobians), Hessianas (Hessians)
Por que gradientes, Jacobianas e Hessianas importam em IA
O aprendizado de máquina (machine learning) moderno é, em grande parte, sobre otimizar um modelo: ajustar parâmetros (parameters) para reduzir uma perda (loss). Em altas dimensões, “derivada (derivative)” se generaliza em uma pequena família de objetos intimamente relacionados:
- Gradiente (gradient): derivada de uma função de valor escalar em relação a uma entrada vetorial.
Usado em toda parte em Descida do Gradiente (Gradient Descent) e Retropropagação (Backpropagation). - Jacobiana (Jacobian): derivada de uma função de valor vetorial em relação a uma entrada vetorial.
Captura como a saída de uma camada inteira ou de um modelo muda com suas entradas. - Hessiana (Hessian): segunda derivada (curvatura) de uma função de valor escalar em relação a uma entrada vetorial.
Explica “como o gradiente muda” e fundamenta a otimização de segunda ordem.
Essas são as ferramentas centrais para entender o comportamento local de funções em muitas dimensões: linearização (linearization) (primeira ordem) e curvatura (curvature) (segunda ordem).
Configuração: funções, formas e notação
Considere:
- Vetor de entrada: (x \in \mathbb{R}^n)
- Saída escalar: (f(x) \in \mathbb{R})
- Saída vetorial: (g(x) \in \mathbb{R}^m)
Em ML, (x) pode ser:
- parâmetros do modelo (\theta) (frequentemente milhões de dimensões),
- ativações (activations) em uma camada,
- um exemplo de entrada.
Um modelo mental útil é: derivadas são aplicações lineares que melhor aproximam a função localmente.
Aproximação linear local (primeira ordem)
Para uma função diferenciável (g:\mathbb{R}^n \to \mathbb{R}^m), perto de um ponto (x),
[ g(x + \Delta x) \approx g(x) + J_g(x),\Delta x ]
onde (J_g(x)) é a jacobiana. Este é o análogo multivariado de “inclinação vezes passo”.
Aproximação quadrática local (segunda ordem)
Para uma função escalar diferenciável (f:\mathbb{R}^n \to \mathbb{R}),
[ f(x+\Delta x) \approx f(x) + \nabla f(x)^\top \Delta x + \frac{1}{2}\Delta x^\top H_f(x),\Delta x ]
onde:
- (\nabla f(x)) é o gradiente
- (H_f(x)) é a hessiana
Essa visão quadrática é de onde vem a “intuição de curvatura”.
Gradientes: subida mais íngreme em muitas dimensões
Definição e forma
Para (f:\mathbb{R}^n \to \mathbb{R}), o gradiente é o vetor de derivadas parciais:
[ \nabla f(x) = \begin{bmatrix} \frac{\partial f}{\partial x_1}\ \vdots\ \frac{\partial f}{\partial x_n} \end{bmatrix} \in \mathbb{R}^n ]
Alguns textos usam gradientes como vetores-linha; em ML é comum tratar gradientes como vetores-coluna. O que importa é ser consistente.
Intuição geométrica
- (\nabla f(x)) aponta na direção de aumento mais íngreme de (f).
- (-\nabla f(x)) aponta na direção de queda mais íngreme, o que motiva a descida do gradiente.
- O gradiente é ortogonal a conjuntos de nível (level sets) (f(x)=c). Em 2D, ele aponta perpendicularmente às linhas de contorno (contour lines).
Derivadas direcionais: gradiente como uma “inclinação em qualquer direção”
Dada uma direção unitária (u), a derivada direcional (directional derivative) é:
[ D_u f(x) = \nabla f(x)^\top u ]
Isso é útil para entender por que o gradiente negativo é o melhor passo local sob uma pequena restrição de passo euclidiano.
Exemplo prático: gradiente de uma perda quadrática
Considere (f(x) = \frac{1}{2}|Ax - b|^2), onde (A\in\mathbb{R}^{m\times n}).
Então:
[ \nabla f(x) = A^\top (Ax - b) ]
Essa forma aparece constantemente em mínimos quadrados (least squares), regressão linear (linear regression) e como um bloco de construção em perdas de aprendizado profundo (deep learning).
Jacobianas: derivadas de funções vetoriais
Definição e forma
Para (g:\mathbb{R}^n \to \mathbb{R}^m), a jacobiana é a matriz:
[ J_g(x) = \begin{bmatrix} \frac{\partial g_1}{\partial x_1} & \cdots & \frac{\partial g_1}{\partial x_n}\ \vdots & \ddots & \vdots\ \frac{\partial g_m}{\partial x_1} & \cdots & \frac{\partial g_m}{\partial x_n} \end{bmatrix} \in \mathbb{R}^{m\times n} ]
Cada linha é o gradiente de um componente de saída (g_i(x)).
Jacobiana como o melhor mapa linear localmente
A jacobiana é a transformação linear que melhor prevê mudanças na saída:
[ \Delta g \approx J_g(x),\Delta x ]
Por isso, jacobianas são centrais para análise de sensibilidade (sensitivity analysis), estabilidade e regras da cadeia (chain rules) no estilo de retropropagação.
Exemplo prático: camada afim (linear)
Em uma camada de rede neural:
[ y = Wx + b ]
com (W\in \mathbb{R}^{m\times n}). A jacobiana de (y) em relação a (x) é:
[ J_{y}(x) = W ]
Assim, localmente (e globalmente, já que é linear), a sensibilidade da camada é exatamente sua matriz de pesos.
Exemplo prático: jacobiana da softmax (softmax) (importante em classificação)
Para logits (logits) (z\in\mathbb{R}^K), as saídas da softmax (p\in\mathbb{R}^K):
[ p_i = \frac{e^{z_i}}{\sum_j e^{z_j}} ]
Sua jacobiana é:
[ \frac{\partial p_i}{\partial z_j} = p_i(\delta_{ij} - p_j) ]
Em forma matricial:
[ J_{\text{softmax}}(z) = \mathrm{diag}(p) - pp^\top ]
Essa estrutura (uma diagonal menos uma matriz de posto 1) é usada para derivar gradientes eficientes para softmax + entropia cruzada (cross-entropy).
Regra da cadeia em múltiplas dimensões (como a retropropagação “realmente” funciona)
Regra da cadeia para jacobianas
Se (h(x) = g(f(x))) com (f:\mathbb{R}^n\to\mathbb{R}^k) e (g:\mathbb{R}^k\to\mathbb{R}^m), então:
[ J_h(x) = J_g(f(x)) , J_f(x) ]
Esta é a forma mais direta da regra da cadeia multivariada: jacobianas se multiplicam.
Caso de perda escalar: por que gradientes retropropagam via transposta
Em ML, você geralmente tem uma perda escalar (L) que depende de vetores intermediários. Suponha:
- (y = f(x)) (vetor)
- (L = \ell(y)) (escalar)
Então:
[ \nabla_x L = J_f(x)^\top \nabla_y L ]
Esse “transposta da jacobiana vezes o gradiente a montante” é o coração algébrico da Retropropagação. Muitas bibliotecas implementam isso via produtos vetor-jacobiana (vector-Jacobian products, VJP) sem nunca materializar (J_f).
Hessianas: segundas derivadas e curvatura
Definição e forma
Para (f:\mathbb{R}^n\to\mathbb{R}), a hessiana é:
[ H_f(x) = \begin{bmatrix} \frac{\partial^2 f}{\partial x_1^2} & \cdots & \frac{\partial^2 f}{\partial x_1 \partial x_n}\ \vdots & \ddots & \vdots\ \frac{\partial^2 f}{\partial x_n \partial x_1} & \cdots & \frac{\partial^2 f}{\partial x_n^2} \end{bmatrix} \in \mathbb{R}^{n\times n} ]
Se (f) é duas vezes continuamente diferenciável, a hessiana é simétrica: (\frac{\partial^2 f}{\partial x_i\partial x_j} = \frac{\partial^2 f}{\partial x_j\partial x_i}).
Intuição de curvatura: como a função “entorta”
A hessiana informa como o gradiente muda com (x). Na direção (u), a segunda derivada direcional é:
[ u^\top H_f(x),u ]
- Se (u^\top H u) é grande e positiva, a função curva fortemente para cima na direção (u).
- Se é negativa, a função curva para baixo (localmente côncava) nessa direção.
Autovalores: eixos de curvatura
Como (H) é (frequentemente) simétrica, ela tem autovalores (eigenvalues) reais (\lambda_i) e autovetores (eigenvectors) ortogonais (v_i). Eles definem direções principais de curvatura:
- (\lambda_i > 0): curva para cima ao longo de (v_i)
- (\lambda_i < 0): curva para baixo ao longo de (v_i)
- (\lambda_i = 0): localmente plana ao longo de (v_i)
Isso é crucial em aprendizado profundo, onde paisagens de perda comumente contêm pontos de sela (saddle points) (curvatura mista positiva/negativa), e não apenas mínimos simples.
Convexidade e garantias de otimização
- Se (H_f(x)) é semidefinida positiva (positive semidefinite, PSD) em todo lugar, (f) é convexa (convex).
- Se (H_f(x)) é definida positiva (positive definite, PD) em todo lugar, (f) é estritamente convexa (mínimo único).
A maioria das redes profundas é não convexa (non-convex), então hessianas frequentemente têm autovalores positivos e negativos.
Métodos de segunda ordem: usando curvatura para se mover de forma mais inteligente
Método de Newton (conceito)
A atualização de Newton para minimizar (f) é:
[ x_{t+1} = x_t - H_f(x_t)^{-1}\nabla f(x_t) ]
Interpretação: “dividir o gradiente pela curvatura”, generalizando “passo = inclinação / curvatura” do caso 1D.
Na prática, para modelos grandes, formar ou inverter (H) explicitamente costuma ser caro demais, mas o método de Newton motiva uma família de métodos aproximados.
Quase-Newton e aproximações de curvatura
Algoritmos como L-BFGS aproximam (H^{-1}) usando histórico de gradientes, oferecendo melhor escalonamento do que a descida do gradiente pura em alguns cenários (comumente para modelos menores ou ajuste fino (fine-tuning)).
Gauss–Newton e estrutura de mínimos quadrados
Para perdas da forma (f(x)=\frac{1}{2}|r(x)|^2) com vetor de resíduos (r), a hessiana exata envolve segundas derivadas de (r). A aproximação de Gauss–Newton (Gauss–Newton) usa:
[ H \approx J_r(x)^\top J_r(x) ]
Essa aproximação é PSD e muitas vezes é mais fácil de usar.
Produtos hessiana-vetor (Hessian-vector products, HVP): curvatura sem a matriz
Mesmo que (H) seja enorme, muitas vezes você consegue computar (H v) de forma eficiente (aproximadamente o custo de algumas retropropagações) usando truques de diferenciação automática. Isso permite:
- diagnósticos baseados em curvatura,
- passos aproximados de segunda ordem,
- estimação de autovalores (por exemplo, iteração de potência (power iteration)).
Como isso aparece na prática de aprendizado profundo
1) Gradientes conduzem o treinamento
No treinamento padrão, você calcula:
[ \nabla_\theta L(\theta) ]
e atualiza os parâmetros usando um otimizador (optimizer) (SGD, Adam, etc.). Esse é o principal uso de derivadas multivariadas em aprendizado profundo; veja Descida do Gradiente e Retropropagação.
2) Jacobianas descrevem sensibilidade e estabilidade
Jacobianas importam quando você se preocupa com como as saídas mudam em relação às entradas ou ativações intermediárias:
- Exemplos adversariais (adversarial examples): sensibilidade da perda às entradas (x) (um gradiente, que é uma jacobiana de uma perda escalar).
- Gradientes explodindo/desvanecendo (exploding/vanishing gradients): multiplicação repetida por jacobianas através de camadas/passos de tempo (por exemplo, em RNNs).
- Fluxos normalizantes (normalizing flows): o log-determinante (log-determinant) da jacobiana aparece nas verossimilhanças (para modelos inversíveis).
3) Hessianas explicam curvatura, “sharpness” e limites de tamanho de passo
Informações da hessiana estão ligadas a:
- escolher taxas de aprendizado (learning rate) estáveis (curvatura positiva grande pode forçar passos menores),
- entender pontos de sela (direções de curvatura negativa),
- incerteza aproximada (por exemplo, aproximações de Laplace (Laplace approximations) em torno de um mínimo).
Uma regra prática comum: se o maior autovalor da hessiana é enorme, passos ingênuos de gradiente podem passar do ponto (overshoot) a menos que a taxa de aprendizado seja pequena.
Calculando esses objetos com diferenciação automática
O ML moderno usa Diferenciação Automática (Automatic Differentiation) em vez de diferenciação simbólica. Frameworks computam gradientes eficientemente via diferenciação automática em modo reverso (reverse-mode AD) (backprop).
Exemplos em PyTorch
import torch
# Example scalar loss f(x) = (x1^2 + 3*x2)^2
x = torch.tensor([2.0, -1.0], requires_grad=True)
f = (x[0]**2 + 3*x[1])**2
f.backward()
print("grad:", x.grad) # ∇f(x)
Jacobiana de uma função de valor vetorial:
import torch
from torch.autograd.functional import jacobian
def g(x):
# g: R^2 -> R^3
return torch.stack([
x[0] * x[1],
x[0]**2,
torch.sin(x[1])
])
x = torch.tensor([2.0, -1.0], requires_grad=True)
J = jacobian(g, x)
print("Jacobian shape:", J.shape) # (3, 2)
print(J)
Hessiana de uma função escalar:
from torch.autograd.functional import hessian
def f(x):
return (x[0]**2 + 3*x[1])**2
x = torch.tensor([2.0, -1.0], requires_grad=True)
H = hessian(f, x)
print("Hessian shape:", H.shape) # (2, 2)
print(H)
Aviso prático: hessianas explícitas não escalam
Para (n) parâmetros, a hessiana é (n\times n). Para (n=10^7), é impossível armazenar. Em aprendizado profundo, você normalmente depende de:
- gradientes ((O(n))),
- produtos jacobiana-vetor ou vetor-jacobiana (baratos),
- produtos hessiana-vetor (baratos-ish),
- aproximações de curvatura de baixo posto ou diagonais.
Armadilhas comuns e convenções
Confusão entre gradiente e jacobiana
- Se a saída é escalar, a derivada em relação a um vetor é um gradiente.
- Se a saída é vetor, a derivada em relação a um vetor é uma jacobiana.
- Se você tira segundas derivadas de um escalar em relação a um vetor, isso é uma hessiana.
Um guia rápido:
- (f:\mathbb{R}^n\to\mathbb{R}) → (\nabla f \in \mathbb{R}^n), (H_f \in \mathbb{R}^{n\times n})
- (g:\mathbb{R}^n\to\mathbb{R}^m) → (J_g \in \mathbb{R}^{m\times n})
Derivadas como vetor-linha vs vetor-coluna
Campos diferentes colocam derivadas em linhas vs colunas, o que muda se regras da cadeia usam transpostas. A prática em ML é amplamente consistente com tratar gradientes como vetores-coluna e usar (J^\top) na propagação no estilo de retropropagação.
Funções não suaves
A unidade linear retificada (ReLU) e operações de máximo não são diferenciáveis em alguns pontos. Na prática, frameworks de diferenciação automática usam subgradientes (subgradients) ou definem derivadas quase em todo lugar, o que é suficiente para otimização no estilo de SGD.
Resumo de intuição: o que cada objeto “significa”
- Gradiente (\nabla f(x)): um vetor apontando para cima; a magnitude indica quão íngreme é.
Usado para “para que lado os parâmetros devem se mover para diminuir a perda?” - Jacobiana (J_g(x)): uma matriz descrevendo a melhor aproximação linear de uma função vetorial perto de (x).
Usada para “como uma saída vetorial inteira muda se as entradas mudarem?” - Hessiana (H_f(x)): uma matriz descrevendo curvatura; como o próprio gradiente muda.
Usada para “quão confiável é o passo do gradiente, e como devemos reescalá-lo?”
Esses três são a linguagem central do cálculo multivariado em IA: gradientes conduzem o aprendizado, jacobianas explicam sensibilidade e composição, e hessianas fornecem intuição de curvatura que motiva métodos (aproximados) de segunda ordem.