Desaparecimento e explosão de gradientes

Aprendizagem profunda intermediária com PyTorch

Michal Oleszak

Machine Learning Engineer

Gradientes que somem

  • Gradientes ficam cada vez menores no backward
  • Camadas iniciais recebem updates pequenos
  • O modelo não aprende

Gráficos mostrando o tamanho do gradiente versus índice da camada: nas camadas iniciais, os gradientes são menores

Aprendizagem profunda intermediária com PyTorch

Gradientes que explodem

  • Gradientes ficam cada vez maiores
  • Updates de parâmetros são grandes demais
  • O treino diverge

Gráficos mostrando o tamanho do gradiente versus índice da camada: nas camadas iniciais, os gradientes são maiores

Aprendizagem profunda intermediária com PyTorch

Solução para gradientes instáveis

  1. Inicialização correta dos pesos
  2. Boas ativações
  3. Batch normalization

 

 

Três passos

Aprendizagem profunda intermediária com PyTorch

Inicialização de pesos

layer = nn.Linear(8, 1)
print(layer.weight)
Parameter containing:
tensor([[-0.0195,  0.0992,  0.0391,  0.0212,
         -0.3386, -0.1892, -0.3170,  0.2148]])
Aprendizagem profunda intermediária com PyTorch

Inicialização de pesos

Boa inicialização garante:

  • Variância das entradas = variância das saídas da camada
  • Variância dos gradientes igual antes e depois da camada

 

Como atingir isso depende da ativação:

  • Para ReLU e parecidas, use inicialização de He/Kaiming
Aprendizagem profunda intermediária com PyTorch

Inicialização de pesos

import torch.nn.init as init

init.kaiming_uniform_(layer.weight)
print(layer.weight)
Parameter containing:
tensor([[-0.3063, -0.2410,  0.0588,  0.2664,
          0.0502, -0.0136,  0.2274,  0.0901]])
Aprendizagem profunda intermediária com PyTorch

Inicialização de He / Kaiming

init.kaiming_uniform_(self.fc1.weight)
init.kaiming_uniform_(self.fc2.weight)
init.kaiming_uniform_(
  self.fc3.weight,
  nonlinearity="sigmoid",
)
Aprendizagem profunda intermediária com PyTorch

Inicialização de He / Kaiming

import torch.nn as nn
import torch.nn.init as init

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(9, 16)
        self.fc2 = nn.Linear(16, 8)
        self.fc3 = nn.Linear(8, 1)


init.kaiming_uniform_(self.fc1.weight) init.kaiming_uniform_(self.fc2.weight) init.kaiming_uniform_( self.fc3.weight, nonlinearity="sigmoid", )




    def forward(self, x):
        x = nn.functional.relu(self.fc1(x))
        x = nn.functional.relu(self.fc2(x))
        x = nn.functional.sigmoid(self.fc3(x))
        return x







Aprendizagem profunda intermediária com PyTorch

Funções de ativação

Um gráfico mostrando a função ReLU. Para valores abaixo de zero, a linha fica horizontal em zero; para valores acima de zero, a curva tem inclinação positiva.

  • Geralmente a ativação padrão
  • nn.functional.relu()
  • Zero para entradas negativas — neurônios mortos

Um gráfico mostrando a função ELU. Parecida com a ReLU, mas com transição curva e suave de valores negativos para a região positiva.

  • nn.functional.elu()
  • Gradientes não nulos para valores negativos — evita neurônios mortos
  • Saída média perto de zero — ajuda contra gradientes que somem
Aprendizagem profunda intermediária com PyTorch

Batch normalization

Após uma camada:

  1. Normalize as saídas da camada:

    • Subtraindo a média
    • Dividindo pelo desvio padrão
  2. Escale e desloque as saídas normalizadas com parâmetros aprendidos

O modelo aprende a distribuição ótima de entradas por camada:

  • Perda cai mais rápido
  • Ajuda contra gradientes instáveis
Aprendizagem profunda intermediária com PyTorch

Batch normalization

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(9, 16)
        self.bn1 = nn.BatchNorm1d(16)

        ...


def forward(self, x): x = self.fc1(x) x = self.bn1(x) x = nn.functional.elu(x) ...
Aprendizagem profunda intermediária com PyTorch

Vamos praticar!

Aprendizagem profunda intermediária com PyTorch

Preparing Video For Download...