Thuta Learning
Computer Vision
ProjectsAIintermediate

Project: Transfer Learning Classifier

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

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

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

Transfer learning ရဲ့ core idea က pretrained resnet18 ဟာ ImageNet ပေါ်မှာ image တွေအများကြီးကနေ generic visual feature (edge, texture, shape) တွေကို သင်ယူထားပြီးသား ဖြစ်တယ်ဆိုတာပါ။ Backbone ရဲ့ parameter အားလုံးကို requires_grad = False သတ်မှတ်ပြီး freeze လုပ်လိုက်တာက gradient calculation ကို ရပ်တန့်စေပြီး၊ compute ကို သက်သာစေရုံသာမက tiny fine-tuning dataset တစ်ခုနဲ့ backprop လုပ်လိုက်ရင် ဖြစ်တတ်တဲ့ catastrophic forgetting (learned general feature တွေ ပျက်စီးသွားခြင်း) ကိုလည်း တားဆီးပေးတယ်။ Final fully-connected layer (model.fc) ကို Linear layer အသစ်တစ်ခုနဲ့ လဲလိုက်တာက ImageNet class 1000 အတွက် specialize လုပ်ထားတဲ့ output head ကို ကျွန်တော်တို့ရဲ့ class အရေအတွက် (ဒီနေရာမှာ 4 ခု) အတွက် head အသစ်နဲ့ အစားထိုးလိုက်တာပါ။

Optimizer ကို model.parameters() အားလုံးအစား model.fc.parameters() တစ်ခုတည်းအပေါ်သာ တည်ဆောက်လိုက်တာက fine-tune လုပ်နေတဲ့ parameter အရေအတွက်ကို သန်းနဲ့ချီရှိတဲ့ backbone ကနေ ရာနဲ့ချီသာရှိတဲ့ fc layer တစ်ခုတည်းအထိ အသေအချာ ကျုံ့ပေးတယ် — sample အနည်းငယ်၊ step အနည်းငယ်နဲ့တောင် reasonable performance ရနိုင်တဲ့ transfer learning ရဲ့ အဓိက promise ပါ။ Training ပြီးနောက် named_parameters() နဲ့ .grad is None ကို စစ်ကြည့်တာက freeze က တကယ် အလုပ်လုပ်ခဲ့လား၊ ဒါမှမဟုတ် requires_grad သတ်မှတ်ချက်ကို ယုံနေတာသက်သက်လား ဆိုတာ အတည်ပြုနိုင်တဲ့ ကောင်းတဲ့ debugging habit တစ်ခုပါ။

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

Tutorial Platform မှာ instructor တွေ upload လုပ်တဲ့ lesson screenshot တွေ ရှုပ်ရှက်/blur ဖြစ်နေသလားဆိုတာကို flag လုပ်ပေးတဲ့ lesson-screenshot quality classifier တစ်ခု ရှိပါတယ်။ Label ရထားတဲ့ screenshot နမူနာအရေအတွက်က နည်းနေလို့ (instructor manual review ကနေ ရလာတာဖြစ်လို့) frozen resnet18 backbone + fine-tuned fc head ဆိုတဲ့ transfer learning approach ကသာ practical ဖြစ်ပါတယ် — sample အနည်းငယ်နဲ့တောင် usable classifier တစ်ခု ရနိုင်တယ်။

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

python
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision.models import resnet18, ResNet18_Weights

torch.manual_seed(0)

num_classes = 4
model = resnet18(weights=ResNet18_Weights.DEFAULT)

# Freeze all pretrained layers first
for param in model.parameters():
    param.requires_grad = False

# Then replace the final layer -- its params require_grad=True by default
in_features = model.fc.in_features
model.fc = nn.Linear(in_features, num_classes)

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.fc.parameters(), lr=1e-3)

# Synthetic images shaped like the inputs resnet18 expects
num_samples = 16
images = torch.randn(num_samples, 3, 224, 224)
labels = torch.randint(0, num_classes, (num_samples,))

model.train()
losses = []
for step in range(5):
    optimizer.zero_grad()
    outputs = model(images)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()
    losses.append(loss.item())
    print(f"Step {step+1}/5 - loss: {loss.item():.4f}")

# Confirm only the new fc layer received gradients
frozen_untouched = all(
    p.grad is None for name, p in model.named_parameters() if not name.startswith("fc")
)
fc_has_grad = all(p.grad is not None for p in model.fc.parameters())
print(f"Backbone parameters untouched (grad is None): {frozen_untouched}")
print(f"New fc layer parameters have gradients: {fc_has_grad}")
You should see
(ပထမဆုံး run မှာ resnet18 pretrained weights ကို download လုပ်ဖို့ progress log တစ်ခု ပေါ်နိုင်ပါတယ်၊ ဒါက internet connection လိုအပ်တယ်။) ပြီးရင် "Step 1/5 - loss: X.XXXX" ကနေ "Step 5/5 - loss: X.XXXX" အထိ line 5 ကြောင်း ထွက်ပါမယ်။ Class 4 ခုအတွက် random guess loss ဖြစ်တဲ့ ln(4)≈1.386 အနီးက စတင်ပြီး၊ fc layer တစ်ခုတည်းက frozen feature 512 dim ပေါ်မှာ sample 16 ခုသာ fit လုပ်ရတာဖြစ်လို့ (heavily overparameterized) step 5 ခုအတွင်းမှာပင် loss က သိသိသာသာ ကျသွားနိုင်ပါတယ်။ နောက်ဆုံး line 2 ကြောင်းက "Backbone parameters untouched (grad is None): True" နဲ့ "New fc layer parameters have gradients: True" ဖြစ်ပါလိမ့်မယ်။

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

Backbone freeze ကို ပြင်ပြီး layer3/layer4 (နောက်ဆုံးဆီရှိ conv block နှစ်ခု) ကိုသာ unfreeze လုပ်ကြည့်ပါ (requires_grad = True ပြန်သတ်မှတ်)၊ optimizer ထဲမှာ layer3/layer4/fc parameter အားလုံးကို ထည့်ပါ။ Trainable parameter အရေအတွက်ကို count လုပ်ပြီး fc-only fine-tuning နဲ့ ဘယ်လောက်ကွာခြားလဲ နှိုင်းယှဉ်ကြည့်ပါ။

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

ပထမဆုံးအကြိမ် run တဲ့အခါ pretrained weights ကို download လုပ်ဖို့ internet connection လိုအပ်ပါတယ် — offline environment ဒါမှမဟုတ် firewall ကန့်သတ်ထားတဲ့ CI pipeline ထဲမှာဆို resnet18(weights=...) ခေါ်ရင် error တက်နိုင်ပါတယ်။

model.fc ကို freeze လုပ်တဲ့ loop ရဲ့ အရင်ကနေ replace လုပ်လိုက်ရင် (order ပြောင်းလိုက်ရင်) freeze loop က layer အသစ်ကိုပါ requires_grad = False လုပ်ပစ်လိုက်နိုင်ပြီး၊ optimizer.step() က ဘာမှ update စရာ မရှိတော့တာကြောင့် loss က error တစ်ခုမှ မတက်ဘဲ step 5 ခုလုံးမှာ တည်ငြိမ်နေမှာပါ။

PyTorch Tutorials — Transfer Learning for Computer VisionComputer Vision

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

  • ပထမဆုံးအကြိမ် run တဲ့အခါ pretrained weights ကို download လုပ်ဖို့ internet connection လိုအပ်ပါတယ် — offline environment ဒါမှမဟုတ် firewall ကန့်သတ်ထားတဲ့ CI pipeline ထဲမှာဆို resnet18(weights=...) ခေါ်ရင် error တက်နိုင်ပါတယ်။
  • model.fc ကို freeze လုပ်တဲ့ loop ရဲ့ အရင်ကနေ replace လုပ်လိုက်ရင် (order ပြောင်းလိုက်ရင်) freeze loop က layer အသစ်ကိုပါ requires_grad = False လုပ်ပစ်လိုက်နိုင်ပြီး၊ optimizer.step() က ဘာမှ update စရာ မရှိတော့တာကြောင့် loss က error တစ်ခုမှ မတက်ဘဲ step 5 ခုလုံးမှာ တည်ငြိမ်နေမှာပါ။
  • နမူနာ code ကို production system ပေါ် တိုက်ရိုက်မစမ်းဘဲ local/test environment တွင် အရင်အတည်ပြုပါ။

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

Backbone freeze ကို ပြင်ပြီး layer3/layer4 (နောက်ဆုံးဆီရှိ conv block နှစ်ခု) ကိုသာ unfreeze လုပ်ကြည့်ပါ (requires_grad = True ပြန်သတ်မှတ်)၊ optimizer ထဲမှာ layer3/layer4/fc parameter အားလုံးကို ထည့်ပါ။ Trainable parameter အရေအတွက်ကို count လုပ်ပြီး fc-only fine-tuning နဲ့ ဘယ်လောက်ကွာခြားလဲ နှိုင်းယှဉ်ကြည့်ပါ။

You'll know it worked when: (ပထမဆုံး run မှာ resnet18 pretrained weights ကို download လုပ်ဖို့ progress log တစ်ခု ပေါ်နိုင်ပါတယ်၊ ဒါက internet connection လိုအပ်တယ်။) ပြီးရင် "Step 1/5 - loss: X.XXXX" ကနေ "Step 5/5 - loss: X.XXXX" အထိ line 5 ကြောင်း ထွက်ပါမယ်။ Class 4 ခုအတွက် random guess loss ဖြစ်တဲ့ ln(4)≈1.386 အနီးက စတင်ပြီး၊ fc layer တစ်ခုတည်းက frozen feature 512 dim ပေါ်မှာ sample 16 ခုသာ fit လုပ်ရတာဖြစ်လို့ (heavily overparameterized) step 5 ခုအတွင်းမှာပင် loss က သိသိသာသာ ကျသွားနိုင်ပါတယ်။ နောက်ဆုံး line 2 ကြောင်းက "Backbone parameters untouched (grad is None): True" နဲ့ "New fc layer parameters have gradients: True" ဖြစ်ပါလိမ့်မယ်။

Project: Transfer Learning Classifier | Thuta Learning