ملفات Keras والإحالات الناجحة الحديثة على وحدات معالجة الموتّرات

1. نظرة عامة

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

قد تكون قراءة الأبحاث المتعلّقة بالتعلم العميق صعبة ومربكة. دعنا نلقي نظرة عملية على بُنى الشبكة العصبونية الالتفافية الحديثة.

ca8cc21f6838eccc.png

المُعطيات

  • لاستخدام وحدات معالجة Keras وTensor (TPU) لإنشاء نماذج مخصَّصة بشكل أسرع.
  • استخدام واجهة برمجة التطبيقات tf.data.Dataset وتنسيق TFRecord لتحميل بيانات التدريب بكفاءة.
  • للغش 😈، باستخدام التعلم الآلي بدلاً من إنشاء نماذجك الخاصة.
  • لاستخدام أنماط نموذج Keras المتسلسلة والوظيفية.
  • لإنشاء مُصنِّف Keras الخاص بك باستخدام طبقة softmax وفقدان الطاقة عبر الإنتروبيا.
  • لضبط نموذجك باستخدام مجموعة جيدة من الطبقات الالتفافية.
  • لاستكشاف أفكار حديثة لبنية الشبكات التجميعية المتقدّمة، مثل الوحدات والجمع المتوسط الشامل وما إلى ذلك
  • لإنشاء شبكة عصبية تلافعية حديثة وبسيطة باستخدام بنية Squeezenet

الملاحظات

إذا لاحظت أي أخطاء في التمرين المعملي الخاص بالرموز، يُرجى إخبارنا بذلك. يمكن تقديم الملاحظات من خلال مشاكل GitHub [ رابط الملاحظات].

2. دليل البدء السريع لخدمة Google Colaboratory

يستخدم هذا التمرين المعملي متعاون Google ولا يتطلب أي إعداد من جانبك. يمكنك تشغيله من جهاز Chromebook. يُرجى فتح الملف أدناه وتنفيذ الخلايا للتعرّف على أوراق ملاحظات Colab.

c3df49e90e5a654f.png Welcome to Colab.ipynb

اختيار إحدى خلفيات وحدة معالجة الموتّرات

8832c6208c99687d.png

في قائمة Colab، اختَر "بيئة التشغيل" > "تغيير نوع بيئة التشغيل"، ثم اختَر "وحدة معالجة الموتّرات". في هذا الدرس التطبيقي حول الرموز البرمجية، ستستخدم وحدة معالجة قوية (TPU) مدعومة بالتدريب المُسرَّع بالأجهزة. سيتم الاتصال بوقت التشغيل تلقائيًا عند التنفيذ الأول، أو يمكنك استخدام الزر "ربط" في أعلى يسار الصفحة.

تنفيذ "دفتر ملاحظات Google"

76d05caa8b4db6da.png

نفِّذ الخلايا واحدة تلو الأخرى عن طريق النقر على خلية واستخدام Shift-ENTER. يمكنك أيضًا تشغيل ورقة الملاحظات بالكامل باستخدام "بيئة التشغيل" > "تشغيل الكل"

جدول المحتويات

429f106990037ec4.png

تحتوي جميع أوراق الملاحظات على جدول محتويات. يمكنك فتحه باستخدام السهم الأسود على اليمين.

الخلايا المخفية

edc3dba45d26f12a.png

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

المصادقة

cdd4b41413100543.png

يمكن لخدمة Colab الوصول إلى حِزم Google Cloud Storage الخاصة بك بشرط المصادقة باستخدام حساب معتمَد. سيؤدي مقتطف الرمز أعلاه إلى بدء عملية مصادقة.

3- [معلومات] ما هي وحدات معالجة الموتّرات (TPU)؟

باختصار

f88cf6facfc70166.png

رمز تدريب أحد النماذج على وحدة معالجة الموتّرات في Keras (ويجب استخدام وحدة معالجة الرسومات أو وحدة المعالجة المركزية (CPU) في حال عدم توفّر وحدة معالجة الموتّرات):

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

سنستخدم اليوم وحدات معالجة الموتّرات لإنشاء مصنِّف زهور وتحسينه بالسرعات التفاعلية (دقائق لكل تمرين تدريبي).

688858c21e3beff2.png

ما هي أسباب استخدام وحدات معالجة الموتّرات؟

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

8eb3e718b8e2ed08.png

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

الأجهزة

وحدة معالجة الوسائط (MXU) ووحدة معالجة الفيديو (VPU)

يتكون معالج TPU v2 من وحدة مضاعفة المصفوفات (MXU) التي تُجري عمليات مضاعفة المصفوفات ووحدة معالجة المتجهات (VPU) لجميع المهام الأخرى، مثل عمليات التنشيط وsoftmax وما إلى ذلك. تعالج وحدة معالجة المتجهات عمليات حسابية بتنسيقَي float32 وint32. من ناحية أخرى، تعمل وحدة قياس الأداء (MXU) بتنسيق نقطة عائمة بدقة مختلطة 16-32 بت.

7d68944718f76b18.png

نقطة عائمة بدقة مختلطة وbfloat16

تحسب MXU عمليات ضرب المصفوفة باستخدام مدخلات bfloat16 ومخرجات float32. ويتم تنفيذ التراكمات المتوسطة بدقة float32.

19c5fc432840c714.png

عادةً ما يكون تدريب الشبكات العصبية مقاومًا للضوضاء الناتجة عن انخفاض دقة النقطة العائمة. وهناك حالات تساعد فيها الضوضاء المحسّن على التقارب. كان يتم استخدام الدقة بنقطة عائمة 16 بت بشكل تقليدي لتسريع العمليات الحسابية، ولكنّ تنسيقَي float16 وfloat32 لهما نطاقات مختلفة جدًا. يؤدي عادةً تقليل الدقة من float32 إلى float16 إلى حدوث عمليات تجاوز حدود الحد الأدنى والحد الأقصى. توجد حلول ولكن يلزم عمل إضافي عادةً لجعل عمل float16.

لهذا السبب، طرحت Google تنسيق bfloat16 في وحدات TPU. وbfloat16 هو تنسيق float32 مقطوع يتضمّن القيمة نفسها تمامًا لبتّي الأس ومدى float32. هذا بالإضافة إلى حقيقة أنّ وحدات معالجة الموتّرات تحتسب عمليات ضرب المصفوفات بدقة مختلطة مع مخرجات bfloat16 والمخرجات float32، وهو ما يعني أنّه لا يلزم عادةً إجراء أي تغييرات في الرموز للاستفادة من دقة الأداء المحسّنة.

المصفوفة الانسيابية

تنفِّذ وحدة MXU عمليات ضرب المصفوفات في الأجهزة باستخدام بنية تُعرف باسم "المصفوفة الانبساطية" التي تتدفق فيها عناصر البيانات من خلال صفيف من وحدات الحساب في الأجهزة. (في المجال الطبي، تشير كلمة "انقباضي" إلى انقباضات القلب وتدفق الدم، هنا لتدفق البيانات).

العنصر الأساسي لعملية ضرب المصفوفة هو ناتج الضرب النقطي بين خط من مصفوفة واحدة وعمود من المصفوفة الأخرى (راجع الرسم التوضيحي أعلى هذا القسم). في عملية ضرب المصفوفات Y=X*W، سيكون عنصر واحد من النتيجة على النحو التالي:

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

في وحدة معالجة الرسومات، يمكن برمجة منتج نقطة هذا في "وحدة معالجة مركزية" لوحدة معالجة الرسومات، ثم تنفيذه على أكبر عدد ممكن من "وحدات المعالجة المركزية" المتاحة بالتوازي لمحاولة احتساب كل قيمة من القيم للمصفوفة الناتجة في آنٍ واحد. إذا كانت المصفوفة الناتجة كبيرة بحجم 128×128، فقد يتطلب ذلك توفر "نواة" قيمتها 128x128=16K، وهو أمر لا يكون ممكنًا عادةً. تحتوي أكبر وحدات معالجة الرسومات على 4,000 نواة تقريبًا. من ناحية أخرى، تستخدم وحدات TPU الحد الأدنى من الأجهزة لوحدات الحوسبة في وحدة MXU: ما مِن شيء آخر سوى bfloat16 x bfloat16 => float32 وحدات تجميع الضرب. وهي صغيرة للغاية لدرجة أنّ وحدة معالجة الموتّرات يمكنها تنفيذ 16 كيلوبايت في وحدة MXU128 × 128 بكسل ومعالجة عملية ضرب المصفوفة هذه دفعة واحدة.

f1b283fc45966717.gif

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

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

وحدة معالجة الموتّرات في السحابة الإلكترونية

عند طلب "Cloud TPU v2" واحدًا على Google Cloud Platform، ستحصل على جهاز افتراضي (VM) يحتوي على لوحة TPU مرفقة بمنفذ PCI. تحتوي لوحة TPU على أربع شرائح TPU ثنائية النواة. يتميز كل نواة من وحدات معالجة الموتّرات بوحدة معالجة المتجهات (VPU) وبحجم 128×128 MXU (وحدة ضرب MatriX). يتم عادةً توصيل "وحدة معالجة الموتّرات" في السحابة الإلكترونية من خلال الشبكة بالجهاز الافتراضي الذي طلبها. وبالتالي، تبدو الصورة الكاملة على النحو التالي:

dfce5522ed644ece.png

صورة توضيحية: جهاز افتراضي (VM) مزوّد بمسرِّع "Cloud TPU" متصل بالشبكة تتكون "وحدة معالجة الموتّرات في Cloud" نفسها من جهاز افتراضي مزوّد بلوحة TPU متصلة بمنفذ PCI وتحتوي على أربع شرائح TPU ثنائية النواة.

لوحات TPU

يتم ربط وحدات معالجة الموتّرات في مراكز بيانات Google بشبكة حوسبة عالية الأداء (HPC) يمكن أن تجعلها تظهر كمسرّع كبير جدًا. وتُطلق Google على هذه المجموعات اسم "الوحدات"، ويمكن أن تتضمّن ما يصل إلى 512 نواة من TPU v2 أو 2048 نواة من TPU v3.

2ec1e0d341e7fc34.jpeg

صورة توضيحية: لوحة TPU v3 لوحات TPU ورفوفها متصلة من خلال رابط HPC.

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

d97b9cc5d40fdb1d.gif

صورة توضيحية: مزامنة التدرجات أثناء التدريب باستخدام خوارزمية التقليل على مستوى شبكة HPC ثنائية الأبعاد (TPU) الخاصة بالطاقة الحلقية المتشابكة (TPU) من Google.

البرامج

تدريب كبير الحجم

الحجم المثالي للمجموعة في وحدات TPU هو 128 عنصر بيانات لكل نواة TPU، ولكن يمكن للأجهزة تحقيق استخدام جيد من 8 عناصر بيانات لكل نواة TPU. تذكَّر أنّ وحدة معالجة الموتّرات في السحابة الإلكترونية تضمّ 8 أنوية.

في هذا الدرس التطبيقي حول الرموز البرمجية، سنستخدم واجهة برمجة التطبيقات Keras API. في Keras، تكون الدُفعة التي تحدِّدها هي الحجم العمومي لوحدة معالجة الموتّرات بالكامل. سيتم تقسيم دفعاتك تلقائيًا إلى 8 دفعات وتشغيلها على الوحدات الثماني لوحدة معالجة النطاق الفائق (TPU).

da534407825f01e3.png

للحصول على نصائح إضافية بشأن الأداء، يمكنك الاطّلاع على دليل أداء TPU. بالنسبة إلى أحجام الدُفعات الكبيرة جدًا، قد يلزم توخي الحذر في بعض الطُرز، ويمكنك الاطّلاع على LARSOptimizer للحصول على مزيد من التفاصيل.

مزيد من المعلومات: XLA

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

edce61112cd57972.png

صورة توضيحية: للتشغيل على وحدة معالجة الموتّرات، تتم أولاً ترجمة الرسم البياني للاحتساب الذي حدّده برنامج Tensorflow إلى تمثيل مبرمج الجبر الخطي المسرّع XLA، ثم تجميعه في رمز XLA في رمز جهاز TPU.

استخدام وحدات معالجة الموتّرات في Keras

تتوفّر وحدات معالجة الموتّرات من خلال واجهة برمجة التطبيقات Keras اعتبارًا من الإصدار 2.1 من Tensorflow. يعمل دعم Keras على وحدات معالجة الموتّرات ومجموعات وحدات معالجة الموتّرات. في ما يلي مثال يعمل مع وحدات معالجة الموتّرات ووحدات معالجة الرسومات ووحدة المعالجة المركزية(CPU):

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

في مقتطف الرمز البرمجي هذا:

  • يعثر TPUClusterResolver().connect() على وحدة معالجة الموتّرات على الشبكة. وتعمل بدون معلَمات على معظم أنظمة Google Cloud (وظائف AI Platform وColloratory وKubeflow والأجهزة الافتراضية للتعلُّم المحسَّن التي تم إنشاؤها من خلال أداة "ctpu up"). وتعرف هذه الأنظمة مكان وحدة TPU بفضل متغيّر البيئة TPU_NAME. في حال إنشاء وحدة TPU يدويًا، يمكنك ضبط متغيّر البيئة TPU_NAME على الجهاز الظاهري الذي تستخدمه، أو استدعاء TPUClusterResolver باستخدام مَعلمات صريحة: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy هو الجزء الذي ينفِّذ التوزيع وخوارزمية مزامنة التدرج "الكامل" التي يطلقها.
  • يتم تطبيق الاستراتيجية من خلال نطاق. يجب تحديد النموذج ضمن نطاق الاستراتيجية().
  • تتوقّع الدالة tpu_model.fit عنصر tf.data.Dataset كمدخل لتدريب TPU.

المهام الشائعة لنقل بيانات وحدة معالجة الموتّرات

  • على الرغم من توفّر العديد من الطرق لتحميل البيانات في نموذج Tensorflow، يجب استخدام واجهة برمجة التطبيقات tf.data.Dataset مع وحدات TPU.
  • وحدات TPU سريعة جدًا، وغالبًا ما تصبح عملية نقل البيانات هي النقطة التي تبطئ الأداء عند تشغيلها. تتوفّر أدوات يمكنك استخدامها لرصد المؤثِّرات السلبية على البيانات ونصائح أخرى بشأن الأداء في دليل أداء TPU.
  • يتم التعامل مع الأرقام int8 أو int16 على أنّها int32. لا تشتمل وحدة معالجة الموتّرات على أجهزة صحيحة تعمل على أقل من 32 بت.
  • بعض عمليات Tensorflow غير متاحة. يمكنك الاطّلاع على القائمة هنا. الخبر السار هو أن هذا القيد لا ينطبق إلا على التعليمات البرمجية للتدريب، أي الانتقال للأمام والخلف من خلال نموذجك. سيظل بإمكانك استخدام جميع عمليات Tensorflow في مسار إدخال البيانات لأنّه سيتم تنفيذها على وحدة المعالجة المركزية.
  • لا يمكن استخدام tf.py_func مع وحدة معالجة الموتّرات.

4. تحميل البيانات

c0ecb860e4cad0a9.jpeg cc4781a7739c49ae.jpeg 81236b00f8bbf39e.jpeg 961e2228974076bb.jpeg 7517dc163bdffcd5.jpeg 96392df4767f566d.png

سوف نعمل على مجموعة بيانات لصور الزهور. والهدف هو تعلُّم تصنيفها إلى 5 أنواع من الزهور. يتم تحميل البيانات باستخدام واجهة برمجة تطبيقات tf.data.Dataset. أولاً، نعرّفك على واجهة برمجة التطبيقات

التدريب العملي

يُرجى فتح ورقة الملاحظات التالية وتنفيذ الخلايا (Shift-ENTER) واتّباع التعليمات أينما يظهر لك التصنيف "مطلوب العمل".

c3df49e90e5a654f.png Fun with tf.data.Dataset (playground).ipynb

معلومات إضافية

لمحة عن مجموعة بيانات "الزهور"

يتم تنظيم مجموعة البيانات في 5 مجلدات. يحتوي كل مجلد على زهور من نوع واحد. وهذه المجلدات تُسمى زهور دوار الشمس، وأقحوانه، والهندباء البرية، والتوليب، والورود. يتم استضافة البيانات في حزمة عامة على Google Cloud Storage. المقتطف:

gs://flowers-public/sunflowers/5139971615_434ff8ed8b_n.jpg
gs://flowers-public/daisy/8094774544_35465c1c64.jpg
gs://flowers-public/sunflowers/9309473873_9d62b9082e.jpg
gs://flowers-public/dandelion/19551343954_83bb52f310_m.jpg
gs://flowers-public/dandelion/14199664556_188b37e51e.jpg
gs://flowers-public/tulips/4290566894_c7f061583d_m.jpg
gs://flowers-public/roses/3065719996_c16ecd5551.jpg
gs://flowers-public/dandelion/8168031302_6e36f39d87.jpg
gs://flowers-public/sunflowers/9564240106_0577e919da_n.jpg
gs://flowers-public/daisy/14167543177_cd36b54ac6_n.jpg

ما سبب أهمية tf.data.Dataset؟

تقبل Keras وTensorflow مجموعات البيانات في جميع دوال التدريب والتقييم. بمجرد تحميل البيانات في مجموعة بيانات، توفر واجهة برمجة التطبيقات جميع الوظائف الشائعة المفيدة لبيانات تدريب الشبكة العصبية:

dataset = ... # load something (see below)
dataset = dataset.shuffle(1000) # shuffle the dataset with a buffer of 1000
dataset = dataset.cache() # cache the dataset in RAM or on disk
dataset = dataset.repeat() # repeat the dataset indefinitely
dataset = dataset.batch(128) # batch data elements together in batches of 128
AUTOTUNE = tf.data.AUTOTUNE
dataset = dataset.prefetch(AUTOTUNE) # prefetch next batch(es) while training

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

أساسيات tf.data.Dataset

تأتي البيانات عادةً في ملفات متعددة، وهنا الصور. يمكنك إنشاء مجموعة بيانات لأسماء الملفات عن طريق استدعاء:

filenames_dataset = tf.data.Dataset.list_files('gs://flowers-public/*/*.jpg')
# The parameter is a "glob" pattern that supports the * and ? wildcards.

يمكنك بعد ذلك "تعيين" دالة لكل اسم ملف سيتم عادةً تحميل الملف وفك ترميزه في بيانات فعلية في الذاكرة:

def decode_jpeg(filename):
  bits = tf.io.read_file(filename)
  image = tf.io.decode_jpeg(bits)
  return image

image_dataset = filenames_dataset.map(decode_jpeg)
# this is now a dataset of decoded images (uint8 RGB format)

للتكرار التحسيني في مجموعة بيانات:

for data in my_dataset:
  print(data)

مجموعات بيانات الصفوف

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

def decode_jpeg_and_label(filename):
  bits = tf.read_file(filename)
  image = tf.io.decode_jpeg(bits)
  label = ... # extract flower name from folder name
  return image, label

image_dataset = filenames_dataset.map(decode_jpeg_and_label)
# this is now a dataset of (image, label) pairs 

for image, label in dataset:
  print(image.numpy().shape, label.numpy())

الخاتمة:عملية تحميل الصور واحدة تلو الأخرى بطيئة.

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

الحلّ

ها هو دفتر الحل. يمكنك استخدامها إذا واجهت مشكلة.

c3df49e90e5a654f.png Fun with tf.data.Dataset (solution).ipynb

المواضيع التي تناولناها

  • 🤔 tf.data.Dataset.list_files
  • 🤔 tf.data.Dataset.map
  • 🤔 مجموعات بيانات من مجموعات القيم
  • 😀 تكرار مجموعات البيانات

يُرجى تخصيص بعض الوقت للاطّلاع على قائمة التحقّق هذه.

5- تحميل البيانات بسرعة

تتميز مسرِّعات الأجهزة لوحدة معالجة Tensor (TPU) التي سنستخدمها في هذا التمرين بالسرعة الكبيرة جدًا. وغالبًا ما يكون التحدي هو تزويدها بالبيانات بسرعة كافية لإبقائها مشغولة. يمكن لـ Google Cloud Storage (GCS) الحفاظ على معدل نقل بيانات مرتفع جدًا، ولكن كما هو الحال مع جميع أنظمة التخزين السحابي، يؤدي بدء الاتصال إلى بعض عمليات النقل في الشبكة ذهابًا وإيابًا. ولذلك، ليس من المثالي تخزين بياناتنا كآلاف من الملفات الفردية. سنقوم بتجميعها في عدد أقل من الملفات واستخدام قوة tf.data.Dataset للقراءة من ملفات متعددة بالتوازي.

القراءة

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

c3df49e90e5a654f.png Flower pictures to TFRecords.ipynb

تنسيق مثالي للبيانات لضمان سرعة معالجة البيانات في GCS

تنسيق ملف TFRecord

إنّ تنسيق الملف المفضّل لمنصة Tensorflow لتخزين البيانات هو تنسيق TFRecord المستند إلى protobuf. يمكنك أيضًا استخدام تنسيقات التسلسل الأخرى، ولكن يمكنك تحميل مجموعة بيانات من ملفات TFRecord مباشرةً عن طريق كتابة:

filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames)
dataset = dataset.map(...) # do the TFRecord decoding here - see below

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

AUTOTUNE = tf.data.AUTOTUNE
ignore_order = tf.data.Options()
ignore_order.experimental_deterministic = False

filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTOTUNE)
dataset = dataset.with_options(ignore_order)
dataset = dataset.map(...) # do the TFRecord decoding here - see below

ورقة الملاحظات الموجزة عن TFRecord

يمكن تخزين ثلاثة أنواع من البيانات في TFRecords: سلاسل بايت (قائمة بالبايت)، وعدد صحيح 64 بت، وعدد عائم 32 بت. يتم تخزينها دائمًا كقوائم، وسيكون عنصر البيانات المفرد قائمة بحجم 1. يمكنك استخدام الدوال المساعدة التالية لتخزين البيانات في TFRecords.

كتابة سلاسل البايت

# warning, the input is a list of byte strings, which are themselves lists of bytes
def _bytestring_feature(list_of_bytestrings):
  return tf.train.Feature(bytes_list=tf.train.BytesList(value=list_of_bytestrings))

كتابة الأعداد الصحيحة

def _int_feature(list_of_ints): # int64
  return tf.train.Feature(int64_list=tf.train.Int64List(value=list_of_ints))

كتابة الأعداد العشرية

def _float_feature(list_of_floats): # float32
  return tf.train.Feature(float_list=tf.train.FloatList(value=list_of_floats))

كتابة TFRecord باستخدام وسائل المساعدة المذكورة أعلاه

# input data in my_img_bytes, my_class, my_height, my_width, my_floats
with tf.python_io.TFRecordWriter(filename) as out_file:
  feature = {
    "image": _bytestring_feature([my_img_bytes]), # one image in the list
    "class": _int_feature([my_class]),            # one class in the list
    "size": _int_feature([my_height, my_width]),  # fixed length (2) list of ints
    "float_data": _float_feature(my_floats)       # variable length  list of floats
  }
  tf_record = tf.train.Example(features=tf.train.Features(feature=feature))
  out_file.write(tf_record.SerializeToString())

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

القراءة من TFRecords

def read_tfrecord(data):
  features = {
    # tf.string = byte string (not text string)
    "image": tf.io.FixedLenFeature([], tf.string), # shape [] means scalar, here, a single byte string
    "class": tf.io.FixedLenFeature([], tf.int64),  # shape [] means scalar, i.e. a single item
    "size": tf.io.FixedLenFeature([2], tf.int64),  # two integers
    "float_data": tf.io.VarLenFeature(tf.float32)  # a variable number of floats
  }

  # decode the TFRecord
  tf_record = tf.io.parse_single_example(data, features)

  # FixedLenFeature fields are now ready to use
  sz = tf_record['size']

  # Typical code for decoding compressed images
  image = tf.io.decode_jpeg(tf_record['image'], channels=3)

  # VarLenFeature fields require additional sparse.to_dense decoding
  float_data = tf.sparse.to_dense(tf_record['float_data'])

  return image, sz, float_data

# decoding a tf.data.TFRecordDataset
dataset = dataset.map(read_tfrecord)
# now a dataset of triplets (image, sz, float_data)

مقتطفات الرموز المفيدة:

قراءة عناصر البيانات الفردية

tf.io.FixedLenFeature([], tf.string)   # for one byte string
tf.io.FixedLenFeature([], tf.int64)    # for one int
tf.io.FixedLenFeature([], tf.float32)  # for one float

قراءة قوائم العناصر الثابتة الحجم

tf.io.FixedLenFeature([N], tf.string)   # list of N byte strings
tf.io.FixedLenFeature([N], tf.int64)    # list of N ints
tf.io.FixedLenFeature([N], tf.float32)  # list of N floats

قراءة عدد متغيّر لعناصر البيانات

tf.io.VarLenFeature(tf.string)   # list of byte strings
tf.io.VarLenFeature(tf.int64)    # list of ints
tf.io.VarLenFeature(tf.float32)  # list of floats

تُعرِض سمة VarLenFeature متجهًا متفرقًا، ويجب اتّخاذ خطوة إضافية بعد فك ترميز TFRecord:

dense_data = tf.sparse.to_dense(tf_record['my_var_len_feature'])

من الممكن أيضًا أن تكون هناك حقول اختيارية في TFRecords. إذا حدّدت قيمة تلقائية عند قراءة حقل، يتم عرض القيمة التلقائية بدلاً من خطأ في حال عدم توفّر الحقل.

tf.io.FixedLenFeature([], tf.int64, default_value=0) # this field is optional

المواضيع التي تناولناها

  • 🎉 تقسيم ملفات البيانات للوصول السريع من GCS
  • 😓 كيفية كتابة TFRecords (هل نسيت بناء الجملة بالفعل؟ لا بأس، يُرجى وضع إشارة مرجعية على هذه الصفحة كورقة معلومات مرجعية)
  • 🎉 جارٍ تحميل مجموعة بيانات من TFRecords باستخدام TFRecordDataset

يُرجى تخصيص بعض الوقت للاطّلاع على قائمة التحقّق هذه.

6- [معلومات] أساسيات مصنِّف الشبكات العصبية

باختصار

إذا كانت جميع المصطلحات الغامقة في الفقرة التالية معروفة لك بالفعل، يمكنك الانتقال إلى التمرين التالي. إذا كنت في بداية مسيرتك في التعلم المتعمق، فمرحبًا بك، ونرجو مواصلة القراءة.

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

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

الشبكة العصبونية الكثيفة

هذه هي أبسط شبكة عصبية لتصنيف الصور. وهو يتألّف من "الخلايا العصبية" المرتبة في طبقات. تعالج الطبقة الأولى بيانات الإدخال وتغذّي نواتجها في الطبقات الأخرى. يُطلق عليها اسم "كثيفة" لأن كل خلية عصبية متصلة بجميع الخلايا العصبية في الطبقة السابقة.

c21bae6dade487bc.png

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

الخلايا العصبية وعمليات التفعيل وخوارزمية RELU

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

644f4213a4ee70e5.png

تُعرف دالة التفعيل الأكثر شيوعًا باسم RELU لوحدة خطية مصحَّحة. وهي دالة بسيطة جدًا كما هو موضّح في الرسم البياني أعلاه.

تفعيل Softmax

تنتهي الشبكة أعلاه بطبقة تتضمّن 5 خلايا عصبية لأنّنا نصنّف الزهور إلى 5 فئات (الورد والتوليب وعشبة الهندباء والأقحوان والدوار الشمسي). يتم تنشيط الخلايا العصبية في الطبقات المتوسطة باستخدام وظيفة تفعيل RELU الكلاسيكية. على الرغم من ذلك، في الطبقة الأخيرة، نريد حساب الأعداد بين 0 و1 التي تمثّل احتمالية أن تكون هذه الزهرة وردة وزهرة توليب وما إلى ذلك. لذلك، سنستخدم دالة تفعيل تُسمّى "softmax".

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

ef0d98c0952c262d.png d51252f75894479e.gif

الخسارة العابرة للإنتروبيا

والآن بعد أن تُنتج شبكتنا العصبية تنبؤات من الصور المدخلة، نحتاج إلى قياس مدى جودتها، أي المسافة بين ما تخبرنا به الشبكة والإجابات الصحيحة، والتي تُعرف غالبًا باسم "التصنيفات". تذكر أن لدينا التسميات الصحيحة لجميع الصور في مجموعة البيانات.

وتناسب أي مسافة، ولكن بالنسبة إلى مشاكل التصنيف، تكون "المسافة بين القصور بين الإنتروبيا" هي الأكثر فعالية. سنسمي هذا دالة الخطأ أو "loss":

7bdf8753d20617fb.png

انحدار التدرج

إنّ "تدريب" الشبكة العصبية يعني في الواقع استخدام صور وعلامات تدريب لتعديل الأوزان والانحيازات من أجل تقليل وظيفة خسارة التشويش المتداخل. إليك طريقة عملها.

إنّ قياس الاتّحاد التبادلي هو دالة للقيم المرجحة والانحيازات ووحدات البكسل في صورة التدريب وفئتها المعروفة.

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

خوارزمية انحدار التدرج2.png

التجميع السريع والزخم

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

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

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

52e824fe4716c4a0.png

رسم توضيحي: نقطة سرج يكون التدرّج 0 ولكنّه ليس الحدّ الأدنى في جميع الاتجاهات. (إسناد الصور Wikimedia: من Nicoguaro - عملك الخاص، CC BY 3.0)

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

مسرد المصطلحات

الدفعة أو الدفعة الصغيرة: يتم تنفيذ التدريب دائمًا على دفعات من بيانات التدريب والعلامات. ويساعد ذلك في تقارب الخوارزمية. عادةً ما يكون بُعد "الدُفعة" هو البعد الأول لمتسابقات البيانات. على سبيل المثال، يحتوي مصفوفة ذات الشكل [100، 192، 192، 3] على 100 صورة بحجم 192×192 بكسل مع ثلاث قيم لكل بكسل (أحمر وأخضر وأزرق).

خسارة الإنتروبيا: دالة خسارة خاصة غالبًا ما تُستخدم في المصنِّفات.

الطبقة الكثيفة: طبقة من الخلايا العصبية التي تتصل فيها كل خلية عصبية بجميع الخلايا العصبية في الطبقة السابقة.

الميزات: يُطلق على مدخلات الشبكة العصبية أحيانًا اسم "الميزات". يُطلق على فن تحديد أجزاء مجموعة البيانات (أو مجموعات الأجزاء) التي يجب تقديمها إلى شبكة عصبية للحصول على توقّعات جيدة اسم "هندسة الميزات".

labels: اسم آخر لكلمة "الفئات" أو الإجابات الصحيحة في مشكلة تصنيف خاضعة للإشراف

معدّل التعلّم: جزء من التدرج يتم من خلاله تعديل الأوزان والانحيازات في كل تكرار في حلقة التدريب.

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

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

الخلية العصبونية: تحسب المجموع المرجّح لمدخلاتها، وتضيف انحيازًا، ثمّ تغذي النتيجة من خلال إحدى وظائف التفعيل.

ترميز واحد فعال: يتم ترميز الفئة 3 من 5 كمتجه مكون من 5 عناصر، جميع الأصفار باستثناء الصف الثالث وهو 1.

relu: وحدة خطية مصحَّحة. وظيفة تفعيل شائعة للخلايا العصبية.

دالّة sigmoid: وهي دالة تنشيط أخرى كانت شائعة ولا تزال مفيدة في حالات خاصة.

softmax: دالة تنشيط خاصة تعمل على متجه، وتزيد من الفرق بين المكوّن الأكبر وجميع المكوّنات الأخرى، كما تسوي المتجه ليكون مجموع قيمه 1 حتى يمكن تفسيره على أنّه متجه من الاحتمالات. تُستخدم كخطوة أخيرة في المصنِّفات.

tensor: يشبه "AdSense" المصفوفة ولكن بعدد عشوائي من الأبعاد. إنّ المتجه هو مصفوفة لاتّجاه واحد. إنّ مصفوفة ثنائية الأبعاد هي مصفوفة. ومن ثم يمكنك الحصول على متسابقات ذات أبعاد 3 أو 4 أو 5 أو أكثر.

7- التعلّم القائم على نقل المهام

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

يمكننا أيضًا استخدام اختصار. تتوفّر شبكات عصبية تفافية مدرَّبة بالكامل للتنزيل. من الممكن قطع الطبقة الأخيرة، وهي رأس تصنيف softmax، واستبدالها بطبقةك الخاصة. تبقى جميع الأوزان والقيم المُعلَّمة كما هي، ولا تتم إعادة تدريب سوى طبقة softmax التي تضيفها. تُسمى هذه التقنية التعلم الانتقالي، وهي تعمل بشكل مدهش طالما أن مجموعة البيانات التي تم تدريب الشبكة العصبية عليها مسبقًا "قريبة بما يكفي" من شبكتك.

التدريب العملي

يُرجى فتح ورقة الملاحظات التالية وتنفيذ الخلايا (Shift-ENTER) واتّباع التعليمات أينما يظهر لك التصنيف "مطلوب العمل".

c3df49e90e5a654f.png Keras Flowers transfer learning (playground).ipynb

معلومات إضافية

من خلال التعلم الآلي، يمكنك الاستفادة من بُنى الشبكة العصبونية الالتفافية المتقدمة التي طوّرها كبار الباحثين ومن التدريب المسبق على مجموعة بيانات ضخمة من الصور. في حالتنا هذه، سننقل التعلم من شبكة مدرَّبة على ImageNet، وهي قاعدة بيانات للصور تحتوي على العديد من النباتات والمشاهد الخارجية، وهي قريبة بما يكفي من الزهور.

b8fc1efd2001f072.png

الصورة التوضيحية: استخدام شبكة عصبية تلافعية معقّدة سبق تدريبها كصندوق أسود، وإعادة تدريب قسم التصنيف فقط وهذا ما يُعرف بالتعرّف على المهام. سنرى لاحقًا كيف تعمل هذه الترتيبات المعقّدة للطبقات التفافية. في الوقت الحالي، هذه مشكلة شخص آخر.

التعرّف على نقل المهام في Keras

في Keras، يمكنك إنشاء مثيل لنموذج مدرَّب مسبقًا من مجموعة tf.keras.applications.*. على سبيل المثال، يعد MobileNet V2 بنية التفافية جيدة للغاية تظل في الحجم معقولاً. عند اختيار include_top=False، ستحصل على النموذج المدّرب مسبقًا بدون طبقة softmax النهائية حتى تتمكّن من إضافة طبقتك الخاصة:

pretrained_model = tf.keras.applications.MobileNetV2(input_shape=[*IMAGE_SIZE, 3], include_top=False)
pretrained_model.trainable = False

model = tf.keras.Sequential([
    pretrained_model,
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(5, activation='softmax')
])

ويجب أيضًا الحرص على ضبط الإعدادات pretrained_model.trainable = False. ويؤدي ذلك إلى تجميد الأوزان والانحيازات للنموذج المدّرب مسبقًا حتى تتمكّن من تدريب طبقة softmax فقط. عادة ما يتضمن ذلك ترجيحات قليلة نسبيًا ويمكن القيام به بسرعة ودون الحاجة إلى مجموعة بيانات كبيرة جدًا. ومع ذلك، إذا كان لديك الكثير من البيانات، يمكن أن تعمل نماذج التعلُّم في نقل البيانات بشكل أفضل باستخدام "pretrained_model.trainable = True". تقدّم الأوزان المدربة مسبقًا قيمًا أولية ممتازة، ويمكن تعديلها من خلال التدريب لتلائم مشكلتك بشكل أفضل.

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

من المفترض أن تحصل على دقة تقارب %75 باستخدام هذا النهج.

الحلّ

ها هو دفتر الحل. يمكنك استخدامها إذا واجهت مشكلة.

c3df49e90e5a654f.png Keras Flowers transfer learning (solution).ipynb

المواضيع التي تناولناها

  • 🤔 كيفية كتابة مصنّف في Keras
  • 🤓 تم ضبطه باستخدام طبقة softmax الأخيرة وفقدان entropi
  • 😈 التعلّم القائم على نقل المهام
  • 🤔 تدريب النموذج الأول
  • 🧐 بعد فقدانها ودقتها أثناء التدريب

يُرجى تخصيص بعض الوقت للاطّلاع على قائمة التحقّق هذه.

8. [INFO] الشبكات العصبية الالتفافية

الملخّص

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

convolutional.gif

صورة توضيحية: فلترة صورة باستخدام فلترَين متتاليين مكوّنَين من 4x4x3=48 وزنًا قابلاً للتعلم لكل منهما

في ما يلي شكل شبكة عصبية تفافية بسيطة في Keras:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

688858c21e3beff2.png

الشبكات العصبية الالتفافية 101

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

ومع ذلك، لن يكون 48 ترجيحًا كافيًا. لإضافة المزيد من درجات الحرية، نكرر العملية نفسها باستخدام مجموعة جديدة من الأوزان. وينتج عن ذلك مجموعة جديدة من مخرجات الفلاتر. لنسميها "قناة" المخرجات بالتشابه مع قنوات R وG وB في صورة الإدخال.

Screen Shot 2016-07-29 at 16.02.37.png

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

d1b557707bcd1cb9.png

رسم توضيحي: تحوّل شبكة عصبية تفافية "مكعبات" البيانات إلى "مكعبات" أخرى من البيانات.

عمليات التفاف ثابتة وأقصى حدّ للتجميع

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

  • التفاف موسّع: فلتر يتم تمريره كما هو موضح أعلاه ولكن بخطوة >1
  • الحد الأقصى لتجميع: نافذة منزلقة تقوم بتطبيق عملية MAX (عادةً على التصحيحات 2×2، ويتكرر كل 2 بكسل)

2b2d4263bb8470b.gif

صورة توضيحية: يؤدي تحريك نافذة الحوسبة بمقدار 3 بكسل إلى الحصول على قيم إخراج أقل. إنّ عمليات الدمج المُعدَّلة أو تجميع الحد الأقصى (الحد الأقصى في نافذة 2×2 تنزلق بخطوة 2) هي طريقة لتصغير مكعب البيانات في السمات الأفقية.

المُصنِّف التدرّبي

وأخيرًا، نرفق رأس تصنيف بتسوية مكعب البيانات الأخير وإمداده بطبقة كثيفة منشَّطة بواسطة softmax. يمكن أن يبدو المصنِّف التدرّبي النموذجي على النحو التالي:

4a61aaffb6cba3d1.png

رسم توضيحي: مصنّف صور يستخدم طبقات تحويلية وطبقات softmax يتم استخدام فلاتر 3×3 و1×1. تأخذ طبقات "التصفية القصوى" الحد الأقصى من مجموعات نقاط البيانات 2×2. يتم تنفيذ قسم التصنيف باستخدام طبقة كثيفة مع تنشيط softmax.

في Keras

يمكن كتابة مكدس الالتفاف الموضح أعلاه بلغة Keras على النحو التالي:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

9. شبكة الالتفاف المخصّصة

التدريب العملي

لننشئ شبكة عصبية تعامُلية ونُدرِبها من البداية. سيتيح لنا استخدام وحدة معالجة TPU إجراء عمليات تكرار سريعة جدًا. يُرجى فتح دفتر البيانات التالي وتنفيذ الخلايا (Shift-ENTER) واتّباع التعليمات كلما ظهر لك تصنيف "مطلوب إجراء".

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

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

معلومات إضافية

كم عدد الطبقات، ما حجم الطبقات؟

يعد تحديد أحجام الطبقات فنًا أكثر من كونه علمًا. عليك أن تجد التوازن الصحيح بين وجود معلمات قليلة جدًا والكثير جدًا من المعلمات (النسب والتحيزات). مع عدد قليل جدًا من التقديرات، لا يمكن للشبكة العصبية تمثيل تعقيد أشكال الزهور. وإذا كان عدد الصور كبيرًا جدًا، قد يكون الجهاز عرضةً "للتأقلم المفرط"، أي التخصص في الصور التدريبية وعدم التمكّن من التعميم. مع وجود الكثير من المعاملات، سيكون تدريب النموذج بطيئًا أيضًا. في Keras، تعرض الدالة model.summary() بنية النموذج وعدد المَعلمات:

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 192, 192, 16)      448       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 192, 192, 30)      4350      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 96, 96, 30)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 96, 96, 60)        16260     
_________________________________________________________________
 ... 
_________________________________________________________________
global_average_pooling2d (Gl (None, 130)               0         
_________________________________________________________________
dense (Dense)                (None, 90)                11790     
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 455       
=================================================================
Total params: 300,033
Trainable params: 300,033
Non-trainable params: 0
_________________________________________________________________

بعض النصائح:

  • وجود طبقات متعددة هو ما يجعل الشبكات العصبية "العميقة" فعالة. بالنسبة لمشكلة التعرف على الزهور البسيطة هذه، تكون 5 إلى 10 طبقات منطقية.
  • استخدِم فلاتر صغيرة. عادةً ما تكون فلاتر 3x3 جيدة في كل مكان.
  • يمكن استخدام فلاتر 1×1 أيضًا ومنخفضة التكلفة. ولا يتمّ "فلترة" أيّ محتوى، بل يتمّ احتساب مجموعات قنوات خطية. استبدِلها بفلاتر حقيقية. (يمكنك الاطلاع على مزيد من المعلومات حول "عمليات الالتفاف 1×1" في القسم التالي).
  • بالنسبة لمشكلة تصنيف مثل هذه، يتم تقليل العينة بشكل متكرر باستخدام الحد الأقصى لطبقات التجميع (أو الالتفافات بخطوة >1). لا يهمّك مكان الزهرة، بل ما يهمّك هو أنّها وردة أو زهرة قشطة، لذا ليس من المهم فقدان معلومات x وy، كما أنّ فلترة المناطق الأصغر حجمًا أرخص.
  • يصبح عدد الفلاتر عادةً مشابهًا لعدد الفئات في نهاية الشبكة (لماذا؟ اطّلِع على خدعة "التجميع المتوسط الشامل" أدناه). في حال التصنيف إلى مئات الفئات، يمكنك زيادة عدد الفلاتر تدريجيًا في الطبقات المتتالية. بالنسبة إلى مجموعة بيانات الزهور التي تتضمّن 5 فئات، لن تكون الفلترة باستخدام 5 فلاتر فقط كافية. يمكنك استخدام عدد الفلاتر نفسه في معظم الطبقات، على سبيل المثال 32 فلترًا، ثم خفضه في النهاية.
  • إنّ الطبقات الكثيفة الأخيرة باهظة التكلفة. ويمكن أن يكون لها أوزان أكثر من جميع الطبقات التجميعية مجتمعة. على سبيل المثال، حتى مع الحصول على نتيجة معقولة جدًا من مكعب البيانات الأخير الذي يتضمّن 24 نقطة بيانات بحجم 24x24x10، ستتكلف طبقة كثيفة تتألف من 100 خلية عصبية 24x24x10x100=576,000 وزنًا. لذا، ننصحك بالتأنّي في اختيار النموذج أو تجربة التجميع المتوسط الشامل (راجِع المعلومات أدناه).

التجميع المتوسط العام

بدلاً من استخدام طبقة كثيفة باهظة التكلفة في نهاية شبكة عصبية تجميعية، يمكنك تقسيم "مكعب" البيانات الواردة إلى عدد الأجزاء التي تتضمّنها فئات البيانات، واحتساب متوسط قيمها وإدخالها من خلال دالة تنشيط softmax. لا تتطلّب طريقة إنشاء قسم التصنيف أيّ أوزان. في Keras، تكون البنية tf.keras.layers.GlobalAveragePooling2D()..

93240029f59df7c2.png

الحلّ

ها هو دفتر الحل. يمكنك استخدامها إذا واجهت مشكلة.

c3df49e90e5a654f.png Keras_Flowers_TPU (solution).ipynb

المواضيع التي تناولناها

  • 🤔 لقد جرّبتُ استخدام الطبقات التفافية.
  • 🤓 لقد جرّبنا تجميع الحد الأقصى والخطوات و"تجميع المتوسط العام" وما إلى ذلك.
  • 👈 تم تكرارنا على نموذج حقيقي سريع في وحدة معالجة الموتّرات

يرجى تخصيص بعض الوقت لاستعراض قائمة التحقق هذه في ذهنك.

10. [معلومات] التصاميم الحديثة للشبكات التجميعية

الملخّص

7968830b57b708c0.png

الرسم التوضيحي: "وحدة" تحويلية ما هو أفضل خيار في هذه المرحلة؟ طبقة الحد الأقصى للتجميع المتبوع بطبقة التفافية 1×1 أم تركيبة مختلفة من الطبقات؟ جرِّب كلّها، واربط النتائج واترك الشبكة تتّخذ القرار. على يسار الصفحة: بنية " inception" التوليدية باستخدام هذه الوحدات

في Keras، لإنشاء نماذج يمكن أن يتفرع فيها تدفق البيانات، عليك استخدام أسلوب النموذج "الوظيفي". يُرجى الاطّلاع على المثال أدناه:

l = tf.keras.layers # syntax shortcut

y = l.Conv2D(filters=32, kernel_size=3, padding='same',
             activation='relu', input_shape=[192, 192, 3])(x) # x=input image

# module start: branch out
y1 = l.Conv2D(filters=32, kernel_size=1, padding='same', activation='relu')(y)
y3 = l.Conv2D(filters=32, kernel_size=3, padding='same', activation='relu')(y)
y = l.concatenate([y1, y3]) # output now has 64 channels
# module end: concatenation

# many more layers ...

# Create the model by specifying the input and output tensors.
# Keras layers track their connections automatically so that's all that's needed.
z = l.Dense(5, activation='softmax')(y)
model = tf.keras.Model(x, z)

688858c21e3beff2.png

حيل أخرى رخيصة

فلاتر صغيرة بحجم 3×3

40a7b15fb7dbe75c.png

في هذا الرسم التوضيحي، تشاهد نتيجة فلترَين متتاليَين 3x3. حاوِل تتبُّع نقاط البيانات التي ساهمت في النتيجة: يحسب هذان الفلاتر المتتاليان بحجم 3×3 بعض التركيبات لمنطقة 5×5. إنها ليست نفس التركيبة التي ستحسبها فلتر 5×5 ولكن الأمر يستحق التجربة لأن فلترين متتاليين 3×3 أرخص من فلتر 5×5 واحد.

عمليات الالتفاف 1×1؟

fd7cac16f8ecb423.png

من الناحية الحسابية، فإنّ تصفية "1x1" هي عملية ضرب بمتغيّر ثابت، وهي ليست مفهومًا مفيدًا جدًا. في الشبكات العصبية التوليدية، يُرجى تذكُّر أنّه يتم تطبيق الفلتر على مكعب بيانات، وليس على صورة ثنائية الأبعاد فقط. وبالتالي، يحسب الفلتر "1×1" المجموع المرجّح لعمود 1×1 من البيانات (راجع الرسم التوضيحي) وعندما تمرِّره على مستوى البيانات، ستحصل على مجموعة خطية من قنوات الإدخال. هذا مفيد حقًا. إذا كنت تنظر إلى القنوات على أنها نتائج عمليات تصفية فردية، على سبيل المثال فلتر لـ "آذان مدببة"، وآخر لـ "صوت خفيف" وثالث لـ "عين الحشرة"، فإن الطبقة الالتفافية "1×1" ستحسب مجموعات خطية متعددة محتملة من هذه الميزات، والتي قد تكون مفيدة عند البحث عن "قطة". علاوة على ذلك، تستخدم طبقات 1×1 أوزان أقل.

11. Squeezenet

تم عرض طريقة بسيطة لتجميع هذه الأفكار في ورقة "Squeezenet". يقترح المؤلفون تصميم وحدة تحويلية بسيطة جدًا، باستخدام طبقات تحويلية 1×1 و3×3 فقط.

1730ac375379269b.png

صورة توضيحية: بنية squeezenet تستند إلى "وحدات النار" يتم التبديل بين طبقة 1×1 والتي "تضغط" على البيانات الواردة في البُعد الرأسي متبوعًا بطبقتين التفافيتين متوازيتين 1×1 و3×3 تعملان على "توسيع" عمق البيانات مرة أخرى.

التدريب العملي

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

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

معلومات إضافية

سيكون من المفيد في هذا التمرين تحديد دالة مساعدة لوحدة squeezenet:

def fire(x, squeeze, expand):
  y = l.Conv2D(filters=squeeze, kernel_size=1, padding='same', activation='relu')(x)
  y1 = l.Conv2D(filters=expand//2, kernel_size=1, padding='same', activation='relu')(y)
  y3 = l.Conv2D(filters=expand//2, kernel_size=3, padding='same', activation='relu')(y)
  return tf.keras.layers.concatenate([y1, y3])

# this is to make it behave similarly to other Keras layers
def fire_module(squeeze, expand):
  return lambda x: fire(x, squeeze, expand)

# usage:
x = l.Input(shape=[192, 192, 3])
y = fire_module(squeeze=24, expand=48)(x) # typically, squeeze is less than expand
y = fire_module(squeeze=32, expand=64)(y)
...
model = tf.keras.Model(x, y)

الهدف هذه المرة هو الوصول إلى دقة 80٪.

الإجراءات المقترَحة

ابدأ بطبقة التفافية واحدة، ثم اتّبِع الخطوات بـ "fire_modules"، بالتناوب مع MaxPooling2D(pool_size=2) طبقات. يمكنك تجربة ما بين طبقتَين و4 طبقات من طبقات "تجميع الحد الأقصى" في الشبكة، بالإضافة إلى وحدة واحدة أو اثنتين أو ثلاث وحدات متتالية لإطلاق النيران بين طبقات "تجميع الحد الأقصى".

في الوحدات الإعلانية، يجب أن تكون مَعلمة "الضغط" أصغر من مَعلمة "expand". هذه المعاملات هي في الواقع أعداد من الفلاتر. تتراوح عادةً من 8 إلى 196. يمكنك تجربة التصاميم التي يزداد فيها عدد الفلاتر تدريجيًا في الشبكة، أو التصاميم البسيطة التي تتضمّن عدد الفلاتر نفسه في جميع وحدات الإطلاق.

يُرجى الاطّلاع على المثال أدناه:

x = tf.keras.layers.Input(shape=[*IMAGE_SIZE, 3]) # input is 192x192 pixels RGB

y = tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu')(x)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.GlobalAveragePooling2D()(y)
y = tf.keras.layers.Dense(5, activation='softmax')(y)

model = tf.keras.Model(x, y)

في هذه المرحلة، قد تلاحظ أن تجاربك لا تسير على ما يرام وأن هدف الدقة البالغة 80٪ يبدو بعيد المنال. حان الوقت للتعرّف على بعض الأفكار الجديدة بتكلفة منخفضة.

التسوية المجمّعة

سيساعدك "متوسّط الدالة على مجموعة" في حلّ مشاكل التقارب التي تواجهها. سنقدّم شرحًا تفصيليًا حول هذه التقنية في ورشة العمل القادمة. وفي الوقت الحالي، يُرجى استخدامه كصندوق مساعد "سحري" من خلال إضافة هذا الخط بعد كل طبقة التفافية في شبكتك، بما في ذلك الطبقات داخل دالة fire_module:

y = tf.keras.layers.BatchNormalization(momentum=0.9)(y)
# please adapt the input and output "y"s to whatever is appropriate in your context

يجب خفض قيمة مَعلمة الزخم من قيمتها التلقائية 0.99 إلى 0.9 لأنّ مجموعة البيانات صغيرة. لا داعي للقلق بشأن هذه التفاصيل الآن.

زيادة البيانات

سوف تحصل على نقاط مئوية أخرى من خلال زيادة البيانات عن طريق عمليات تحويل سهلة مثل تقلب اليسار واليمين لتغييرات التشبع:

4ed2958e09b487ca.png

ad795b70334e0d6b.png

من السهل جدًا إجراء ذلك في Tensorflow باستخدام واجهة برمجة التطبيقات tf.data.Dataset API. حدِّد دالة تحويل جديدة لبياناتك:

def data_augment(image, label):
    image = tf.image.random_flip_left_right(image)
    image = tf.image.random_saturation(image, lower=0, upper=2)
    return image, label

بعد ذلك، استخدمها في تحويل البيانات النهائي (مجموعات بيانات التدريب والتحقق من صحة الخلية، الدالة "get_batched_dataset"):

dataset = dataset.repeat() # existing line
# insert this
if augment_data:
  dataset = dataset.map(data_augment, num_parallel_calls=AUTO)
dataset = dataset.shuffle(2048) # existing line

لا تنسَ جعل ميزة "تعزيز البيانات" اختيارية وإضافة الرمز البرمجي اللازم للتأكّد من تعزيز مجموعة بيانات التدريب فقط. لا داعي لإضافة المزيد من البيانات إلى مجموعة التحقّق.

يجب أن تكون الدقة بنسبة 80% في الـ 35 حقبة قريبة الآن.

الحلّ

ها هو دفتر الحل. يمكنك استخدامها إذا واجهت مشكلة.

c3df49e90e5a654f.png Keras_Flowers_TPU_squeezenet.ipynb

المواضيع التي تناولناها

  • 🤔 نماذج "الأسلوب الوظيفي" في Keras
  • 🤓 بنية Squeezenet
  • 🤓 زيادة البيانات باستخدام tf.data.datset

يُرجى تخصيص بعض الوقت لمراجعة قائمة التحقّق هذه.

12. Xception المحسَّن

عمليات التفاف يمكن فصلها

ازدادت مؤخرًا شعبية طريقة مختلفة لتنفيذ الطبقات التجميعية، وهي عمليات التجميع القابلة للفصل حسب العمق. أعلم أنّه اسم طويل، ولكنّ المفهوم بسيط جدًا. ويتم تنفيذها في Tensorflow وKeras على النحو التالي: tf.keras.layers.SeparableConv2D.

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

615720b803bf8dda.gif

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

يتم استخدام الالتفاف القابل للفصل في أحدث بُنى الشبكات الالتفافية: MobileNetV2، وXception، وEfficientNet. بالمناسبة، إنّ MobileNetV2 هو ما استخدمته سابقًا لنقل التعلُّم.

وهي أرخص من عمليات الالتفاف المنتظمة واكتشفت فعاليتها في الممارسة العملية. في ما يلي عدد الوزن للمثال الموضّح أعلاه:

الطبقة الالتفافية: 4 × 4 × 3 × 5 = 240

الطبقة الالتفافية القابلة للفصل: 4 × 4 × 3 + 3 × 5 = 48 + 15 = 63

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

التدريب العملي

أعِد تشغيل البرنامج من دفتر ملاحظات "التعلم التحويلي"، ولكن اختَر Xception هذه المرة كنموذج مدرَّب مسبقًا. تستخدم Xception عمليات التفاف قابلة للفصل فقط. اترك جميع الأوزان قابلة للتدريب. سنُجري تحسينًا على الأوزان المدربة مسبقًا في بياناتنا بدلاً من استخدام الطبقات المدربة مسبقًا على هذا النحو.

c3df49e90e5a654f.png Keras Flowers transfer learning (playground).ipynb

الهدف: دقة تزيد عن %95 (نعم، هذا ممكن حقًا)

بما أنّ هذا هو التمرين النهائي، يتطلب بعض العمل الإضافي على الرموز البرمجية وعلم البيانات.

معلومات إضافية عن الضبط

يتوفّر Xception في النماذج العادية المدربة مسبقًا في tf.keras.application.* لا تنس ترك جميع الأوزان قابلة للتدريب هذه المرة.

pretrained_model = tf.keras.applications.Xception(input_shape=[*IMAGE_SIZE, 3],
                                                  include_top=False)
pretrained_model.trainable = True

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

9b1af213b2b36d47.png

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

في Keras، يتم تحديد معدل التعلم من خلال استدعاء يمكنك من خلاله حساب معدل التعلم المناسب لكل حقبة. سيُجري Keras معدّل التعلّم الصحيح إلى المحسَّن لكل حقبة.

def lr_fn(epoch):
  lr = ...
  return lr

lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_fn, verbose=True)

model.fit(..., callbacks=[lr_callback])

الحلّ

ها هو دفتر الحل. يمكنك استخدامها إذا واجهت مشكلة.

c3df49e90e5a654f.png 07_Keras_Flowers_TPU_xception_fine_tuned_best.ipynb

المواضيع التي تناولناها

  • ويحتوي على ميزة الالتفاف القابل للفصل بين العمق
  • 🤓 الجداول الزمنية لمعدّل التعلّم
  • 😈 تحسين نموذج مدرَّب مسبقًا

يُرجى تخصيص بعض الوقت لمراجعة قائمة التحقّق هذه.

13. تهانينا!

لقد أنشأت أول شبكة عصبية تلافعية حديثة ودربتها على دقة تزيد عن% 90، وكرّرت عمليات التدريب المتتالية في دقائق معدودة بفضل وحدات TPU.

استخدام وحدات معالجة الموتّرات في التطبيقات

تتوفّر وحدات معالجة الموتّرات ووحدات معالجة الرسومات في Vertex AI من Google Cloud:

أخيرًا، يسرّنا تلقّي ملاحظاتك. يُرجى إخبارنا إذا لاحظت أي محتوى غير صحيح في هذا التمرين المعملي أو إذا كنت تعتقد أنه ينبغي تحسينه. يمكن تقديم الملاحظات من خلال مشاكل GitHub [ رابط الملاحظات].

HR.png

معرّف مارتن غورنر صغير.jpg
المؤلف: "مارتن غورنر"
Twitter: @martin_gorner