Transformers documentation

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

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

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

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

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

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.

from transformers import TrainingArguments

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

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

بالنسبة إلى دالة خسارة مخصصة، شمل num_items_in_batch حتى يقسم Trainer الخسارة على عدد أهداف التنبؤ عبر جميع الدُفعات الفرعية. وهذا يُطبّع الخسارة بناءً على الرموز بدلاً من عدد خطوات ثابت باستخدام gradient_accumulation_steps. وإلا، فإن Trainer يقسم الخسارة على gradient_accumulation_steps.

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 تلك المواضع ويحسب على labels[..., 1:]، لذا يتطابق المقام مع عدد أهداف التنبؤ التي تستخدمها الدالة الخسارة. عندما يوفر مُجمِّع البيانات shift_labels مباشرةً، كما هو الحال في مُجمِّع خالٍ من الحشو، يحسب Trainer على ذلك المصفوفة بدلاً من ذلك. أما أنواع الدوال الخسارة الأخرى، مثل LM المقنّع والتصنيف، فتحسب على مصفوفة التسميات كاملة.

إذا كنت تُعرّف فئة فرعية من Trainer وتُعيد تعريف compute_loss()، فاضبط loss_is_scaled_for_ga لتوضيح كيفية تطبيع الخسارة لديك: False لمتوسط لكل دفعة، حيث يقوم Trainer بعد ذلك بقسمتها على gradient_accumulation_steps، أو True إذا كنت قد قسمتها بالفعل على num_items_in_batch.

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

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

  • اقرأ وثيقة استخدام ذاكرة وحدة معالجة الرسوميات لفهم ما الذي يدفع إلى استخدام الذاكرة على وحدة معالجة الرسوميات أثناء التدريب.
  • اطّلع على دليل Gradient checkpointing لمعرفة كيفية تقليل ذاكرة التفعيل عن طريق إعادة حساب التفعيلات بدلاً من تخزينها مؤقتاً.
  • اطّلع على دليل التدريب بدقة مختلطة لمعرفة كيفية استخدام أنواع بيانات بدقة أقل لتقليل الذاكرة وتسريع التدريب.
  • اقرأ منشور المدونة Gradient Accumulation Fix لمعرفة كيفية حساب تراكم التدرجات.
Update on GitHub