# تراكم التدرجات

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

تتراكم التدرجات عبر *n* دفعات مصغّرة قبل أن يحدّث المُحسِّن الأوزان. على سبيل المثال، مع حجم دفعة لكل جهاز يساوي 8 وخطوات تراكم تساوي 4، يكون حجم الدفعة الفعّال 32.

```text
Step 1: mini-batch 1 → forward → backward → grads = G₁
Step 2: mini-batch 2 → forward → backward → grads = G₁ + G₂
Step 3: mini-batch 3 → forward → backward → grads = G₁ + G₂ + G₃
Step 4: mini-batch 4 → forward → backward → grads = G₁ + G₂ + G₃ + G₄
        → optimizer.step()  ← same update as if batch_size × 4
        → zero_grad()
```

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

تجميع التدرجات لعدد `gradient_accumulation_steps` عبر `per_device_train_batch_size`.

```py
from transformers import TrainingArguments

args = TrainingArguments(
    ...,
    per_device_train_batch_size=8,
    gradient_accumulation_steps=4,
)
```

## تحديد مقياس الدالة

بالنسبة إلى [دالة خسارة مخصصة](./trainer_recipes#custom-loss-function)، شمل `num_items_in_batch` حتى يقسم [Trainer](/docs/transformers/main/ar/main_classes/trainer#transformers.Trainer) الخسارة على عدد أهداف التنبؤ عبر جميع الدُفعات الفرعية. وهذا يُطبّع الخسارة بناءً على الرموز بدلاً من عدد خطوات ثابت باستخدام `gradient_accumulation_steps`. وإلا، فإن [Trainer](/docs/transformers/main/ar/main_classes/trainer#transformers.Trainer) يقسم الخسارة على `gradient_accumulation_steps`.

```py
import torch.nn.functional as F

def compute_loss(outputs, labels, num_items_in_batch=None):
    logits = outputs["logits"]
    loss = F.cross_entropy(logits, labels, reduction="sum")
    return loss / num_items_in_batch
```

في نماذج LM السببية، يحسب `num_items_in_batch` التسميات *المزاحة*. تقوم الدالة الخسارة بإزاحة التسميات بحيث يستهدف التنبؤ عند الموضع `i` الرمز الموجود عند الموضع `i + 1`، مما يترك الموضع 0 في كل تسلسل دون هدف. يستثني [Trainer](/docs/transformers/main/ar/main_classes/trainer#transformers.Trainer) تلك المواضع ويحسب على `labels[..., 1:]`، لذا يتطابق المقام مع عدد أهداف التنبؤ التي تستخدمها الدالة الخسارة. عندما يوفر مُجمِّع البيانات `shift_labels` مباشرةً، كما هو الحال في مُجمِّع خالٍ من الحشو، يحسب [Trainer](/docs/transformers/main/ar/main_classes/trainer#transformers.Trainer) على ذلك المصفوفة بدلاً من ذلك. أما أنواع الدوال الخسارة الأخرى، مثل LM المقنّع والتصنيف، فتحسب على مصفوفة التسميات كاملة.

إذا كنت تُعرّف فئة فرعية من [Trainer](/docs/transformers/main/ar/main_classes/trainer#transformers.Trainer) وتُعيد تعريف [compute_loss()](/docs/transformers/main/ar/main_classes/trainer#transformers.Trainer.compute_loss)، فاضبط `loss_is_scaled_for_ga` لتوضيح كيفية تطبيع الخسارة لديك: `False` لمتوسط لكل دفعة، حيث يقوم [Trainer](/docs/transformers/main/ar/main_classes/trainer#transformers.Trainer) بعد ذلك بقسمتها على `gradient_accumulation_steps`، أو `True` إذا كنت قد قسمتها بالفعل على `num_items_in_batch`.

```py
class MyTrainer(Trainer):
    loss_is_scaled_for_ga = True

    def compute_loss(self, model, inputs, return_outputs=False, num_items_in_batch=None):
        ...
        return loss_sum / num_items_in_batch
```

## الخطوات التالية

- اقرأ وثيقة [استخدام ذاكرة وحدة معالجة الرسوميات](./model_memory_anatomy) لفهم ما الذي يدفع إلى استخدام الذاكرة على وحدة معالجة الرسوميات أثناء التدريب.
- اطّلع على دليل [Gradient checkpointing](./grad_checkpointing) لمعرفة كيفية تقليل ذاكرة التفعيل عن طريق إعادة حساب التفعيلات بدلاً من تخزينها مؤقتاً.
- اطّلع على دليل [التدريب بدقة مختلطة](./mixed_precision_training) لمعرفة كيفية استخدام أنواع بيانات بدقة أقل لتقليل الذاكرة وتسريع التدريب.
- اقرأ منشور المدونة [Gradient Accumulation Fix](https://unsloth.ai/blog/gradient) لمعرفة كيفية حساب تراكم التدرجات.

