DataLoader menerima sebuah Dataset dan menyajikannya sebagai deretan batch siap ditelusuri. Topik ini membahas parameter batch_size, shuffle, drop_last, dan num_workers, beserta bentuk tensor yang dikembalikan setiap batch. Setelah loader bekerja, perulangan pelatihan cukup menelusuri loader dengan pernyataan for.
Dari item ke batch#
DataLoader membungkus Dataset dan, setiap kali ditelusuri, mengumpulkan item demi item menjadi batch berukuran batch_size. Nilai len(loader) sama dengan jumlah item dibagi batch_size dan dibulatkan ke atas. Bila jumlah item tidak habis dibagi batch_size, batch terakhir berisi sisa item yang lebih sedikit. Karena item contoh berupa pasangan (fitur, label), setiap batch yang dihasilkan juga berupa pasangan tensor: x berbentuk , yaitu item dengan fitur, sedangkan y berbentuk . Alur dari sampler, dataset, hingga batch diilustrasikan pada diagram berikut.
import torch
from torch.utils.data import TensorDataset, DataLoader
torch.manual_seed(0)
fitur = torch.randn(100, 4) # shape: (100, 4)
label = torch.randint(0, 3, (100,)) # shape: (100,)
dataset = TensorDataset(fitur, label)
loader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=0)
print("Jumlah batch:", len(loader))
nomor = 0
for x, y in loader:
nomor += 1
print(f"batch {nomor}: x {tuple(x.shape)}, y {tuple(y.shape)}, label {y.tolist()}")Jumlah batch: 4
batch 1: x (32, 4), y (32,), label [0, 0, 2, 2, 2, 1, 0, 2, 2, 1, 0, 1, 0, 1, 0, 0, 1, 2, 1, 1, 1, 2, 2, 2, 0, 0, 1, 0, 1, 2, 2, 1]
batch 2: x (32, 4), y (32,), label [0, 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 2, 0, 1, 0, 1, 1, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1]
batch 3: x (32, 4), y (32,), label [1, 2, 1, 2, 2, 2, 1, 2, 1, 1, 1, 2, 1, 0, 1, 1, 1, 1, 0, 1, 2, 1, 1, 0, 2, 2, 1, 1, 1, 2, 0, 2]
batch 4: x (4, 4), y (4,), label [2, 1, 2, 0]Keluaran memperlihatkan tiga perilaku sekaligus. Perulangan for x, y in loader adalah pola yang persis digunakan saat pelatihan, sehingga mengenali bentuknya lebih awal menghemat waktu nanti. Dengan batch_size=32, 100 item menghasilkan empat batch, dan batch keempat hanya berisi empat item sisa. Label pada setiap batch tampak bercampur karena shuffle=True. Mekanisme pengacakan dibahas pada bagian tersendiri.
import torch
from torch.utils.data import TensorDataset, DataLoader
torch.manual_seed(0)
citra = torch.randn(64, 1, 28, 28) # 64 citra keabuan 28x28, shape: (64, 1, 28, 28)
label = torch.randint(0, 10, (64,)) # kelas 0 sampai 9
dataset = TensorDataset(citra, label)
loader = DataLoader(dataset, batch_size=16, num_workers=0)
x, y = next(iter(loader))
print("Jumlah batch:", len(loader))
print("Shape batch citra:", tuple(x.shape))
print("Shape batch label:", tuple(y.shape))Jumlah batch: 4
Shape batch citra: (16, 1, 28, 28)
Shape batch label: (16,)Untuk data citra, dimensi channel, tinggi, dan lebar dari satu item ikut menumpuk menjadi batch empat dimensi . Contoh di atas menggunakan 64 citra keabuan 28x28 sehingga satu batch berisi . Layer konvolusi pada modul CNN menuntut masukan berbentuk empat dimensi ini. Karena itu, mencetak shape setiap batch menjadi kebiasaan debug yang berharga.
Pengacakan dengan shuffle#
Parameter shuffle=True memerintahkan urutan item diacak pada setiap penelusuran. Mekanisme di baliknya adalah sampler, yaitu komponen yang menentukan urutan indeks yang dibaca dari dataset. shuffle=False menggunakan sampler berurutan dari indeks 0 sampai akhir, sedangkan shuffle=True menggunakan sampler acak yang urutannya berbeda pada setiap epoch. Dengan torch.manual_seed(0) di awal program, urutan acak tersebut tetap dapat direproduksi, sifat yang berguna saat menguji kode.
import torch
from torch.utils.data import TensorDataset, DataLoader
torch.manual_seed(0)
label = torch.arange(10) # label 0 sampai 9 agar urutannya mudah dilacak
dataset = TensorDataset(label, label)
loader_urut = DataLoader(dataset, batch_size=5, shuffle=False, num_workers=0)
loader_acak = DataLoader(dataset, batch_size=5, shuffle=True, num_workers=0)
print("shuffle=False:", [y.tolist() for _, y in loader_urut])
print("shuffle=True :", [y.tolist() for _, y in loader_acak])shuffle=False: [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
shuffle=True : [[3, 5, 0, 6, 1], [2, 4, 9, 7, 8]]Pengacakan penting karena data yang tersusun menurut pola tertentu membuat pembaruan bobot berdenyut, misalnya satu batch penuh kelas yang sama. Urutan acak menggabungkan sampel-sampel yang beragam di dalam satu batch, sehingga arah pembaruan lebih stabil.
drop_last dan batch sisa#
Batch sisa yang tidak penuh kadang tidak diinginkan, misalnya saat layer tertentu mengharapkan ukuran batch yang seragam. Parameter drop_last=True memerintahkan DataLoader membuang batch terakhir bila jumlahnya kurang dari batch_size. Contoh berikut menggunakan 100 item dengan batch_size=32 sehingga sisa batchnya hanya empat item.
import torch
from torch.utils.data import TensorDataset, DataLoader
fitur = torch.arange(200, dtype=torch.float32).reshape(100, 2) # 100 item, shape: (100, 2)
label = torch.zeros(100, dtype=torch.long)
dataset = TensorDataset(fitur, label)
tanpa_potong = DataLoader(dataset, batch_size=32, drop_last=False, num_workers=0)
dengan_potong = DataLoader(dataset, batch_size=32, drop_last=True, num_workers=0)
batch_terakhir = list(tanpa_potong)[-1][0]
print("drop_last=False:", len(tanpa_potong), "batch, terakhir:", tuple(batch_terakhir.shape))
batch_terakhir = list(dengan_potong)[-1][0]
print("drop_last=True :", len(dengan_potong), "batch, terakhir:", tuple(batch_terakhir.shape))drop_last=False: 4 batch, terakhir: (4, 2)
drop_last=True : 3 batch, terakhir: (32, 2)Perbedaannya tipis tetapi nyata: drop_last=False menghasilkan empat batch dengan batch terakhir berukuran (4, 2), sedangkan drop_last=True menghasilkan tiga batch penuh. Pemotongan ini merupakan konsekuensi yang harus disadari, karena data yang dibuang tetap bagian dari data pelatihan. Pada dataset kecil, persentase data yang hilang bisa signifikan, sehingga drop_last=True lazimnya dicadangkan untuk dataset besar atau kebutuhan ukuran batch yang ketat.
Jumlah worker num_workers#
Parameter num_workers mengatur proses pembacaan data. Nilai bawaan 0 berarti __getitem__ dijalankan langsung oleh proses utama, sehingga pembacaan data dan komputasi model bergantian menunggu satu sama lain. Nilai di atas 0 memunculkan sejumlah proses worker yang membaca data secara paralel, dan perbedaannya terasa ketika __getitem__ membaca file dari disk seperti pada topik dataset kustom. Nilai yang lazim untuk dataset menengah adalah dua sampai empat, sedangkan dataset kecil biasanya selesai lebih cepat tanpa worker sama sekali karena proses tambahan sendiri menambah biaya awal.
DataLoader juga menerima parameter sampler untuk mengatur urutan indeks secara eksplisit, misalnya WeightedRandomSampler untuk dataset dengan kelas yang tidak seimbang. Parameter shuffle dan sampler tidak dapat dipasang bersamaan, sehingga cukup satu yang dipasang. Detail sampler tingkat lanjut berada di luar cakupan topik ini.
Kesalahan umum#
Mengindeks loader seperti list. DataLoader tidak mendukung loader[0], dan pemanggilan semacam itu melempar TypeError. Untuk mengintip satu batch, gunakan next(iter(loader)), sedangkan untuk seluruh data gunakan perulangan for. Kebiasaan mencetak len(loader) di awal juga membantu memastikan jumlah batch sesuai harapan.
shuffle=True pada data validasi dan uji. Kesalahan ini tidak memunculkan error, tetapi membuat metrik sulit direproduksi karena urutan data berubah setiap penelusuran. Perbaikannya dengan memasang shuffle=False, atau cukup menggunakan nilai bawaannya, pada loader evaluasi dan menyisakan pengacakan hanya untuk loader pelatihan.
drop_last=True tanpa menghitung sisanya. Pada dataset kecil, batch sisa yang dibuang bisa mencakup porsi data yang besar, dan kehilangan itu tidak pernah ditampilkan sebagai peringatan. Perbaikannya dengan memeriksa len(loader) dikalikan batch_size terhadap jumlah item, atau menurunkan batch_size agar sisa batchnya wajar.
Ringkasan#
DataLoadermenyajikanDatasetsebagai deretan batch.len(loader)adalah jumlah batch, bukan jumlah item, dan penelusurannya menggunakan perulanganfor.batch_sizemenentukan ukuran batch,shuffle=Truemengacak urutan item pada tiap epoch dan hanya relevan untuk data pelatihan, sedangkandrop_last=Truemembuang batch sisa yang tidak penuh.- Bentuk batch mengikuti item: untuk vektor fitur dan untuk citra.
num_workers=0cukup untuk data kecil, sedangkan nilai di atas nol menguntungkan ketika pembacaan file menjadi hambatan.
Referensi#
- torch.utils.data — PyTorch Docs
— dokumentasi
DataLoaderbeserta parameterbatch_size,shuffle,drop_last,num_workers, dan sampler. - Learn the Basics — PyTorch Tutorials
— seri tutorial dasar resmi yang menempatkan
DataLoaderdi atasDataset.