Я тренирую 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:
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:
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:
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 в комментариях.
Любая помощь. Спасибо
источник
Ответы:
Я не вижу причин, по которым снижение скорости обучения должно приводить к скачкам потерь, которые вы наблюдаете. Это должно «замедлить» то, насколько быстро вы «двигаетесь», что в случае потери, которая в противном случае постоянно сокращается, в худшем случае должно просто привести к плато в ваших потерях (а не к этим скачкам).
Первое, что я наблюдаю в вашем коде, это то, что вы воссоздаете оптимизатор с нуля каждую эпоху. Я еще недостаточно поработал с PyTorch, чтобы сказать наверняка, но разве это не разрушает внутреннее состояние / память оптимизатора каждый раз? Я думаю, что вы должны просто создать оптимизатор один раз, перед циклом через эпохи. Если это действительно ошибка в вашем коде, то она также должна оставаться ошибкой в том случае, если вы не используете затухание скорости обучения ... но, возможно, вам просто повезло и вы не испытываете таких же негативных последствий ошибка.
Для снижения скорости обучения я бы рекомендовал использовать для этого официальный API , а не ручное решение. В вашем конкретном случае вы захотите создать планировщик StepLR с помощью:
optimizer
= оптимизатор ADAM, который вы, вероятно, должны создавать только один раз.step_size = 25
gamma = 0.25
Затем вы можете просто позвонить
scheduler.step()
в начале каждой эпохи (или, может быть, в конце? Пример в ссылке на API вызывает его в начале каждой эпохи).Если после вышеуказанных изменений у вас по-прежнему возникает проблема, было бы также полезно запустить каждый из ваших экспериментов несколько раз и построить средние результаты (или построить линии для всех экспериментов). Теоретически ваши эксперименты должны быть идентичны в течение первых 25 эпох, но мы по-прежнему видим огромные различия между этими двумя цифрами даже в те первые 25 эпох, в которых не происходит спада скорости обучения (например, одна фигура начинается с потерей ~ 28K, другая начинается с потери ~ 40К). Это может быть просто из-за разных случайных инициализаций, поэтому было бы хорошо усреднить этот недетерминированный из ваших графиков.
источник