كيفية كتابة خطوط أنابيب أنيقة للتعلم الآلي

مرحبا هبر.



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





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



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



ما هي الناقلات؟



ناقلهي سلسلة من الخطوات في تحويل البيانات. يتم إنشاؤه وفقًا لنمط تصميم الأنبوب والمرشح القديم (تذكر ، على سبيل المثال ، أوامر unix bash ذات الأنابيب "|" أو ">" عوامل إعادة التوجيه). ومع ذلك ، فإن خطوط الأنابيب هي كائنات في التعليمات البرمجية. وبالتالي ، يمكن أن يكون لديك فئة لكل مرشح (أي لكل مرحلة في خط الأنابيب) ، بالإضافة إلى فئة أخرى لدمج كل هذه المراحل في خط أنابيب مكتمل. يمكن لبعض خطوط الأنابيب أن تجمع بين خطوط أنابيب أخرى في سلسلة أو متوازية ، ولها العديد من المدخلات أو المخرجات ، إلخ. من المريح التفكير في خطوط أنابيب التعلم الآلي على أنها:



  • القناة والمرشحات . مراحل بيانات معالجة خط الأنابيب ، والمراحل تدير حالتها الداخلية ، والتي يمكن تعلمها من البيانات.
  • . ; , . , – .
  • (DAG). , . : , , , , (, fit_transform ), , ( RNN). , , .








الناقل طرق الناقلون (أو مراحل خط الأنابيب) يجب أن يكون الطريقتين التاليتين:



  • " صالح " للتدريب على البيانات واكتساب حالة (على سبيل المثال ، هذه الحالة هي أوزان الشبكة العصبية)
  • " التحويل " (أو "التنبؤ") للمعالجة الفعلية للبيانات وإنشاء التنبؤ.
  • ملحوظة: إذا كانت مرحلة خط الأنابيب لا تتطلب إحدى هذه الطرق ، فيمكن أن ترث المرحلة من NonFittableMixin أو NonTransformableMixin ، والتي ستوفر تنفيذًا لإحدى هذه الطرق افتراضيًا بحيث لا تفعل شيئًا.




يمكن أيضًا تحديد الطرق التالية اختياريًا في مراحل خطوط الأنابيب :



  • fit_transform” , , , .
  • " الإعداد " الذي سيستدعي طريقة "الإعداد" في كل مرحلة من مراحل خط الأنابيب هذه. على سبيل المثال ، إذا كانت مرحلة خط الأنابيب تحتوي على شبكة عصبية TensorFlow أو PyTorch أو Keras ، فيمكن لهذه المراحل إنشاء الرسوم البيانية العصبية الخاصة بها والتسجيل للعمل مع وحدة معالجة الرسومات في طريقة "الإعداد" قبل التركيب. لا يوصى بإنشاء رسوم بيانية مباشرة في منشئي المسرح قبل التركيب ؛ هناك عدة أسباب لذلك. على سبيل المثال ، قبل البدء ، يمكن نسخ الخطوات عدة مرات باستخدام معلمات تشعبية مختلفة كجزء من خوارزمية التعلم الآلي الآلي ، التي تبحث عن أفضل المعلمات التشعبية لك.
  • " Teardown " ، هذه الطريقة من الناحية الوظيفية هي عكس "الإعداد": فهي تدمر الموارد.




يتم توفير الطرق التالية افتراضيًا ، مما يوفر تحكمًا في المعامل التشعبي:







إعادة تركيب خطوط الأنابيب والتجميع الصغير والتعلم عبر الإنترنت



للخوارزميات التي تستخدم الدُفعات المصغرة ، مثل تعلم الشبكات العصبية العميقة (DNN) أو الخوارزميات التي تتعلم عبر الإنترنت ، مثل التعلم المعزز (RL) لخطوط الأنابيب أو مراحلها المثالية إنه مناسب لربط عدة مكالمات بحيث تتبع واحدًا تلو الآخر بالضبط ، ويتم تعديلها سريعًا حسب حجم الدُفعات الصغيرة. يتم دعم هذه الميزة في بعض خطوط الأنابيب وفي بعض مراحل خطوط الأنابيب ، ولكن في مرحلة ما قد تتم إعادة تعيين التوافق المحقق نظرًا لحقيقة أنه سيتم استدعاء طريقة "الملاءمة" مرة أخرى. كل هذا يتوقف على كيفية برمجة مرحلة خط الأنابيب الخاصة بك. من الناحية المثالية ، لا ينبغي شطف مرحلة خط الأنابيب إلا بعد استدعاء طريقة "teardown" ثم استدعاء "setupحتى التوافق التالي ، ولم يتم مسح البيانات بين التركيبات أو أثناء التحويل.



استخدام نقاط التحقق في الناقلات من



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



إيجابيات وسلبيات استخدام نقاط التفتيش في خطوط الأنابيب:



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




عيوب استخدام نقاط التوقف في خطوط الأنابيب:



  • يستخدم الأقراص ، لذلك إذا قمت بذلك بشكل خاطئ ، يمكن أن يتباطأ الرمز الخاص بك. لتسريع الأمور ، يمكنك على الأقل استخدام RAM Disk أو تحميل مجلد ذاكرة التخزين المؤقت على ذاكرة الوصول العشوائي الخاصة بك.
  • قد يستغرق هذا مساحة كبيرة على القرص. أو الكثير من مساحة ذاكرة الوصول العشوائي عند استخدام دليل مثبت على ذاكرة الوصول العشوائي.
  • يصعب إدارة الحالة المخزنة على القرص: فبرنامجك به التعقيد الإضافي اللازم لجعل الكود يعمل بشكل أسرع. لاحظ أنه من منظور البرمجة الوظيفية ، لن تكون وظائفك ورمزك نظيفين بعد الآن ، حيث تحتاج إلى إدارة الآثار الجانبية المرتبطة باستخدام القرص. يمكن أن تكون الآثار الجانبية المرتبطة بإدارة حالة القرص (ذاكرة التخزين المؤقت) أرضًا خصبة لجميع أنواع الحشرات الغريبة
...



من المعروف أن بعض أصعب الأخطاء في البرمجة تنشأ من مشكلات إبطال ذاكرة التخزين المؤقت.



في علوم الكمبيوتر ، هناك شيئان صعبان حقًا: إبطال ذاكرة التخزين المؤقت وتسمية الكيان. - فيل كارلتون




نصائح حول كيفية إدارة الحالة والتخزين المؤقت في خطوط الأنابيب بشكل صحيح.



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



يجب ألا تتحكم مراحل التحويل في إعدادات نقاط الاختبار في البيانات الصادرة عن




لإدارة هذا ، يجب استخدام مكتبة أنابيب خاصة يمكنها القيام بكل هذا من أجلك.



لماذا ا؟



لماذا لا تتحكم مراحل خط الأنابيب في وضع نقاط التفتيش في البيانات التي تنتجها؟ لنفس الأسباب الوجيهة التي تستخدم فيها مكتبة أو إطار عمل عند العمل ، ولا تقم بإعادة إنتاج الوظائف المقابلة بنفسك:



  • سيكون لديك مفتاح تبديل بسيط يجعل من السهل تنشيط نقاط التوقف أو إلغاء تنشيطها بالكامل قبل النشر في الإنتاج.
  • , , , : , , . , .
  • / (I/O) . , . : , . ?
  • , , – . , , .
  • , , , , , , . , . .
  • , , (, , ) . , ( , ) . , , , , , , . , . , .




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



لا تضرب هذا الجدار. دفق البيانات في



ناقل تعلم الآلة



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



لا تفهموني خطأ ، فإن العمل مع خطوط أنابيب scikit-Learn ممتع للغاية. لكن لم يتم تصنيفهم للبث. ليس فقط scikit-Learn ، ولكن معظم المكتبات الموجودة في خطوط الأنابيب لا تستفيد من إمكانيات البث عندما تستطيع ذلك. توجد مشكلات متعددة في جميع أنحاء نظام Python البيئي. في معظم المكتبات الموصولة بالأنابيب ، يتم حظر كل مرحلة تمامًا وتتطلب تحويل جميع البيانات مرة واحدة. لا يوجد سوى عدد قليل من مكتبات البث المتاحة.



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



في شركتنا ، تمكنت Neuraxle بالفعل من القيام بشيء واحد أفضل من scikit-Learn: يتعلق الأمر بخطوط الأنابيب المتسلسلة التي يمكن استخدامها باستخدام فئة MiniBatchSequentialPipeline.... حتى الآن ، هذا الشيء ليس متعدد الخيوط (ولكن هذا في الخطط). كحد أدنى ، يقوم بالفعل بنقل البيانات إلى خط الأنابيب في شكل دفعات صغيرة أثناء عملية التركيب أو التحويل ، قبل جمع النتائج ، مما يسمح بالعمل مع خطوط الأنابيب الكبيرة تمامًا كما هو الحال في scikit-Learn ، ولكن هذه المرة باستخدام الدُفعات المصغرة ، وكذلك العديد من الاحتمالات الأخرى ، بما في ذلك: المساحات الفائقة ، وطرق التثبيت ، والتعلم الآلي للآلة ، وما إلى ذلك.



حل Python المتزامن



  • يمكن استدعاء طريقة التركيب و / أو التحويل عدة مرات متتالية لتحسين الملاءمة مع الدُفعات الصغيرة الجديدة.
  • , -. , , .
  • , . , setup. , , . , TensorFlow, , , , C++, Python, GPU. joblib . .
  • , . , – , , , , .
  • . , , ; , . , , , , ( Joiner). , . , , , .




علاوة على ذلك ، نريد التأكد من أن أي كائن في Python يمكن مشاركته بين سلاسل العمليات بحيث يمكن تسلسلها وإعادة تحميلها. في هذه الحالة ، يمكن إرسال الرمز ديناميكيًا للمعالجة على أي عامل (يمكن أن يكون كمبيوتر آخر أو عملية أخرى) ، حتى لو لم يكن الرمز الضروري نفسه موجودًا على هذا العامل. يتم ذلك باستخدام سلسلة من المسلسلات الخاصة بكل فئة تجسد مرحلة خط الأنابيب. بشكل افتراضي ، تحتوي كل خطوة من هذه الخطوات على مُسلسل يسمح لك بمعالجة كود Python العادي ، وللحصول على تعليمات برمجية أكثر تعقيدًا ، استخدم GPU واستيراد الكود بلغات أخرى. يتم ببساطة تسلسل النماذج باستخدام المدخرينثم يعاد تحميله في العامل. إذا كان العامل محليًا ، فيمكن إجراء تسلسل للكائنات إلى قرص موجود في ذاكرة الوصول العشوائي ، أو إلى دليل مثبت في ذاكرة الوصول العشوائي.



تنازلات للتضمين



هناك شيء آخر مزعج متأصل في معظم المكتبات للتعلم الآلي عبر الأنابيب. يتعلق الأمر بكيفية التعامل مع المعلمات الفائقة. خذ scikit-Learn على سبيل المثال. غالبًا ما يلزم تحديد مساحات المعامِلات الفائقة (تُعرف أيضًا بالتوزيعات الإحصائية لقيم المعلمات الفائقة ) خارج خط الأنابيب ، مع وجود خطوط سفلية كفواصل بين مراحل خط (خطوط) الأنابيب. في حين بحث عشوائية و شبكة البحثتسمح لك باستكشاف شبكات المعلمات الفائقة أو مساحات احتمالية المعامل الفائق كما هو محدد في توزيعات scipy ، لا توفر scikit-Learn نفسها مسافات افتراضية للمعلمات الفائقة لكل مصنف ومحول. يمكن تعيين مسؤولية أداء هذه الوظائف لكل كائن في خط الأنابيب. وبالتالي ، سيكون الكائن مكتفًا ذاتيًا وسيحتوي على معلماته الفائقة. هذا لا ينتهك مبدأ المسؤولية الفردية ، ومبدأ الفتح / الإغلاق ومبادئ البرمجة الشيئية SOLID.



التوافق والتكامل عند تشفير



خطوط أنابيب التعلم الآلي ، من المفيد أن تضع في اعتبارك أنه يجب أن تكون متوافقة مع العديد من الأدوات الأخرى ، ولا سيما scikit-Learn.و TensorFlow و Keras و PyTorch والعديد من مكتبات التعلم الآلي والعميق الأخرى.

على سبيل المثال ، كتبنا طريقة .tosklearn()تسمح لنا بتحويل مراحل خط الأنابيب أو خط أنابيب كامل إلى BaseEstimatorكائن أساسي في مكتبة scikit-Learn. بالنسبة إلى مكتبات التعلم الآلي الأخرى ، تكمن المهمة في كتابة فئة جديدة ترث من مجموعتنا BaseStepوتجاوز عمليات التركيب والتحويل في كود معين ، وكذلك ، ربما ، الإعداد والهدم. تحتاج أيضًا إلى تحديد برنامج حفظ يقوم بحفظ النموذج الخاص بك وتحميله. ها هي وثائق الفصل BaseStepوأمثلة لها.



خاتمة



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



  • في كود التعلم الآلي ، من المنطقي استخدام خطوط الأنابيب وتحديد كل مرحلة من خط الأنابيب كمثال للفصل.
  • يمكن بعد ذلك تحسين الهيكل بأكمله باستخدام نقاط التوقف للمساعدة في العثور على أفضل المعلمات التشعبية وتنفيذ الكود بشكل متكرر على نفس البيانات (ولكن ربما باستخدام معلمات تشعبية مختلفة أو كود مصدر معدل).
  • , RAM. , .
  • , – BaseStep, , .



All Articles