Thuta Learning
Deep Learning with PyTorch
AdvancedAIintermediate

Learning Rate Scheduling

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Learning Rate Scheduling concept ကို နားလည်ရှင်းပြနိုင်ရန်
  • နမူနာ PyTorch code ကို ကိုယ်တိုင် run ပြီး output စစ်နိုင်ရန်
  • Tutorial Platform project နှင့် production scenario တွင် မှန်ကန်စွာအသုံးချနိုင်ရန်

နားလည်ထားရမယ့် အချက်

Learning rate က optimizer တစ်ခုစီ parameter update လုပ်တိုင်း ဘယ်လောက်ကြီးတဲ့ step လှမ်းမလဲဆိုတာကို ထိန်းချုပ်ပေးတယ်။ မြင့်လွန်းရင် update တွေက good minima ကို ကျော်သွားလို့ loss က diverge ဖြစ်တာ (သို့) oscillate ဖြစ်တာတွေ ဖြစ်တတ်တယ်၊ နိမ့်လွန်းရင်တော့ training က တအားနှေးသွားတာ (သို့) ထွက်လို့မရတဲ့ shallow local minimum ထဲ ညပ်နေတတ်တယ်။ Training တစ်လျှောက် fixed learning rate တစ်ခုတည်းက ideal မဖြစ်တတ်ဘူး၊ ဘာလို့ဆိုတော့ ဒီ failure mode နှစ်ခုက training stage အလိုက် trade-off ကွာသွားလို့ပဲ — အစောပိုင်းမှာ model က good solution ကနေ ဝေးနေသေးတဲ့အခါ learning rate မြင့်မြင့်က progress မြန်မြန်ရအောင် လုပ်ပေးပြီး loss landscape ကို ကုန်ကျစရိတ်သက်သာစွာ explore လုပ်ပေးတယ်၊ နောက်ပိုင်းမှာတော့ model က convergence ကို ရောက်လုနီးမှာ learning rate မြင့်မြင့်နဲ့ဆိုရင် good minimum အနီးမှာ ခုန်နေပြီး settle မဝင်နိုင်တော့ဘူး၊ ဒါကြောင့် rate ငယ်ငယ်၊ သတိထားထား လှမ်းရမယ့်အချိန်ဖြစ်တယ်။ Learning rate scheduling က fixed policy တစ်ခုအလိုက် rate ကို အချိန်နဲ့အမျှ decay လုပ်ပေးလို့ ဒါကို automate လုပ်ပေးတယ် — ဥပမာ StepLR က epoch အရေအတွက် fix ထားတာတစ်ခုစီအလွန်မှာ multiplicative factor တစ်ခုနဲ့ ချလိုက်တယ်၊ CosineAnnealingLR ကတော့ cosine curve တစ်ခုအတိုင်း smooth ဖြစ်စွာ decay လုပ်ပေးတယ်။ ဒါနဲ့ ဆက်စပ်တဲ့ technique တစ်ခုဖြစ်တဲ့ warmup ကတော့ အစမှာ ဆန့်ကျင်ဘက် လုပ်ပေးတယ် — step ပထမဆုံးနည်းနည်းအတွက် rate ကို target ထက် နိမ့်နိမ့် ထိန်းထားတယ်၊ model ရဲ့ weight တွေ လုံးဝ မ settle ရသေးခင် early gradient ကြီးကြီးတွေက instability ဖြစ်စေနိုင်လို့ပဲ။

လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်

Tutorial Platform ရဲ့ sentiment classifier ကို review data အသစ်ကနေ train လုပ်တဲ့အခါ fixed learning rate တစ်ခုတည်းက အစောပိုင်း overshoot ဖြစ်နိုင်တယ် (epoch ပထမဆုံးနှစ်ခုသုံးခုကို ခုန်နေရင်း learn မလုပ်နိုင်ဘဲ ဖြုန်းသွားတာ) (သို့) training တစ်လျှောက်လုံး တအားနှေးနေနိုင်တယ် (scheduled retraining job တစ်ခုမှာ compute budget ဖြုန်းသွားတာ)။ StepLR schedule တစ်ခုက rate မြင့်မြင့်ကနေ စပြီး epoch အနည်းငယ်တိုင်း ချသွားတာက model ကို coarse pattern တွေ (ရှင်းရှင်းလင်းလင်း negative word တွေလိုမျိုး) ကို မြန်မြန် ဖမ်းယူစေပြီး၊ training ရှေ့ဆက်လာတာနဲ့အမျှ subtler case တွေ (sarcasm, mixed sentiment) ကို ပိုသေချာစွာ fine-tune လုပ်စေနိုင်တယ် — ဒါကို platform က periodic model refresh အတွက် ခွဲထားတဲ့ fixed training-time budget အတွင်းမှာပဲ လုပ်ဆောင်နိုင်တယ်။

အတူတူ စမ်းရေးကြည့်မယ်

python
import torch
import torch.nn as nn

model = nn.Linear(4, 2)
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=3, gamma=0.5)

for epoch in range(9):
    optimizer.step()
    current_lr = optimizer.param_groups[0]["lr"]
    print(f"epoch {epoch}: lr = {current_lr:.5f}")
    scheduler.step()
You should see
epoch 0: lr = 0.10000
epoch 1: lr = 0.10000
epoch 2: lr = 0.10000
epoch 3: lr = 0.05000
epoch 4: lr = 0.05000
epoch 5: lr = 0.05000
epoch 6: lr = 0.02500
epoch 7: lr = 0.02500
epoch 8: lr = 0.02500

step_size=3 ဖြစ်လို့ epoch 3 ခုတစ်ကြိမ်စီမှာ learning rate ကို gamma=0.5 နဲ့ ပွားလို့ တစ်ဝက်စီ ကျသွားတာကို တွေ့ရတယ်။

၅ မိနစ် စမ်းကြည့်

scheduler ကို StepLR အစား torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=9) နဲ့ လဲပြီး ပြန် run ကြည့်ပါ — learning rate ကျဆင်းပုံက StepLR နဲ့ ဘယ်လို ကွာလဲ compare လုပ်ကြည့်ပါ။

သတိလေးတစ်ချက်

scheduler.step() ကို optimizer.step() မတိုင်ခင် ခေါ်မိရင် (သို့) epoch loop အစား batch loop တိုင်းမှာ ခေါ်မိရင် learning rate က ရည်ရွယ်ထားတာထက် မြန်မြန် ကျသွားတတ်တယ် — StepLR ရဲ့ step_size က 'scheduler.step() ခေါ်တဲ့ အကြိမ်ရေ' ကို ရေတွက်တာဖြစ်လို့

current learning rate ကို scheduler.get_last_lr() နဲ့ စစ်မယ့်အစား optimizer.defaults['lr'] ကို ကြည့်တတ်ကြတယ် — ဒါက scheduler တင်တင် မဆက်ဆံခင် initial lr ကိုပဲ ထားပြသနေမှာဖြစ်လို့ decay ဖြစ်ပြီးနောက် အမှန်တကယ် သုံးနေတဲ့ rate ကို မဖော်ပြနိုင်ဘူး

PyTorch Docs — How to adjust learning rateDeep Learning

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • scheduler.step() ကို optimizer.step() မတိုင်ခင် ခေါ်မိရင် (သို့) epoch loop အစား batch loop တိုင်းမှာ ခေါ်မိရင် learning rate က ရည်ရွယ်ထားတာထက် မြန်မြန် ကျသွားတတ်တယ် — StepLR ရဲ့ step_size က 'scheduler.step() ခေါ်တဲ့ အကြိမ်ရေ' ကို ရေတွက်တာဖြစ်လို့
  • current learning rate ကို scheduler.get_last_lr() နဲ့ စစ်မယ့်အစား optimizer.defaults['lr'] ကို ကြည့်တတ်ကြတယ် — ဒါက scheduler တင်တင် မဆက်ဆံခင် initial lr ကိုပဲ ထားပြသနေမှာဖြစ်လို့ decay ဖြစ်ပြီးနောက် အမှန်တကယ် သုံးနေတဲ့ rate ကို မဖော်ပြနိုင်ဘူး
  • နမူနာ code ကို production system ပေါ် တိုက်ရိုက်မစမ်းဘဲ local/test environment တွင် အရင်အတည်ပြုပါ။

လေ့ကျင့်ခန်း

scheduler ကို StepLR အစား torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=9) နဲ့ လဲပြီး ပြန် run ကြည့်ပါ — learning rate ကျဆင်းပုံက StepLR နဲ့ ဘယ်လို ကွာလဲ compare လုပ်ကြည့်ပါ။

You'll know it worked when: epoch 0: lr = 0.10000 epoch 1: lr = 0.10000 epoch 2: lr = 0.10000 epoch 3: lr = 0.05000 epoch 4: lr = 0.05000 epoch 5: lr = 0.05000 epoch 6: lr = 0.02500 epoch 7: lr = 0.02500 epoch 8: lr = 0.02500 step_size=3 ဖြစ်လို့ epoch 3 ခုတစ်ကြိမ်စီမှာ learning rate ကို gamma=0.5 နဲ့ ပွားလို့ တစ်ဝက်စီ ကျသွားတာကို တွေ့ရတယ်။

Learning Rate Scheduling | Thuta Learning