Conexões Residuais

Demonstrações interativas da aula de conexões residuais

Quatro visualizações que acompanham os slides: o treino ao vivo de uma rede plain hl = fl[hl−1, θl] contra uma rede residual hl = hl−1 + fl[hl−1, θl], o gradiente quebrado e o termo identidade em ∂y/∂f1 = I + …, os 2n caminhos da entrada à saída e a variância que dobra a cada bloco, σout² = 2σin², controlada pelo batch norm.

1 · Plain vs residual: treino ao vivo

A rede plain processa as camadas em sequência, hl = fl[hl−1, θl], enquanto a rede residual adiciona uma cópia da entrada a cada bloco, hl = hl−1 + fl[hl−1, θl]. Como nos slides, cada bloco fl é ReLU seguida de Linear, com uma transformação Linear inicial antes dos blocos. Na rede residual a soma da junção é dividida por √2 para manter a variância das ativações, o papel que o batch norm cumpre nas ResNets reais (seção 4). As duas redes partem exatamente dos mesmos pesos (inicialização He) e recebem os mesmos passos de otimização (Adam, η = 0.01) numa regressão 1D com 80 pontos. A única diferença é a presença do skip. Aumente a profundidade e observe a degradação da rede plain, o fenômeno que motivou a ResNet.

Dados, função alvo (tracejada) e ajustes: plain (ciano) vs residual (laranja)

log₁₀ MSE por passo de treino

💡 Com 4 a 8 blocos as duas redes ajustam bem e a comparação quase empata. Com 16 ou 20 blocos a rede plain frequentemente trava numa aproximação grosseira (a curva ciano de loss estagna ordens de grandeza acima) enquanto a residual recupera todas as oscilações do alvo. Use 🎲 para repetir o experimento com outros dados e outra inicialização: em algumas sementes a plain até escapa, mas raramente alcança a residual, que converge de forma consistente em todas.

2 · Gradiente quebrado e o termo identidade

Pela regra da cadeia, numa rede plain o gradiente atravessa um produto de derivadas: ∂f4/∂f1 = (∂f4/∂f3)(∂f3/∂f2)(∂f2/∂f1). Em redes muito profundas, ∂y/∂x se torna errático em relação à entrada, o gradiente quebrado (shattered gradient). Na rede residual a derivada tem múltiplos termos, ∂y/∂f1 = I + ∂f2/∂f1 + …, e o termo identidade I garante um caminho que não passa por nenhum produto. À esquerda, a derivada ∂y/∂x de redes recém-inicializadas (curvas centradas e normalizadas para comparar a forma). À direita, a norma ‖∂y/∂hl por camada, em escala log. O ganho g multiplica os pesos He dos blocos: com g < 1 as derivadas encolhem e o produto da rede plain dissipa. No ramo residual a entrada de cada bloco é normalizada, papel que o batch norm cumpre na prática (seção 4).

∂y/∂x em função de x: plain (ciano) vs residual (laranja), curvas normalizadas

log₁₀ ‖∂y/∂hl‖ por camada l (l = 0 é a entrada)

💡 Com profundidade 30 e g = 1 a curva ciano vira ruído, pequenos deslocamentos em x mudam o gradiente por completo, enquanto a laranja preserva estrutura suave. Com g = 0.7 a norma da plain despenca em linha reta na escala log (decaimento exponencial) e a residual fica presa perto de 10⁰: é o termo I impedindo a dissipação. Com g = 1.3 compare o crescimento das duas.

3 · Um bloco por vez: 2n caminhos

Abrindo a expressão da rede residual, a saída vira uma soma de contribuições: y = x + f1[x] + f2[x + f1[x]] + … Cada bloco pode ser pulado (segue pela skip connection) ou aplicado (segue por fi), então uma rede com n blocos residuais tem 2n caminhos distintos da entrada à saída, e 2n−1 deles passam por cada fi específica. Use ⏭ para percorrer os caminhos um a um no grafo. O gráfico da direita conta quantos caminhos existem com cada profundidade k (coeficiente binomial C(n, k)): a saída funciona como um ensemble implícito de redes de profundidades diferentes.

Grafo com os blocos fi e as skip connections; o caminho atual em laranja

Número de caminhos por profundidade k; a barra do caminho atual em laranja

💡 Com n = 4 existem 16 caminhos e 8 deles passam por f1. Repare na distribuição: só 1 caminho usa todos os blocos e só 1 não usa nenhum (a identidade pura, que carrega o termo I do gradiente); a maioria tem profundidade intermediária. Suba para n = 5 e veja os 32 caminhos: dobrar os blocos dobra o número de caminhos, o crescimento é exponencial.

4 · Variância das ativações e batch norm

Assumindo independência entre a entrada X e a saída do ramo processado Y, a variância da soma é Var[X+Y] = Var[X] + Var[Y]. Com inicialização He os dois ramos têm a mesma variância, então σout² = 2σin²: a variância dobra a cada bloco residual e logo excede a precisão de ponto flutuante. O batch norm padroniza as ativações do mini batch, hi ← (hi − μh)/(σh + ε), e depois reescala com γhi + β, com γ = 1 e β = 0 na inicialização. Aplicado antes de cada bloco, o ramo processado passa a contribuir variância 1, e a variância total cresce 1, 2, 3, …, linear em vez de exponencial. A simulação abaixo propaga um batch de 128 amostras N(0, 1) por blocos ReLU → Linear de largura 32.

log₂ da variância das ativações após cada bloco k; tracejado: referência 2k

Histograma das ativações após o último bloco

💡 Em escala log₂, a curva sem batch norm (ciano) é uma reta de inclinação ≈ 1, cada bloco dobra a variância: com 10 blocos ela passa de 2¹⁰ ≈ 1000. A curva com batch norm (laranja) segue log₂(k+1), crescimento linear. No histograma, as ativações sem batch norm se espalham tanto que as com batch norm viram um pico estreito no centro. Use 🎲 para confirmar que o comportamento não depende dos pesos sorteados, é estrutural.