Thuta Learning
Deep Learning with PyTorch
BasicAIintermediate

Loss Functions နှင့် Optimizers

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

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

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

Loss function တစ်ခုက 'model က အခုဘယ်လောက် မှားနေသလဲ' ဆိုတာကို network တိုးတက်အောင် သုံးလို့ရမယ့် number တစ်ခုတည်းအဖြစ် ပြောင်းပေးတယ်—ဥပမာ `nn.MSELoss` က regression ပြဿနာအတွက် predicted value နဲ့ actual value ကြားက squared difference ရဲ့ average ကို တွက်ပြီး၊ error ကြီးလေလေ penalty ပိုကြီးလေလေ ပေးတယ်။ Loss value တစ်ခုတည်းကတော့ ဘယ်လောက်ဆိုးနေတယ်ဆိုတာကိုပဲ ပြောပြတယ်—ဘာကို ပြောင်းရမလဲဆိုတာတော့ မပြောပြဘူး။ ဒီနေရာမှာ optimizer (`torch.optim.SGD`, `Adam` စသည်) က ဝင်လာတယ်—autograd က `loss.backward()` နဲ့ တွက်ပြီးသား gradient တွေကို ယူပြီး parameter တစ်ခုချင်းစီကို loss လျော့ကျမယ့် direction ဘက်ကို update rule နဲ့ ရွှေ့ပေးတယ်။ Training loop တိုင်းရဲ့ နှလုံးခုန်သံဟာ call သုံးခုနဲ့ ဖွဲ့စည်းထားတယ်၊ order ကလည်း အရေးကြီးတယ်—`loss.backward()` က gradient တွေကို တွက်ပြီး parameter တစ်ခုစီရဲ့ `.grad` ထဲ ပေါင်းထည့်ပေးတယ်၊ `optimizer.step()` က ဒီ gradient တွေကို ဖတ်ပြီး parameter တွေကို update လုပ်တယ်၊ `optimizer.zero_grad()` က `.grad` ကို ပြန် zero ပြန်ချတယ်။ နောက်ဆုံး step ကို မေ့လွယ်တယ်—PyTorch က default အနေနဲ့ gradient တွေကို စုစည်းသိမ်းဆည်းထားတယ် (advanced technique တချို့မှာ အသုံးဝင်တယ်)၊ zero_grad ကျော်သွားရင် batch များစွာက gradient တွေ တိတ်တိတ်ဆိတ်ဆိတ် ရောနှောသွားတတ်တယ်။

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

Tutorial Platform ရဲ့ relevance-ranking model train လုပ်နေတဲ့အခါ ၊ loss function က model ရဲ့ predicted ranking score ဟာ learner click data ကနေ ညွှန်ပြနေတဲ့ 'မှန်ကန်တဲ့' ranking နဲ့ ဘယ်လောက်ကွာဟနေသလဲဆိုတာ တိုင်းတာပေးပြီး၊ optimizer ကတော့ training step ထောင်ချီအတွင်း ဒီ error signal ကို weight ပိုကောင်းလာအောင် တကယ်ပြောင်းပေးတဲ့ အရာပါ။ forward -> loss -> backward -> step -> zero_grad sequence ကို order မှန်မှန်၊ step တိုင်းမှာ မှန်မှန်ကန်ကန် လုပ်နိုင်ခြင်းက model တစ်ခုကို တဖြည်းဖြည်း တိုးတက်စေတာနဲ့ လုံးဝ မတိုးတက်ဘဲ ဒါမှမဟုတ် လုံးဝ မှားယွင်းစွာ သင်ယူတာကြား ခြားနားချက်ပါပဲ။

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

python
import torch
import torch.nn as nn

torch.manual_seed(0)

model = nn.Linear(1, 1)
loss_fn = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

x = torch.tensor([[2.0]])
y_true = torch.tensor([[10.0]])

# One manual training step
prediction = model(x)
loss_before = loss_fn(prediction, y_true)
print("Loss before step:", loss_before.item())

loss_before.backward()   # compute gradients
optimizer.step()         # update parameters using gradients
optimizer.zero_grad()    # clear gradients for next round

prediction_after = model(x)
loss_after = loss_fn(prediction_after, y_true)
print("Loss after step:", loss_after.item())
You should see
Step မလုပ်ခင် positive loss value တစ်ခု print ထုတ်ပြီးမှ၊ step လုပ်ပြီးနောက် loss value ငယ်သွားတာကို print ထုတ်ပါတယ်—algebra အရ ဒီ single-example setup မှာ lr=0.01 နဲ့ SGD update တစ်ကြိမ်က loss ကို 0.81 နဲ့ မြှောက်လိုက်တာနဲ့ တူတူပါပဲ၊ ဒါကြောင့် print ထုတ်တဲ့ 'loss after' က 'loss before' ထက် ~19% လျော့ကျသွားပါတယ်။

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

Manual step အတူတူကို သုံးကြိမ် ဆက်တိုက် run ကြည့်ပါ (forward -> loss -> backward -> step -> zero_grad ကို အကြိမ်တိုင်း)၊ အကြိမ်တိုင်းအပြီး loss ကို print ထုတ်ပါ—ဆက်လျော့ကျနေတယ်ဆိုတာ သေချာအောင်လုပ်ပါ၊ ပြီးရင် optimizer.zero_grad() ကို ဖယ်ကြည့်ပြီး ဘယ်လိုပြောင်းလဲသွားလဲ ကြည့်ပါ။

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

loss.backward() မလုပ်ခင် optimizer.step() ကို ခေါ်မိတာ—step() က parameter တစ်ခုစီရဲ့ .grad ထဲမှာ အခုရှိနေတာကို ဖတ်တာမို့ စောစော ခေါ်လိုက်ရင် ယခင် step ရဲ့ gradient အဟောင်း ဒါမှမဟုတ် None ကို သုံးမိပြီး training ကို တိတ်တိတ်ဆိတ်ဆိတ် ပျက်စီးစေနိုင်တယ်။

Step တွေကြား optimizer.zero_grad() ကို မေ့တာ—PyTorch က default အနေနဲ့ gradient တွေကို .grad ထဲ စုစည်းနေတာမို့ နောက် step တွေက gradient အသစ်ကို အဟောင်းအပေါ် ထပ်ပေါင်းသွားတယ်၊ တကယ်တမ်းက မျှော်လင့်မထားတဲ့ learning rate ကြီးထွားနေတဲ့ effect နဲ့ train လုပ်နေသလို ဖြစ်သွားတယ်။

PyTorch Docs — OptimizationDeep Learning

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

  • loss.backward() မလုပ်ခင် optimizer.step() ကို ခေါ်မိတာ—step() က parameter တစ်ခုစီရဲ့ .grad ထဲမှာ အခုရှိနေတာကို ဖတ်တာမို့ စောစော ခေါ်လိုက်ရင် ယခင် step ရဲ့ gradient အဟောင်း ဒါမှမဟုတ် None ကို သုံးမိပြီး training ကို တိတ်တိတ်ဆိတ်ဆိတ် ပျက်စီးစေနိုင်တယ်။
  • Step တွေကြား optimizer.zero_grad() ကို မေ့တာ—PyTorch က default အနေနဲ့ gradient တွေကို .grad ထဲ စုစည်းနေတာမို့ နောက် step တွေက gradient အသစ်ကို အဟောင်းအပေါ် ထပ်ပေါင်းသွားတယ်၊ တကယ်တမ်းက မျှော်လင့်မထားတဲ့ learning rate ကြီးထွားနေတဲ့ effect နဲ့ train လုပ်နေသလို ဖြစ်သွားတယ်။
  • နမူနာ code ကို production system ပေါ် တိုက်ရိုက်မစမ်းဘဲ local/test environment တွင် အရင်အတည်ပြုပါ။

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

Manual step အတူတူကို သုံးကြိမ် ဆက်တိုက် run ကြည့်ပါ (forward -> loss -> backward -> step -> zero_grad ကို အကြိမ်တိုင်း)၊ အကြိမ်တိုင်းအပြီး loss ကို print ထုတ်ပါ—ဆက်လျော့ကျနေတယ်ဆိုတာ သေချာအောင်လုပ်ပါ၊ ပြီးရင် optimizer.zero_grad() ကို ဖယ်ကြည့်ပြီး ဘယ်လိုပြောင်းလဲသွားလဲ ကြည့်ပါ။

You'll know it worked when: Step မလုပ်ခင် positive loss value တစ်ခု print ထုတ်ပြီးမှ၊ step လုပ်ပြီးနောက် loss value ငယ်သွားတာကို print ထုတ်ပါတယ်—algebra အရ ဒီ single-example setup မှာ lr=0.01 နဲ့ SGD update တစ်ကြိမ်က loss ကို 0.81 နဲ့ မြှောက်လိုက်တာနဲ့ တူတူပါပဲ၊ ဒါကြောင့် print ထုတ်တဲ့ 'loss after' က 'loss before' ထက် ~19% လျော့ကျသွားပါတယ်။

Loss Functions နှင့် Optimizers | Thuta Learning