انتقل إلى المحتوى الرئيسي

الوحدة 9 — الممثّل والناقد وA2C وPPO

انتهت الوحدة الثامنة بفكرة الخطّ الأساسي V(s)V(s) لكنّها تركت السؤال معلّقًا: كيف نتعلّم VV نفسه بجانب السياسة؟ الإجابة هي بنية الممثّل-الناقد، والاسم يُلخّص الفكرة: شبكة تختار الأفعال (الممثّل)، وشبكة تُقيّمها (الناقد). ثمّ نبني على هذه الفكرة A2C ثمّ PPO، وهذا الأخير الأكثر استعمالًا في العمل الصناعي منذ 2017.

الميزة كإشارة تعلّم

قدّمنا سابقًا الميزة:

A(s,a)=Q(s,a)V(s)A(s, a) = Q(s, a) - V(s)

هذه الكمّية أنظف من QQ: تخبرنا كم كان الفعل aa أفضل من متوسّط ما تعمله السياسة في ss. مصادقتها على الاتّجاه لا تتأثّر بمقياس المكافأة (تكبير كلّ المكافآت بـ100 لا يُغيّر ميزة الأفعال النسبيّة، بخلاف QQ نفسه).

تقدير عمليّ للميزة عبر TD:

A^(st,at)=rt+1+γV(st+1)V(st)\hat{A}(s_t, a_t) = r_{t+1} + \gamma V(s_{t+1}) - V(s_t)

هذا خطأ TD الذي رأيناه في الوحدة 5، مطبَّقًا هنا بوصفه بديلًا عن الميزة.

A2C: ممثّل-ناقد متزامن

A2C (Advantage Actor-Critic) يجمع في خوارزميّة واحدة:

  • شبكة الممثّل πθ(as)\pi_\theta(a \mid s) تُنتج توزيعًا احتماليًّا على الأفعال.
  • شبكة الناقد Vϕ(s)V_\phi(s) تُنتج تقديرًا للقيمة.

في كلّ خطوة (أو دفعة من خطوات) نُحسّن خسارتين:

Lπ=A^(s,a)logπθ(as),LV=(A^(s,a))2\mathcal{L}_{\pi} = -\hat{A}(s, a) \log \pi_\theta(a \mid s), \qquad \mathcal{L}_{V} = \left( \hat{A}(s, a) \right)^2

نُضيف عادةً بونصًا للـإنتروبيا (βaπ(a)logπ(a)-\beta \sum_a \pi(a) \log \pi(a)) لتشجيع الاستكشاف ومنع السياسة من الانهيار إلى فعل واحد جشعًا:

Ltotal=Lπ+cVLVβH(π)\mathcal{L}_{\text{total}} = \mathcal{L}_{\pi} + c_V \mathcal{L}_{V} - \beta \mathcal{H}(\pi)

في التنفيذ، الشبكتان تتقاسمان الجذع (عدة طبقات مشتركة) وينقسمان في نهاية إلى رأسين — رأس السياسة ورأس القيمة. هذا يُقلّل الأوزان ويُشجّع تعلّم تمثيلات مشتركة.

المشكلة التي أوجدت PPO

يبقى في A2C خلل: تحديثات الممثّل بلا سقف. إن أعطى ناقد شابّ ميزة ضخمة على فعل، يُحرّك الممثّل توزيعه تحريكًا كبيرًا، فتتغيّر السياسة تغييرًا حادًّا؛ فتنهار العيّنات اللاحقة (لأنّها تخضع لسياسة جديدة تمامًا)، فيتذبذب التدريب أو ينفجر.

الحلّ الأصلي من TRPO كان قيدًا صارمًا على تباعد كوليبك-لايبلر بين السياسة القديمة والجديدة. لكنّه صعب التنفيذ.

PPO (Proximal Policy Optimization) من شولمان وآخرين 2017 اقترح صيغة أبسط تُنجز الأثر نفسه: قصّ نسبة الاحتماليّة.

هدف PPO المقصوص

نُعرّف نسبة الاحتماليّة:

rt(θ)=πθ(atst)πθold(atst)r_t(\theta) = \frac{\pi_\theta(a_t \mid s_t)}{\pi_{\theta_{\text{old}}}(a_t \mid s_t)}

الهدف الكلاسيكي هو rt(θ)A^tr_t(\theta) \hat{A}_t (يعادل تدرّج السياسة بأخذ نسبة الأهمّية). PPO يقصّ:

LCLIP(θ)=E[min(rtA^t,clip(rt,1ϵ,1+ϵ)A^t)]\mathcal{L}^{\text{CLIP}}(\theta) = \mathbb{E}\left[ \min\left( r_t \hat{A}_t, \operatorname{clip}(r_t, 1 - \epsilon, 1 + \epsilon) \hat{A}_t \right) \right]

مع ϵ=0,2\epsilon = 0{,}2 في الغالب. القراءة الحدسيّة: كلّما ابتعدت السياسة الجديدة عن القديمة (نسبة rtr_t خارج [1ϵ,1+ϵ][1-\epsilon, 1+\epsilon])، توقّف الهدف عن مكافأة الابتعاد. هذا يُبقي التحديث في «قرب» السياسة القديمة، ومن ثمّ اسم «proximal».

فرقُ PPO عن A2C يبدو صغيرًا (تعديل صيغة الخسارة)، لكنّه يجعل التدريب أكثر استقرارًا بمراتب، ويسمح باستخدام كلّ دفعة من العيّنات عدّة مرّات (num_epochs = 4 أو 10) بدل مرّة واحدة.

الهايبربارامترات التي فعلًا تهمّ

قائمة قصيرة تركّز على ما يؤثّر:

  • معدّل التعلّم: عادةً 3×1043 \times 10^{-4} مع Adam، حسّاسيّته أعلى من كثير من المسائل الأخرى.
  • num_steps (طول الدُفعة): 128 إلى 2048. طويل جدًّا يُبطئ التكرارات، قصير جدًّا يعطي ميزة مضطربة.
  • num_epochs: 4 إلى 10 مرّات على نفس الدفعة. أكثر من 20 يُخاطر بتحوّل السياسة بعيدًا.
  • clip_epsilon: 0,20{,}2 نقطة بداية.
  • gamma: 0,990{,}99 للمعظم.
  • gae_lambda (لتقدير GAE للميزة): 0,950{,}95.
  • ent_coef (بونص الإنتروبيا): 0,010{,}01، مهمّ في مسائل الاستكشاف الصعبة.

مقارنة تنفيذنا بـStable-Baselines3 على LunarLander

نُطلق تجربتين على LunarLander-v2:

from stable_baselines3 import PPO
import gymnasium as gym

# النسخة المرجعيّة: SB3
env = gym.make("LunarLander-v2")
modele = PPO("MlpPolicy", env, verbose=0, seed=42,
learning_rate=3e-4, n_steps=1024, batch_size=64,
n_epochs=4, gamma=0.99, gae_lambda=0.95,
clip_range=0.2, ent_coef=0.01)
modele.learn(total_timesteps=1_000_000)

نُقارن منحنى المكافأة على مليون خطوة، متوسّط 5 بذور، مع فترات ثقة ±σ\pm \sigma. النتائج النموذجيّة:

  • SB3-PPO: يصل إلى 250\approx 250 (شرط الحلّ 200) في نحو 400 ألف خطوة.
  • تنفيذنا اليدوي: يصل إلى 220\approx 220 في نحو 700 ألف خطوة.
  • فروق التنفيذ: SB3 يستعمل GAE λ\lambda لا خطأ TD خامًا، وطبقة تسوية على المُدخلات، وقصّ التدرّجات عند 0.5، ووضعية "advantage normalization". كلّها تفاصيل تنفيذ تُتلخّص في «تفاصيل صغيرة تعطي 30% تحسين».

الدرس: PPO في الورقة والخوارزميّة العامّة ليس ما يُنتج نتائج SB3. تفاصيل التنفيذ هي 30% من الأداء، ولذلك يجب دومًا القياس مقابل مرجع صناعي مُختبَر قبل نشر تنفيذ جديد.

عدم اتّساق بين المكتبات

اسم PPO يخفي فروقات في التنفيذ بين SB3 وRLLib وCleanRL. يُنشرون النتائج مع بذورهم الخاصّة، ومقارنة عادلة تتطلّب إعادة التنفيذ بذاته أو استعمال ذخيرة (rl-zoo) موحّدة. عدم توحيد التنفيذ سبب أساسي لصعوبة تكرار الأوراق.

الخلاصة

  • الممثّل-الناقد يمزج شبكة السياسة وشبكة القيمة؛ الميزة A=QVA = Q - V هي إشارة تعلّم الممثّل.
  • A2C يُطبّق ذلك بحساب مباشر، لكنّه غير مستقرّ عند ميزات كبيرة.
  • PPO يقصّ نسبة الاحتماليّة إلى [1±ϵ][1 \pm \epsilon]، فيمنع تحديثات فادحة ويُعيد استخدام الدفعات؛ نقطة بداية العمل الصناعي الحديثة.
  • تفاصيل التنفيذ (GAE، تسوية الميزة، قصّ التدرّجات، تسوية المُدخل) تُنتج فارق 30%30\% في الأداء بالنسبة لخوارزميّة PPO نفسها.

الوحدة الأخيرة: مشروع كامل يجمع كلّ ما سبق على LunarLander، مع اهتمام خاصّ بتباين البذور وبتقييم لا يخدع نفسه.