A perda salta abruptamente quando decaimento da taxa de aprendizado com o otimizador Adam no PyTorch

10

Estou treinando uma auto-encoderrede com Adamotimizador (with amsgrad=True) e MSE losspara a tarefa de separação de fonte de áudio de canal único. Sempre que decai a taxa de aprendizado por um fator, a perda de rede aumenta bruscamente e depois diminui até a próxima queda na taxa de aprendizado.

Estou usando o Pytorch para implementação e treinamento de rede.

Following are my experimental setups:

 Setup-1: NO learning rate decay, and 
          Using the same Adam optimizer for all epochs

 Setup-2: NO learning rate decay, and 
          Creating a new Adam optimizer with same initial values every epoch

 Setup-3: 0.25 decay in learning rate every 25 epochs, and
          Creating a new Adam optimizer every epoch

 Setup-4: 0.25 decay in learning rate every 25 epochs, and
          NOT creating a new Adam optimizer every time rather
          using PyTorch's "multiStepLR" and "ExponentialLR" decay scheduler 
          every 25 epochs

Estou obtendo resultados muito surpreendentes para as configurações 2, 3 e 4 e não consigo explicar nenhuma explicação. A seguir estão meus resultados:

Setup-1 Results:

Here I'm NOT decaying the learning rate and 
I'm using the same Adam optimizer. So my results are as expected.
My loss decreases with more epochs.
Below is the loss plot this setup.

Trama-1:

Resultados da Configuração-1

optimizer = torch.optim.Adam(lr=m_lr,amsgrad=True, ...........)

for epoch in range(num_epochs):
    running_loss = 0.0
    for i in range(num_train):
        train_input_tensor = ..........                    
        train_label_tensor = ..........
        optimizer.zero_grad()
        pred_label_tensor = model(train_input_tensor)
        loss = criterion(pred_label_tensor, train_label_tensor)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    loss_history[m_lr].append(running_loss/num_train)

Setup-2 Results:  

Here I'm NOT decaying the learning rate but every epoch I'm creating a new
Adam optimizer with the same initial parameters.
Here also results show similar behavior as Setup-1.

Because at every epoch a new Adam optimizer is created, so the calculated gradients
for each parameter should be lost, but it seems that this doesnot affect the 
network learning. Can anyone please help on this?

Trama-2:

Resultados da Configuração-2

for epoch in range(num_epochs):
    optimizer = torch.optim.Adam(lr=m_lr,amsgrad=True, ...........)

    running_loss = 0.0
    for i in range(num_train):
        train_input_tensor = ..........                    
        train_label_tensor = ..........
        optimizer.zero_grad()
        pred_label_tensor = model(train_input_tensor)
        loss = criterion(pred_label_tensor, train_label_tensor)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    loss_history[m_lr].append(running_loss/num_train)

Setup-3 Results: 

As can be seen from the results in below plot, 
my loss jumps every time I decay the learning rate. This is a weird behavior.

If it was happening due to the fact that I'm creating a new Adam 
optimizer every epoch then, it should have happened in Setup #1, #2 as well.
And if it is happening due to the creation of a new Adam optimizer with a new 
learning rate (alpha) every 25 epochs, then the results of Setup #4 below also 
denies such correlation.

Trama-3:

Resultados da Instalação-3

decay_rate = 0.25
for epoch in range(num_epochs):
    optimizer = torch.optim.Adam(lr=m_lr,amsgrad=True, ...........)

    if epoch % 25 == 0  and epoch != 0:
        lr *= decay_rate   # decay the learning rate

    running_loss = 0.0
    for i in range(num_train):
        train_input_tensor = ..........                    
        train_label_tensor = ..........
        optimizer.zero_grad()
        pred_label_tensor = model(train_input_tensor)
        loss = criterion(pred_label_tensor, train_label_tensor)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    loss_history[m_lr].append(running_loss/num_train)

Setup-4 Results:  

In this setup, I'm using Pytorch's learning-rate-decay scheduler (multiStepLR)
which decays the learning rate every 25 epochs by 0.25.
Here also, the loss jumps everytime the learning rate is decayed.

Como sugerido por @Dennis nos comentários abaixo, tentei com ambas ReLUe 1e-02 leakyReLUnão - linearidades. Mas, os resultados parecem se comportar de maneira semelhante e a perda primeiro diminui, depois aumenta e depois satura em um valor mais alto do que o que eu obteria sem diminuir a taxa de aprendizado.

O gráfico 4 mostra os resultados.

Trama-4:

insira a descrição da imagem aqui

scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer=optimizer, milestones=[25,50,75], gamma=0.25)

scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer=optimizer, gamma=0.95)

scheduler = ......... # defined above
optimizer = torch.optim.Adam(lr=m_lr,amsgrad=True, ...........)

for epoch in range(num_epochs):

    scheduler.step()

    running_loss = 0.0
    for i in range(num_train):
        train_input_tensor = ..........                    
        train_label_tensor = ..........
        optimizer.zero_grad()
        pred_label_tensor = model(train_input_tensor)
        loss = criterion(pred_label_tensor, train_label_tensor)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    loss_history[m_lr].append(running_loss/num_train)

EDITAR% S:

  • Conforme sugerido nos comentários e respostas abaixo, fiz alterações no meu código e treinei o modelo. Eu adicionei o código e os gráficos para o mesmo.
  • Tentei com vários lr_schedulerin PyTorch (multiStepLR, ExponentialLR)e plotagens para o mesmo estão listados Setup-4como sugerido por @Dennis nos comentários abaixo.
  • Tentando com leakyReLU como sugerido por @Dennis nos comentários.

Qualquer ajuda. obrigado

vinaykumar2491
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Ben N

Respostas:

8

Não vejo razão para que as taxas de aprendizado decadentes criem os tipos de saltos nas perdas que você está observando. Ele deve "desacelerar" a rapidez com que você "se move", o que, no caso de uma perda que, de outra forma, diminui consistentemente, deve, na pior das hipóteses, levar a um platô nas suas perdas (em vez daqueles saltos).

A primeira coisa que observo no seu código é que você recria o otimizador do zero a cada época. Ainda não trabalhei o suficiente com o PyTorch para ter certeza, mas isso não destrói o estado / memória interna do otimizador sempre? Eu acho que você deve criar o otimizador apenas uma vez, antes do ciclo através das épocas. Se esse é realmente um bug no seu código, também deve ser um bug no caso em que você não usa o declínio da taxa de aprendizado ... mas talvez você simplesmente tenha sorte lá e não tenha os mesmos efeitos negativos do erro.

Para diminuir a taxa de aprendizado, recomendo usar a API oficial para isso , em vez de uma solução manual. No seu caso particular, convém instanciar um agendador StepLR , com:

  • optimizer = o otimizador do ADAM, que você provavelmente deve instanciar apenas uma vez.
  • step_size = 25
  • gamma = 0.25

Você pode simplesmente chamar scheduler.step()no início de cada época (ou talvez no final - o exemplo no link da API o chama no início de cada época).


Se, após as alterações acima, você ainda enfrentar o problema, também seria útil executar cada um de seus experimentos várias vezes e traçar resultados médios (ou traçar linhas para todos os experimentos). Teoricamente, seus experimentos devem ser idênticos durante as primeiras 25 épocas, mas ainda vemos grandes diferenças entre as duas figuras, mesmo durante as primeiras 25 épocas em que não ocorre uma queda na taxa de aprendizado (por exemplo, uma figura começa com uma perda de ~ 28K, a outra começa com uma perda de ~ 40K). Isso pode ser simplesmente devido a diferentes inicializações aleatórias; portanto, seria bom calcular a média de que os resultados não são determinados por seus gráficos.

Dennis Soemers
fonte
11
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Ben N