PyTorchでAdamオプティマイザーを使用して学習率を低下させると、損失が突然跳ね上がります


10

オプティマイザー(を使用)と、シングルチャネルオーディオソース分離タスクでauto-encoderネットワークをトレーニングしています。学習率を1要素ずつ減衰させると、ネットワーク損失は急激に跳ね上がり、次の学習率の減衰まで減少します。Adamamsgrad=TrueMSE 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:

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:

Setup-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が示唆しているように、私はReLU1e-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_schedulerinで試してみPyTorch (multiStepLR, ExponentialLR)ましSetup-4たが、@ Dennisのコメントで提案されているように、同じプロットが以下にリストされています。
  • コメントで@Dennisが提案したとおり、leakyReLUを試してみます。

助けて。ありがとう


コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
Ben N

回答:


8

学習率の低下が、あなたが観察している損失の種類のジャンプを作成する理由はありません。それはあなたがどれだけ速く「移動」するかを「遅くする」べきであり、そうでなければ一貫して縮小する損失の場合、実際には、最悪の場合、(それらのジャンプではなく)単に損失のプラトーにつながるはずです。

コードで最初に確認することは、エポックごとにオプティマイザをゼロから再作成することです。私はまだPyTorchで十分に確認できていませんが、毎回オプティマイザの内部状態/メモリを破壊するだけではありませんか?エポックをループする前に、オプティマイザを1回だけ作成する必要があると思います。これが実際にコードのバグである場合、学習率の減衰を使用しない場合でも実際にはバグであるはずです...しかし、単にそこで幸運になり、同じ効果が得られない可能性がありますバグ。

学習率の低下については、手動のソリューションではなく、公式APIを使用することをお勧めします。特定のケースでは、StepLRスケジューラを次のようにインスタンス化します。

  • optimizer = ADAMオプティマイザ。これはおそらく一度だけインスタンス化する必要があります。
  • step_size = 25
  • gamma = 0.25

その後、単にscheduler.step()すべてのエポックの開始時に(またはおそらく最後に)呼び出すことができます。APIリンクの例では、すべてのエポックの開始時に呼び出します。


上記の変更後も引き続き問題が発生する場合は、各実験を複数回実行して平均結果をプロットする(またはすべての実験の線をプロットする)ことも役立ちます。実験は最初の25エポックの間は理論的に同一である必要がありますが、学習率の減衰が発生しない最初の25エポックの間でも、2つの数値間に大きな違いが見られます(たとえば、1つの数値は〜28Kの損失で始まり、もう1つの数値は〜40Kの損失で開始します)。これは単にランダムな初期化が異なることが原因である可能性があるため、プロットからその非決定性を平均化することは良いことです。


1
コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
Ben N
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.