Dataset এবং DataLoader: ব্যাখ্যা এবং উদাহরণ
Machine Learning এবং Deep Learning মডেলে ডেটাসেটের সঠিক ব্যবস্থাপনা অত্যন্ত গুরুত্বপূর্ণ। Dataset এবং DataLoader হল এমন দুটি উপাদান যা ডেটা লোড করা, ব্যাচ আকারে বিভক্ত করা এবং মডেলের জন্য প্রি-প্রসেসিং এর কাজ সহজ করে।
1. Dataset কী?
Dataset হলো ডেটা স্টোরেজের একটি কাঠামো, যা প্রতিটি ডেটা আইটেম লোড এবং সংরক্ষণ করে। PyTorch এবং Chainer এর মত ফ্রেমওয়ার্কে কাস্টম ডেটাসেট তৈরি করার জন্য বিশেষ ক্লাস রয়েছে। এখানে __getitem__() এবং __len__() মেথড ব্যবহার করে কাস্টম ডেটাসেট তৈরি করা হয়।
2. DataLoader কী?
DataLoader হলো এমন একটি ফাংশন বা পদ্ধতি যা ডেটাসেট থেকে ডেটা লোড করে এবং ব্যাচ আকারে ট্রেনিং বা ভ্যালিডেশন সেটে বিভক্ত করে। এটি সাধারণত শাফলিং (shuffling) এবং ব্যাচিং (batching) সাপোর্ট করে, যাতে মডেল প্রশিক্ষণ অধিক কার্যকরী হয়।
উদাহরণ: XOR ফাংশনের জন্য Dataset এবং DataLoader ব্যবহার
নিচে একটি উদাহরণ দেওয়া হলো যেখানে XOR ফাংশনের জন্য ডেটাসেট এবং DataLoader তৈরি করা হয়েছে।
import chainer
import chainer.functions as F
import chainer.links as L
from chainer import Chain, optimizers, Variable, datasets, iterators
# কাস্টম Dataset তৈরি
class XORCustomDataset(chainer.dataset.DatasetMixin):
def __init__(self):
# XOR ইনপুট এবং আউটপুট ডেটা ডিফাইন করা
self.x_data = [[0, 0], [0, 1], [1, 0], [1, 1]]
self.y_data = [0, 1, 1, 0] # XOR output values
def __len__(self):
return len(self.x_data)
def get_example(self, i):
return self.x_data[i], self.y_data[i]
# Dataset ইনস্ট্যান্স তৈরি করা
xor_dataset = XORCustomDataset()
# DataLoader (Iterator) তৈরি
batch_size = 2
train_iter = iterators.SerialIterator(xor_dataset, batch_size, shuffle=True)
# মডেল তৈরি করা
class XORNetwork(Chain):
def __init__(self):
super(XORNetwork, self).__init__()
with self.init_scope():
self.l1 = L.Linear(2, 3) # হিডেন লেয়ার
self.l2 = L.Linear(3, 1) # আউটপুট লেয়ার
def __call__(self, x):
h = F.sigmoid(self.l1(x)) # হিডেন লেয়ার
y = F.sigmoid(self.l2(h)) # আউটপুট লেয়ার
return y
# মডেল ও Optimizer সেটআপ
model = XORNetwork()
optimizer = optimizers.Adam()
optimizer.setup(model)
# Training Loop
epochs = 1000
for epoch in range(epochs):
total_loss = 0
train_iter.reset() # ইটারেটর রিসেট করা হচ্ছে প্রতিটি epoch এ
for batch in train_iter:
x_batch, y_batch = zip(*batch)
# ডেটাকে ভ্যারিয়েবলে রূপান্তর
x = Variable(chainer.backends.cuda.to_cpu(x_batch))
y = Variable(chainer.backends.cuda.to_cpu(y_batch))
# Forward Propagation এবং লস গণনা
y_pred = model(x)
loss = F.mean_squared_error(y_pred, y.reshape(-1, 1))
total_loss += loss.data
# Backward Propagation এবং Optimizer আপডেট
model.cleargrads()
loss.backward()
optimizer.update()
if epoch % 200 == 0:
print(f'Epoch {epoch}, Average Loss: {total_loss / len(xor_dataset)}')
# Model Evaluation
print("\nEvaluating the trained model on XOR function:")
predictions = []
for x in xor_dataset:
y_pred = model(Variable(chainer.backends.cuda.to_cpu(x[0])))
predictions.append(int(y_pred.data > 0.5)) # Threshold set at 0.5
print(f"Predictions: {predictions}")
print(f"Actual Values: {[item[1] for item in xor_dataset]}")
ব্যাখ্যা
Dataset Creation:
XORCustomDatasetক্লাসটি তৈরি করা হয়েছে, যেখানে__len__()এবংget_example()মেথড ব্যবহার করা হয়েছে।x_dataএবংy_dataআমাদের ইনপুট এবং আউটপুট ডেটা ধারণ করছে।
DataLoader (Iterator):
train_iterহলোSerialIteratorএর একটি উদাহরণ যাxor_datasetথেকে প্রতিটি ব্যাচ লোড করে।batch_size2 হিসেবে নির্ধারণ করা হয়েছে এবংshuffle=Trueদিয়ে ডেটাকে শাফল করা হয়েছে।
Training Loop:
- Training Loop এর সময় DataLoader থেকে প্রতিটি ব্যাচ নেওয়া হয়, যা Forward এবং Backward Propagation এর মাধ্যমে ট্রেনিং করে।
Model Evaluation:
- ট্রেনিং শেষে মডেলটি ইনপুটের জন্য প্রেডিকশন তৈরি করে এবং Threshold ব্যবহার করে আউটপুট 0 বা 1 হিসেবে দেখায়।
সংক্ষেপে
Dataset এবং DataLoader মডেলের ট্রেনিং এবং ইভ্যালুয়েশন প্রক্রিয়াকে সহজ ও কার্যকর করে তোলে। Chainer বা PyTorch এর মত ফ্রেমওয়ার্কে কাস্টম Dataset এবং DataLoader ব্যবহার করা ট্রেনিং পদ্ধতিকে আরও কার্যকর করতে সহায়ক।
PyTorch বা টেনসরফ্লো এর মত deep learning ফ্রেমওয়ার্কে মডেল training এর জন্য ডেটা ব্যবস্থাপনা খুবই গুরুত্বপূর্ণ। এই ক্ষেত্রে Dataset এবং DataLoader দুটি গুরুত্বপূর্ণ উপাদান হিসেবে ব্যবহৃত হয়।
Dataset এর ধারণা
Dataset হলো একটি ডেটা অবজেক্ট যা সাধারণত মডেল training এর জন্য ডেটাকে সংগঠিত করে রাখে। একটি Dataset ক্লাসে ডেটার প্রতিটি ইনস্ট্যান্স এবং তার লেবেল বা টার্গেট ভ্যালু সংরক্ষিত থাকে। PyTorch এ torch.utils.data.Dataset ক্লাসটি এই কাজের জন্য ব্যবহৃত হয়, যা থেকে একটি কাস্টম ডেটাসেট ক্লাস তৈরি করা যায়।
Dataset এর গুরুত্বপূর্ণ বৈশিষ্ট্য
- ডেটা লোডিং: Dataset থেকে প্রতিটি ইনডেক্সের মাধ্যমে একটি ডেটা পয়েন্ট এবং তার টার্গেট ভ্যালু বের করা যায়।
- ট্রান্সফর্মেশন: Dataset এ ডেটা প্রি-প্রসেসিং করা যায়, যেমন normalization, resizing ইত্যাদি।
- কাস্টমাইজেশন: PyTorch এ
__len__এবং__getitem__মেথড ব্যবহার করে কাস্টম Dataset তৈরি করা যায়।
উদাহরণ:
ধরা যাক, আমাদের একটি ইমেজ ডেটাসেট আছে। আমরা এই ডেটাসেটটিকে PyTorch এর Dataset ক্লাস দিয়ে ব্যবহার করতে চাই।
from torch.utils.data import Dataset
from PIL import Image
class CustomImageDataset(Dataset):
def __init__(self, img_paths, labels, transform=None):
self.img_paths = img_paths
self.labels = labels
self.transform = transform
def __len__(self):
return len(self.img_paths)
def __getitem__(self, idx):
image = Image.open(self.img_paths[idx])
label = self.labels[idx]
if self.transform:
image = self.transform(image)
return image, label
এই CustomImageDataset ক্লাসের মাধ্যমে ডেটাসেটকে ইনডেক্স করে ইমেজ এবং লেবেল এক্সেস করা যায়।
DataLoader এর ধারণা
DataLoader হলো এমন একটি টুল যা Dataset থেকে ডেটা batching, shuffling এবং multi-threaded ভাবে লোড করতে সাহায্য করে। DataLoader মডেল training এর সময় Dataset থেকে ডেটা সহজেই লোড করার প্রক্রিয়া পরিচালনা করে। এটি mini-batch এর মাধ্যমে ডেটা লোড করার কাজটি খুব দ্রুত এবং efficient করে।
DataLoader এর গুরুত্বপূর্ণ বৈশিষ্ট্য
- Batching: DataLoader Dataset থেকে নির্দিষ্ট সংখ্যক ডেটা পয়েন্ট নিয়ে mini-batch তৈরি করে। যেমন, batch size 32 হলে প্রতিবার 32টি ডেটা পয়েন্ট একসাথে লোড হবে।
- Shuffling: ডেটাকে এলোমেলোভাবে মেশানো যায়, যা মডেলের accuracy বাড়াতে সাহায্য করে।
- Parallel Processing: DataLoader multi-threaded প্রসেসিং সাপোর্ট করে, যা ডেটা লোডিং দ্রুত করে তোলে।
- Data Augmentation: ডেটা লোড করার সময় augmentation techniques প্রয়োগ করে ডেটাকে enhance করা যায়।
উদাহরণ:
DataLoader ব্যবহার করার উদাহরণ নীচে দেওয়া হল:
from torch.utils.data import DataLoader
# ডেটাসেট এবং DataLoader ইনিশিয়ালাইজ করা
dataset = CustomImageDataset(img_paths=img_paths, labels=labels, transform=transform)
data_loader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=4)
এখানে,
batch_size=32: প্রতি batch এ ৩২টি ইমেজ এবং লেবেল লোড হবে।shuffle=True: প্রতি epoch এ ডেটা এলোমেলোভাবে সাজানো হবে।num_workers=4: ডেটা লোডিং দ্রুত করতে চারটি প্রসেসর থ্রেড ব্যবহার করা হবে।
Dataset এবং DataLoader এর সম্পর্ক
- Dataset থেকে DataLoader ডেটা টেনে আনে এবং batch তৈরি করে।
- DataLoader এর মাধ্যমে আমরা মডেল training, validation বা testing এ ডেটা batching এবং augmentation প্রয়োগ করতে পারি।
Dataset এবং DataLoader এর মাধ্যমে ডেটাকে সহজে এবং দ্রুত মডেলের জন্য প্রস্তুত করা যায়, যা মডেলের performance এবং efficiency বাড়ায়।
Chainer Dataset Module এর ব্যবহার
Chainer-এর dataset মডিউল ডেটা পরিচালনা, লোড করা, এবং ট্রেনিংয়ে প্রক্রিয়াজাত করার জন্য বিভিন্ন টুলস সরবরাহ করে। এই মডিউলটি বিশেষভাবে কার্যকর যখন বড় ডেটাসেট নিয়ে কাজ করতে হয়, কারণ এটি ডেটাকে সহজেই কাস্টম ডেটাসেটে রূপান্তর করার সুযোগ দেয়।
Chainer-এর dataset মডিউলে প্রধানত তিনটি বিষয় থাকে:
- DatasetMixin: কাস্টম ডেটাসেট তৈরি করার জন্য ব্যবহার করা হয়।
- TransformDataset: ডেটার উপর প্রি-প্রসেসিং অপারেশন চালানোর জন্য ব্যবহৃত হয়।
- SplitDatasetRandom এবং SplitDataset: ডেটাসেটকে ট্রেনিং এবং টেস্ট সেটে বিভক্ত করতে সাহায্য করে।
উদাহরণ: Chainer Dataset মডিউল ব্যবহার করে কাস্টম ডেটাসেট তৈরি
নিচে আমরা Chainer Dataset মডিউল ব্যবহার করে একটি কাস্টম ডেটাসেট তৈরি এবং তা ব্যবহার করবো।
1. কাস্টম Dataset তৈরি:
import chainer
from chainer import dataset
import numpy as np
# কাস্টম ডেটাসেট তৈরি
class CustomDataset(dataset.DatasetMixin):
def __init__(self, data, labels):
self.data = data
self.labels = labels
# ডেটাসেটের দৈর্ঘ্য রিটার্ন করে
def __len__(self):
return len(self.data)
# নির্দিষ্ট ইনডেক্সের ডেটা এবং লেবেল রিটার্ন করে
def get_example(self, i):
return self.data[i], self.labels[i]
# ডামি ডেটাসেট তৈরি
data = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=np.float32)
labels = np.array([0, 1, 1, 0], dtype=np.int32)
# ডেটাসেট ইনস্ট্যান্স তৈরি
custom_dataset = CustomDataset(data, labels)
print("Dataset Length:", len(custom_dataset))
print("Example Data:", custom_dataset[0])
এখানে আমরা CustomDataset নামে একটি ডেটাসেট তৈরি করেছি, যেখানে __len__() মেথড ডেটাসেটের মোট দৈর্ঘ্য এবং get_example() মেথড নির্দিষ্ট ইনডেক্সের ডেটা এবং লেবেল প্রদান করে।
2. TransformDataset: ডেটার উপর প্রি-প্রসেসিং অপারেশন চালানো
TransformDataset ব্যবহার করে ডেটাসেটে প্রি-প্রসেসিং অপারেশন যেমন Normalization বা Augmentation সহজেই করা যায়।
from chainer.dataset import TransformDataset
# ডেটা ট্রান্সফর্ম করার জন্য ফাংশন
def transform(data):
x, y = data
x = x / np.max(x) # Normalization
return x, y
# TransformDataset তৈরি
transformed_dataset = TransformDataset(custom_dataset, transform)
# উদাহরণ দেখানো
for i in range(len(transformed_dataset)):
print("Transformed Data:", transformed_dataset[i])
3. SplitDatasetRandom এবং SplitDataset: ডেটাসেট ভাগ করা
SplitDatasetRandom এবং SplitDataset ব্যবহার করে ডেটাসেটকে ট্রেনিং এবং টেস্ট সেটে ভাগ করা যায়।
from chainer.dataset import split_dataset_random
# ডেটাসেটকে 75% ট্রেনিং এবং 25% টেস্টে ভাগ করা
train_size = int(len(custom_dataset) * 0.75)
train, test = split_dataset_random(custom_dataset, train_size, seed=0)
print("Train Dataset Length:", len(train))
print("Test Dataset Length:", len(test))
ব্যাখ্যা
- CustomDataset: ডেটাসেট মডিউল ব্যবহার করে একটি কাস্টম ডেটাসেট তৈরি করা হয়েছে।
- TransformDataset: ডেটার উপর Normalization চালানো হয়েছে।
- split_dataset_random: ডেটাসেটকে ট্রেনিং এবং টেস্টে বিভক্ত করা হয়েছে।
সংক্ষেপে
Chainer Dataset Module ডেটা প্রি-প্রসেসিং, কাস্টম ডেটাসেট তৈরির এবং ডেটাসেট বিভাজনের জন্য একটি সহজ উপায় প্রদান করে, যা বড় ডেটাসেট পরিচালনা করতে কার্যকর।
PyTorch এ custom Dataset তৈরি করার জন্য torch.utils.data.Dataset ক্লাসটি ইনহেরিট করে একটি নতুন ক্লাস তৈরি করতে হয় এবং এতে ডেটা লোড করার জন্য প্রয়োজনীয় মেথড যেমন __len__ এবং __getitem__ ওভাররাইড করতে হয়।
এরপর এই Dataset টি DataLoader এর মাধ্যমে লোড করে মডেল training এর জন্য ডেটা batching এবং shuffling এর মতো সুবিধা পাওয়া যায়।
Custom Dataset তৈরি করা
ধরা যাক, আমাদের একটি ইমেজ ডেটাসেট রয়েছে, যেখানে প্রতিটি ইমেজ এর path এবং corresponding label আছে। আমরা এই ডেটাসেটটি PyTorch এর Dataset ক্লাস থেকে তৈরি করব।
import torch
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import os
class CustomImageDataset(Dataset):
def __init__(self, img_dir, labels, transform=None):
self.img_dir = img_dir # ইমেজ ফোল্ডারের path
self.labels = labels # লেবেলের তালিকা
self.transform = transform # ট্রান্সফর্মেশন অপশন
def __len__(self):
# মোট ইমেজ সংখ্যা রিটার্ন করবে
return len(self.labels)
def __getitem__(self, idx):
# ইমেজ এবং এর সাথে লেবেল লোড করা
img_path = os.path.join(self.img_dir, f"image_{idx}.jpg") # ধরে নেয়া হয়েছে ইমেজ নাম "image_{idx}.jpg" আকারে আছে
image = Image.open(img_path).convert("RGB") # ইমেজকে RGB ফরম্যাটে কনভার্ট করা
label = self.labels[idx]
# ট্রান্সফর্মেশন থাকলে ইমেজে প্রয়োগ করা
if self.transform:
image = self.transform(image)
return image, label
এখানে,
img_dirহলো ইমেজ ফোল্ডার যেখানে সব ইমেজ সংরক্ষিত আছে।labelsএকটি তালিকা যা প্রতিটি ইমেজ এর corresponding লেবেল ধারণ করে।transformহলো একটি অপশনাল প্যারামিটার, যেখানে ইমেজ augmentation বা normalization করা যায়।
DataLoader এর মাধ্যমে ডেটা লোড করা
DataLoader এর মাধ্যমে এই custom dataset টি ব্যবহার করে mini-batch এ ডেটা লোড করা যায়। DataLoader ডেটা batching, shuffling এবং multi-threaded loading করতে পারে।
from torchvision import transforms
# ডেটাসেট এর জন্য ট্রান্সফর্মেশন তৈরি
transform = transforms.Compose([
transforms.Resize((128, 128)), # ইমেজকে 128x128 সাইজে রিসাইজ করা
transforms.ToTensor(), # ইমেজকে টেনসরে কনভার্ট করা
])
# লেবেল লিস্ট তৈরি (উদাহরণস্বরূপ কিছু dummy labels)
labels = [0, 1, 0, 1, 0] # ৫টি ইমেজের জন্য লেবেল
# Custom Dataset initialize করা
dataset = CustomImageDataset(img_dir="path/to/images", labels=labels, transform=transform)
# DataLoader তৈরি করা
data_loader = DataLoader(dataset, batch_size=2, shuffle=True, num_workers=2)
# ডেটা লোড করে দেখা
for images, labels in data_loader:
print("Batch of images:", images.shape) # প্রতিটি batch এর image shape
print("Batch of labels:", labels) # প্রতিটি batch এর label
break # শুধু প্রথম batch টেস্ট করার জন্য break
কোড ব্যাখ্যা
transform: ইমেজকে resize এবং টেনসর ফরম্যাটে কনভার্ট করা হয়েছে যাতে এটি PyTorch মডেলে ব্যবহারযোগ্য হয়।CustomImageDataset: Custom ডেটাসেট অবজেক্ট যা ইমেজ এবং লেবেল প্রদান করবে।DataLoader: Dataset থেকে batch তৈরি করে মডেলে ডেটা পাঠানোর জন্য প্রস্তুত করে।
এভাবে DataLoader এর মাধ্যমে mini-batch লোড করার সুবিধা পাওয়া যায়, যা training এবং validation এ গুরুত্বপূর্ণ। DataLoader এর shuffle=True সেট করা হলে ডেটা এলোমেলোভাবে লোড হবে যা মডেল training এ bias কমাতে সাহায্য করে।
PyTorch এ custom dataset তৈরি করার জন্য torch.utils.data.Dataset ক্লাসটি ইনহেরিট করে একটি নতুন dataset ক্লাস তৈরি করতে হয়। এই ক্লাসের মাধ্যমে ডেটা এবং তার লেবেলগুলো ইনডেক্স করে সহজে এক্সেস করা যায়। এখানে একটি উদাহরণসহ custom dataset তৈরি করা দেখানো হলো।
ধরা যাক, আমাদের একটি ডেটাসেট রয়েছে যেখানে টেক্সট ফাইল থেকে ডেটা লোড করতে হবে, এবং প্রতিটি টেক্সট এর সাথে একটি লেবেল (positive বা negative sentiment) যুক্ত থাকবে।
ধাপ ১: Dataset তৈরি করা
আমরা একটি TextDataset নামের custom dataset ক্লাস তৈরি করব। এখানে প্রতিটি টেক্সট এবং তার সাথে একটি লেবেল সংরক্ষিত থাকবে।
import torch
from torch.utils.data import Dataset
class TextDataset(Dataset):
def __init__(self, texts, labels, transform=None):
"""
texts (list of str): টেক্সট ডেটা লিস্ট হিসেবে থাকবে
labels (list of int): টেক্সটের corresponding লেবেল (0 বা 1)
transform (callable, optional): Transform অ্যাপ্লাই করার অপশন
"""
self.texts = texts
self.labels = labels
self.transform = transform
def __len__(self):
# ডেটাসেটের মোট নমুনা সংখ্যা
return len(self.texts)
def __getitem__(self, idx):
# নির্দিষ্ট ইনডেক্সের টেক্সট এবং লেবেল ফেরত দেয়
text = self.texts[idx]
label = self.labels[idx]
# transform থাকলে তা অ্যাপ্লাই করা হয়
if self.transform:
text = self.transform(text)
return text, label
ধাপ ২: উদাহরণ হিসেবে কিছু ডেটা তৈরি করা
এখন আমরা কিছু উদাহরণ হিসেবে টেক্সট এবং তার লেবেল তৈরি করব, এবং এই ডেটা TextDataset ক্লাসে ব্যবহার করব।
# উদাহরণ হিসেবে টেক্সট এবং লেবেল ডেটা তৈরি
texts = [
"I love this product, it is fantastic!",
"This is the worst experience I've had.",
"Absolutely wonderful service and support.",
"I am very disappointed with the quality.",
"Excellent quality and fast delivery!"
]
labels = [1, 0, 1, 0, 1] # 1: positive sentiment, 0: negative sentiment
ধাপ ৩: Dataset Initialize করা
আমরা TextDataset এর একটি instance তৈরি করব যেখানে texts এবং labels ব্যবহার করা হবে।
# Dataset instance তৈরি
dataset = TextDataset(texts=texts, labels=labels)
ধাপ ৪: Dataset থেকে ডেটা অ্যাক্সেস করা
এখন আমরা dataset এর item গুলোতে এক্সেস করতে পারি এবং প্রতিটি টেক্সট এবং তার লেবেল দেখতে পারি।
# ডেটাসেটের প্রতিটি আইটেম প্রিন্ট করা
for i in range(len(dataset)):
text, label = dataset[i]
print(f"Text: {text}")
print(f"Label: {label}\n")
আউটপুট:
এটি চলানোর ফলে আউটপুটটি নিম্নরূপ হতে পারে:
Text: I love this product, it is fantastic!
Label: 1
Text: This is the worst experience I've had.
Label: 0
Text: Absolutely wonderful service and support.
Label: 1
Text: I am very disappointed with the quality.
Label: 0
Text: Excellent quality and fast delivery!
Label: 1
ধাপ ৫: DataLoader ব্যবহার করা (ঐচ্ছিক)
এখন আমরা এই dataset টি DataLoader এর মাধ্যমে mini-batches আকারে লোড করতে পারি।
from torch.utils.data import DataLoader
# DataLoader তৈরি করা
data_loader = DataLoader(dataset, batch_size=2, shuffle=True)
# DataLoader থেকে ব্যাচ লোড করা এবং দেখানো
for batch in data_loader:
texts, labels = batch
print("Batch of Texts:", texts)
print("Batch of Labels:", labels)
ব্যাখ্যা:
- Texts: টেক্সট ডেটার একটি লিস্ট বা আরে, যা প্রতিটি টেক্সট এবং তার সাথে সংযুক্ত লেবেল প্রদান করে।
- Labels: টেক্সটের sentiment অনুযায়ী লেবেল প্রদান করা হয়েছে (১ মানে positive, ০ মানে negative)।
- DataLoader:
batch_size=2ব্যবহার করা হয়েছে, যাতে প্রতি ব্যাচে ২টি করে টেক্সট এবং লেবেল লোড হয় এবংshuffle=Trueকরে ডেটাকে এলোমেলোভাবে সাজানো হয়েছে।
এই কোডের মাধ্যমে আমরা custom dataset এবং DataLoader এর মাধ্যমে ডেটা লোড করার পুরো প্রক্রিয়া সহজে করতে পারি।
Read more