Optimization Algorithm
تحدّث خوارزمية التحسين أوزان النموذج لتقليل خسارته أثناء التدريب. يغطي هذا الموضوع الانحدار المتدرج والزخم وAdam وAdamW وMuon، مع أمثلة برمجية.
خوارزمية التحسين، أو المحسِّن، هي القاعدة التي تستخدمها عملية التدريب لتغيير معلمات النموذج حتى تنخفض دالة الخسارة. في التعلم العميق، يتلقى المحسِّن تدرّج الخسارة بالنسبة إلى كل وزن في النموذج من الانتشار العكسي، ويقرر مقدار تحريك كل وزن واتجاهه. يحدد المحسِّن، إلى جانب معدل التعلم، سرعة تقارب التدريب واستقراره ومقدار الذاكرة التي يحتاج إليها، وغالبًا مدى قدرة النموذج النهائي على التعميم.
كيفية عمل المحسّنات#
تكاد كل محسّنات التعلم العميق تكون شكلًا من أشكال الانحدار المتدرّج: احسب تدرّج الخسارة g على دفعة مصغّرة، ثم حرّك الأوزان خطوة صغيرة في الاتجاه المعاكس له، w ← w − η·g. وتختلف المحسّنات فيما تفعله بـ g قبل اتخاذ الخطوة. تحسب طرق الزخم متوسط التدرجات بمرور الوقت لبناء سرعة في الاتجاهات المتسقة. وتقسم الطرق التكيفية خطوة كل معلمة على تقدير متحرك لحجم تدرّجها. أما Muon فيجعل تحديث كل مصفوفة أوزان متعامدًا بوصفها وحدةً كاملة. وتستخدم طرق الرتبة الثانية الانحناء أيضًا، ما يجعل كل خطوة أكثر استنارةً وأعلى كلفةً بكثير في الحساب. أما الطرق التي لا تحتاج إلى تدرّج، مثل الخوارزميات التطورية والبحث العشوائي، فتحسّن الأداء بتجربة المرشحين والإبقاء على الأفضل:
تكون قاعدة التحديث أهم ما يكون عندما يكون سطح الخسارة سيئ التكييف، إذ ينحني بشدة في بعض الاتجاهات وبشكل طفيف في اتجاهات أخرى. ويُظهر تشغيل ثلاثة محسّنات من نقطة البداية نفسها داخل وادٍ ضيق الفرق بينها:
import torch
# A long, narrow valley: f(w) = w1^2 + 50 * w2^2, with its minimum at (0, 0)
scale = torch.tensor([1.0, 50.0])
optimizers = {
"SGD": lambda p: torch.optim.SGD(p, lr=0.015),
"SGD + momentum": lambda p: torch.optim.SGD(p, lr=0.015, momentum=0.9),
"Adam": lambda p: torch.optim.Adam(p, lr=0.1),
}
for name, make_optimizer in optimizers.items():
w = torch.tensor([5.0, 1.0], requires_grad=True)
optimizer = make_optimizer([w])
# Same loss and starting point for every optimizer; only the update rule differs
for step in range(100):
loss = (scale * w**2).sum()
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"{name:15s} f(w) after 100 steps: {(scale * w**2).sum().item():.6f}")يتوقف SGD البسيط عند 0.056531 لأن الاتجاه الحاد w2 يحدّ معدل تعلمه: فأي معدل يتجاوز 0.02 يجعل w2 يتجاوز القيمة المطلوبة بمقدار أكبر في كل خطوة، وعند 0.021 ترتفع الخسارة إلى نحو 9.5 مليارات خلال 100 خطوة. ومع هذا الحد، يكون التقدم في الاتجاه اللطيف w1 بطيئًا. ويصل الزخم إلى 0.000216 ببناء السرعة على امتداد w1، بينما يصل Adam إلى 0.001953 بمنح كل إحداثي حجم خطوة خاصًا به.
خوارزميات التحسين الشائعة#
- الانحدار المتدرّج العشوائي (SGD): يتخذ خطوات عكس تدرّج الدفعة المصغّرة. وقد درّب معظم الشبكات الالتفافية البارزة باستخدام زخم قدره 0.9، ويخزّن قيمة إضافية واحدة لكل معلمة.
- AdaGrad وRMSProp: يضبطان خطوة كل معلمة استنادًا إلى سجل تدرجاتها المربّعة. يقسم AdaGrad على الجذر التربيعي لمجموعها المتراكم، الذي لا ينخفض، لذا تتقلص خطواته طوال التدريب. أما RMSProp فيستخدم بدلًا من ذلك متوسطًا يتناقص أسيًا، ما يحافظ على استجابة أحجام الخطوات.
- Adam: يجمع بين الزخم وضبط المقياس على طريقة RMSProp، ويصحح كلا المتوسطين المتحركين لانطلاقهما من الصفر. وتنجح إعداداته الافتراضية، بمعدل تعلم 0.001 وβ1 = 0.9 وβ2 = 0.999، في مشكلات كثيرة.
- AdamW: Adam مع اضمحلال أوزان منفصل، إذ يقلّص الأوزان مباشرةً بدلًا من ذلك عبر ضبط مقياس التدرّج التكيفي. وهو المحسِّن القياسي لـالمحوّلات والنماذج اللغوية الكبيرة (LLMs).
- Muon: يجعل تحديث الزخم لكل مصفوفة أوزان ثنائية الأبعاد متعامدًا باستخدام تكرارات نيوتن-شولز، ويحتفظ بمخزن حالة واحد لكل معلمة. وقد وسّعته Moonshot AI ليُستخدم في التدريب المسبق للنماذج اللغوية الكبيرة.
- L-BFGS: طريقة شبه نيوتونية تبني تقديرًا للانحناء من التدرجات الحديثة. وتتقارب في خطوات قليلة في المسائل الملساء ذات الدفعة الكاملة، لكن تدرجات الدفعات المصغّرة المشوشة تجعلها غير ملائمة للشبكات الكبيرة.
تنفّذ حزمة المحسّنات في PyTorch كل هذه الطرق، بما فيها torch.optim.Muon، إلى جانب مجدولات معدل التعلم المتوافقة معها جميعًا.
المحسِّن والمصطلحات ذات الصلة#
- دالة الخسارة: الهدف الذي يقلّله المحسِّن، مثل الإنتروبيا المتقاطعة للتصنيف أو متوسط مربع الخطأ للانحدار.
- مُجدول معدل التعلم: يضبط حجم الخطوة η أثناء التدريب، باستخدام الإحماء أو اضمحلال الخطوات أو التلدين الجيبي، بالتزامن مع أي محسِّن.
- ضبط المعلمات الفائقة: بحث خارجي في إعدادات مثل المحسِّن ومعدل التعلم وحجم الدفعة، وتكلفة كل مرشح فيه تنفيذ جولة تدريب كاملة أو جزئية. وتؤدي الطرق الخالية من التدرّج، مثل التحسين البايزي والبحث التطوري، هذه المهمة لأن درجة التحقق لا يمكن اشتقاقها بالنسبة إلى خيارات مثل المحسِّن.
اختيار المحسِّن#
يُختار المحسِّن ومعدل التعلم معًا، لأن لكل محسِّن نطاقه الخاص: يبدأ SGD مع الزخم عادةً بين 0.01 و0.1، وتبدأ محسّنات عائلة Adam عند نحو 0.001. ويتخذ تدريب Ultralytics YOLO هذا الاختيار تلقائيًا: يتجاهل الخيار الافتراضي optimizer="auto" الخيار lr0 وينتقي AdamW بمعدل تعلم يتناسب مع عدد الفئات للتشغيلات التي تصل إلى 10,000 تكرار، أو MuSGD، وهو مزيج من SGD وMuon استُخدم لتدريب نقاط التحقق المنشورة لـYOLO26، للجداول الأطول؛ أما تسمية محسِّن فتُفعّل lr0:
from ultralytics import YOLO
# حمّل نموذج YOLO26n مدرّبًا مسبقًا
model = YOLO("yolo26n.pt")
# اختر SGD صراحةً؛ لا يُطبَّق lr0 إلا عندما لا تكون قيمة المحسِّن "auto"
results = model.train(data="coco8.yaml", epochs=5, optimizer="SGD", lr0=0.01)باستخدام optimizer="SGD"، يفعّل المدرّب أيضًا زخم نيستيروف، مستخدمًا الوسيطة momentum، وقيمتها الافتراضية 0.937، بوصفها المعامل.










