7-bo‘lim

Dataset va DataLoader

TensorDataset, o'z Dataset sinfingiz, DataLoader bilan paketlash, aralashtirish, drop_last va ma'lumotni bo'lish.

🕑 9 daqiqa o‘qish 📄 636 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Tayyor TensorDataset
  2. O'z Dataset sinfingiz
  3. DataLoader - paketlash
  4. Aralashtirish nima uchun kerak
  5. Ma'lumotni bo'lish
  6. Foydali sozlamalar
  7. Xulosa

Hozirgacha biz butun ma'lumotni bir vaqtda modelga berdik. Real loyihada bu mumkin emas: 100 000 ta rasm xotiraga sig'maydi. PyTorch buni ikkita sinf bilan hal qiladi:

  • Dataset - «menda nechta namuna bor va i-namuna nimadan iborat» degan savolga javob beradi.
  • DataLoader - o'sha namunalarni paketlarga bo'lib, aralashtirib beradi.

Tayyor TensorDataset #

Ma'lumot allaqachon tenzorda bo'lsa, eng qisqa yo'l:

Python
import torch
from torch.utils.data import Dataset, DataLoader, TensorDataset, random_split

torch.manual_seed(42)

X = torch.randn(100, 3)
y = (X.sum(dim=1) > 0).long()

tds = TensorDataset(X, y)
print("namunalar soni:", len(tds))

xb, yb = tds[0]
print("bitta namuna:", xb.shape, "nishon =", yb.item())
Natija
namunalar soni: 100
bitta namuna: torch.Size([3]) nishon = 1

tds[0] bitta namunani qaytardi - paketni emas. Bu muhim farq.

O'z Dataset sinfingiz #

Ma'lumot fayllarda, papkalarda yoki ma'lumotlar bazasida bo'lsa, o'z sinfingizni yozasiz. Faqat uchta metod kerak:

Python
class HaroratDataset(Dataset):
    def __init__(self, selsiy):
        self.x = torch.tensor(selsiy, dtype=torch.float32).unsqueeze(1)
        self.y = self.x * 1.8 + 32

    def __len__(self):
        return len(self.x)

    def __getitem__(self, i):
        return self.x[i], self.y[i]

hd = HaroratDataset([0.0, 10.0, 25.0, 37.0, 100.0])
print("uzunlik:", len(hd))
for i in range(3):
    a, b = hd[i]
    print(f"  {a.item():6.1f}C -> {b.item():6.1f}F")
Natija
uzunlik: 5
     0.0C ->   32.0F
    10.0C ->   50.0F
    25.0C ->   77.0F
MetodVazifasi
__init__Ma'lumot manzilini tayyorlaydi - yo'llar ro'yxati, jadval, tenzor
__len__Namunalar sonini qaytaradi
__getitem__(i)Bitta namunani (kirish, nishon) ko'rinishida qaytaradi
Og'ir ishni __getitem__ ga qoldiring

Rasmlar bilan ishlaganda __init__ da faqat fayl yo'llarini saqlang, rasmning o'zini esa __getitem__ da o'qing. Aks holda butun to'plam xotiraga yuklanadi va katta ma'lumotda dastur ishga ham tushmaydi.

DataLoader - paketlash #

Python
dl = DataLoader(tds, batch_size=16, shuffle=True)
print("paketlar soni:", len(dl))

for i, (xb, yb) in enumerate(dl):
    print(f"  {i+1}-paket: {tuple(xb.shape)}  nishonlar {tuple(yb.shape)}")
    if i == 2:
        break
Natija
paketlar soni: 7
  1-paket: (16, 3)  nishonlar (16,)
  2-paket: (16, 3)  nishonlar (16,)
  3-paket: (16, 3)  nishonlar (16,)

100 ta namuna, 16 talik paket - 100 / 16 = 6.25, demak 7 ta paket. Oxirgisi to'liq bo'lmaydi:

Python
oxirgi = None
for xb, yb in dl:
    oxirgi = xb
print("oxirgi paket shakli:", tuple(oxirgi.shape))

dl2 = DataLoader(tds, batch_size=16, shuffle=True, drop_last=True)
print("drop_last=True bilan paketlar:", len(dl2))
Natija
oxirgi paket shakli: (4, 3)
drop_last=True bilan paketlar: 6

Oxirgi paketda 16 emas, 4 ta namuna bor. drop_last=True uni butunlay tashlab yuboradi.

100 namuna, batch_size=16 Dataset len = 100 ds[i] -> 1 namuna DataLoader aralashtiradi va paketga yig'adi O'quv sikli for xb, yb in dl: 7 marta aylanadi Bir davrda chiqadigan paketlar 16 16 16 16 16 16 4 to'liq emas drop_last=True bo'lsa, oxirgi paket tashlanadi va 6 ta paket qoladi
DataLoader har davrda ma'lumotni qayta aralashtirib, paketlarga bo'ladi

Aralashtirish nima uchun kerak #

Python
d = DataLoader(tds, batch_size=4, shuffle=False)
xb, yb = next(iter(d))
print("shuffle=False birinchi nishonlar:", yb.tolist())

d = DataLoader(tds, batch_size=4, shuffle=True, generator=torch.Generator().manual_seed(0))
xb, yb = next(iter(d))
print("shuffle=True  birinchi nishonlar:", yb.tolist())
Natija
shuffle=False birinchi nishonlar: [1, 0, 0, 0]
shuffle=True  birinchi nishonlar: [1, 0, 1, 1]
Tartiblangan ma'lumotda shuffle=False - jiddiy xato

Ma'lumot sinf bo'yicha tartiblangan bo'lsa (avval barcha mushuklar, keyin barcha itlar), shuffle=False bilan model bir necha davr davomida faqat mushuk ko'radi, keyin faqat it.

Natijada u har paketda «hammasi bitta sinf» deb o'rganadi va yo'qotish sakrab turadi. O'quv to'plamida doim shuffle=True, validatsiya va testda esa kerak emas.

Ma'lumotni bo'lish #

Model qanchalik o'rganganini bilish uchun u ko'rmagan ma'lumot kerak:

Python
oq, val = random_split(tds, [80, 20], generator=torch.Generator().manual_seed(42))
print("o'quv:", len(oq), "| validatsiya:", len(val))
Natija
o'quv: 80 | validatsiya: 20
To'plamUlushiVazifasi
O'quv (train)~70-80%Model parametrlarni shundan o'rganadi
Validatsiya~10-15%Sozlamalarni tanlash va o'qishni kuzatish
Test~10-15%Faqat bir marta, oxirida - haqiqiy baho
generator nima uchun berildi

random_split tasodifiy bo'ladi. generator=torch.Generator().manual_seed(42) berilsa, bo'linish har safar bir xil chiqadi - natijalaringiz takrorlanadigan bo'ladi.

Foydali sozlamalar #

SozlamaMa'nosi
batch_sizeBir paketdagi namunalar soni - 32 yoki 64 dan boshlang
shuffle=TrueHar davrda tartibni aralashtiradi - o'quv to'plamida shart
drop_last=TrueTo'liq bo'lmagan oxirgi paketni tashlaydi
num_workers=4Ma'lumotni parallel o'qiydi - rasm to'plamlarida tezlik beradi
pin_memory=TrueGPU ga ko'chirishni tezlashtiradi (9-bo'limda)
num_workers ni Windows da ehtiyot bilan ishlating

Linux va macOS da num_workers=4 odatda muammosiz. Windows da esa kodni if __name__ == "__main__": ichiga olmasangiz, dastur o'zini cheksiz qayta ishga tushirishi mumkin. Ishlamasa, num_workers=0 qilib qo'ying.

Amaliy topshiriq
  1. TensorDataset yarating va len() hamda ds[0] natijasini chop eting.
  2. Santimetrni dyuymga aylantiradigan Dataset sinfini yozing.
  3. Uning __len__ va __getitem__ metodlarini sinab ko'ring.
  4. DataLoader ni batch_size=8 bilan yaratib, paketlar sonini hisoblang.
  5. Qo'lda hisoblangan paketlar sonini dastur natijasi bilan solishtiring.
  6. Oxirgi paket shaklini chop etib, u nega kichikroq ekanini tushuntiring.
  7. drop_last=True qo'shib, paketlar soni qanday o'zganini ko'ring.
  8. shuffle=False va shuffle=True da birinchi paket nishonlarini solishtiring.
  9. random_split bilan ma'lumotni 80/20 ga bo'ling.
  10. generator ni olib tashlab, bo'linish har safar o'zgarishini tekshiring.

Xulosa #

  • Dataset bitta namunani beradi, DataLoader ulardan paket yasaydi.
  • Tenzor tayyor bo'lsa, TensorDataset eng qisqa yo'l.
  • O'z sinfingizda uchta metod kerak: __init__, __len__, __getitem__.
  • __getitem__ bitta namunani qaytaradi - paketni emas.
  • Og'ir o'qishni __getitem__ ga qoldiring, __init__ da faqat yo'llarni saqlang.
  • Paketlar soni - namunalar sonining paket hajmiga bo'linganidan yuqoriga yaxlitlangani.
  • Oxirgi paket to'liq bo'lmasligi mumkin; drop_last=True uni tashlaydi.
  • O'quv to'plamida shuffle=True majburiy - tartiblangan ma'lumotda usiz model buziladi.
  • Validatsiya va testda aralashtirish kerak emas.
  • random_split ma'lumotni bo'ladi; generator bilan bo'linish takrorlanadigan bo'ladi.

Keyingi bo'limda shu qismlarning hammasini bitta to'liq o'quv sikliga birlashtiramiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.