العمليات والمعلومات في قلب كل عمل. إن ضعف وفرصة هذه اللحظة هو مسألة ما إذا كان بإمكان عملك أتمتة عملياتك باستخدام الذكاء الاصطناعي ، وجني مكافآت القيام بذلك. لقد فتح Chatgpt ، وهو غرض عام منظمة العفو الدولية ، أعيننا لما يمكن أن تفعله الذكاء الاصطناعي. ما يهم الآن هو توجيه قوة الذكاء الاصطناعى إلى مشاكل عملك وإلغاء قفل قيمة بيانات الملكية الخاصة بك . في هذا المستند ، سأريكم كيف.
أنت لا تريد منظمة العفو الدولية التي يمكنها الدردشة فقط ؛ ما تريده حقًا هو الأتمتة التي تؤدي العمل الذي يحافظ على تشغيل عملك-من خلال عمليات الأعمال بدقة كبيرة وحجم. تتمثل الطريقة المثبتة لتخصيص الذكاء الاصطناعي لعمليات عملك في ضبط LLM على بياناتك وعلى الإجراء الذي تريد القيام به من الذكاء الاصطناعي.
دعنا نتحدث على وجه التحديد عن الضبط الدقيق الذي سنفعله في هذا المستند والتكنولوجيا وراءه. المدرجة أدناه هي الأدوات الخمسة التي سنستخدمها على نطاق واسع:
في نهاية اليوم ، يجب أن تسلب شيئين من هذه الوثيقة:
سأصف لك مشكلة صعبة في العالم حقيقي ، وما هي ما فعله باحثو التعلم الآلي بالفعل ، والحدود الجديدة التي تمكنا من الضغط على استخدام أدوات SOTA القوية. سنقوم بتدريب النماذج على وحدات معالجة الرسومات في السحابة. سنقوم أيضًا بوضع ممارسات MLOPS قوية في العمل-باستخدام MLFLOW لتنظيم تجاربنا ومعلماتنا. وعلى طول الطريق ، سأشير إلى نمط تصميم هذا المشروع حتى تتمكن من تخصيص قاعدة الشرف لمشاريع التعلم العميق الخاصة بك.
لنبدأ بخلفية المشكلة.
هناك عملية جيدة لإيجاد مشكلات مناسبة للتعلم الآلي ومجموعات بيانات الجودة هي البدء من خلال تصفح المواقع مع المعايير. توفر المعايير إطارًا مرجعيًا لمستوى صعوبة مشكلة التعلم الآلي ، والذي نستخدمه لقياس تقدمنا أثناء تطوير النموذج. مجموعة بيانات معينة مع معايير راسخة هي مجموعة بيانات شروط الخدمة غير العادلة (TOS غير عادلة) ؛ إليك بيان مشكلة مثيرة للاهتمام: استخدم منظمة العفو الدولية للعثور على جميع الجمل غير العادلة من حيث عقود الخدمة. السياق هو أن قانون المستهلك الأوروبي بشأن العقود غير العادلة يحدد البنود غير العادلة وأنواع مختلفة من الجمل غير العادلة. ما يجعل TOS غير عادلة مثالية لتصنيف النص هو أنه تم تصنيفه يدويًا وفقًا لما تم تعيينه في القانون الأوروبي.
Chalkidis et al. (2021) طبقت ثماني طرق مختلفة للتعلم الآلي على TOS غير عادلة وحصل عليها Macro F1 تتراوح من 75 إلى 83 ، وفي الشكل 1 أدناه ، ننتقل من نتائجها المنشورة.
| طريقة | غير عادل | |
|---|---|---|
| Micro F1 | ماكرو F1 | |
| TFIDF-SVM | 94.7 | 75.0 |
| بيرت | 95.6 | 81.3 |
| روبرتا | 95.2 | 79.2 |
| ديبرتا | 95.5 | 80.3 |
| Longformer | 95.5 | 80.9 |
| Bigbird | 95.7 | 81.3 |
| قانوني | 96.0 | 83.0 |
| Caselaw-Bert | 96.0 | 82.3 |
أشياء مثيرة للاهتمام يمكننا أن نستنتجها من هذا الجدول هي:
بالنظر إلى البيانات ، فإن اختلال التوازن في الطبقة موجود بالتأكيد ، وهو سبب وجيه للنقطة الأولى والثانية أعلاه.
هناك ثمانية أنواع مختلفة من الجمل غير العادلة. قام مؤلفو تلك الورقة بتطوير نماذج تصنيف متعددة العلامات للأنواع الثمانية ، لكننا سنقوم ببساطة ببناء نموذج تصنيف ثنائي يصنف جملة على أنها عادلة أو غير عادلة.
دعونا نتصميم كيف سنفعل ذلك.
__init__.py يعرض واجهات برمجة التطبيقات العامة للوحدة النمطية التي يمكن أن نختصرها بشكل مريح للوظائف العميقة الشديدة مثل هذا المثال: from . fine_tune_clsify_head import TransformerModule يتيح الاستيراد أعلاه في architectures/__init__.py رمزًا خارج architectures من استيراد TransformerModule دون الحاجة إلى تذكر فتات الخبز المؤدية إلى مكان وجود هذه الوظيفة ، مثل هذه:
from architectures import TransformerModuleإليك ما يبدو عليه هيكل المشروع من جذر وحدة Lightning_Mlflow:
.
├── architectures
│ ├── __init__.py
│ └── fine_tune_clsify_head.py
├── config
│ ├── __init__.py
│ └── train_config.py
├── data
│ ├── __init__.py
│ └── lex_glue.py
└── train.py
السؤال الرئيسي هو لماذا يتم تنظيم المشروع بهذه الطريقة. والإجابة هي أن فصل المخاوف يتم تأسيسه بين العدوى الفرعية الثلاثة ونقطة دخول واحدة. دعنا نسير عبر كل واحدة من هذه الوحدات بدورها:
architectures : تحدد بشكل أساسي كل ما يحتاج Pytorch إلى معرفته باستثناء البياناتconfig : يحتفظ بجميع المعلمات ويمكن تقسيمه إلى train_config.py و inference_config.py وأي شيء آخرdata : يحتفظ بجميع منطق معالجة البيانات والإعداداتtrain.py : نقطة السيطرة المركزية ؛ هذا هو الجزء الوحيد من التعليمات البرمجية التي يمكن أن ترى architectures config data ؛ مكالمات Mlflow SDK تذهب هنامع هذا المقدمة المختصرة عن الطريق ، دعنا نشعر بأكمامنا ونحاول فهم الرمز في كل وحدة من الوحدات النمطية. لنبدأ مع البنية/fine_tune_clsify_head.py. يتم تنظيم هذا الرمز مثل الشكل 3 أدناه.

من الواضح أن الأساليب الرئيسية داخل هذه الفئة التي يجب فهمها هي: المُنشئ ، والتمرير للأمام عبر الشبكة ، والمقاييس ، والخطوات. سنناقش كل من هذه بدوره. لنبدأ بالمقدم. هذا المقتطف هو ما يبدو عليه الرمز:
ما هو مهم حقًا هنا هو أن المنشئ يحمل نموذجًا مسبقًا من وجه المعانقة ، ويقوم بإنشاء ضبط دقيق فعال (PEFT). PEFT هي طريقة حافة النزيف لضبط نماذج اللغة الكبيرة ، وهي عبارة عن تطبيق وجه معانقة لـ Qlora ، وهو مزيج من ثلاث استراتيجيات كفاءة مختلفة: القياس الكمي ، المرتبة المنخفضة ، والمحول. الكمي هو فكرة أن عدد صحيح بايت واحد هو بدقة عددية كافية لحساب التدرج في التعلم العميق. تأتي الرتبة المنخفضة من مفهوم الجبر الخطي بأن رتبة المصفوفة هي عدد الأبعاد غير المليئة بمساحة المتجه. يمكن فهم ضبط المحول كنوع من تعميم ضبط رأس الشبكة ، عن طريق إعادة تجهيز جزء من الأوزان في العديد من الطبقات.
دعونا نلقي نظرة على الطريقة forward :
نظرًا لأن التدريب على الشبكة العصبية تتضمن التناوب بين Backprop و READ للأمام ، فإن هذا يحدد الجزء الأمامي ، والشيء البارز هو أن وسيطات forward هي: input_ids ، attention_mask ، label . هذه هي مخرجات الرمز المميز للوجه المعانقة ، وهي تسمح لنا بربط المعانقة للوجه وبرق Pytorch.
بعد ذلك ، دعونا نلقي نظرة على طريقة _compute_metrics :
هناك بعض الأشياء التي تستحق الإشارة إليها هنا. أولاً ، لاحظ كيفية تفريغ السجلات من تقييم الوظيفة الأمامية ثم تحويلها إلى احتمالات عبر وظيفة softmax. هذا ، بدوره ، يؤدي إلى التنبؤ الثنائي. نستخدم التنبؤ والفعلي ( batch["label"] ) لحساب الدقة ، F1 ، الدقة ، والاستدعاء.
أخيرًا ، دعنا نتحدث عن training_step و validation_step و test_step .
إنها تبدو متشابهة تقريبًا ، مع وجود اختلاف مهم هو training_step في إرجاع outputs["loss"] بدلاً من metrics . هذا أمر منطقي لأن Backprop تقلل من الخسارة بشكل تكراري ؛ training_step هو مجرد تجريد Pytorch Lightning لحلقة التدريب.
حسنًا ، لقد انتهينا الآن من architectures ، دعنا نغوص في config/train_config.py ، والذي يبدو أن الشكل 7 أدناه.
هذا الرمز محسّن ذاتيًا ، ولكن هناك بعض الخيارات التي يجب استدعاؤها. تم تعيين pretrained_model على roberta-base ، وإذا أردنا تغييره إلى أي اسم طراز وجه معانقة يدعم Autotokenizer ، فلا يزال من المفترض أن يعمل كل شيء (تم اختباره). تم العثور على دقة النموذج لتكون أكثر حساسية لـ max_length و batch_size ، لذلك فهي هي المقاييس الرئيسية التي يجب اللعب بها ، وكلاهما على كل من الدقة والحمل الحسابي. على Azure ML ، استخدمت مثيل Standard_NC24ADS_A100_V4. أثبتت VRAM على وحدة معالجة الرسومات A100 أنها العامل المقيد لهذين الفصلين. ما وجدته هو أن 256 كان أكبر batch_size لن يتسبب في رمي CUDA خطأ خارج الذاكرة.
كان تحديد max_length 128 أسهل لأن الغالبية العظمى من الجمل كانت تحت هذا الحد من الرمز المميز.
أخيرًا ، كما سنرى لاحقًا ، تم اختيار max_epochs من 10 عن طريق التجربة والخطأ كقياس التحقق من الصحة F1 التي كنا نتتبعها في Mlflow كان في تسوية بحلول تلك النقطة.
حسنًا ، دعنا نتحدث عن البيانات. كل ما تحتاج إلى معرفته هو في فئة LexGlueDataModule في البيانات/lex_glue.py ، وهذا هو بنيته:
هناك عدد غير قليل من التفاصيل الدقيقة في LexGlueDataModule ، ولكن الفكرة الرئيسية هي أن طريقة setup تجلب البيانات مباشرة من الوجه المعانقة ، ثم يجب أن يحدث نوع من الرمز المميز. تفاصيل هذا الرمز المميز في طريقة _shared_transform ، والتي هي مجرد واجهة عالية المستوى لطريقة رد الاتصال _preprocess .
أخيرًا ، نحن على استعداد لـ Train.py ، نقطة التحكم المركزية لكل شيء. تذكر عندما بدأنا هذا القسم بهيكل الدليل للمشروع؟ هذا الهيكل هو توصيل رسالة مهمة: يتم حل التبعيات لأسفل في شجرة الدليل. بمعنى آخر ، قمنا بتقييد التعليمات البرمجية على استدعاء رمز آخر فقط على نفس المستوى أو أقل. هذا التقييد بالتأكيد لا يأتي من بيثون. إنه فرض نفسه ، ولماذا؟ للقضاء على التخمين. ليس هناك شك في أن سلاسل التبعية المربكة هي مشكلة كبيرة في قواعد الكود الكبيرة. ما يعنيه كل هذا هو أن train.py سوف يستورد الوظيفة من كل وحدة من الوحدات الأخرى ثم وضع تشغيل تدريب. دعونا نلقي نظرة على قطعة الكود الموجودة في قلبها:
نحن نستند إلى فئة مدرب البرق في Pytorch ، ونشغل الإيقاف المبكر ، ونضع الدقة استنادًا إلى الجهاز الذي نحن عليه عبر precision="bf16-mixed" if torch. cuda.is_available() else "32-true" . نقوم بتكوين mlflow لتتبع كل شيء. لوضع كل شيء معًا ، نستورد الوظائف من الوحدات الثلاث الأخرى التي وصفناها سابقًا:
from architectures . fine_tune_clsify_head import TransformerModule
from config import TrainConfig
from data import LexGlueDataModuleيتم لف الوظائف الأساسية في فئاتنا الفرعية من فئات Pytorch Lightning Supercasses ، ولذا فإننا نستند إليها:
model = TransformerModule (
pretrained_model = config . pretrained_model , num_classes = config . num_classes ,
lr = config . lr , )
datamodule = LexGlueDataModule (
pretrained_model = config . pretrained_model , max_length = config . max_length ,
batch_size = config . batch_size , num_workers = config . num_workers ,
debug_mode_sample = config . debug_mode_sample , ) وأخيرًا ، نستدعي طرق fit test لكائن trainer :
trainer . fit ( model = model , datamodule = datamodule )
best_model_path = checkpoint_callback . best_model_path
# Evaluate the last and the best models on the test sample.
trainer . test ( model = model , datamodule = datamodule )
trainer . test (
model = model , datamodule = datamodule , ckpt_path = best_model_path , ) لقد اتصلنا test مرتين حتى نختبر كل من النموذج الأخير في وقت التوقف وأفضل نموذج وفقًا لمقياسنا. هذا مثال مثالي على الوظيفة الغنية التي تأتي مع البرق Pytorch.
وهذا يختتم تجول الرمز. الآن دعنا نغطس في نتائج النموذج.
إليك لوحة معلومات تضعها جميعًا معًا:
الاستفادة من التكامل الضيق بين Azure و MLFlow ، تم توفير المقاييس من تشغيل التدريب لدينا لسهولة الاستهلاك والتصور في وحدة التحكم على شبكة الإنترنت Azure ML. استحوذت MLFlow على الطريق أكثر من مجرد المقاييس ، ولكنها تعمق في وظائفها الكاملة وحالات الاستخدام الأوسع لـ MLOPs هي ليوم آخر. في الوقت الحالي ، دعونا نركز على القصة التي يكشفها لنا تصور البيانات.
شيء واحد ينبثق من المخطط الأيسر العلوي هو أن التدريب قد تحسن من الخسارة على عينة التحقق من الصحة. علاوة على ذلك ، بين 125 و 190 خطوة ، يبدأ المنحنى في التسوية ، وهو مؤشر محتمل على أن المزيد من التدريب قد يكون غير ضروري. لكن كونك رتابة ، نرى أن التورط لم يحدث بعد ، والأكثر من ذلك ، كان المنحنى شحريًا مرة أخرى من 190 إلى 210 ، لذلك ربما كان ينبغي علينا أن ندعه يركض لمدة 5 عصر آخر.
المؤامرة اليمنى العليا ، ومن المثير للاهتمام ، سرد قصة مماثلة. أبرز خاصية هي مدى ارتفاع قيم الدقة ، والوحدة هنا هي النسبة المئوية. إن الخطوط التي تصل إلى 90 ٪ من البداية أمر منطقي لأن مجموعة البيانات غير متوازنة عند نسبة 1: 9 بين الظلم والعادل. هذا هو بالضبط السبب في أن المقياس المفضل هو F1 ، وهو ما نعرضه في الرسم البياني الأيسر السفلي.
تظهر منحنيات F1 هنا النمط الكلاسيكي حيث يتحسن النموذج بسرعة في البداية ولكنه يصل في النهاية إلى نقطة العائد المتناقص. السؤال المثير للاهتمام الذي تثيره منحنيات F1 هو كيف يمكننا التوفيق بين الخسارة و F1 ، عندما يقترح أحدهم المدقق بينما يترك الآخر مساحة للمضي قدمًا؟ الجزء التالي من النظرية سوف يكسر هذا اللغز.
نلاحظ العالم في شكل أحداث منفصلة ، ولكن البنيات المستمرة (على سبيل المثال الاحتمال) غالبًا ما تكون أكثر فائدة في الرياضيات. يتم ترميز النتائج في مجموعة بيانات TOS غير العادلة "عادلة" أو "غير عادلة" ، وهناك توزيع احتمال كامن يولد تلك النتائج. إن توزيع الاحتمالات الكامنة هذا هو ما يمكن أن تعمل معه وظيفة فقدان الإدخال المتقاطع. لذا ، في التعلم العميق ، نتحسن للمقياس المستمر ، لكننا نحكم على مدى جودة نموذجنا من خلال المقياس المنفصل ، لأن المستمر (الكامن) والمنفصل (لوحظ) هو تقريب بعضهما البعض. هذه هي الفكرة.
لذلك عندما يلمح F1 إلى قصة مختلفة عن الخسارة ، لا يوجد سوى اثنين من التفسيرات المحتملة: العشوائية وعدم التوازن الطبقي. في الواقع ، هذا هو السبب في أن الدقة و F1 أكثر تقلبًا من الخسارة.
يبدو أن العشوائية هي التفسير المحتمل للفجوة بين أفضل درجة التحقق من صحة F1 بنسبة 70 ٪ واختبار درجة F1 بنسبة 78 ٪ (من الجدول الأيمن السفلي).
هذه المسرحية من خلال تحليل اللعب لمقاييس تقييم النموذج تضع هذا القسم إلى نهايته. بعد ذلك ، احصل على التدريب العملي على جعل هذا المشروع خاصًا بك. سيساعدك دليل التثبيت أدناه على البدء في العبث بالرمز.
الخطوة 1. استنساخ هذا المستودع في دليل العمل المحلي:
$ git clone https://github.com/zjohn77/lightning-mlflow-hf.git
$ cd lightning-mlflow-hf الخطوة 2. جميع تبعيات المشروع في environment.yml . هل ستنشئ بيئة افتراضية لذلك. التعليمات أدناه مخصصة conda ، ولكن لا يوجد في هذه التبعيات يمنع venv أو poetry .
$ conda env create -n lightning-mlflow-hf -f environment.yml الخطوة 3. في نهاية التدريب ، ستقوم وظيفة copy_dir_to_abs بنسخ المخرجات إلى تخزين Blob Azure. إذا كان Azure هو أيضًا ما تستخدمه ، فما عليك سوى تمرير بيانات الاعتماد إلى هذه الوظيفة وكنت جميعًا تم تعيينك. خلاف ذلك ، استبدل سير العمل الخاص بك.
الخطوة 4. في بيئتك الافتراضية ، ستتغير إلى أو توجه IDE إلى مكان train.py وتشغيله:
$ python train.pyإذا لم تكن هناك أخطاء ، فسيتم طباعة بعض رسائل الوجه المعانقة والكثير من رسائل Lightning Pytorch. بعد بضع دقائق ، يجب أن تبدأ في طباعة شريط التقدم. اجلس ضيقة واتركها تفعل الشيء. عندما ينتهي التشغيل أخيرًا ، سيتم طباعة جدول ASCII الذي يلخص مقاييس التقييم للنموذج النهائي إلى وحدة التحكم. هذا كل ما في الأمر!
أي مساهمة مرحب بها. نستخدم طلبات سحب GitHub لمراجعة التعليمات البرمجية ، ونحن نستخدم التنسيق الأسود لضمان اتساق نمط الكود.
اختبارات الوحدة واختبارات DOC موضع ترحيب للغاية.
خارطة الطريق هي العمل قيد التقدم. تحقق مرة أخرى قريبا.
Ilias Chalkidis ، Abhik Jana ، Dirk Hartung ، Michael Bommarito ، Ion Androutsopoulos ، Daniel Martin Katz ، Nikolaos Altras. (2021). lexglue: مجموعة بيانات قياسية لفهم اللغة القانونية باللغة الإنجليزية . تم الاسترجاع من Arxiv: https://arxiv.org/abs/2110.00976