بناء نموذج تعلم عميق صغير باستخدام PyTorch خطوة بخطوة

PyTorch شرح بالعربي: بناء نموذج تعلم عميق صغير خطوة بخطوة

إذا كنت بدأت تتعلم بايثون وتريد الدخول لعالم التعلم العميق عمليًا، فمكتبة PyTorch واحدة من أفضل الاختيارات. في هذا الدليل سنقدم لك PyTorch شرح بالعربي من خلال مشروع عملي كامل: بناء نموذج بسيط لتصنيف الصور (Digits) خطوة بخطوة، من تجهيز البيانات وحتى حفظ النموذج واستخدامه للتنبؤ.

يفترض هذا الشرح أنك تعرف أساسيات بايثون، وإذا لم تكن كذلك يمكنك الرجوع إلى: مسار تعلم لغة بايثون من الصفر خطوة بخطوة.

ما هي PyTorch ولماذا هي مهمة في التعلم العميق؟

PyTorch هي مكتبة مفتوحة المصدر بلغة بايثون لبناء نماذج التعلم العميق (Deep Learning) تم تطويرها بواسطة فيسبوك. تتميز بأنها:

  • مرنة جدًا ومناسبة للتجارب البحثية والمشاريع العملية.
  • تتعامل مع الـ GPU بسهولة لتسريع التدريب.
  • تسمح لك ببناء نماذج الشبكات العصبية خطوة بخطوة وبشكل واضح.

في هذا المقال سنركز على الجانب العملي: كيف تنشئ أول نموذج تصنيف صور بسيط باستخدام PyTorch، وهو تطبيق مباشر لمفاهيم الذكاء الاصطناعي والتعلم العميق.

نظرة عامة على المشروع

سنقوم ببناء نموذج لتصنيف الأرقام المكتوبة يدويًا (0–9) باستخدام مجموعة بيانات MNIST الشهيرة، بخطوات عملية:

  1. تثبيت PyTorch وتجهيز بيئة العمل.
  2. تحميل وتجهيز البيانات (الصور والـ Labels).
  3. بناء نموذج شبكة عصبية بسيطة (Neural Network).
  4. تحديد دالة الخسارة (Loss) والمُحسّن (Optimizer).
  5. تدريب النموذج (Training Loop).
  6. تقييم النموذج على بيانات الاختبار.
  7. حفظ النموذج واستخدامه للتنبؤ على بيانات جديدة.

1. تثبيت PyTorch وتجهيز البيئة

أول خطوة في PyTorch شرح بالعربي هي التأكد من تثبيت المكتبة بشكل صحيح. يفضّل العمل داخل بيئة افتراضية (virtual environment) في بايثون.

أولًا: إنشاء وتفعيل بيئة افتراضية (اختياري لكن مستحسن)

python -m venv venv
source venv/bin/activate  # على لينكس/ماك
# أو على ويندوز:
venv\Scripts\activate

ثانيًا: تثبيت PyTorch

ادخل على الموقع الرسمي لـ PyTorch لاختيار الأمر المناسب حسب نظامك وكرت الشاشة، لكن في أغلب الحالات (بدون GPU) يكفي:

pip install torch torchvision torchaudio

نستخدم torchvision لتحميل مجموعات بيانات الصور الجاهزة مثل MNIST.

2. استيراد المكتبات والتأكد من توفر GPU

افتح ملف جديد مثل mnist_pytorch.py أو Notebook، وابدأ باستيراد المكتبات:

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

فحص توفر كرت الشاشة (CUDA):

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print("Using device:", device)

إذا ظهرت cuda فهذا يعني أن التدريب سيستخدم الـ GPU، وإلا سيتم التدريب على المعالج (CPU).

3. تحميل وتجهيز بيانات MNIST

مجموعة MNIST تتكون من صور أرقام مكتوبة بخط اليد بحجم 28x28 باللون الرمادي (Grayscale)، مع Label من 0 إلى 9. PyTorch يجعل تحميلها سهلًا.

3.1. تعريف التحويلات (Transforms)

نحتاج لتحويل الصور إلى Tensors وتطبيعها (Normalization) لتسهيل التدريب:

transform = transforms.Compose([
    transforms.ToTensor(),  # تحويل الصورة من PIL أو NumPy إلى Tensor
    transforms.Normalize((0.5,), (0.5,))  # تطبيع لقيم البكسلات
])

3.2. تحميل بيانات التدريب والاختبار

train_dataset = datasets.MNIST(
    root="data",
    train=True,
    transform=transform,
    download=True
)

test_dataset = datasets.MNIST(
    root="data",
    train=False,
    transform=transform,
    download=True
)

3.3. إنشاء DataLoader

الـ DataLoader يساعد على تقسيم البيانات إلى دفعات (batches) وترتيبها عشوائيًا في كل Epoch:

batch_size = 64

train_loader = DataLoader(
    train_dataset,
    batch_size=batch_size,
    shuffle=True
)

test_loader = DataLoader(
    test_dataset,
    batch_size=batch_size,
    shuffle=False
)

4. بناء نموذج شبكة عصبية بسيطة

في هذا المشروع سنبدأ بنموذج بسيط Fully Connected Network (بدون طبقات Convolution) ليسهل فهم الفكرة. سنقوم بـ:

  • تحويل الصورة 28x28 إلى متجه (vector) طوله 784.
  • تمريره عبر طبقتين مخفيتين (Hidden Layers).
  • طبقة خرج بعدد 10 فئات (الأرقام من 0 إلى 9).
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.flatten = nn.Flatten()  # لتحويل الصورة إلى متجه
        self.fc1 = nn.Linear(28*28, 128)  # من 784 إلى 128
        self.fc2 = nn.Linear(128, 64)    # من 128 إلى 64
        self.fc3 = nn.Linear(64, 10)     # من 64 إلى 10 (الفئات)

        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.flatten(x)     # [batch, 1, 28, 28] -> [batch, 784]
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))
        x = self.fc3(x)         # بدون Softmax هنا لأن CrossEntropyLoss تتضمنه
        return x

ثم ننشئ كائن من النموذج ونرسله إلى الجهاز (CPU أو GPU):

model = SimpleNN().to(device)
print(model)

5. اختيار دالة الخسارة والمُحسّن

لكي ندرّب النموذج نحتاج إلى:

  • دالة خسارة (Loss Function) تقيس مدى خطأ النموذج.
  • Optimizer لتحديث الأوزان داخل الشبكة.

لدالة الخسارة في مشكلة تصنيف متعددة الفئات نستخدم غالبًا CrossEntropyLoss.

للمُحسّن يمكن البدء بـ Adam كخيار مناسب للمبتدئين.

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

6. حلقة التدريب (Training Loop)

هذه هي مرحلة "تعلم" النموذج من البيانات. في كل Epoch:

  1. نمر على جميع بيانات التدريب على شكل Batches.
  2. نحسب التنبؤات (forward pass).
  3. نحسب الخسارة بين التنبؤات والـ Labels الصحيحة.
  4. نرجع بالانتشار العكسي (backpropagation) لتحديث الأوزان.
num_epochs = 5

for epoch in range(num_epochs):
    model.train()  # وضع النموذج في وضع التدريب
    running_loss = 0.0

    for images, labels in train_loader:
        images = images.to(device)
        labels = labels.to(device)

        # 1. تصفير التدرجات السابقة
        optimizer.zero_grad()

        # 2. تمرير أمامي
        outputs = model(images)

        # 3. حساب الخسارة
        loss = criterion(outputs, labels)

        # 4. الانتشار العكسي
        loss.backward()

        # 5. تحديث الأوزان
        optimizer.step()

        running_loss += loss.item()

    avg_loss = running_loss / len(train_loader)
    print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {avg_loss:.4f}")

اضبط عدد الـ Epochs حسب الوقت المتاح لديك وقوة الجهاز. في مثالنا اخترنا 5 فقط للبساطة.

7. تقييم النموذج على بيانات الاختبار

بعد التدريب يجب أن نقيس أداء النموذج على بيانات لم يسبق له رؤيتها (test set) لنحسب الدقة (Accuracy).

model.eval()  # وضع التقييم (يعطل Dropout/BatchNorm إن وجدت)
correct = 0
total = 0

with torch.no_grad():  # إيقاف حساب التدرجات
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)

        outputs = model(images)          # شكلها [batch_size, 10]
        _, predicted = torch.max(outputs, 1)  # اختيار الفئة الأعلى احتمالاً
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

accuracy = 100 * correct / total
print(f"Test Accuracy: {accuracy:.2f}%")

إذا كانت النسبة في حدود 90% أو أكثر لنموذج بسيط مثل هذا، فهذه نتيجة جيدة كبداية. لاحقًا يمكنك استخدام شبكات Convolutional Neural Networks (CNN) لتحسين الأداء.

8. حفظ النموذج المدرب

بدلًا من إعادة تدريب النموذج كل مرة، يمكن حفظ الأوزان المدربة في ملف ثم إعادة تحميلها لاحقًا.

8.1. حفظ النموذج

model_path = "simple_mnist_model.pth"
torch.save(model.state_dict(), model_path)
print("Model saved to", model_path)

8.2. تحميل النموذج لاحقًا

model = SimpleNN().to(device)
model.load_state_dict(torch.load(model_path, map_location=device))
model.eval()

هكذا يمكنك استخدام النموذج في سكربت آخر أو عند نشره في خدمة ويب (API) مثلاً، ويمكنك الربط مع ما تعلمته في: بناء RESTful APIs باستخدام FastAPI لنشر نموذجك.

9. عمل تنبؤ (Prediction) لصورة واحدة

لتجربة النموذج على صورة واحدة من مجموعة الاختبار:

import matplotlib.pyplot as plt

# الحصول على عينة واحدة
image, label = test_dataset[0]

plt.imshow(image.squeeze(), cmap="gray")
plt.title(f"True Label: {label}")
plt.show()

# تجهيز الصورة للنموذج
image = image.unsqueeze(0).to(device)  # إضافة بُعد batch

with torch.no_grad():
    output = model(image)
    _, predicted = torch.max(output, 1)

print("Predicted Label:", predicted.item())

يمكنك تجربة هذا على أكثر من صورة للتأكد من أداء النموذج والتعرّف على الحالات التي يخطئ فيها.

10. كيف تطور هذا النموذج الصغير لمشاريع أكبر؟

بعد فهم هذا المثال البسيط في PyTorch شرح بالعربي، يمكنك البناء عليه لتطبيقات أكثر واقعية:

  • استبدال النموذج البسيط بـ CNN مكوّن من طبقات Convolution وPooling.
  • استخدام مجموعات بيانات أكبر وأكثر تعقيدًا مثل CIFAR-10 أو صور مخصّصة.
  • دمج النموذج في تطبيق ويب (Django أو FastAPI) ونشره على خادم مثل AWS.
  • تحسين الأداء عن طريق ضبط الـ Hyperparameters مثل:
    • حجم الـ Batch.
    • معدل التعلّم (Learning Rate).
    • عدد الطبقات والعُقد في النموذج.

إذا كنت مهتمًا بمسار أعم في الذكاء الاصطناعي والتعلم العميق، يمكنك أيضًا قراءة: أهم تقسيمات أنواع الذكاء الاصطناعي.

نصائح عملية للمبتدئين مع PyTorch

  • ابدأ بنماذج صغيرة: كما فعلنا هنا. لا تبدأ بنماذج ضخمة قبل فهم الأساسيات.
  • استخدم GPU إن توفّر: خاصة مع بيانات كبيرة، سيُحدث فارقًا كبيرًا في وقت التدريب.
  • راقب الخسارة (Loss): إذا لم تنخفض مع الوقت فغالبًا هناك مشكلة في الكود أو الإعدادات.
  • قسّم المشكلة: تأكد من عمل كل جزء (البيانات، النموذج، التدريب) على حدة قبل دمجها.
  • اقرأ الـ Docs الرسمية: توثيق PyTorch واضح ويحتوي أمثلة كثيرة.

خلاصة: PyTorch شرح بالعربي من مشروع حقيقي

في هذا المقال نفذنا مشروع عملي كامل لتصنيف الصور باستخدام PyTorch:

  • جهّزنا البيانات باستخدام torchvision.datasets.MNIST و DataLoader.
  • بنينا شبكة عصبية بسيطة باستخدام nn.Module.
  • استخدمنا CrossEntropyLoss وAdam لتدريب النموذج.
  • قيّمنا الأداء على بيانات الاختبار وحسبنا الدقة.
  • حفظنا النموذج وشرحنا كيفية استخدامه للتنبؤ.

الفكرة الأساسية في التعلم العميق باستخدام PyTorch هي فهم هذه الدورة: بيانات → نموذج → خسارة → تدريب → تقييم → نشر. بمجرد استيعابها يمكنك الانتقال إلى مشروعات أكبر وأكثر تعقيدًا بثقة.

إذا كانت لديك خلفية في بايثون وتريد التعمق أكثر في الذكاء الاصطناعي وتطبيقاته المختلفة، فالمشروع الذي بنيناه هنا خطوة عملية ممتازة على هذا الطريق.

حول المحتوى:

مشروع عملي لبناء وتدريب نموذج تصنيف صور صغير باستخدام PyTorch: تجهيز البيانات، بناء النموذج، التدريب، التقييم، ونشر النموذج بخطوات واضحة للمبتدئين.

هل كان هذا مفيدًا لك؟

أضف تعليقك