Ir para o conteúdo

7. Regularization

Um modelo que acerta perfeitamente os dados de treino não é o objetivo — é um sinal de alerta. O que queremos de fato é um modelo que vá bem em dados que ele nunca viu, e essas duas coisas puxam para lados opostos. Regularização é o nome de toda técnica que piora de propósito o ajuste no treino em troca de um ajuste melhor em todo o resto.

Formalmente, o treinamento minimiza a perda que conseguimos medir, sobre os \(N\) exemplos que por acaso temos:

\[ \hat{R}(\theta) = \frac{1}{N}\sum_{i=1}^{N} L\big(f_\theta(x^{(i)}), y^{(i)}\big) \]

mas o que nos interessa é a perda sobre toda a distribuição de onde os dados vieram, que não conseguimos medir:

\[ R(\theta) = \mathbb{E}_{(x,y)\sim \mathcal{D}}\big[L(f_\theta(x), y)\big] \]

A diferença \(R(\theta) - \hat{R}(\theta)\) é a lacuna de generalização, e toda técnica deste capítulo é uma tentativa de mantê-la pequena.

Vendo acontecer

Nada explica overfitting melhor do que assistir a ele. Abaixo, 12 pontos com ruído são sorteados de uma função suave e um polinômio do grau que você escolher é ajustado a eles por mínimos quadrados. A linha tracejada é a verdade que queremos recuperar; os "×" são pontos separados que o ajuste nunca viu.

Três experimentos que valem a pena, nesta ordem:

  1. Grau 1, depois 3, depois 14, com \(\lambda = 0\). O grau 1 não consegue curvar. O grau 3 chega perto da verdade. O grau 14 passa por cima de cada ponto de treino — o erro de treino desaba para praticamente zero — e dá guinadas violentas entre eles. Isso é overfitting: não um modelo errado, e sim um modelo que está certo sobre o ruído.
  2. Fique no grau 14 e aumente o \(\lambda\). Nada no modelo encolhe; ele continua com 15 coeficientes. Mas a curva selvagem se acalma e o erro fora da amostra cai. Capacidade nunca foi o problema — capacidade sem restrição era.
  3. Fique no grau 14, \(\lambda = 0\), e arraste o número de pontos para cima. O mesmo modelo que era inútil com 12 pontos fica razoável com 60. Mais dados também é regularização, e é a mais eficaz de todas.

Acompanhe o ‖w‖² no rodapé

Percorra os graus com 12 pontos e siga os coeficientes: \(\lVert w \rVert^2\) vai de cerca de \(5\) no grau 3 para \(5\times10^{5}\) no grau 14. Coeficientes enormes de sinais alternados são exatamente como uma curva produz aquelas guinadas entre os pontos, e é sobre essa observação que todo método de penalização deste capítulo é construído: com uma quantidade fixa de dados, pesos enormes são a assinatura de um modelo que está decorando.

A ressalva importa. Suba os dados para 60 pontos e o grau 14 generaliza bem ainda tendo uma norma enorme — ou seja, a norma sozinha não é um veredito, e é por isso que limitantes baseados apenas no tamanho dos pesos explicam muito menos sobre redes profundas do que gostaríamos1.

Viés e variância

As duas falhas daquele simulador têm nome, e vêm de decompor o erro esperado de um modelo em partes. Para a perda quadrática, em um ponto \(x\), tomando a média sobre todos os conjuntos de treino que poderíamos ter sorteado:

\[ \mathbb{E}\big[(y - \hat{f}(x))^2\big] \;=\; \underbrace{\big(\mathbb{E}[\hat{f}(x)] - f(x)\big)^2}_{\text{viés}^2} \;+\; \underbrace{\mathbb{E}\big[(\hat{f}(x) - \mathbb{E}[\hat{f}(x)])^2\big]}_{\text{variância}} \;+\; \underbrace{\sigma^2}_{\text{ruído}} \]

Leia os três termos como três reclamações diferentes:

  • Viés — o modelo erra sistematicamente, do mesmo jeito, não importa qual conjunto de treino ele receba. O ajuste de grau 1 é enviesado: ele não consegue curvar, então erra a curva sempre.
  • Variância — o modelo muda radicalmente conforme o conjunto de treino que calhou de ver. O ajuste de grau 14 tem variância enorme: sorteie outros 12 pontos e você obtém uma curva completamente diferente.
  • Ruído — a parte irredutível, \(\sigma^2 = 0{,}032\) no simulador. Nenhum modelo vence isso, e um modelo que fica abaixo disso nos dados de treino está ajustando ruído por definição.

A capacidade do modelo troca o primeiro pelo segundo, e é esse o clássico tradeoff viés-variância:

Underfitting e overfitting. Fonte: GeeksforGeeks2

  • Viés demais (underfitting)


    Erro de treino e de validação altos e próximos um do outro.

    • Aumente a capacidade: mais camadas, mais unidades.
    • Treine por mais tempo — pode ser que você simplesmente não tenha convergido.
    • Acrescente ou construa features; revise o pipeline de dados.
    • Reduza a regularização que você já tem.
  • Variância demais (overfitting)


    Erro de treino baixo, erro de validação bem mais alto. A lacuna é o sintoma.

    • Mais dados, ou aumento de dados para simular mais dados.
    • Penalize os pesos (L1/L2), acrescente dropout, pare cedo.
    • Reduza a capacidade — último recurso, não o primeiro.
    • Verifique se não há vazamento antes de acreditar em qualquer coisa disso.

A curva em U não é mais a história completa

O quadro clássico diz que o erro de teste cai, atinge um mínimo e sobe para sempre conforme a capacidade cresce. Redes modernas quebram isso: empurre a capacidade para além do ponto em que o modelo interpola perfeitamente o conjunto de treino e o erro de teste muitas vezes volta a cair, às vezes abaixo do primeiro mínimo. Isso é o duplo descenso34, e é por isso que "é só diminuir o modelo" é um conselho ruim para redes profundas. A curva que lhe ensinaram continua descrevendo o regime subparametrizado — a maioria das redes profundas simplesmente não vive nele.

Penalizando os pesos: L1 e L2

A lição do simulador foi que decorar exige coeficientes enormes. Então some o tamanho deles à perda e deixe o otimizador equilibrar os dois objetivos:

\[ \tilde{J}(w) = J(w) + \frac{\lambda}{2}\sum_i w_i^2 \]

O gradiente da penalidade é \(\lambda w\), então um passo de gradiente vira

\[ w \leftarrow w - \eta\nabla J(w) - \eta\lambda w = \underbrace{(1 - \eta\lambda)}_{\text{encolhe}} w - \eta \nabla J(w) \]

Cada passo multiplica os pesos por um fator um pouco menor que 1 antes de aplicar o gradiente — que é exatamente por que a mesma ideia se chama weight decay5. Um peso só sobrevive se o gradiente continuar empurrando-o de volta para cima, então a penalidade age como uma pressão constante rumo a zero, da qual os pesos úteis precisam se safar.

\[ \tilde{J}(w) = J(w) + \lambda\sum_i |w_i| \]

O gradiente da penalidade é \(\lambda\,\mathrm{sign}(w)\) — do mesmo tamanho por menor que \(w\) seja. Onde a L2 empurra proporcionalmente (e portanto empurra cada vez mais de leve conforme o peso encolhe), a L1 empurra com força constante até zero, e segura ali.

O resultado são zeros exatos, não apenas valores pequenos: a L1 faz seleção de variáveis como efeito colateral da otimização6.

Por que a L1 dá zeros e a L2 não

Isso é mais fácil de ver do que de provar. Abaixo, as elipses são as curvas de nível da perda sem regularização e a região sombreada é o que a penalidade permite; a solução penalizada fica onde a menor elipse toca essa região. Arraste o ponto branco — o ótimo sem penalidade — e veja o que cada penalidade faz com ele.

arraste o ponto para mover o ótimo sem regularização

As formas são o argumento inteiro. A região da L2 é um círculo, que é liso em todo ponto, então o lugar onde ele encosta pela primeira vez em uma elipse quase nunca cai sobre um eixo — as duas coordenadas terminam pequenas, mas vivas. A região da L1 é um losango, e um losango é só quinas; as quinas ficam sobre os eixos, e uma elipse que encolhe atinge uma quina vindo de uma faixa larga de direções. Isso é esparsidade: não um acidente numérico, mas consequência da forma.

Tente arrastar o \(\hat{w}\) para perto de um dos eixos e aumentar o \(\lambda\) — a solução da L1 gruda no eixo e fica lá, enquanto a da L2 desliza rumo à origem sem nunca chegar.

Weight decay não é penalidade L2 quando você usa Adam

Somar \(\frac{\lambda}{2}\lVert w \rVert^2\) à perda e encolher os pesos por \((1-\eta\lambda)\) a cada passo são a mesma operação no SGD puro — como mostra a derivação acima. Elas deixam de ser a mesma coisa no instante em que o otimizador reescala o gradiente por parâmetro, porque a penalidade é reescalada junto. É exatamente esse o defeito que o AdamW corrige, tratado no capítulo de otimização. No PyTorch: torch.optim.AdamW(..., weight_decay=0.01) encolhe; Adam(..., weight_decay=0.01) penaliza, e as duas coisas não significam o mesmo.

Não penalize tudo

Penalize matrizes de pesos. Deixe de fora os vieses (eles deslocam, não escalam, e encolhê-los apenas enviesa a saída) e o ganho/deslocamento de toda camada de normalização (encolher o \(\gamma\) rumo a 0 briga justamente com aquilo que a camada existe para fazer). \(\lambda\) típico: \(10^{-5}\) a \(10^{-2}\) para CNNs treinadas com SGD, \(0{,}01\)\(0{,}1\) para Transformers com AdamW.

Dropout: quebrar as co-adaptações

O dropout7 ataca uma falha diferente. Uma rede consegue decorar formando grupos co-adaptados de neurônios: detectores que só funcionam porque algum outro neurônio específico está ali para corrigi-los. Um comitê desses é frágil, e é exatamente ele que falha em dados novos.

A solução é bruta. A cada passo de treino, cada unidade é apagada de forma independente com probabilidade \(p\):

\[ m_j \sim \text{Bernoulli}(1-p), \qquad \tilde{h}_j = \frac{m_j}{1-p}\, h_j \]

Nenhuma unidade pode contar com a presença de outra, porque qualquer uma delas pode sumir no próximo passo. Cada neurônio é forçado a ser útil sozinho, e a rede para de depositar toda a confiança em poucos caminhos frágeis.

Há uma segunda leitura da mesma equação. Cada máscara é uma sub-rede diferente, e com \(n\) unidades existem \(2^n\) delas compartilhando pesos. Treinar com dropout treina esse conjunto inteiro um pouquinho de cada vez, e testar sem dropout aproxima a média das previsões de todas — um ensemble pelo preço de um único modelo.

Esquerda: rede padrão com duas camadas ocultas. Direita: uma rede reduzida produzida pelo dropout; as unidades marcadas foram descartadas naquele passo. Fonte: Srivastava et al.7

O \(1/(1-p)\) que todo mundo erra

Apagar unidades no treino diminui o valor esperado do que a camada seguinte recebe. Isso precisa ser compensado, e há duas formas de fazer:

quando o que acontece no teste
Dropout original (artigo de 2014) multiplica os pesos por \(1-p\) no teste a inferência precisa conhecer \(p\) e reescalar
Dropout invertido (o que todo mundo implementa) divide por \(1-p\) durante o treino nada — a inferência é uma passagem direta comum

Todo framework em uso hoje faz a versão invertida, e é por isso que o model.eval() simplesmente desliga o dropout em vez de reescalar coisa alguma. Veja a esperança sendo preservada:

Deixe rodando: a média da saída de treino converge para a saída de inferência, qualquer que seja o \(p\). É esse o sentido inteiro de dividir por \(1-p\) — a camada seguinte enxerga a mesma entrada esperada nos dois modos, então a rede que você treina é a rede que você põe em produção. Suba o \(p\) para 0,9 e veja a média demorar muito mais para assentar: dropout pesado preserva a média mas acrescenta uma variância enorme, e é por isso que ele atrasa a convergência.

Esquecer o model.eval()

Dropout ativo na inferência torna as previsões aleatórias, e a batch normalization continua atualizando as estatísticas correntes. É o bug mais comum em código de aluno — e ele não quebra nada, apenas piora os resultados em silêncio e os torna irreprodutíveis. Sempre model.eval() para validação e inferência, model.train() para voltar.

Onde o dropout é usado hoje

Camadas totalmente conectadas O território natural dele. \(p = 0{,}2\)\(0{,}5\)
Camadas convolucionais Raramente, e com \(p\) pequeno; o compartilhamento de pesos já regulariza e a BatchNorm concorre
Transformers Sim, mas com moderação (\(p = 0{,}1\) típico) nos blocos de atenção e MLP, além de stochastic depth
Camada de saída Nunca
Camada de entrada Ocasionalmente, com \(p\) pequeno (10–20%) — mais próximo de aumento de dados que de dropout

Dropout e BatchNorm se desentendem

Juntos, eles brigam: o dropout muda a variância das ativações entre treino e inferência, enquanto a BatchNorm memorizou estatísticas do regime de treino. O descompasso está documentado8, e as regras práticas que saíram dali são pôr o dropout depois da camada de normalização, nunca entre a convolução e a BN, e usar menos dos dois do que você usaria de cada um sozinho. Quando as arquiteturas modernas escolhem um, costumam escolher a normalização.

Camadas de normalização

A batch normalization9 padroniza a entrada de uma camada usando as estatísticas do mini-batch atual:

\[ \hat{x} = \frac{x - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}}, \qquad y = \gamma \hat{x} + \beta \]

onde \(\mu_B\) e \(\sigma_B^2\) são a média e a variância sobre o batch, e \(\epsilon \approx 10^{-5}\) mantém a raiz longe de zero. O \(\gamma\) e o \(\beta\) aprendidos deixam a camada desfazer a normalização se for isso que ajuda — inclusive recuperando a identidade, de modo que a camada nunca custa poder de representação à rede.

O \(\epsilon\) vai dentro da raiz

\(\dfrac{x-\mu}{\sqrt{\sigma^2+\epsilon}}\), e não \(\dfrac{x-\mu}{\sigma+\epsilon}\). A segunda forma é um erro de digitação comum e não é equivalente: ela altera a escala de toda ativação por uma quantidade que depende de \(\sigma\), em vez de apenas proteger uma divisão.

Treino e inferência são contas diferentes

Esta é a parte que derruba as pessoas, e vale ser exato aqui, porque é também de onde vem o efeito regularizador.

estatísticas usadas \(\gamma,\beta\) estatísticas correntes
Treino (model.train()) média/variância do batch atual aprendidos atualizadas
Inferência (model.eval()) médias correntes fixas, coletadas no treino aprendidos congeladas

No treino, o valor normalizado de uma amostra depende de quais outras amostras caíram no batch dela — então a mesma imagem ganha uma representação um pouco diferente dependendo da companhia. Isso é ruído injetado na passagem direta, e é por isso que a batch normalization regulariza. Na inferência o batch não existe e a rede precisa ser determinística, então as médias armazenadas assumem.

Repare no que isso não diz: a batch normalization não é "desligada" na inferência. Ela sempre roda — apenas troca quais estatísticas usa. Desligá-la mudaria a escala de toda ativação e destruiria o modelo.

Por que funciona — não pelo motivo dado originalmente

O artigo original explicava o benefício como redução do internal covariate shift: a deriva na distribuição de entrada de cada camada conforme as camadas abaixo aprendem. Essa história foi testada diretamente e não se sustentou — uma rede com ruído injetado de propósito depois da normalização, restaurando a deriva, treina igualmente bem10. A explicação atual é que a normalização deixa a superfície de perda mais suave e seus gradientes mais previsíveis, o que é o que permite taxas de aprendizado maiores. A técnica funciona; o mecanismo do resumo de 2015, não.

LayerNorm, e por que os Transformers a usam no lugar

A batch normalization tem uma fraqueza estrutural: ela precisa de um batch. Isso quebra com batch de tamanho 1, com sequências de comprimento variável, e faz treino e inferência se comportarem de forma diferente por construção.

A LayerNorm11 normaliza sobre as features de uma única amostra, em vez de sobre o batch:

\[ \mu = \frac{1}{d}\sum_{j=1}^{d} x_j, \qquad \sigma^2 = \frac{1}{d}\sum_{j=1}^{d}(x_j - \mu)^2 \]

Cada amostra passa a ser normalizada pelas próprias estatísticas. Não há nada a promediar no batch, então não há estatísticas correntes, treino e inferência são a mesma conta, e o tamanho do batch é irrelevante. É por isso que todo Transformer a usa — e também por que a LayerNorm não regulariza: sem batch, não há ruído vindo da composição do batch.

Parar cedo

Treine tempo suficiente um modelo com capacidade sobrando e ele vai começar a ajustar o ruído. A perda de validação registra o momento: ela cai junto com a de treino por um tempo, atinge o fundo e depois sobe enquanto a de treino continua descendo. Early stopping é a decisão de guardar o modelo do fundo dessa curva.

A receita tem três partes, e a terceira é a que as pessoas esquecem:

  1. Avalie em uma partição de validação a cada época (ou a cada \(k\) passos).
  2. Paciência12 — quantas avaliações sem melhora você tolera antes de parar. Pequena demais e você desiste por causa de ruído; grande demais e você gasta computação depois do ponto sem volta.
  3. Restaure o melhor checkpoint. Parar não basta — os pesos que estão na memória quando você para são os piores, de paciência épocas depois do mínimo. Guarde uma cópia do melhor.

Abaixo, um polinômio de grau 15 é ajustado a 10 pontos ruidosos por gradiente descendente puro. Nada é penalizado e nada é descartado; a única coisa que varia é quando você para.

O painel da direita é o ponto: um treino, dois modelos muito diferentes. A curva verde — a que você guarda — acompanha a verdade. A vermelha custou noventa vezes mais computação (20 000 épocas contra 225), passa por cima de cada ponto de treino e é pior em todo o resto. E a perda de treino dela é genuinamente menor. A armadilha é essa.

Early stopping é regularização, num sentido preciso

Não é um truque pregado por fora. Para um modelo linear treinado por gradiente descendente a partir de zero, parar depois de \(t\) passos entrega quase exatamente a solução ridge com \(\lambda \approx 1/(\eta t)\): o gradiente descendente pega primeiro as direções bem determinadas dos dados e por último as ruidosas e mal determinadas, então parar cedo deixa estas últimas perto de zero — a mesma coisa que a penalidade L2 faz explicitamente13. Treinar mais e regularizar menos são dois nomes para um só botão.

Mais dados, e como fabricá-los

Volte ao primeiro simulador e arraste o número de pontos de 12 para 60 com grau 14 e sem penalidade. O modelo que era inútil fica bom. Nada no modelo mudou — a restrição veio dos dados. Vale dizer isso sem rodeios, porque reordena todas as prioridades deste capítulo: quando o problema é overfitting, mais dados é a melhor resposta disponível, e todo o resto é o que se faz quando não dá para conseguir mais.

Muitas vezes dá para fabricar alguns, porém, explorando invariâncias que você já conhece:

Um gato rotacionado continua sendo um gato, então uma imagem de treino rotacionada é um exemplo extra de graça. Cada transformação que você aplica afirma uma invariância que o modelo deveria ter — e é por isso que aumento de dados é conhecimento de domínio disfarçado, e por que a transformação errada atrapalha: espelhar dígitos horizontalmente ensina ao modelo que 2 e 5 são a mesma coisa.

train_tf = transforms.Compose([
    transforms.RandomResizedCrop(224, scale=(0.6, 1.0)),
    transforms.RandomHorizontalFlip(),          # um gato espelhado é um gato
    transforms.ColorJitter(0.3, 0.3, 0.3),      # um gato sob luz mais quente também
    transforms.ToTensor(),
])
val_tf = transforms.Compose([                   # nunca aumente a validação
    transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(),
])

Políticas automáticas (RandAugment14 e parentes) buscam o conjunto de transformações para você e hoje são padrão em visão.

Em vez de exigir probabilidade 1 na classe correta, exija \(1-\alpha\):

\[ y^{\text{LS}}_k = (1-\alpha)\, y_k + \frac{\alpha}{K} \]

Com alvos one-hot, a entropia cruzada só é minimizada quando o logit correto vai para o infinito, o que é um convite direto ao excesso de confiança. O suavizamento (\(\alpha = 0{,}1\) tipicamente) dá ao ótimo uma posição finita15. Ele melhora acurácia e calibração de forma confiável — mas também colapsa a geometria da penúltima camada, o que atrapalha se você pretende usar aqueles embeddings para busca ou destilação16.

Treine com combinações convexas de pares de exemplos e de seus rótulos17:

\[ \tilde{x} = \lambda x_i + (1-\lambda) x_j, \qquad \tilde{y} = \lambda y_i + (1-\lambda) y_j \]

com \(\lambda \sim \text{Beta}(\alpha, \alpha)\). Parece absurdo — imagens meio gato, meio cachorro, com rótulos meio a meio — e funciona, porque força o modelo a se comportar linearmente entre os exemplos de treino em vez de fazer qualquer coisa ali. Esse "qualquer coisa entre os pontos" era exatamente o que o polinômio com overfitting estava fazendo.

Juntando tudo

Nenhuma técnica isolada é o regularizador; treinos reais empilham várias, e elas não são intercambiáveis. Ordenadas pelo que de fato fazem:

Mecanismo Técnica Onde ela se justifica
Restringir os pesos L2 / weight decay Quase sempre ligada. 1e-4 com SGD, 0,010,1 com AdamW
L1 Quando você quer esparsidade ou seleção de variáveis; raro em redes profundas
Injetar ruído Dropout Camadas densas, blocos de Transformer. \(p = 0{,}1\)\(0{,}5\)
Batch normalization CNNs — como efeito colateral; o trabalho principal dela é otimização
Aumento de dados, mixup Visão e áudio, onde as invariâncias são conhecidas. A alavanca mais forte depois de dados crus
Limitar a busca Early stopping De graça, sempre. Custa uma partição de validação
Suavizar o alvo Label smoothing Classificação com muitas classes, \(\alpha = 0{,}1\)
Acrescentar dados Mais dados rotulados Vence todas as linhas acima. Tente isso primeiro

Uma ordem sensata para tentar as coisas

  1. Faça o modelo dar overfitting primeiro. Um modelo que não consegue decorar um subconjunto pequeno tem um bug, não um problema de regularização — e nenhuma dose de dropout conserta um pipeline quebrado.
  2. Ligue as de graça: weight decay e early stopping.
  3. Acrescente aumento de dados se o domínio tiver invariâncias que você saiba nomear.
  4. Só então recorra a dropout, label smoothing, mixup — um de cada vez, medindo cada um.
  5. Diminua o modelo por último. Capacidade raramente é o problema real.

Lendo as duas curvas

O que você vê O que significa O que fazer
Treino ↓, validação ↓, próximas Saudável, ainda aprendendo Continue treinando
Treino ↓, validação estaciona e ↑ Overfitting daqui em diante Pare cedo; regularize; consiga dados
Treino e validação altos e próximos Underfitting Mais capacidade, treino mais longo, menos regularização
Erro de treino ≫ validação (validação melhor) Dropout/BN ainda ligados na avaliação, ou vazamento entre as partições Cheque o model.eval() e a partição
Validação pulando muito Conjunto de validação pequeno demais, ou taxa de aprendizado alta Partição maior, η menor
Validação perfeita Vazamento. Sempre vazamento Audite como a partição foi construída

Pontos-chave

  1. O alvo é a lacuna de generalização, não a perda de treino. Perda de treino zero é um sintoma a investigar, não uma conquista.
  2. Underfitting e overfitting se diagnosticam com dois números, nunca com um: erro de treino e erro de validação, lidos juntos.
  3. O overfitting aparece nos pesos — coeficientes enormes de sinais alternados — e é isso que faz penalizá-los funcionar.
  4. A L2 encolhe os pesos proporcionalmente e nunca chega a zero; a L1 empurra com força constante e produz zeros exatos. A diferença é a forma da região que cada uma permite.
  5. O dropout quebra co-adaptações e aproxima um ensemble de \(2^n\) sub-redes. As implementações modernas escalam por \(1/(1-p)\) durante o treino, então a inferência é uma passagem direta comum.
  6. A normalização ajuda primeiro a otimização e regulariza em segundo lugar; o ruído regularizador da batch norm vem da composição do batch, que é exatamente o que a LayerNorm abre mão.
  7. Early stopping não é um truque — para modelos lineares está provado que ele fica perto do ridge, com \(\lambda \approx 1/(\eta t)\).
  8. Mais dados vence tudo isso. Aumento de dados é a segunda melhor coisa, porque é mais dados construídos a partir do que você já sabia.

Recursos Adicionais

Três lugares para ir em seguida, na ordem que faz sentido:

  1. Machine Learning Fundamentals: Bias and Variance — Starmer, J., StatQuest. Dez minutos sobre a decomposição com que este capítulo abre, em ritmo mais calmo e com outro conjunto de figuras. Assista primeiro se a seção de viés-variância pareceu abstrata:

  2. A Recipe for Training Neural Networks — Karpathy, A. A contraparte prática desta página: a ordem em que realmente se fazem as coisas, por que você deve provocar overfitting em um único batch antes de qualquer outra coisa, e um catálogo dos erros que parecem overfitting mas são bugs.

  3. Deep Learning, capítulo 7 — Regularization for Deep Learning — Goodfellow, I., Bengio, Y., & Courville, A. O tratamento de referência, com as derivações que esta página só menciona — inclusive a prova de que early stopping e L2 coincidem em modelos lineares.

Referências bibliográficas

As obras citadas ao longo do texto, na ordem em que aparecem:


  1. Zhang, C., Bengio, S., Hardt, M., Recht, B., & Vinyals, O. (2017). Understanding deep learning requires rethinking generalization — ICLR. Redes ajustam perfeitamente rótulos aleatórios, algo que nenhum limitante baseado no tamanho dos pesos prevê. 

  2. Underfitting and Overfitting in Machine Learning — GeeksforGeeks. Fonte da figura acima. 

  3. Belkin, M., Hsu, D., Ma, S., & Mandal, S. (2019). Reconciling modern machine-learning practice and the classical bias–variance trade-offPNAS 116(32), 15849–15854. Onde a curva de duplo descenso foi batizada. 

  4. Nakkiran, P., Kaplun, G., Bansal, Y., et al. (2021). Deep Double Descent: Where Bigger Models and More Data Hurt — ICLR. Mostra o efeito em redes reais, ao longo do tamanho do modelo, do conjunto de dados e do tempo de treino. 

  5. Hoerl, A. E., & Kennard, R. W. (1970). Ridge Regression: Biased Estimation for Nonorthogonal ProblemsTechnometrics 12(1), 55–67. A penalidade L2, vinda da estatística, décadas antes do deep learning. 

  6. Tibshirani, R. (1996). Regression Shrinkage and Selection via the LassoJournal of the Royal Statistical Society B 58(1), 267–288. A penalidade L1, e o argumento de esparsidade desenhado acima. 

  7. Srivastava, N., Hinton, G., Krizhevsky, A., Sutskever, I., & Salakhutdinov, R. (2014). Dropout: A Simple Way to Prevent Neural Networks from OverfittingJMLR 15, 1929–1958. 

  8. Li, X., Chen, S., Hu, X., & Yang, J. (2019). Understanding the Disharmony between Dropout and Batch Normalization by Variance Shift — CVPR. Mede o descompasso e deriva as regras de posicionamento. 

  9. Ioffe, S., & Szegedy, C. (2015). Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift — ICML. 

  10. Santurkar, S., Tsipras, D., Ilyas, A., & Madry, A. (2018). How Does Batch Normalization Help Optimization? — NeurIPS. O experimento que desmonta a explicação do internal covariate shift. 

  11. Ba, J. L., Kiros, J. R., & Hinton, G. E. (2016). Layer Normalization

  12. Prechelt, L. (1998). Early Stopping — But When? — em Neural Networks: Tricks of the Trade, Springer LNCS 1524. Compara critérios de parada em treinos reais; as heurísticas de paciência ainda em uso vêm daí. 

  13. Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep Learning, capítulo 7 — MIT Press. A seção 7.8 prova a equivalência entre early stopping e L2 para modelos lineares. 

  14. Cubuk, E. D., Zoph, B., Shlens, J., & Le, Q. V. (2020). RandAugment: Practical Automated Data Augmentation with a Reduced Search Space — NeurIPS. 

  15. Szegedy, C., Vanhoucke, V., Ioffe, S., Shlens, J., & Wojna, Z. (2016). Rethinking the Inception Architecture for Computer Vision — CVPR. A seção 7 introduz o label smoothing. 

  16. Müller, R., Kornblith, S., & Hinton, G. (2019). When Does Label Smoothing Help? — NeurIPS. Confirma os ganhos e mostra o que ele faz com a penúltima camada. 

  17. Zhang, H., Cissé, M., Dauphin, Y. N., & Lopez-Paz, D. (2018). mixup: Beyond Empirical Risk Minimization — ICLR.