تقنية

تصفير التدرجات في PyTorch: ماذا يبقى إذا لم نمسح المساهمة القديمة؟

مشتقة جديدة سالبة تجمع مع القديمة الموجبة إن لم يمسح المخزن فتغير التحديث
مسح المساهمة القديمة لا يصفّر المعامل نفسه.

تضيف backward في PyTorch المشتقات إلى مخازن التدرجات بدل استبدالها تلقائيًا؛ لذلك يلزم تحديد متى نريد الاحتفاظ بها ومتى نمسحها. [1]

الخلاصة السريعة

عند تحديثين مستقلين في مثالنا، نمسح مساهمة التحديث الأول قبل جمع مشتقة الثاني؛ إبقاؤها يغير الرقم الذي يستخدمه التحديث.

  • تمثل التدرجات المخزنة مشتقات متراكمة؛ مسحها لا يعني جعل المعاملات صفرًا أو حذف تاريخ المحسن. [1]
  • لخسارة نصف مربع الفرق عن 2، عند w يساوي 5، يكون التدرج 3؛ بمعدل 0.5 يصبح المعامل 3.5.
  • الخسارة التالية نصف مربع الفرق عن 6، ومشتقتها عند 3.5 هي سالب 2.5؛ إبقاء 3 القديم يجعل المخزن 0.5.
  • نزول بسيط بالمعدل نفسه يعطي 4.75 مع التدرج الحالي وحده، و 3.25 مع القديم؛ الاحتفاظ المقصود للتجميع عند نقطة ثابتة مسألة أخرى.

ميّز المخزن عن المعامل

توضح وصفة PyTorch أن استدعاء backward يضيف التدرج إلى الموجود في المخزن، وأن مسحه جزء من دورة التدريب المعتادة عندما لا نريد التراكم السابق. [1]

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

كلمة «تصفير» هنا تصف التخلص من المساهمة السابقة؛ لا نتعهد بأن كل تنفيذ يحتفظ بعدها بمصفوفة أصفار بدل إزالة قيمة المخزن. المهم في الحساب ألا تضيف المشتقة القديمة إلى الجديدة دون قصد.

اتبع التحديث الأول

نكتب خسارة أولى L1 = نصف (w − 2)². مشتقتها w − 2. عند المعامل 5 يكون التدرج 3. نفترض أن المخزن خالٍ من أي مساهمة أقدم، وأن معدل التعلم 0.5.

بقاعدة النزول البسيط نحصل على w الجديد = 5 − 0.5 × 3 = 3.5. الآن صارت لدينا قيمة معامل جديدة، لكن تطبيق تحديث المعامل لا يشكل في هذا التصور عملية مسح للمشتقة المخزنة. نكتب في السجل «المعامل 3.5، والتدرج القديم 3» كي لا نخلط المتغيرين.

احسب مشتقة الخطوة التالية

نغير الخسارة في المثال إلى L2 = نصف (w − 6)². مشتقتها w − 6، ولذلك عند المعامل الحالي 3.5 تكون سالب 2.5. هذا تدرج حسابه عند القيمة الجديدة، لا عند المعامل 5 الذي أنتج المشتقة الأولى.

لو بقي 3 في المخزن وأضفنا سالب 2.5، نحصل على 0.5. أما عند مسح المساهمة القديمة، فالمساهمة المتاحة للتحديث المستقل هي سالب 2.5 وحدها. الإشارة مختلفة بين الرقمين؛ ليس الفرق مجرد تسمية مكان تخزين.

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

قارن نتيجتي التحديث المستقل

من المعامل 3.5 وبالمعدل 0.5، استخدام المشتقة الحالية وحدها يعطي 3.5 − 0.5 × (سالب 2.5) = 4.75. أما استعمال المخزن 0.5 فيعطي 3.5 − 0.5 × 0.5 = 3.25. الأرقام حسابات مكتوبة، وليست تجربة PyTorch.

لم نطلب جمع خسارتين عند نقطة واحدة وتأجيل تحديثهما. في التجميع المقصود قد نحتفظ بمساهمات وفق هدف محدد؛ هنا أجرينا تحديثًا بين الخسارتين، وطلبنا خطوة مستقلة للثانية. الفرق في المقصود هو ما يحدد الحاجة إلى المسح.

قبل تفسير خطوة مفاجئة، افحص توقيت جمع التدرج ومسحه وتحديث المعامل، بدل افتراض أن backward استبدل المخزن. لا يثبت المثال خطأ كل تراكم؛ يوضح خطأ إبقاء مساهمة حين لا يشملها الهدف الذي اخترناه.

المصادر ومتابعة القراءة

  1. PyTorch: Zeroing out gradients (يفتح في نافذة جديدة)docs.pytorch.org

أُعدّ هذا المقال بصياغة عربية أصلية بالاستناد إلى المصادر أعلاه، وهو مدخل تمهيدي إلى الموضوع. اقرأ منهجية المحتوى وحدوده.