حلقة التدريب

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

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

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

يتأثر تنفيذ حلقة التدريب العامة لـ Swift for TensorFlow بشدة بـ Fastai's Learner . لمزيد من المعلومات حول تصميمها، يرجى الرجوع إلى "fastai: واجهة برمجة التطبيقات ذات الطبقات للتعلم العميق" وعرض Sylvain Gugger "Fast.ai - حلقة تدريب قابلة للتخصيص بشكل لا نهائي" .

الاستخدام

يوفر مثال ResNet-CIFAR10 عرضًا جيدًا لكيفية استخدام حلقة التدريب هذه عمليًا. أولاً، قم باستيراد الوحدة:

import TrainingLoop

ثم اختر الواجهة الخلفية للتسريع عن طريق إعداد Device . في هذه الحالة، سنختار الواجهة الخلفية المستندة إلى X10 XLA ونستخدم أول مسرع متاح:

let device = Device.defaultXLA

الخطوة التالية هي تكوين مجموعة البيانات والنموذج والمحسن لاستخدامه مع حلقة التدريب الخاصة بك:

let dataset = CIFAR10(batchSize: 10, on: device)
var model = ResNet(classCount: 10, depth: .resNet56, downsamplingInFirstStage: false)
var optimizer = SGD(for: model, learningRate: 0.001)

ثم قم بإعداد حلقة التدريب:

var trainingLoop = TrainingLoop(
  training: dataset.training,
  validation: dataset.validation,
  optimizer: optimizer,
  lossFunction: softmaxCrossEntropy,
  metrics: [.accuracy])

تفترض حلقة التدريب أن مجموعة البيانات التي تستخدمها تتوافق مع Epochs API، وتسمح لك بتحديد الانقسامات داخل مجموعة البيانات لاستخدامها في التدريب والتحقق من الصحة. يمكن استخدام أي دالة خسارة بمجرد وضعها في غلاف متوافق، مثل softmaxCrossEntropy الموجود هنا .

تشمل المقاييس الحالية التي يمكن التقاطها ما يلي:

  • loss
  • accuracy
  • top5Accuracy
  • matthewsCorrelationCoefficient
  • perplexity

وأخيرا، لأداء التدريب، يمكنك استدعاء ما يلي:

try! trainingLoop.fit(&model, epochs: 10, on: device)

سيؤدي هذا إلى تدريب النموذج لمدة 10 فترات باستخدام الواجهة الخلفية للمسرع التي حددناها. سيتم عرض الإحصائيات أثناء التدريب على وحدة التحكم باستخدام مطالبة متحركة.

عمليات الاسترجاعات

يتم تخصيص حلقة التدريب المعممة هذه عبر استخدام عمليات الاسترجاعات. يمكن ربط عمليات الاسترجاعات هذه بنقاط مختلفة داخل الحلقة.

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

  • تسجيل الإحصائيات إلى ملفات ذات قيمة مفصولة بفاصلة (CSV).
  • ضبط معدل التعلم وفق جدول زمني مخصص
  • مراقبة ورسم تقدم التدريب عبر TensorBoard

بالإضافة إلى ذلك، يمكنك إنشاء عمليات رد الاتصال المخصصة الخاصة بك لإضافة مجموعة من الوظائف الإضافية إلى حلقة التدريب القياسية.

تسجيل CSV

تقوم فئة CSVLogger بتغليف رد الاتصال الذي سيكتب إحصائيات التدريب بتنسيق قيمة مفصولة بفاصلة إلى ملف من اختيارك. سيبدأ هذا الملف بأعمدة تحمل عنوان epoch و batch وأي مقاييس قمت بتمكينها في حلقة التدريب الخاصة بك. سيتم بعد ذلك كتابة صف واحد لكل دفعة، بالقيم الحالية لتلك الأعمدة.

لإضافة تسجيل CSV إلى حلقة التدريب الخاصة بك، قم بإضافة شيء مثل ما يلي إلى مجموعة من عمليات الاسترجاعات المقدمة إلى callbacks: المعلمة الخاصة بـ TrainingLoop الخاصة بك:

try! CSVLogger(path: "file.csv").log

على سبيل المثال، تستخدم عينة LeNet-MNIST هذا ضمن حلقة التدريب الخاصة بها.

جداول معدلات التعلم

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

يوفر رد الاتصال learningRateScheduler وسيلة لوصف جداول معدل التعلم المكونة من أجزاء مختلفة، لكل منها شكلها المميز. يتم تحقيق ذلك عن طريق تحديد LearningRateSchedule الذي يتكون من ScheduleSegment التي يحتوي كل منها على Shape بواسطة وظيفة، ومعدل التعلم الأولي، ومعدل التعلم النهائي.

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

learningRateScheduler(
  schedule: makeSchedule(
    [
      ScheduleSegment(shape: linear, startRate: 0, endRate: peakLearningRate, stepCount: 10),
      ScheduleSegment(shape: linear, endRate: 0)
    ]
  )
)

يحدد كل من ScheduleSegment معدل التعلم الذي يبدأ عند 0 ويزيد خطيًا إلى peakLearningRate معدل التعلم عبر سلسلة من 10 خطوات منفصلة، ​​ثم يبدأ بمعدل التعلم النهائي من الخطوة السابقة وينخفض ​​خطيًا إلى 0 بنهاية عملية التدريب.

التكامل TensorBoard

TensorBoard هي أداة تصور قوية لمراقبة التدريب النموذجي، أو تحليل التدريب عند اكتماله، أو مقارنة عمليات التدريب. يدعم Swift for TensorFlow تصور TensorBoard من خلال استخدام وحدة TensorBoard في مستودع النماذج، والذي يوفر عمليات رد اتصال تسجل مقاييس التدريب.

يوضح نموذج GPT2-WikiText2 كيفية إضافة تسجيل TensorBoard إلى تدريب النموذج الخاص بك. أولاً، قم باستيراد وحدة TensorBoard . بعد ذلك يكون الأمر بسيطًا مثل إضافة tensorBoardStatisticsLogger() إلى عمليات الاسترجاعات الخاصة بـ TrainingLoop callbacks: array.

افتراضيًا، سيؤدي ذلك إلى تسجيل كل تدريب يتم تشغيله ضمن دليل run/tensorboard/stats . لعرض هذا داخل Tensorboard، قم بتشغيل

tensorboard --logdir ./run/tensorboard/stats

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

تصميم Swift لتكامل TensorFlow TensorBoard مستوحى من TensorboardX . تقوم عمليات رد الاتصال TensorBoard مباشرة بإنشاء المخازن المؤقتة المناسبة لبروتوكول الأحداث والتلخيص وكتابتها في ملف سجل أثناء التدريب.

عمليات الاسترجاعات المخصصة

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

func customCallback<L: TrainingLoopProtocol>(_ loop: inout L, event: TrainingLoopEvent) throws
{
  if event == .updateStart {
    ...
  }
}

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

  • fitStart
  • fitEnd
  • epochStart
  • epochEnd
  • trainingStart
  • trainingEnd
  • validationStart
  • validationEnd
  • batchStart
  • batchEnd
  • updateStart
  • inferencePredictionEnd

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