နားလည်ထားရမယ့် အချက်
Model တစ်ခုကို train လုပ်ဖို့ data ကို အထပ်ထပ် ကျွေးရတယ်၊ PyTorch က ဒီအလုပ်ကို responsibility နှစ်ခု ရှင်းရှင်းလင်းလင်း ခွဲပေးထားတယ်။ `Dataset` က မေးခွန်းတစ်ခုတည်းကိုသာ ဖြေတယ် — index တစ်ခု ပေးလိုက်ရင် sample တစ်ခုက ဘာလဲ? — `__getitem__` (sample တစ်ခုနဲ့ label ကို return ပြန်တာ) နဲ့ `__len__` (sample ဘယ်နှစ်ခုရှိလဲ ပြောတာ) ကို implement လုပ်ပေးရုံပါ၊ batching၊ shuffling၊ ဒါမှမဟုတ် iteration order အကြောင်း ဘာမှ မပြောဘူး။ `DataLoader` ကတော့ ဘယ် `Dataset` ကိုမဆို wrap ပြီး ဒါတွေအားလုံးကို ကိုင်တွယ်ပေးတယ် — sample တစ်ခုချင်းစီကို batch တွေအဖြစ် စုပေးတယ်၊ epoch တစ်ခုချင်းစီမှာ sample order ကို shuffle လုပ်နိုင်တယ်၊ model က batch ယခင်တစ်ခုအတွက် train လုပ်နေချိန်မှာ worker process တွေသုံးပြီး batch နောက်တစ်ခုကို parallel load/preprocess လုပ်တောင် လုပ်နိုင်တယ်။ ဒီ separation က အရေးကြီးတာက sample တစ်ခုချင်းစီ train လုပ်တာက computational အရ waste ဖြစ်ပြီး (modern hardware တွေက parallel batch operation အတွက် တည်ဆောက်ထားတာဖြစ်ပြီး scalar တစ်ခုချင်းစီ အတွက် မဟုတ်ဘူး) statistical အရလည်း noisy ဖြစ်တယ် (sample တစ်ခုတည်းကနေ estimate လုပ်တဲ့ gradient က batch တစ်ခုလုံးရဲ့ average ထက် အလွန်တွန့်လိမ်နေတတ်ပြီး training ကို မတည်ငြိမ်စေတယ်)။ 'item တစ်ခုကို ဘယ်လို access လုပ်မလဲ' နဲ့ 'item များစွာကို ဘယ်လို efficient စွာ ကျွေးမလဲ' ဆိုတဲ့ concern နှစ်ခုကို ခွဲထားတာကြောင့် Dataset တစ်ခုတည်းကိုပဲ batch size၊ shuffling strategy၊ ဒါမှမဟုတ် parallel loading setup ကွဲပြားနေပေမဲ့ code မပြောင်းဘဲ ပြန်သုံးနိုင်တယ်။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Tutorial Platform က upload လုပ်ထားတဲ့ lesson screenshot ထောင်ပေါင်းများစွာအပေါ် duplicate-image detector ကို train လုပ်တဲ့အခါ image file တွေနဲ့ label တွေကို custom `Dataset` တစ်ခုထဲ wrap လုပ်တယ်၊ ဒီ `Dataset` ရဲ့ `__getitem__` က image တစ်ခုချင်းစီကို load ပြီး resize လုပ်ပေးတယ် — image တွေ နောက်ဆုံးမှာ ဘယ်လို batch ဖြစ်ဖြစ် ဒီ logic ကို နေရာတစ်ခုတည်းမှာပဲ ထားထားတယ်။ ဒီအပေါ်မှာ `DataLoader` တစ်ခု ပတ်ပြီး epoch တစ်ခုချင်းစီမှာ image 32 ခုပါတဲ့ batch shuffle လုပ်ထားတာကို model ကို ကျွေးပေးတယ်၊ ဒါကြောင့် training က course အလိုက် အစဉ်လိုက်တူတူ အမြဲမတွေ့ဘဲ mix အသစ်ကို တွေ့ရမယ်၊ မဟုတ်ရင် ဘယ် course က ဦးဆုံး upload ဖြစ်လာလဲဆိုတာအပေါ် model ကို bias ဖြစ်စေနိုင်တယ်။ Platform က training hardware ပိုအားကောင်းတာဆီ upgrade လုပ်ရင်လည်း ဒီ `Dataset` တစ်ခုတည်းကိုပဲ `DataLoader` ကြီးတစ်ခုမှာ ပြန်သုံးနိုင်တယ်။
အတူတူ စမ်းရေးကြည့်မယ်
import torch
from torch.utils.data import Dataset, DataLoader
class ToyDataset(Dataset):
def __init__(self, num_samples=20):
self.features = torch.randn(num_samples, 3)
self.labels = torch.randint(0, 2, (num_samples,))
def __len__(self):
return len(self.features)
def __getitem__(self, idx):
return self.features[idx], self.labels[idx]
dataset = ToyDataset()
loader = DataLoader(dataset, batch_size=4, shuffle=True)
batch_features, batch_labels = next(iter(loader))
print("Batch features shape:", batch_features.shape)
print("Batch labels shape:", batch_labels.shape)`Batch features shape: torch.Size([4, 3])` နဲ့ `Batch labels shape: torch.Size([4])` ကို print ထုတ်ပြီး DataLoader က sample လေးခုကို shuffle လုပ်ထားတဲ့ batch တစ်ခုအဖြစ် စုစည်းပေးထားကြောင်း သေချာစေတယ်။၅ မိနစ် စမ်းကြည့်
`batch_size` ကို 5 အဖြစ် ပြောင်းပြီး `len(loader)` ကို print ထုတ်ကြည့်ပါ၊ sample 20 ခုပါတဲ့ dataset တစ်ခုလုံးကို တစ်ကြိမ် ဖြတ်သန်းတဲ့အခါ batch ဘယ်နှစ်ခု ရလာလဲ ကြည့်ပါ။
သတိလေးတစ်ချက်
`__getitem__` ကနေ tensor အစား raw Python list ဒါမှမဟုတ် number ကို ပြန်ပေးခြင်း — `DataLoader` ရဲ့ default batching (`collate_fn`) က tensor-like sample ကို မျှော်လင့်ထားတာကြောင့် error တက်နိုင်တယ် ဒါမှမဟုတ် batch shape မှားတာကို တိတ်တဆိတ် ဖြစ်စေနိုင်တယ်။
Validation ဒါမှမဟုတ် test `DataLoader` မှာ `shuffle=True` ချထားခြင်း — shuffling က training အတွက်ပဲ အရေးကြီးတယ်၊ evaluation မှာတော့ overhead အလကားတိုးပေးရုံသာမက run တစ်ခုနဲ့တစ်ခု ရလဒ်တွေကို ပြန်နှိုင်းယှဉ်ဖို့ ပိုခက်စေတယ်။
PyTorch Docs — Datasets & DataLoaders — Deep Learning