مكتبة باي تورش : الجزء 2

نستكمل ما بدأناه في المقالة السابقة وسنشرح في هذه المقالة الأوامر الأخرى الموجودة في المكتبة وإستخداماتها المتقدمة.

Autograd - محرك التمايز التلقائي

عند تدريب أي نموذج تعلم عميق نحتاج لحساب مشتقات الأوزان حتى نعرف طرق تقليل قيمة دالة الخطأ أو دالة الخسارة أو كما تعرف ب:

Loss Function

لو كان لدينا شبكة عصبية فيها ملايين الأوزان عليك أن تشتق الأوزان بشكل يدوي , وهذا يعد شيئاً مستحيلاً فلهذا أتت تقنية :

Automatic Differentiation

شبكة عصبية ذات مئات العقد والتي من الصعب اشتقاق أوزانها بشكل يدوي

أو الاشتقاق التلقائي , وفي باي تورش يتم تنفيذها عبر محرك يسمى :

torch.autograd


عندما نستدعي الدالة :

.backward()

يقوم باي تورش بالسير عكسياً من الجذور إلى الأوراق ويحسب المشتقات تلقائياً باستخدام قاعدة السلسلة (Chain Rule) في حساب التفاضل والتكامل .

راجع من هنا التفاضل والتكامل

مثال عن الأوتوقراد :

import torch

# Create tensors with gradient tracking enabled
x = torch.tensor(2.0, requires_grad=True)
w = torch.tensor(3.0, requires_grad=True)
b = torch.tensor(1.0, requires_grad=True)

# Build a simple equation: y = w*x + b
y = w * x + b
print(y)
# Output: tensor(7., grad_fn=<AddBackward0>)

# Compute gradients automatically
y.backward()

# Gradient of y with respect to each variable
print(x.grad)  # dy/dx = w = 3.0
print(w.grad)  # dy/dw = x = 2.0
print(b.grad)  # dy/db = 1.0
tensor(7., grad_fn=<AddBackward0>)
tensor(3.)
tensor(2.)
tensor(1.)

الشرح


requires_grad=True

عندما نضع هذا الخيار يقوم باي تورش بمتابعة كل عملية تتم على هذا الموتر ويحفظها في الرسم البياني الحسابي .


y = w * x + b

هذه عملية بسيطة لكن باي تورش لا يرى فقط النتيجة بل يحفظ شجرة العمليات كاملة , ولاحظ أن المخرج يحتوي على :

grad_fn=<AddBackward0>

وهذا يعني أن باي تورش يعرف أن آخر عملية تمت هي عملية جمع وأنه قادر على اشتقاقها لاحقاً .


y.backward()

هذه هي الخطوة التي تقوم بحساب جميع المشتقات الجزئية تلقائياً , وتقوم بتخزينها في الخاصية :

.grad

لكل موتر فيه :

requires_grad=True


الشبكات العصبية

وهذه هي الوظيفة الأساسية للمكتبة تقريباً وهي بناء الشبكات العصبية ويمكننا بنائها بالجزء الآتي :

torch.nn

وهي وحدة في مكتبة باي تورش توفر لنا كل الأساسيات اللازمة لبناء شبكة عصبية مثل :

  • الطبقات/Layers

  • دوال تنشيط الشبكة / Activation functions : دالة تجمع أوزان المدخلات قبل تواجد المخرجات مما يسمح للشبكة العصبية بتحليل الأنماط

  • دوال الخطأ / Loss functions : دالة رياضية تقيس بُعد توقعات نموذج الذكاء الاصطناعي عن القيم الفعلية والحقيقية للبيانات .

مثال على بناء شبكة عصبية بسيطة

import torch
import torch.nn as nn
import torch.optim as optim

# Define a simple neural network
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(2, 4)   # Input layer: 2 features -> 4 neurons
        self.fc2 = nn.Linear(4, 1)   # Output layer: 4 neurons -> 1 output
        self.relu = nn.ReLU()        # Activation function

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# Create the model
model = SimpleNN()
print(model)

# Sample input
sample_input = torch.tensor([[1.0, 2.0]])
output = model(sample_input)
print(output)
SimpleNN(
  (fc1): Linear(in_features=2, out_features=4, bias=True)
  (fc2): Linear(in_features=4, out_features=1, bias=True)
  (relu): ReLU()
)
tensor([[0.0394]], grad_fn=<AddmmBackward0>)

الشرح


class SimpleNN(nn.Module):

هنا قمنا بإنشاء كلاس جديد للنموذج الخاص بنا , ويجب أن يرث من :

nn.Module

حتى يستفيد من كل المميزات مثل تتبع الأوزان وحساب المشتقات تلقائياً .


self.fc1 = nn.Linear(2, 4)

طبقة خطية تأخذ مدخلين وتخرج 4 قيم , ورياضياً تقوم بحساب :

y = Wx + b

b = Bias أو الإنحياز

بينما W

هي مصفوفة الأوزان Weights array


self.relu = nn.ReLU()

دالة تنشيط شهيرة تقوم بإرجاع القيمة نفسها إذا كانت موجبة وإرجاع صفر إذا كانت سالبة , وهي تساعد الشبكة على تعلم العلاقات غير الخطية .


def forward(self, x):

هذه هي الدالة التي يجب أن تحددها في كل نموذج , وهي تشرح كيف تنتقل البيانات عبر الشبكة من المدخل إلى المخرج .


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

الآن دعنا نشاهد كيف يتم تدريب النموذج فعلياً , حلقة التدريب هي أساس لأي نموذج تعلم عميق:

import torch
import torch.nn as nn
import torch.optim as optim

# Create the model, loss function, and optimizer
model = SimpleNN()
criterion = nn.MSELoss()                              # Loss function
optimizer = optim.SGD(model.parameters(), lr=0.01)    # Optimizer

# Fake training data
X_train = torch.randn(100, 2)
y_train = torch.randn(100, 1)

# Training loop
for epoch in range(50):
    # 1. Forward pass
    predictions = model(X_train)

    # 2. Compute loss
    loss = criterion(predictions, y_train)

    # 3. Clear old gradients
    optimizer.zero_grad()

    # 4. Backward pass (compute gradients)
    loss.backward()

    # 5. Update weights
    optimizer.step()

    if (epoch + 1) % 10 == 0:
        print(f"Epoch {epoch+1}, Loss: {loss.item():.4f}")
Epoch 10, Loss: 1.1842
Epoch 20, Loss: 1.0703
Epoch 30, Loss: 1.0183
Epoch 40, Loss: 0.9923
Epoch 50, Loss: 0.9777

شرح الخطوات الخمس


  1. التمرير الأمامي - Forward Pass :

نقوم بتمرير البيانات عبر النموذج للحصول على التنبؤات .

  1. حساب الخطأ - Loss Function

نقارن التنبؤات بالقيم الحقيقية لمعرفة مدى دقة النموذج , وكلما كان الخطأ أصغر كلما كان النموذج أفضل في الأداء .

  1. تصفير المشتقات - zero_grad

خطوة مهمة جداً , لأن باي تورش يقوم بتراكم المشتقات بشكل افتراضي , فإذا لم نقم بتصفير المشتقات في كل دورة فإن المشتقات سيتم جمعها من الدورات السابقة ولا ينتج لدينا نتيجة صحيحة من خلال التدريب .

  1. التمرير الخلفي - Backward Pass

من خلال استدعاء الدالة البرمجية في المكتبة :

loss.backward()

تقوم الدالة بحساب مشتقات دالة الخطأ بالنسبة لجميع الأوزان في الشبكة بشكل تلقائي .

  1. تحديث الأوزان - Optimizer and Updating weights :

من خلال استدعاء الدالة :

optimizer.step()

يقوم بتحديث الأوزان باستخدام المشتقات المحسوبة والخوارزمية المختارة

هنا استخدمنا وهي خوارزمية الانحدار التدرجي العشوائي أو ماتعرف بـ :

Stochastic gradient descent - SGD

وهي خوارزمية مبنية على الإشتقاق الرياضي .

مصادر ومراجع :

ملاحظة للأمانة العلمية

هذا المقال الوحيد في المدونة الذي تم الإعتماد فيه على جزئية بسيطة جداً فقط على الذكاء الاصطناعي في الكتابة والشرح وأستخدمت أوبوس من النموذج اللغوي الشهير كلود , أيضاً للتعليم الشخصي والتجارب الخاصة في مكتبة باي تورش.