ساخت dataloader سفارشی با کمک DataLoader و Dataset پایتورچ


در پروژه های یادگیری ماشین، مخصوصا یادگیری عمیق، ما با حجم بسیار بالای داده (big data) روبرو هستیم. و هندل کردن چنین داده ای جهت آموزش یک شبکه عصبی میتواند بسیار سخت و پیچیده باشد. از طرفی کدهای مربوط به پردازش نمونه‌ها  و آموزش شبکه عصبی هم میتواند بسیار شلوغ باشد. ما به طور ایده آل دوست داریم، که کد مربوط به آموزش مدل، با کد مربوط به داده جدا باشد تا یک کد خوانا و مدولار داشته باشیم. پایتورچ برای حل این مسئله دو تا کلاس به اسم Dataset و DataLoader دارد که کار با داده را بسیار ساده و راحت می‌کنند. در این پست میخواهیم با Dataset و DataLoader آشنا شویم و در آخر هم توضیح میدهیم که چطور میتوان یک DataLoader اختصاصی برای داده خود با کمک ابزار PyTorch بسازیم.

در کتابخانه Pytorch.utils.data دو کلاس به اسم Dataset و DataLoader وجود دارد که کار با داده را بسیار ساده می‌کنند. به طور کلی Dataset یک نمونه از داده و لیبل متناظر با آن را در خود ذخیره می‌کند و  DataLoader یک حلقه دور داده می پیچد و با کمک آن امکان دسترسی ساده به sample ها را فراهم می‌کند. DataLoader برای لود کردن داده از یک Dataset و ساخت minibatch استفاده می شود.

ساخت dataloader سفارشی برای داده با کمک DataLoader و Dataset پایتورچ

کلاس Dataset در پایتورچ

Dataset یک کلاس abstract هست. یعنی یک نقشه (blueprint) برای سایر کلاسها است. ما با کمک ارث بری برنامه نویسی شئی گرای پایتون، از روی کلاسDataset، کلاس مخصوص لود کردن داده خود را تعریف می‌کنیم.

 

نکته: به کلاسی که شامل یک یا چندین متد abstract باشد، کلاس abstract گفته می‌شود، و به متدی که تعریف شده ولی پیاده‌‎سازی نشده هم متد abstract گفته می‌شود.

Python

class CustomDataset(Dataset):
      def __init__(self,<arguments>):
          pass
      def __len__(self):
          pass
      def __getitem__(self, index):
          pass

کلاس Dataset مسئول لود کردن داده (فقط یک سمپل از داده) از یک منبع و پیش پردازش، و تبدیل داده به تنسور است.

کلاس Dataset شامل سه متد اصلی است:

  • متد جادویی __init__
  • در این متد، آماده‌سازی جهت خواندن داده انجام میشه و یه سری شناسه های مرتبط جهت خواندن و تبدیلات داده تعریف می‌شود.
  • متد جادویی __len__
    • این متد تعداد نمونه های داده را بر می‌گرداند
  • متد جادویی __getitem__
    • این متد، اندیس داده را دریافت کرده و اون داده و به همراه لیبل را خوانده، پیش پردازشهای لازم رو انجام داده و در خروجی قرار میدهد.
    • این متد توسط DataLoader جهت پیش پردازش و لود کردن داده استفاده می شود.

کلاس DataLoader در پایتورچ

کلاس DataLoader پایتورچ، یک کلاس utility است و برای لود کردن داده از یک دیتاست و ساخت minibatch جهت آموزش شبکه‌های عصبی استفاده می‌شود. کلاس DataLoader بر روی کلاس Dataset ساخته شده است که یک رابط استاندارد برای دسترسی داده فراهم می‌کند. کلاس DataLoader یک object از کلاس Dataset دریافت می‌کند و یک راهی فراهم می‌کند تا بتوان روی داده به صورت  batchدسترسی پیدا کرد و داده را به چندین batch تقسیم کند و آماده ارائه آن به شبکه عصبی جهت آموزش بکند.

ساخت dataloader سفارشی برای داده با کمک DataLoader و Dataset پایتورچ

کلاس DataLoader مسئول batching داده و آماده کردن آن به فرمت مناسب جهت به ارائه به شبکه عصبی است.

کلاس DataLoader برای هندل کردن داده‌های بزرگ، data augmentation، shuffling و سایر تسک‌‎های پیش پردازش طراحی شده است.

مزایای استفاده از DataLoader

  • Efficient data loading: به کاربر اجازه می‌دهد تا داده را به صورت موازی لود کند.
  • Data augmentation: به کاربر اجازه میدهد تا قبل اعمال داده به شبکه ی عصبی، یه سری تبدیلاتی روی داده اعمال کند.
  • flexibility: بسیار منعطف است و میتوان با کمک آن فرمتها و منابع مختلف داده را هندل کرد. میتوان با کمکش داده از فایلهای خارجی را بارگذاری کرد و همچنین پیش پردازشها سفارشی روی داده اعمال کرد.
  • Shuffling: به کاربر اجازه میدهد که درهر تکرار آموزش شبکه عصبی داده را shuffle کرد. با این کار از overfitting شبکه جلوگیری می‌کند و خاصیت عمومیت (generalization) شبکه را بهبود میدهد.

 



فرض کنید یک داده ای به اسم dataset داریم، که داخل اون تعدادی فایل تکست داریم و میخواهیم با کمک Dataset و DataLoader یک دیتالودر سفارشی برای این داده بسازیم.

ساخت dataloader سفارشی برای داده با کمک DataLoader و Dataset پایتورچ

اول یک کلاس برای لود کردن تنها یک نمونه با کمک Dataset میسازیم. سپس با کمک DataLoader داده را batching میکنیم.

مرحله اول: وارد کردن کتابخانه های مورد نیاز  پایتون

Python

import torch
import glob
import pandas as pd
from torch.utils.data import Dataset,DataLoader

مرحله دوم: ساخت کلاس سفارشی برای لود کردن نمونه ها

Python

class CustomDataset(Dataset):
      def __init__(self,pathname):
         self.file_names= glob.glob(pathname+ '\*\*.txt')
         self.class_map= {'S':0,'Z':1}

در این متد، اسم فایلهای تسکت را با کمک تابع glob مشخص میکنیم تا در متد getitem از اونا برای خواندن فایلها استفاده کنیم.

همچنین مشخص کردیم که نمونه های داخل فایل S لیبل 0 و نمونه های داخل Z هم لیبل یک بگیرند.

شما هم بهتر هست فایلهای هر کلاس را داخل یک فولدر بسازید و طبق روال ما، برای آنها یک نقشه لیبل تعریف کنید تا موقع خوندن نمونه ها یک لیبل مناسب برای آنها در نظر بگیرد.

Python

      def __len__(self):
          len(self.file_names)

همونطور که قبلا اشاره کردیم، این متد باید تعداد کل نمونه های داده را برگرداند. از آنجا که اسم همه فایلها به صورت یک لیست داخل شناسه file_names است، برای همین طول این لیست را برمیگردانیم.

Python

      def __getitem__(self,indx):
          filename= self.file_names[indx]
          df= pd.read_csv(filename,header=None)
          sample= df.iloc[:,0].to_numpy()
          sample= torch.from_numpy(sample).type(torch.float32)       
          chr= filename.split('\\')[-1][0]
          label= self.class_map[chr]
          return sample,label

در این متد هم،  هر بار یک نمونه از داده (نمونه ای که کاربر به index مشخص می‌کند) با کمک کتابخانه پانداس خوانده می‌شود، و به تنسور تبدیل میشود. همچنین بسته به اینکه از کدام فایل خوانده شده، طبق نقشه لیبل، لیبل آن ساخته شده و همراه با سمپل به خروجی داده می شود.

خب ما تا اینجای کار تونستیم یک کلاس برای ساخت Dataset سفارشی بسازیم. در ادامه باید از روی این کلاس یک object بسازیم.

مرحله سوم: ساخت Object از روی کلاس تعریف شده

Python

ds= CustomDataset('dataset')

حال اگر به صفحه متغیرها نگاه کنیم، میبینم که object از نوع CustonDataset ساخته شده که داخلش 200 فایل هست.

ساخت dataloader سفارشی برای داده با کمک DataLoader و Dataset پایتورچ

ما با کمک این کلاس، همانند زیر فقط میتوانیم در هر لحظه یک نمونه از داده را بخوانیم.

Python

Index=0
sample,label= ds[index]

برای مثال در این کد، ما اولین نمونه از داده را خواندیم و در دو متغیر sample, label داده ورودی و لیبل آنرا قرار دادیم.

اما مسئه این است که ما میخواهیم داده را batch بندی کنیم و در داخل هر تکه، چندین نمونه را داشته باشیم. این وظیفه DataLoader هست که در ادامه توضیح میدهیم که چطور میتوان اینکار را انجام داد.

مرحله چهارم: Batching داده با استفاده از DataLoader

حال این object آماده هست تا بدیم به DataLoader، تا داده را batchبندی کند.

Python

data_loader= DataLoader(ds,batch_size=32,shuffle=True)
  • ds همان objectی است که که از روی کلاس Dataset ساختیم.
  • batch_size مشخص میکند که در هر تکه چندین نمونه قرار بگیرید که ما اینجا، 32 در نظر گرفتیم.
  • Shuffle هم مشخص میکند که در هر تکرار آموزش شبکه عصبی، آیا ترتیب داده ها به صورت تصادفی تغییر کند یا نه. که ما True گذاشته ایم تا ترتیب تغییر کنه و از احتمال overfitting شبکه جلوگیری کند.

مرحله پنجم: ایجاد یک حلقه جهت دستری به batchها

حال اگر بخواهیم به هر تکه دسترسی داشته باشیم، یک حلقه مینویسیم و در هر تکرار یک تکه از داده را جدا کرده و به شبکه عصبی اعمال میکنیم تا آموزش ببیند.

Python

for x_batch,y_batch  in data_loader:
    print(x_batch.shape,y_batch.shape)

>>>
torch.Size([32, 4097]) torch.Size([32])
torch.Size([32, 4097]) torch.Size([32])
torch.Size([32, 4097]) torch.Size([32])
torch.Size([32, 4097]) torch.Size([32])
torch.Size([32, 4097]) torch.Size([32])
torch.Size([32, 4097]) torch.Size([32])
torch.Size([8, 4097]) torch.Size([8])

ما در این کد فقط اندازه هر تکه و لیبلهاش را چاپ کردیم. شما در عمل باید این تکه و لیبلهاش رو به شبکه ارائه بدهید.

در دوره تخصصی و پروژه محور پایتورچ مباحث مرتبط با ساخت dataloader  سفارشی برای داده های مختلف را کامل آموزش داده ایم.

ما در دوره پایتورچ سه هدف اصلی داریم:

  • یادگیری تئوری ریاضیات شبکه های عصبی و روشهای بهینه سازی
  • یادگیری کار با ابزار پایتورچ به صورت تخصصی
    • ساخت dataloader ها اختصاصی برای داده های خودمان
    • پیاده‌سازی شبکه های عصبی با ابزار پایتورچ
  • انجام پروژه های عملی

 


دیدگاه ها

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

code