قضيت بضع ساعات أتصفح /Karpathy/AutoResearch Repo سطرا بسطر. زاوية "عملاء الذكاء الاصطناعي يقومون بأبحاث" هي ما يجذب كل الانتباه، لكن أعتقد أن الأمر الأكثر إثارة للاهتمام هو ما يوجد فعليا داخل نص التدريب والقرارات الهندسية التي تجعل حلقة البحث ضيقة. إنها واحدة من أكثر إعدادات التدريب ذات الصف الواحد كثافة التي قرأتها. دعوني أبدأ بالشيء الذي يجعل المشروع بأكمله ممكنا: ميزانية الوقت ثابتة عند ساعة جدارية تبلغ 300 ثانية. لا خطوات ثابتة، ولا رموز ثابتة، ولا فلاپ ثابت. ثوان ساعة الحائط. قد يبدو هذا تفصيلا بسيطا لكنه السبب الرئيسي لعمل الحلقة الذاتية. يمكن للوكيل أن يجعل النموذج أكبر بثلاث مرات، ويقطع حجم الدفعة إلى النصف، ويبدل بنية مختلفة تماما، والنتيجة لا تزال قابلة للمقارنة مباشرة مع كل تجربة أخرى لأنهم جميعا حصلوا على 5 دقائق تدريب على نفس وحدة معالجة الرسومات. إذا قمت بإصلاح الخطوات بدلا من ذلك، فإن النموذج الأكبر سيحصل على تحديثات أقل تدرجا في الثانية وستعاقبه بشكل غير عادل. إذا قمت بإصلاح الرموز، ستواجه نفس المشكلة. إصلاح وقت الجدران يعني أنك تطرح السؤال الصحيح: بالنظر إلى هذا الجهاز وكل هذا الوقت، ما هو أفضل نموذج يمكنك إنتاجه؟ كل شيء آخر هو متغير حر. يمكن للوكيل استكشاف السطح الكامل لباريتو بين حجم النموذج مقابل سرعة الانتقال وسرعة التقارب دون أن تتعارض أي من هذه المقايضات مع بروتوكول التقييم. كما يتم اختيار المقياس بعناية. إنها بتات لكل بايت، وليس فقدان إنتروبيا متقاطع. الإنتروبيا المتقاطعة تعتمد على حجم المفردات. النموذج الذي يحتوي على 32 ألف رمز ونموذج يحتوي على 8 آلاف رمز سيكون له قيم خسارة مختلفة جدا حتى لو ضغطوا البيانات بشكل متساو. يقوم BPB بتطبيع هذا الأمر عن طريق جمع الإنتروبيا المتقاطعة لكل رمز في NATs، وجمع أطوال UTF-8 بايت للرموز المستهدفة، وتحويل NAT لكل بايت إلى بت لكل بايت. لذا حتى لو غير الوكيل شيئا يؤثر على توزيع التوكن الفعال، تبقى المقارنة عادلة. هذان الخياران، زمن الجدار الثابت ومقياس ثابت للمفردات، يحولان ما كان سيكون بحثا فوضويا لا مثيل له إلى مشكلة تحسين نظيفة. والآن النموذج نفسه. إنه GPT لكن مع مجموعة من الحيل الحديثة التي تستحق الفهم. أولا، RMSnorm في كل مكان. على مدخلات الكتل (قبل النورم)، وأيضا على الاستعلامات والمفاتيح قبل حاصل ضرب نقطة الانتباه. هذا الموضوع في QK-norm مهم لأنه بدونه يمكن أن تنمو معايير Q و K بشكل لا حدود له أثناء التدريب، مما يجعل لوجيت الانتباه يصبح أكثر حدة ويتشبع Softmax. تطبيع Q و K يحافظ على منتجات DOT في نطاق مستقر بغض النظر عن عمق الشبكة أو كيفية تطور ديناميكيات التدريب. الاهتمام نفسه هو FA 3، محمل من خلال مكتبة النواة. يستخدم تطبيق فارونيل على هوبر (sm_90) ويعود إلى بناء مجتمع على بطاقات رسومات قديمة. نمط الانتباه هو "SSSL" والذي يعني ثلاث طبقات من انتباه نافذة الانزلاق (نافذة = نصف طول التسلسل) تليها طبقة واحدة من الانتباه السببي الكامل، تتكرر. هذا هو النمط البسيط إلى الكثيف الذي تراه في ميسترال وجيما2. طبقات الانتباه المحلية رخيصة حسابيا لأن مصفوفة الانتباه مخططة، وتسمح الطبقة الدورية العالمية بتدفق المعلومات عبر السياق الكامل. مع 8 طبقات ونمط مكون من 4 أحرف تحصل على طبقات 0,1,2 محلية، طبقة 3 عالمية، طبقات 4,5,6 محلية، والطبقة 7 عالمية. الطبقة الأخيرة تجبر على العمولة بغض النظر عن النمط. موضوع تضمين القيمة دقيق وأعتقد أنه غير مقدر بالكامل. كل طبقة أخرى تحصل على جدول تضمين خاص بها، منفصل تماما عن تضمين الرمز الرئيسي، الذي يربط معرفات الرموز مباشرة بمتجهات بعد القيم. يتم خلط هذه القيم مع قيم الانتباه عبر بوابة مكتسبة: v = v + 2 * سيغمويد (W_gate @ x:32) * ve. وزن البوابة مهيأ صفرا، لذا سيغمويد(0) = 0.5، مضروبا في 2 يعطي 1.0، وهو نقطة بداية محايدة. مع التدريب، يمكن للنموذج تعلم تضخيم أو قمع تضمين القيمة لكل رأس بناء على أول 32 بعدا من الحالة المخفية. وهذا من خط عمل ResFormer والحدس هو أنه يمنح الانتباه اختصارا مباشرا لهوية الرمز. يمكن لمتجهات القيمة أن تحمل معلومات حول "أي رمز موجود في هذا الموقع" دون الحاجة لتجاوز هذه المعلومات من التحويلات المتبقية من الطبقات السابقة. هي في الأساس اتصال تخطي من المدخل مباشرة إلى قيم الانتباه، مع بوابة بحيث يمكن للنموذج أن يقرر متى يكون مفيدا. هناك أيضا مقاييس قابلة للتعلم لكل طبقة على التدفق المتبقي: x = lambda_residi * x + lambda_x0i * x0، حيث x0 هو التضمين المعياري من الطبقة 0. كل طبقة يمكنها التحكم بشكل مستقل في مدى استماعها للبقايا الجارية مقابل الإدخال الأصلي. تبدأ لامبدا المتبقية من 1.0، ولامبدات x0 تبدأ من 0.1. هذه نسخة ناعمة من فكرة "البقايا المفككة". في المحول القياسي، التيار المتبقي هو مجموع جميع مخرجات الطبقة السابقة ويزداد تلوثا كلما تعمقت. إعطاء كل طبقة حق الوصول إلى التضمين الأصلي النظيف يعني أنها لن تحتاج إلى تعلم "التراجع" عن الطبقات السابقة لاستعادة معلومات منخفضة المستوى. يتم تحديد اللوجيتس إلى حد 15 عبر tanh(logits/15)*15، مما يمنع النموذج من أن يكون واثقا بشكل مفرط في بداية التدريب عندما تكون التمثيلات لا تزال صاخبة. لكن بصراحة، الجزء الأكثر إثارة للاهتمام في الملف كله هو المحسن. MuonAdamW هو محسن مدمج يرسل قواعد تحديث مختلفة بناء على مجموعة المعلمات. التضمينات (تضمين الرموز، تضمين القيمة، رأس إلغاء التضمين) والمقاييس لكل طبقة تحصل على AdamW قياسي مع معدلات تعلم مختلفة لكل مجموعة. الانتشار جامح. تضمين LR هو 0.6، وإلغاء تضمين LR هو 0.004، وهذا فرق 150 مرة، وهو مقصود. مصفوفة التضمين ترى كل رمز وتحتاج إلى تحديث مكثف. مصفوفة عدم التضمين هي مسبار خطي على التمثيل النهائي وتستفيد من الاستقرار. معدلات التعلم في التضمين، وتضمين القيمة، وعدم التضمين كلها مدرجة بواسطة (d_model / 768)^(-0.5) وهو تصحيح مستوحى من muP. مع تغير عرض النموذج، تتغير معدلات التعلم للحفاظ على ثبات ديناميكيات تعلم الميزات على المقياس. معدلات التعلم القياسي لللامبدا لكل طبقة يتم التعامل معها بشكل منفصل ولا تحصل على هذا التكبير. مصفوفات الوزن ثنائية الأبعاد في المحول، إسقاطات الانتباه وأوزان mlp، تحصل على Muon، وهنا تصبح الأمور مثيرة للاهتمام حقا. يأخذ ميون التدرج، ويطبق زخم نيستروف، ثم يشغل تكرار نيوتن-شولتز لتقريب التحليل القطبي لمصفوفة التدرج. التحليل القطبي يفصل المصفوفة G إلى G = U * S حيث U متعامد وS هو نصف محدد موجب متماثل. يحسب Muon U، أقرب مصفوفة متعامدة للتدرج، ويستخدم ذلك كاتجاه للتحديث. تكرار نيوتن-شولتز يتكون من 5 خطوات. بالنسبة للمصفوفات الطويلة (صفوف أكثر من الأعمدة)، A = X^T @ X ثم X -> aX + X @ (bA + cA^2). بالنسبة للمصفوفات العريضة، A = X @ X^T ثم X -> aX + (bA + cA^2) @ X. المعاملات مشفرة من حساب مسبق. يسمونه "Polar Express". يتم تجميع كل شيء إلى نواة واحدة مدمجة عبر Torch.compile. لماذا هذا مهم؟ لأن تدرج معيار فروبينيوس (الذي يستخدمه آدم وSGD) في مصفوفات الوزن خاطئ هندسيا. الاتجاه "الصحيح" الأكثر انحدارا لمصفوفة الوزن هو الذي يقلل الخسارة مع شرط أن يكون للتحديث معيار طيفي وحدة، وليس معيار فروبينيوس وحدة. العامل القطبي المتعامد يعطيك هذا بالضبط. عمليا، هذا يعني أن Muon يقوم بتحديثات فعالة أكبر بكثير لأنه لا يضيع حجم الخطوة على تحجيم القيم المفردة. بل يدورها فقط. لهذا السبب يتقارب الميون أسرع بكثير من آدم في مصفوفات وزن المحولات. Muon يحافظ على مخازن الزخم لكل عنصر (نفس شكل المعلمات، مكدسة عبر كل مجموعة أشكال)، لكنه على عكس آدم لا يتتبع العزوم الثانية لكل عنصر. تقديرات العزم الثاني تكون لكل صف أو لكل عمود بعد التعامد، وليست لكل عنصر. وهنا يأتي دور نورمون. فوق الميون الأساسي يوجد نورموون، وهو نظام تقليل التباين. بعد التعامد، يحسب تقديرات العزم الثاني لكل صف (أو لكل عمود حسب نسبة العرض)، ويحافظ على متوسط متحرك أسي لها، ويعيد تكبير التحديث بحيث يحصل كل بعد مخرج على حجم خطوة تكيفي خاص به. هي في الأساس فكرة التكيف في آدم لكنها مطبقة في نظام الإحداثيات المتعامد بدلا من فضاء المعلمات الخام. كما أن تناقص الوزن غير معياري. إنها "حذرة"، أي أنها تضعف المعاملات فقط عندما يتفق اتجاه تحديث الميون مع علامة المعلمات: قناع = (g * بارامات) >= 0. هذا يتجنب وضع الفشل المعروف حيث يدفع تراجع الوزن المعاملات نحو الصفر ضد رغبات التحديث، مما قد يزعزع استقرار التدريب. تفصيل صغير أعجبني: بعد أول خطوة تدريب، يستدعي الكود gc.collect(), gc.freeze(), gc.disable() لإيقاف جامع القمامة في بايثون تماما. GC في بايثون يعمل بشكل دوري ويسبب توقفات ~500 مللي ثانية. عندما تكون ميزانيتك الإجمالية 300 ثانية وكل خطوة ربما 300 مللي ثانية، فإن توقف عشوائي في اللعبة الكبرى يكلفك ما يقارب خطوتي تدريب. يفعلون gc.collect() يدويا كل 5000 خطوة كحل وسط. هذا النوع من الأشياء لا تتعلمه إلا من خلال تحليل جولات التدريب الحقيقية وملاحظة انخفاضات سرعة التمرير الغامضة. أول 11 خطوة (من 0 إلى 10) لا تحتسب ضمن ميزانية الوقت أيضا. هذا هو الإحماء حيث يقوم torch.compile بعمله ويتم تنفيذ نوى CUDA لاختبار IT. بدون هذا الاستثناء، ستحصل التجارب المختلفة على مستويات مختلفة من التدريب "الحقيقي" حسب مدة التجميع لتكوين النموذج المحدد. مرة أخرى، اختيار تصميم يبدو صغيرا لكنه حاسم لجعل التجارب قابلة للمقارنة. الآن انظر إلى الخارج. حلقة البحث التلقائي الفعلية هي: يقرأ الوكيل program.md (ملف Markdown يصف مهمته)، يعدل .py التدريب، يلتزم، يعمل لمدة 5 دقائق، يتحقق مما إذا val_bpb تحسين، يحتفظ أو يعيد، ويكرر. program.md يقول صراحة "لا تتوقف أبدا." يركض العميل إلى أجل غير مسمى حتى يقتله الإنسان. ~12 تجربة في الساعة، ~100 تجربة طوال الليل أثناء نومك. ...