Потеря резко возрастает, когда я теряю скорость обучения с помощью оптимизатора Адама в PyTorch

11

Я тренирую auto-encoderсеть с Adamоптимизатором (с amsgrad=True) и MSE lossдля одноканальной задачи разделения аудиоисточников. Всякий раз, когда я уменьшаю скорость обучения на коэффициент, потери в сети резко скачут, а затем уменьшаются до следующего снижения скорости обучения.

Я использую Pytorch для реализации сети и обучения.

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

Я получаю очень удивительные результаты для установок № 2, № 3, № 4 и не могу объяснить это. Ниже приведены мои результаты:

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.

Участок-1:

Результаты настройки 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?

Участок-2:

Результаты настройки 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.

Сюжетно-3:

Результаты настройки-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.

Как предложено @Dennis в комментариях ниже, я пробовал как с нелинейностями, так ReLUи с другими 1e-02 leakyReLU. Но результаты, похоже, ведут себя аналогично, и потери сначала уменьшаются, а затем увеличиваются, а затем насыщаются при более высоком значении, чем то, что я достиг бы без снижения скорости обучения.

График-4 показывает результаты.

Сюжетно-4:

введите описание изображения здесь

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)

правок:

  • Как предлагается в комментариях и ответах ниже, я внес изменения в свой код и обучил модель. Я добавил код и графики для того же.
  • Я попытался с различными lr_schedulerв PyTorch (multiStepLR, ExponentialLR)и участки для того же перечислены в Setup-4как это было предложено @Dennis в комментариях ниже.
  • Попытка с помощью leakyReLU, как предложено @Dennis в комментариях.

Любая помощь. Спасибо

vinaykumar2491
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Бен

Ответы:

8

Я не вижу причин, по которым снижение скорости обучения должно приводить к скачкам потерь, которые вы наблюдаете. Это должно «замедлить» то, насколько быстро вы «двигаетесь», что в случае потери, которая в противном случае постоянно сокращается, в худшем случае должно просто привести к плато в ваших потерях (а не к этим скачкам).

Первое, что я наблюдаю в вашем коде, это то, что вы воссоздаете оптимизатор с нуля каждую эпоху. Я еще недостаточно поработал с PyTorch, чтобы сказать наверняка, но разве это не разрушает внутреннее состояние / память оптимизатора каждый раз? Я думаю, что вы должны просто создать оптимизатор один раз, перед циклом через эпохи. Если это действительно ошибка в вашем коде, то она также должна оставаться ошибкой в ​​том случае, если вы не используете затухание скорости обучения ... но, возможно, вам просто повезло и вы не испытываете таких же негативных последствий ошибка.

Для снижения скорости обучения я бы рекомендовал использовать для этого официальный API , а не ручное решение. В вашем конкретном случае вы захотите создать планировщик StepLR с помощью:

  • optimizer = оптимизатор ADAM, который вы, вероятно, должны создавать только один раз.
  • step_size = 25
  • gamma = 0.25

Затем вы можете просто позвонить scheduler.step()в начале каждой эпохи (или, может быть, в конце? Пример в ссылке на API вызывает его в начале каждой эпохи).


Если после вышеуказанных изменений у вас по-прежнему возникает проблема, было бы также полезно запустить каждый из ваших экспериментов несколько раз и построить средние результаты (или построить линии для всех экспериментов). Теоретически ваши эксперименты должны быть идентичны в течение первых 25 эпох, но мы по-прежнему видим огромные различия между этими двумя цифрами даже в те первые 25 эпох, в которых не происходит спада скорости обучения (например, одна фигура начинается с потерей ~ 28K, другая начинается с потери ~ 40К). Это может быть просто из-за разных случайных инициализаций, поэтому было бы хорошо усреднить этот недетерминированный из ваших графиков.

Деннис Соемерс
источник
1
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Бен