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

أهداف الدورة التعليمية
- لاستخدام Keras ووحدات معالجة الموتّرات (TPU) لإنشاء نماذجك المخصّصة بشكل أسرع
- لاستخدام واجهة برمجة التطبيقات tf.data.Dataset وتنسيق TFRecord لتحميل بيانات التدريب بكفاءة
- للتغشيش 😈، يمكنك استخدام التعلّم القائم على نقل المهام بدلاً من إنشاء نماذجك الخاصة.
- لاستخدام أنماط النماذج التسلسلية والوظيفية في Keras
- لإنشاء مصنّف Keras الخاص بك باستخدام طبقة softmax وفقدان الإنتروبيا المتقاطعة
- لضبط النموذج بدقة من خلال اختيار جيد للطبقات الالتفافية
- استكشاف أفكار حديثة حول بنية الشبكات العصبية الالتفافية، مثل الوحدات وتجميع المتوسط العام، وما إلى ذلك
- لإنشاء شبكة عصبية التفافية حديثة بسيطة باستخدام بنية Squeezenet
الملاحظات
إذا لاحظت أي خطأ في هذا الدرس العملي، يُرجى إخبارنا بذلك. يمكن تقديم الملاحظات من خلال مشاكل GitHub [ رابط الملاحظات].
2. البدء السريع في Google Colaboratory
يستخدم هذا التمرين المعملي Google Collaboratory ولا يتطلّب أي إعداد من جانبك. يمكنك تشغيلها من جهاز Chromebook. يُرجى فتح الملف أدناه وتنفيذ الخلايا للتعرّف على دفاتر ملاحظات Colab.
اختيار واجهة خلفية لوحدة معالجة Tensor

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

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

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

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

يمكن أن يصل Colab إلى حِزم Google Cloud Storage الخاصة بك إذا تم إثبات هويتك باستخدام حساب معتمَد. سيؤدي مقتطف الرمز البرمجي أعلاه إلى بدء عملية مصادقة.
3- [INFO] ما هي وحدات معالجة الموتّرات (TPU)؟
باختصار

في ما يلي الرمز البرمجي لتدريب نموذج على وحدة معالجة الموتّرات في Keras (والرجوع إلى وحدة معالجة الرسومات أو وحدة المعالجة المركزية في حال عدم توفّر وحدة معالجة الموتّرات):
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=...)
سنستخدم وحدات معالجة Tensor اليوم لإنشاء مصنّف للزهور وتحسينه بسرعات تفاعلية (دقائق لكل عملية تدريب).

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

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

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

عادةً ما يكون تدريب الشبكة العصبونية مقاومًا للتشويش الناتج عن دقة الأرقام العشرية المتغيرة المنخفضة. في بعض الحالات، تساعد الضوضاء المحسِّن في التوافق. يتم عادةً استخدام دقة النقطة العائمة ذات 16 بت لتسريع العمليات الحسابية، ولكن نطاقات تنسيقات float16 وfloat32 مختلفة تمامًا. يؤدي تقليل الدقة من float32 إلى float16 عادةً إلى حدوث تجاوزات ونقص في التدفق. تتوفّر حلول، ولكن عادةً ما يكون من الضروري إجراء عمل إضافي لجعل float16 تعمل.
لهذا السبب، قدّمت Google تنسيق bfloat16 في وحدات TPU. bfloat16 هو float32 مختصر يتضمّن أجزاء الأسّ والنطاق نفسها تمامًا كما في float32. بالإضافة إلى ذلك، بما أنّ وحدات TPU تحسب عمليات ضرب المصفوفات بدقة مختلطة مع إدخالات 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]
على وحدة معالجة الرسومات، يمكن برمجة هذا المنتج النقطي في "نواة" وحدة معالجة الرسومات ثم تنفيذه على أكبر عدد ممكن من "النوى" المتاحة بالتوازي لمحاولة حساب كل قيمة من المصفوفة الناتجة في وقت واحد. إذا كانت المصفوفة الناتجة كبيرة بحجم 128x128، سيتطلّب ذلك توفّر 128x128=16 ألف "نواة"، وهو أمر غير ممكن عادةً. تحتوي أكبر وحدات معالجة الرسومات على حوالي 4000 نواة. من ناحية أخرى، تستخدم وحدة معالجة الموتّرات الحد الأدنى من الأجهزة لوحدات الحوسبة في MXU: bfloat16 x bfloat16 => float32 وحدات ضرب وتجميع فقط، لا شيء آخر. وهي صغيرة جدًا لدرجة أنّ وحدة معالجة الموتّرات يمكنها تنفيذ 16 ألفًا منها في وحدة MXU بحجم 128x128 ومعالجة عملية ضرب المصفوفات هذه دفعة واحدة.

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

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

صورة توضيحية: مجموعة TPU v3. لوحات ورفوف وحدات المعالجة الموتّرة (TPU) المتصلة من خلال شبكة ربط بينية للحوسبة عالية الأداء
أثناء التدريب، يتم تبادل التدرجات بين نوى TPU باستخدام خوارزمية all-reduce ( شرح جيد لخوارزمية all-reduce هنا). يمكن للنموذج الذي يتم تدريبه الاستفادة من الأجهزة من خلال التدريب على أحجام دفعات كبيرة.

صورة توضيحية: مزامنة التدرجات أثناء التدريب باستخدام خوارزمية all-reduce على شبكة الحوسبة العالية الأداء (HPC) ذات الشبكة الحلقية الثنائية الأبعاد في وحدات TPU من Google
البرنامج
التدريب باستخدام حجم الدفعة الكبير
حجم الدفعة المثالي لوحدات TPU هو 128 عنصر بيانات لكل نواة TPU، ولكن يمكن أن تُظهر الأجهزة بالفعل استخدامًا جيدًا من 8 عناصر بيانات لكل نواة TPU. تذكَّر أنّ وحدة Cloud TPU واحدة تتضمّن 8 نوى.
في هذا الدرس العملي، سنستخدم Keras API. في Keras، الدفعة التي تحدّدها هي حجم الدفعة العام لوحدة TPU بأكملها. سيتم تلقائيًا تقسيم الدفعات إلى 8 أجزاء وتشغيلها على 8 نوى في وحدة معالجة Tensor.

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

توضيح: لتشغيل الرسم البياني للحساب على وحدة معالجة المؤثّرات، يتم أولاً تحويله إلى تمثيل XLA (مترجم الجبر الخطي المسرَّع)، ثم يتم تجميعه بواسطة XLA في رمز آلة وحدة معالجة المؤثّرات.
استخدام وحدات معالجة الموتّرات في Keras
يمكن استخدام وحدات TPU من خلال Keras API بدءًا من الإصدار 2.1 من TensorFlow. تعمل ميزة التوافق مع Keras على وحدات معالجة الموتّرات (TPU) ومجموعات وحدات معالجة الموتّرات (TPU). في ما يلي مثال يعمل على وحدة معالجة الموتّرات ووحدات معالجة الرسومات ووحدة المعالجة المركزية:
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 وColaboratory وKubeflow وDeep Learning VMs التي تم إنشاؤها من خلال الأداة المساعدة "ctpu up"). تعرف هذه الأنظمة مكان وحدة معالجة الموتّرات بفضل متغيّر البيئة TPU_NAME. إذا أنشأت وحدة معالجة الموتّرات يدويًا، يمكنك إما ضبط متغير البيئة TPU_NAME على الجهاز الظاهري الذي تستخدمه منه، أو استدعاءTPUClusterResolverباستخدام مَعلمات صريحة:TPUClusterResolver(tp_uname, zone, project) TPUStrategyهو الجزء الذي ينفّذ التوزيع وخوارزمية مزامنة التدرّج "all-reduce".- يتم تطبيق الاستراتيجية من خلال نطاق. يجب تحديد النموذج ضمن نطاق الاستراتيجية().
- تتوقّع الدالة
tpu_model.fitعنصر tf.data.Dataset كإدخال للتدريب على وحدة معالجة الموتّرات (TPU).
مهام النقل الشائعة إلى TPU
- على الرغم من توفّر العديد من الطرق لتحميل البيانات في نموذج Tensorflow، إلا أنّه يجب استخدام واجهة برمجة التطبيقات
tf.data.Datasetمع وحدات TPU. - تتسم وحدات TPU بالسرعة العالية، وغالبًا ما يصبح استيعاب البيانات هو عنق الزجاجة عند تشغيلها. تتوفّر أدوات يمكنك استخدامها لرصد المشاكل التي تؤدي إلى مؤثِّر سلبي في البيانات ونصائح أخرى لتحسين الأداء في دليل أداء وحدة معالجة الموتّرات.
- يتم التعامل مع الأرقام من النوع int8 أو int16 على أنّها أرقام من النوع int32. لا تتضمّن وحدة معالجة الموتّرات وحدة أجهزة للأعداد الصحيحة تعمل على أقل من 32 بت.
- بعض عمليات Tensorflow غير متاحة. القائمة متاحة هنا. والخبر السارّ هو أنّ هذا القيد ينطبق فقط على رمز التدريب، أي التمرير الأمامي والخلفي عبر النموذج. سيظل بإمكانك استخدام جميع عمليات Tensorflow في مسار إدخال البيانات لأنّها سيتم تنفيذها على وحدة المعالجة المركزية.
tf.py_funcغير متوافق مع وحدة معالجة Tensor.
4. جارٍ تحميل البيانات

سنعمل على مجموعة بيانات لصور الزهور. والهدف هو تعلُّم تصنيفها إلى 5 أنواع من الزهور. يتم تحميل البيانات باستخدام واجهة برمجة التطبيقات tf.data.Dataset. أولاً، دعنا نتعرّف على واجهة برمجة التطبيقات.
التجربة العملية
يُرجى فتح دفتر الملاحظات التالي وتنفيذ الخلايا (Shift-ENTER) واتّباع التعليمات أينما ظهرت لك التصنيفات "مطلوب عمل".
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())
الخلاصة:تحميل الصور واحدة تلو الأخرى عملية بطيئة.
أثناء تكرار مجموعة البيانات هذه، ستلاحظ أنّه يمكنك تحميل صورة أو صورتَين في الثانية. هذا بطيء جدًا! يمكن لمسرّعات الأجهزة التي سنستخدمها في التدريب الحفاظ على هذا المعدّل عدة مرات. انتقِل إلى القسم التالي لمعرفة كيفية تحقيق ذلك.
Solution
إليك دفتر ملاحظات الحلّ. يمكنك استخدامها إذا واجهتك مشكلة.
Fun with tf.data.Dataset (solution).ipynb
المواضيع التي تناولناها
- 🤔 tf.data.Dataset.list_files
- 🤔 tf.data.Dataset.map
- 🤔 مجموعات بيانات الصفوف
- 😀 تكرار مجموعات البيانات
يُرجى تخصيص بعض الوقت لمراجعة قائمة التحقّق هذه في ذهنك.
5- تحميل البيانات بسرعة
إنّ مسرّعات الأجهزة "وحدة معالجة الموتّرات" (TPU) التي سنستخدمها في هذا الدرس التطبيقي سريعة جدًا. ويتمثل التحدي غالبًا في تزويدها بالبيانات بسرعة كافية لإبقائها مشغولة. يمكن أن يحافظ Google Cloud Storage (GCS) على معدل نقل بيانات مرتفع جدًا، ولكن كما هو الحال مع جميع أنظمة التخزين السحابي، يؤدي بدء الاتصال إلى تكلفة بعض عمليات الإرسال والاستلام على الشبكة. لذلك، لا يُعدّ تخزين بياناتنا على شكل آلاف الملفات الفردية خيارًا مثاليًا. سنجمّعها في عدد أقل من الملفات ونستخدم قوة tf.data.Dataset للقراءة من ملفات متعددة بالتوازي.
القراءة الكاملة
يمكنك العثور على الرمز الذي يحمّل ملفات الصور ويغيّر حجمها إلى حجم شائع ثم يخزّنها في 16 ملف TFRecord في دفتر الملاحظات التالي. يُرجى قراءته بسرعة. ليس من الضروري تنفيذها لأنّه سيتم توفير بيانات منسَّقة بشكل صحيح بتنسيق TFRecord لبقية الدرس العملي.
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'])
من الممكن أيضًا أن تتضمّن ملفات TFRecord حقولاً اختيارية. إذا حدّدت قيمة تلقائية عند قراءة حقل، سيتم عرض القيمة التلقائية بدلاً من رسالة خطأ في حال كان الحقل غير متوفّر.
tf.io.FixedLenFeature([], tf.int64, default_value=0) # this field is optional
المواضيع التي تناولناها
- 🤔 تقسيم ملفات البيانات للوصول إليها بسرعة من GCS
- 😓 كيفية كتابة TFRecords (هل نسيت البنية؟ لا بأس، يمكنك إضافة إشارة مرجعية إلى هذه الصفحة كمرجع سريع)
- 🤔 تحميل مجموعة بيانات من TFRecords باستخدام TFRecordDataset
يُرجى تخصيص بعض الوقت لمراجعة قائمة التحقّق هذه في ذهنك.
6. [INFO] الدليل الإرشادي للمصنّف المستند إلى الشبكة العصبونية
باختصار
إذا كنت تعرف جميع المصطلحات بالخط العريض في الفقرة التالية، يمكنك الانتقال إلى التمرين التالي. إذا كنت مبتدئًا في مجال التعلّم العميق، أهلاً بك، ويُرجى مواصلة القراءة.
بالنسبة إلى النماذج التي تم إنشاؤها كتسلسل من الطبقات، يوفّر Keras واجهة Sequential API. على سبيل المثال، يمكن كتابة مصنّف صور يستخدم ثلاث طبقات كثيفة في 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, ... )

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

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

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

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

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

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

صورة توضيحية: نقطة سرج يكون الانحدار 0 ولكنّه ليس الحد الأدنى في جميع الاتجاهات. (معلومات تحديد مصدر الصورة Wikimedia: By Nicoguaro - Own work, CC BY 3.0)
الحلّ هو إضافة بعض الزخم إلى خوارزمية التحسين حتى تتمكّن من تجاوز نقاط السرج بدون توقّف.
مسرد المصطلحات
الدُفعات أو الدُفعات الصغيرة: يتم التدريب دائمًا على دُفعات من بيانات التدريب والتصنيفات. يساعد ذلك الخوارزمية في التوافق. عادةً ما تكون سمة "الحزمة" هي السمة الأولى لموترات البيانات. على سبيل المثال، يحتوي متّجه متعدّد الأبعاد بالشكل [100, 192, 192, 3] على 100 صورة بحجم 192x192 بكسل مع ثلاث قيم لكل بكسل (النموذج اللوني أحمر أخضر أزرق).
فقدان الإنتروبيا المتقاطعة: دالة فقدان خاصة تُستخدم غالبًا في أدوات التصنيف.
الطبقة الكثيفة: هي طبقة من الخلايا العصبية حيث تكون كل خلية عصبية مرتبطة بجميع الخلايا العصبية في الطبقة السابقة.
الميزات: يُطلق أحيانًا على مدخلات الشبكة العصبية اسم "الميزات". يُطلق على فن تحديد أجزاء مجموعة البيانات (أو مجموعات الأجزاء) التي يجب إدخالها إلى الشبكة العصبونية للحصول على توقّعات جيدة اسم "هندسة الخصائص".
التصنيفات: اسم آخر "للفئات" أو الإجابات الصحيحة في مشكلة التصنيف الخاضع للإشراف
معدّل التعلّم: جزء من التدرّج يتم من خلاله تعديل الأوزان والانحيازات في كل تكرار من حلقة التدريب.
القيم المنطقية: تُسمى نواتج إحدى طبقات الخلايا العصبية قبل تطبيق دالة التنشيط "القيم المنطقية". يأتي المصطلح من "الدالة اللوجستية" المعروفة أيضًا باسم "الدالة السينية" التي كانت دالة التنشيط الأكثر شيوعًا. تم اختصار "مخرجات الخلايا العصبية قبل الدالة اللوجستية" إلى "اللوغاريتمات".
loss: دالة الخطأ التي تقارن نواتج الشبكة العصبية بالإجابات الصحيحة
الخلية العصبية: تحسب المجموع المرجّح لمدخلاتها، وتضيف تحيّزًا، وتمرّر النتيجة من خلال دالة تنشيط.
الترميز الأحادي: يتم ترميز الفئة 3 من 5 كمتجه من 5 عناصر، وكلها أصفار باستثناء العنصر الثالث الذي تكون قيمته 1.
relu: وحدة خطية مصحَّحة دالّة تفعيل شائعة للعصبونات
sigmoid: دالّة تفعيل أخرى كانت شائعة وما زالت مفيدة في حالات خاصة.
softmax: هي دالة تنشيط خاصة تعمل على متّجه، وتزيد الفرق بين أكبر مكوّن وجميع المكوّنات الأخرى، كما أنّها تعمل على تسوية المتّجه ليكون مجموع عناصره 1، وبالتالي يمكن تفسيره على أنّه متّجه احتمالات. يُستخدَم كخطوة أخيرة في المصنّفات.
متّجه متعدّد الأبعاد: "متّجه متعدّد الأبعاد" يشبه المصفوفة ولكن مع عدد عشوائي من الأبعاد. الموتر أحادي الأبعاد هو متجه. الموتر الثنائي الأبعاد هو مصفوفة. ويمكنك بعد ذلك الحصول على موترات ذات 3 أو 4 أو 5 أبعاد أو أكثر.
7. التعلم القائم على نقل المهام
بالنسبة إلى مشكلة تصنيف الصور، من المحتمل ألا تكون الطبقات الكثيفة كافية. علينا التعرّف على الطبقات الالتفافية والطرق العديدة التي يمكنك ترتيبها بها.
ولكن يمكننا أيضًا استخدام اختصار. تتوفّر شبكات عصبونية التفافية مدرَّبة بالكامل يمكن تنزيلها. من الممكن إزالة الطبقة الأخيرة، وهي رأس تصنيف softmax، واستبدالها بطبقة خاصة بك. تبقى جميع الأوزان والتحيزات المدرَّبة كما هي، ولا تعيد تدريب سوى طبقة softmax التي تضيفها. يُعرف هذا الأسلوب باسم "التعلّم القائم على نقل المهام"، وهو يعمل بشكل مذهل طالما أنّ مجموعة البيانات التي تم تدريب الشبكة العصبية عليها مسبقًا "قريبة بما يكفي" من مجموعة البيانات الخاصة بك.
التجربة العملية
يُرجى فتح دفتر الملاحظات التالي وتنفيذ الخلايا (Shift-ENTER) واتّباع التعليمات أينما ظهرت لك التصنيفات "مطلوب عمل".
Keras Flowers transfer learning (playground).ipynb
معلومات إضافية
من خلال ميزة "التعلّم القائم على نقل المهام"، يمكنك الاستفادة من بنى الشبكات العصبونية الالتفافية المتقدّمة التي طوّرها كبار الباحثين، ومن التدريب المُسبَق على مجموعة بيانات ضخمة من الصور. في حالتنا، سنستخدم أسلوب التعلّم القائم على نقل المهام من شبكة تم تدريبها على ImageNet، وهي قاعدة بيانات للصور تحتوي على العديد من النباتات والمشاهد الخارجية، وهي قريبة بما يكفي من الزهور.

صورة توضيحية: استخدام شبكة عصبونية التفافية معقّدة تم تدريبها مسبقًا كصندوق أسود، وإعادة تدريب رأس التصنيف فقط هذا ما يُعرف باسم التعلّم القائم على نقل المهام. سنتعرّف لاحقًا على طريقة عمل هذه الترتيبات المعقّدة للطبقات الالتفافية. في الوقت الحالي، هذه مشكلة تخص شخصًا آخر.
التعلّم القائم على نقل المهام في 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 باتّباع هذا الأسلوب.
Solution
إليك دفتر ملاحظات الحلّ. يمكنك استخدامها إذا واجهتك مشكلة.
Keras Flowers transfer learning (solution).ipynb
المواضيع التي تناولناها
- 🤔 كيفية كتابة مصنّف في Keras
- 🤓 تم ضبطه باستخدام طبقة softmax الأخيرة وفقدان الإنتروبيا المتقاطعة
- 😈 التعلّم القائم على نقل المهام
- 🤔 تدريب النموذج الأول
- 🧐 فقدان البيانات ودقتها أثناء التدريب
يُرجى تخصيص بعض الوقت لمراجعة قائمة التحقّق هذه في ذهنك.
8. [INFO] الشبكات العصبونية الالتفافية
باختصار
إذا كنت تعرف جميع المصطلحات بالخط العريض في الفقرة التالية، يمكنك الانتقال إلى التمرين التالي. إذا كنت مبتدئًا في استخدام الشبكات العصبونية الالتفافية، يُرجى مواصلة القراءة.

صورة توضيحية: فلترة صورة باستخدام فلترَين متتاليَين يتألف كل منهما من 48 وزنًا قابلاً للتعلم (4x4x3).
في ما يلي شكل شبكة عصبونية التفافية بسيطة في 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'])

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

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

صورة توضيحية: تحوّل شبكة عصبية التفافية "مكعبات" البيانات إلى "مكعبات" أخرى من البيانات.
الالتفافات المخطَّطة، والتجميع الأقصى
ومن خلال إجراء عمليات الالتفاف بخطوة 2 أو 3، يمكننا أيضًا تقليل حجم مكعّب البيانات الناتج في أبعاده الأفقية. هناك طريقتان شائعتان لإجراء ذلك:
- الالتفاف المتقطع: فلتر منزلق كما هو موضح أعلاه ولكن مع خطوة >1
- التجميع الأقصى: نافذة منزلقة تطبّق عملية MAX (عادةً على رقع 2x2، يتم تكرارها كل بكسلَين)

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

صورة توضيحية: مصنّف صور يستخدم طبقات التفافية وطبقات softmax يستخدم فلاتر 3x3 و1x1. تأخذ طبقات maxpool الحد الأقصى لمجموعات من نقاط البيانات 2x2. يتم تنفيذ رأس التصنيف باستخدام طبقة كثيفة مع تنشيط 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. شبكة عصبية التفافية مخصّصة
التجربة العملية
لننشئ شبكة عصبونية التفافية وندربها من البداية. سيسمح لنا استخدام وحدة معالجة الموتّرات بتكرار العمليات بسرعة كبيرة. يُرجى فتح دفتر الملاحظات التالي وتنفيذ الخلايا (Shift-ENTER) واتّباع التعليمات أينما ظهرت لك التصنيفات "مطلوب عمل".
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 مناسبة في كل مكان.
- يمكن أيضًا استخدام فلاتر 1x1 وهي غير مكلفة. ولا "تفلتر" هذه الأنظمة أي شيء، بل تحسب التركيبات الخطية للقنوات. يمكنك استخدامها بالتناوب مع الفلاتر الحقيقية. (مزيد من المعلومات عن "الالتفافات 1x1" في القسم التالي)
- بالنسبة إلى مشكلة تصنيف مثل هذه، يجب تقليل عدد العيّنات بشكل متكرّر باستخدام طبقات اختزال الحد الأقصى (أو الالتفافات مع القفزة > 1). لا يهمك مكان وجود الزهرة، بل يهمك فقط أن تكون وردة أو نبتة هندباء، لذا فإنّ فقدان معلومات x وy ليس مهمًا، كما أنّ فلترة المناطق الأصغر حجمًا أقل تكلفة.
- يصبح عدد الفلاتر عادةً مشابهًا لعدد الفئات في نهاية الشبكة (لماذا؟ راجِع خدعة "تجميع المتوسط العالمي" أدناه). إذا كنت تصنّف إلى مئات الفئات، عليك زيادة عدد الفلاتر تدريجيًا في الطبقات المتتالية. بالنسبة إلى مجموعة بيانات الزهور التي تحتوي على 5 فئات، لن يكون التصفية باستخدام 5 فلاتر فقط كافيًا. يمكنك استخدام عدد الفلاتر نفسه في معظم الطبقات، مثلاً 32، ثم تقليله في النهاية.
- الطبقات الكثيفة النهائية مكلفة. ويمكن أن يكون لها أوزان أكثر من جميع الطبقات الالتفافية مجتمعة. على سبيل المثال، حتى مع الحصول على ناتج معقول جدًا من مكعّب البيانات الأخير الذي يتضمّن 24×24×10 نقاط بيانات، ستكلّف طبقة كثيفة تتضمّن 100 عصبون 24×24×10×100=576,000 وزنًا. لذا، ننصحك بالتفكير مليًا أو تجربة تجميع المتوسط العام (راجِع ما يلي).
تجميع المتوسط العالمي
بدلاً من استخدام طبقة كثيفة مكلفة في نهاية شبكة عصبية التفافية، يمكنك تقسيم "المكعب" الوارد للبيانات إلى أكبر عدد ممكن من الأجزاء التي تتضمّنها الفئات، ثم حساب متوسط قيمها وإدخالها من خلال دالة تنشيط softmax. لا تتطلّب طريقة إنشاء رأس التصنيف هذه أي أوزان. في Keras، تكون بنية الجملة tf.keras.layers.GlobalAveragePooling2D().

Solution
إليك دفتر ملاحظات الحلّ. يمكنك استخدامها إذا واجهتك مشكلة.
Keras_Flowers_TPU (solution).ipynb
المواضيع التي تناولناها
- 🤔 تجربة الطبقات الالتفافية
- 🤓 جرّبتُ استخدام التجميع الأقصى والخطوات والتجميع المتوسط العام وغير ذلك.
- 😀 تكرار سريع لنموذج من العالم الحقيقي على وحدة معالجة الموتّرات
يُرجى تخصيص بعض الوقت لمراجعة قائمة التحقّق هذه في ذهنك.
10. [INFO] Modern convolutional architectures
باختصار

صورة توضيحية: "وحدة" التفافية ما هو الأفضل في هذه المرحلة؟ طبقة تجميع الحد الأقصى متبوعة بطبقة التفافية 1x1 أو مجموعة مختلفة من الطبقات؟ جرِّبها كلها، ثم ادمج النتائج ودَع الشبكة تحدّد الأفضل. على اليسار: بنية الالتفاف " 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)

الحيل الرخيصة الأخرى
فلاتر صغيرة بحجم 3x3

في هذا الرسم التوضيحي، يمكنك الاطّلاع على نتيجة فلترَين متتاليَين بحجم 3x3. حاوِل تتبُّع نقاط البيانات التي ساهمت في النتيجة، لأنّ هذين الفلترَين المتتاليَين بحجم 3x3 يحسبان بعض المجموعات من منطقة 5x5. لا تمثّل هذه الطريقة التركيبة نفسها التي يحسبها فلتر 5x5، ولكنّها تستحق التجربة لأنّ فلترَين متتاليَين 3x3 أقل تكلفة من فلتر 5x5 واحد.
1x1 convolutions ?

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

صورة توضيحية: بنية SqueezeNet استنادًا إلى "وحدات إطلاق النار". تتضمّن هذه الطبقات طبقة 1x1 "تضغط" البيانات الواردة في البُعد العمودي، تليها طبقتان متوازيتان من الطبقات الالتفافية 1x1 و3x3 "توسّع" عمق البيانات مرة أخرى.
التجربة العملية
تابِع العمل في دفتر الملاحظات السابق وأنشِئ شبكة عصبونية التفافية مستوحاة من SqueezeNet. سيكون عليك تغيير رمز النموذج إلى "الأسلوب الوظيفي" في Keras.
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 طبقات تجميع أقصى في الشبكة، وكذلك استخدام وحدة fire واحدة أو اثنتَين أو ثلاث وحدات متتالية بين طبقات تجميع أقصى.
في وحدات إطلاق النار، يجب أن تكون المَعلمة "squeeze" أصغر من المَعلمة "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 لأنّ مجموعة البيانات صغيرة. لا داعي للقلق بشأن هذه التفاصيل في الوقت الحالي.
تحسين البيانات
ستحصل على بضع نقاط مئوية إضافية من خلال تحسين البيانات باستخدام عمليات تحويل سهلة، مثل عمليات قلب التغييرات في تشبع اللون من اليمين إلى اليسار:


يمكن إجراء ذلك بسهولة بالغة في TensorFlow باستخدام واجهة برمجة التطبيقات tf.data.Dataset. حدِّد دالة تحويل جديدة لبياناتك:
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 حقبة.
Solution
إليك دفتر ملاحظات الحلّ. يمكنك استخدامها إذا واجهتك مشكلة.
Keras_Flowers_TPU_squeezenet.ipynb
المواضيع التي تناولناها
- 🤔 نماذج "الأسلوب الوظيفي" في Keras
- 🤓 بنية Squeezenet
- 🤓 زيادة البيانات باستخدام tf.data.datset
يُرجى تخصيص بعض الوقت لمراجعة قائمة التحقّق هذه في ذهنك.
12. Xception fine-tuned
الالتفافات القابلة للفصل
في الآونة الأخيرة، أصبح أسلوب مختلف لتنفيذ الطبقات الالتفافية رائجًا، وهو الالتفافات القابلة للفصل حسب العمق. أعلم أنّها عبارة طويلة، لكنّ المفهوم بسيط جدًا. يتم تنفيذها في Tensorflow وKeras كـ tf.keras.layers.SeparableConv2D.
تُشغّل عملية الالتفاف المنفصلة أيضًا فلترًا على الصورة، ولكنّها تستخدم مجموعة مميزة من الأوزان لكل قناة من قنوات الصورة المُدخلة. ويتبع ذلك "التفاف 1x1"، وهو سلسلة من الجداءات النقطية التي تؤدي إلى مجموع مرجّح للقنوات التي تمّت فلترتها. مع تحديد أوزان جديدة في كل مرة، يتم احتساب أكبر عدد ممكن من عمليات إعادة التركيب المرجّحة للقنوات حسب الحاجة.

صورة توضيحية: الالتفافات القابلة للفصل المرحلة 1: الالتفافات مع فلتر منفصل لكل قناة المرحلة 2: إعادة التركيب الخطي للقنوات يتم تكرار ذلك باستخدام مجموعة جديدة من الأوزان إلى أن يتم الوصول إلى العدد المطلوب من قنوات الإخراج. يمكن تكرار المرحلة 1 أيضًا، مع استخدام معاملات ترجيح جديدة في كل مرة، ولكن نادرًا ما يحدث ذلك في الواقع.
تُستخدم الالتفافات القابلة للفصل في معظم بنى الشبكات الالتفافية الحديثة: MobileNetV2 وXception وEfficientNet. بالمناسبة، MobileNetV2 هو النموذج الذي استخدمته في التعلّم القائم على نقل المهام سابقًا.
وهي أقل تكلفة من الالتفافات العادية، وقد تبيّن أنّها فعّالة بنفس القدر في التطبيق العملي. في ما يلي عدد مرات الظهور حسب الأهمية للمثال الموضّح أعلاه:
الطبقة الالتفافية: 4 × 4 × 3 × 5 = 240
الطبقة التفافية القابلة للفصل: 4 × 4 × 3 + 3 × 5 = 48 + 15 = 63
ويُترك للقارئ مهمة حساب عدد عمليات الضرب المطلوبة لتطبيق كل نمط من مقاييس الطبقة الالتفافية بطريقة مماثلة. تكون الالتفافات القابلة للفصل أصغر حجمًا وأكثر فعالية من الناحية الحسابية.
التجربة العملية
أعِد التشغيل من دفتر ملاحظات "التعلّم القائم على نقل المهام" في وضع التجربة، ولكن اختَر Xception كنموذج مدرَّب مسبقًا هذه المرة. تستخدم Xception الالتفافات القابلة للفصل فقط. اترك جميع الأوزان قابلة للتدريب. سنعمل على تحسين الأوزان المدرَّبة مسبقًا على بياناتنا بدلاً من استخدام الطبقات المدرَّبة مسبقًا كما هي.
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
للحصول على نتائج جيدة عند الضبط الدقيق لنموذج، عليك الانتباه إلى معدّل التعلّم واستخدام جدول معدّل تعلّم يتضمّن فترة تحسين الأداء. مثال:

سيؤدي البدء بمعدّل تعلّم عادي إلى تعطيل الأوزان المُدرَّبة مسبقًا للنموذج. يتم الاحتفاظ بها تدريجيًا إلى أن يتمكّن النموذج من فهم بياناتك وتعديلها بطريقة منطقية. بعد عملية الإحماء، يمكنك مواصلة استخدام معدّل تعلّم ثابت أو متناقص بشكل كبير.
في Keras، يتم تحديد معدّل التعلّم من خلال دالة ردّ الاتصال التي يمكنك من خلالها احتساب معدّل التعلّم المناسب لكل حقبة. ستمرِّر Keras معدّل التعلّم الصحيح إلى أداة التحسين لكل حقبة.
def lr_fn(epoch):
lr = ...
return lr
lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_fn, verbose=True)
model.fit(..., callbacks=[lr_callback])
Solution
إليك دفتر ملاحظات الحلّ. يمكنك استخدامها إذا واجهتك مشكلة.
07_Keras_Flowers_TPU_xception_fine_tuned_best.ipynb
المواضيع التي تناولناها
- 🤔 Depth-separable convolution
- 🤓 جداول معدّل التعلّم
- 😈 ضبط نموذج مدرَّب مسبقًا
يُرجى تخصيص بعض الوقت لمراجعة قائمة التحقّق هذه في ذهنك.
13. تهانينا!
لقد أنشأت أول شبكة عصبونية التفافية حديثة ودربتها لتحقيق دقة تزيد عن% 90، مع تكرار عمليات التدريب المتتالية في غضون دقائق فقط بفضل وحدات معالجة الموتّرات (TPU).
وحدات معالجة الموتّرات في التطبيقات العملية
تتوفّر وحدات معالجة الموتّرات ووحدات معالجة الرسومات على Vertex AI من Google Cloud:
أخيرًا، يسرّنا تلقّي ملاحظاتك. يُرجى إعلامنا إذا لاحظت أي خطأ في هذا المختبر أو إذا كنت تعتقد أنّه يجب تحسينه. يمكن تقديم الملاحظات من خلال مشاكل GitHub [ رابط الملاحظات].

|
|

