بدون شهادة دكتوراه من خلال TensorFlow وKeras والتعلّم المتعمق

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

يستخدم هذا الدرس التطبيقي العملي مجموعة بيانات MNIST، وهي مجموعة من 60,000 رقم مصنّف شغلت أجيالاً من حاملي شهادات الدكتوراه لمدة عقدَين تقريبًا. ستحلّ المشكلة باستخدام أقل من 100 سطر من رموز Python / TensorFlow البرمجية.

أهداف الدورة التعليمية

  • ما هي الشبكة العصبية وكيفية تدريبها؟
  • كيفية إنشاء شبكة عصبية أساسية ذات طبقة واحدة باستخدام tf.keras
  • كيفية إضافة المزيد من الطبقات
  • كيفية إعداد جدول معدّل التعلّم
  • كيفية إنشاء شبكات عصبونية التفافية
  • كيفية استخدام تقنيات التسوية: الإسقاط، والتسوية الدفعية
  • ما هو فرط التخصيص؟

المتطلبات

متصفّح فقط يمكن إجراء ورشة العمل هذه بالكامل باستخدام Google Colaboratory.

الملاحظات

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

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

Welcome to Colab.ipynb

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

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

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

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

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

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

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

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

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

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

keras_01_mnist.ipynb

أثناء تنفيذ دفتر الملاحظات، ركِّز على الرسومات البيانية. يمكنك الاطّلاع على التفسيرات أدناه.

بيانات التدريب

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

ستصنّف الشبكة العصبية التي سننشئها الأرقام المكتوبة بخط اليد في فئاتها العشر (من 0 إلى 9). ويتم ذلك استنادًا إلى مَعلمات داخلية يجب أن تكون لها قيمة صحيحة لكي يعمل التصنيف بشكل جيد. يتم تعلُّم هذه "القيمة الصحيحة" من خلال عملية تدريب تتطلّب "مجموعة بيانات مصنَّفة" تحتوي على صور والإجابات الصحيحة المرتبطة بها.

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

التدريب

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

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

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

يمثّل المحور السيني عدد "الحقب" أو التكرارات خلال مجموعة البيانات بأكملها.

التوقّعات

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

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

Tensors

يتم تخزين البيانات في مصفوفات. تتلاءم صورة بتدرّج الرمادي بحجم 28×28 بكسل مع مصفوفة ثنائية الأبعاد بحجم 28×28. ولكن بالنسبة إلى صورة ملونة، نحتاج إلى المزيد من الأبعاد. هناك 3 قيم ألوان لكل بكسل (أحمر وأخضر وأزرق)، لذا سيلزم جدول ثلاثي الأبعاد بالأبعاد [28 و28 و3]. ولتخزين مجموعة من 128 صورة ملونة، يجب استخدام جدول رباعي الأبعاد بالأبعاد [128, 28, 28, 3].

تُسمّى هذه الجداول المتعدّدة الأبعاد "موترات"، وتُسمّى قائمة أبعادها "الشكل".

باختصار

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

witch.png

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

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[28, 28, 1]),
    tf.keras.layers.Dense(200, activation="relu"),
    tf.keras.layers.Dense(60, activation="relu"),
    tf.keras.layers.Dense(10, activation='softmax') # classifying into 10 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, ... )

طبقة كثيفة واحدة

الأرقام المكتوبة بخط اليد في مجموعة بيانات MNIST هي صور بتدرّج الرمادي بحجم 28x28 بكسل. أبسط طريقة لتصنيفها هي استخدام 28x28=784 بكسل كمدخلات لشبكة عصبية ذات طبقة واحدة.

Screen Shot 2016-07-26 at 12.32.24.png

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

تمثّل الصورة أعلاه شبكة عصبية ذات طبقة واحدة مع 10 خلايا عصبية للناتج لأنّنا نريد تصنيف الأرقام إلى 10 فئات (من 0 إلى 9).

باستخدام عملية ضرب المصفوفات

في ما يلي كيفية تمثيل طبقة شبكة عصبونية تعالج مجموعة من الصور من خلال عملية ضرب المصفوفات:

matmul.gif

باستخدام العمود الأول من الأوزان في مصفوفة الأوزان W، نحسب المجموع المرجّح لجميع وحدات البكسل في الصورة الأولى. يتوافق هذا المجموع مع العصبون الأول. باستخدام العمود الثاني من الأوزان، نكرّر العملية نفسها مع العصبون الثاني وهكذا حتى العصبون العاشر. يمكننا بعد ذلك تكرار العملية للصور الـ 99 المتبقية. إذا أطلقنا على المصفوفة التي تحتوي على 100 صورة اسم X، فإنّ جميع المجموعات المرجّحة للخلايا العصبية العشر، والتي يتم احتسابها على 100 صورة، هي ببساطة X.W، أي عملية ضرب مصفوفات.

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

وأخيرًا، نطبّق دالة تنشيط، مثل "softmax" (الموضّحة أدناه) ونحصل على الصيغة التي تصف شبكة عصبية ذات طبقة واحدة، يتم تطبيقها على 100 صورة:

Screen Shot 2016-07-26 at 16.02.36.png

في Keras

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

tf.keras.layers.Dense(10, activation='softmax')

التعمّق في التفاصيل

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

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

دوال التنشيط: relu وsoftmax وsigmoid

عادةً ما تستخدم دالة التنشيط "relu" لجميع الطبقات باستثناء الطبقة الأخيرة. ستستخدِم الطبقة الأخيرة في المصنّف التنشيط "softmax".

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

تُعرف دالة التنشيط الأكثر شيوعًا باسم "RELU"، وهي اختصار لعبارة Rectified Linear Unit. إنّها دالة بسيطة للغاية كما يمكنك أن ترى في الرسم البياني أعلاه.

كانت دالة التفعيل التقليدية في الشبكات العصبية هي "الدالة السينية"، ولكن تبيّن أنّ "دالة التفعيل المستقيمة" تتمتّع بخصائص تقارب أفضل في كل مكان تقريبًا، وهي الآن الخيار المفضّل.

تفعيل Softmax للتصنيف

تحتوي الطبقة الأخيرة من شبكتنا العصبية على 10 عصبونات لأنّنا نريد تصنيف الأرقام المكتوبة بخط اليد إلى 10 فئات (من 0 إلى 9). يجب أن تعرض 10 أرقام بين 0 و1 تمثّل احتمال أن يكون هذا الرقم 0 أو 1 أو 2 وما إلى ذلك. لذلك، سنستخدم في الطبقة الأخيرة دالة تنشيط تُسمى "softmax".

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

يُطلق على ناتج الطبقة الأخيرة، قبل التفعيل، اسم "اللوغاريتمات" في بعض الأحيان. إذا كان هذا المتجه L = [L0, L1, L2, L3, L4, L5, L6, L7, L8, L9]، يكون:

فقدان الإنتروبيا المتقاطعة

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

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

النزول المتدرّج

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

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

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

gradient descent2.png

التقسيم إلى دفعات صغيرة والزخم

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

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

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

صورة توضيحية: نقطة سرج يكون التدرّج اللوني 0، ولكنّه ليس الحد الأدنى في جميع الاتجاهات. (معلومات تحديد مصدر الصورة ويكيميديا: 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 أبعاد أو أكثر.

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

keras_01_mnist.ipynb

لنستعرض كل الخلايا في ورقة الملاحظات هذه.

الخلية "المَعلمات"

يتم هنا تحديد حجم الدفعة وعدد مرات التدريب وموقع ملفات البيانات. تتم استضافة ملفات البيانات في حزمة Google Cloud Storage (GCS)، ولهذا السبب يبدأ عنوانها بـ gs://

الخلية "عمليات الاستيراد"

يتم استيراد جميع مكتبات Python الضرورية هنا، بما في ذلك TensorFlow وmatplotlib للرسومات البيانية.

الخلية "أدوات العرض المرئي [RUN ME]"

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

الخلية "tf.data.Dataset: تحليل الملفات وإعداد مجموعات بيانات التدريب والتحقّق"

استخدمت هذه الخلية واجهة برمجة التطبيقات tf.data.Dataset لتحميل مجموعة بيانات MNIST من ملفات البيانات. ليس من الضروري قضاء الكثير من الوقت في هذه الخلية. إذا كنت مهتمًا بواجهة برمجة التطبيقات tf.data.Dataset، إليك برنامجًا تعليميًا يشرحها: خطوط نقل البيانات السريعة في وحدات TPU. في الوقت الحالي، تشمل الأساسيات ما يلي:

يتم تخزين الصور والتصنيفات (الإجابات الصحيحة) من مجموعة بيانات MNIST في سجلات ذات طول ثابت في 4 ملفات. يمكن تحميل الملفات باستخدام دالة السجلّ الثابت المخصّصة:

imagedataset = tf.data.FixedLengthRecordDataset(image_filename, 28*28, header_bytes=16)

لدينا الآن مجموعة بيانات من وحدات بايت للصور. ويجب فك ترميزها إلى صور. نحدّد دالة لإجراء ذلك، ولا يتم ضغط الصورة، لذا لا تحتاج الدالة إلى فك ترميز أي شيء (decode_raw لا تفعل أي شيء أساسًا). يتم بعد ذلك تحويل الصورة إلى قيم نقطة عائمة بين 0 و1. يمكننا إعادة تشكيلها هنا كصورة ثنائية الأبعاد، ولكننا في الواقع نحتفظ بها كمجموعة مسطحة من وحدات البكسل بحجم 28*28 لأنّ هذا ما تتوقّعه الطبقة الكثيفة الأولية.

def read_image(tf_bytestring):
    image = tf.decode_raw(tf_bytestring, tf.uint8)
    image = tf.cast(image, tf.float32)/256.0
    image = tf.reshape(image, [28*28])
    return image

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

imagedataset = imagedataset.map(read_image, num_parallel_calls=16)

نستخدم النوع نفسه من القراءة وفك الترميز للتصنيفات، ونربط .zip الصور والتصنيفات معًا:

dataset = tf.data.Dataset.zip((imagedataset, labelsdataset))

لدينا الآن مجموعة بيانات من الأزواج (صورة، تصنيف). هذا ما يتوقّعه نموذجنا. لسنا مستعدين تمامًا لاستخدامها في دالة التدريب بعد:

dataset = dataset.cache()
dataset = dataset.shuffle(5000, reshuffle_each_iteration=True)
dataset = dataset.repeat()
dataset = dataset.batch(batch_size)
dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)

تحتوي واجهة برمجة التطبيقات tf.data.Dataset على جميع دوال الأدوات المساعدة اللازمة لإعداد مجموعات البيانات:

يخزّن .cache مجموعة البيانات مؤقتًا في ذاكرة الوصول العشوائي. هذه مجموعة بيانات صغيرة جدًا، لذا ستنجح العملية. .shuffle ترتّبها بشكل عشوائي مع مخزن مؤقت يتضمّن 5,000 عنصر. من المهم ترتيب بيانات التدريب بشكل عشوائي. تكرّر .repeat مجموعة البيانات. وسنتدرّب عليه عدة مرات (عدة دورات تدريبية). تجمع .batch صورًا وتصنيفات متعددة في "مطابقة مصغّرة". أخيرًا، يمكن .prefetch استخدام وحدة المعالجة المركزية لإعداد المجموعة التالية أثناء تدريب المجموعة الحالية على وحدة معالجة الرسومات.

يتم إعداد مجموعة بيانات التحقّق بطريقة مشابهة. نحن الآن جاهزون لتحديد نموذج واستخدام مجموعة البيانات هذه لتدريبه.

الخلية "نموذج Keras"

ستكون جميع نماذجنا عبارة عن تسلسلات مباشرة من الطبقات، لذا يمكننا استخدام نمط tf.keras.Sequential لإنشائها. في البداية، تكون طبقة كثيفة واحدة. تحتوي هذه الطبقة على 10 عُقد عصبية لأنّنا نصنّف الأرقام المكتوبة بخط اليد إلى 10 فئات. تستخدم هذه الطبقة وظيفة التنشيط "softmax" لأنّها الطبقة الأخيرة في المصنّف.

يحتاج نموذج Keras أيضًا إلى معرفة شكل المدخلات. يمكن استخدام tf.keras.layers.Input لتحديدها. في هذه الحالة، تكون متجهات الإدخال متجهات مسطّحة لقيم وحدات البكسل بطول 28*28.

model = tf.keras.Sequential(
  [
    tf.keras.layers.Input(shape=(28*28,)),
    tf.keras.layers.Dense(10, activation='softmax')
  ])

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

# print model layers
model.summary()

# utility callback that displays training curves
plot_training = PlotTraining(sample_rate=10, zoom=1)

يتم إعداد النموذج في Keras باستخدام الدالة model.compile. نستخدم هنا أداة التحسين الأساسية 'sgd' (النزول التدريجي العشوائي). يتطلّب نموذج التصنيف دالة خسارة إنتروبيا متقاطعة، تُسمى 'categorical_crossentropy' في Keras. أخيرًا، نطلب من النموذج حساب مقياس 'accuracy'، وهو النسبة المئوية للصور المصنّفة بشكل صحيح.

توفّر Keras الأداة المساعدة model.summary() الرائعة التي تطبع تفاصيل النموذج الذي أنشأته. أضاف المدرّب اللطيف الأداة PlotTraining (المحدّدة في خلية "أدوات التصوّر") التي ستعرض منحنيات تدريب مختلفة أثناء التدريب.

الخطوة "تدريب النموذج والتحقّق من صحته"

يتم التدريب هنا من خلال استدعاء model.fit وتمرير كلّ من مجموعتَي بيانات التدريب والتحقّق. تُجري Keras تلقائيًا جولة من التحقّق في نهاية كل حقبة.

model.fit(training_dataset, steps_per_epoch=steps_per_epoch, epochs=EPOCHS,
          validation_data=validation_dataset, validation_steps=1,
          callbacks=[plot_training])

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

الخلية "عرض التوقعات"

بعد تدريب النموذج، يمكننا الحصول على توقّعات منه من خلال استدعاء model.predict():

probabilities = model.predict(font_digits, steps=1)
predicted_labels = np.argmax(probabilities, axis=1)

لقد أعددنا هنا مجموعة من الأرقام المطبوعة المعروضة من الخطوط المحلية، وذلك كاختبار. تذكَّر أنّ الشبكة العصبية تعرض متجهًا من 10 احتمالات من "softmax" النهائي. للحصول على التصنيف، علينا معرفة الاحتمالية الأكبر. تتيح لك الدالة np.argmax من مكتبة numpy إجراء ذلك.

لفهم سبب الحاجة إلى المَعلمة axis=1، يُرجى تذكُّر أنّنا عالجنا مجموعة من 128 صورة، وبالتالي يعرض النموذج 128 متّجهًا من الاحتمالات. يكون شكل موتر الإخراج [128, 10]. نحتسب argmax على مستوى الاحتمالات العشرة التي يتم عرضها لكل صورة، وبالتالي axis=1 (المحور الأول هو 0).

يتعرّف هذا النموذج البسيط على% 90 من الأرقام. لا بأس بهذه النتيجة، ولكنّك ستعمل الآن على تحسينها بشكل كبير.

godeep.png

لتحسين دقة التعرّف، سنضيف المزيد من الطبقات إلى الشبكة العصبية.

Screen Shot 2016-07-27 at 15.36.55.png

نحتفظ بدالة التنشيط softmax في الطبقة الأخيرة لأنّها الأنسب للتصنيف. في الطبقات الوسيطة، سنستخدم دالة التنشيط الأكثر كلاسيكية: دالة سيغمويد:

على سبيل المثال، يمكن أن يبدو النموذج على النحو التالي (لا تنسَ الفواصل، تأخذ tf.keras.Sequential قائمة طبقات مفصولة بفواصل):

model = tf.keras.Sequential(
  [
      tf.keras.layers.Input(shape=(28*28,)),
      tf.keras.layers.Dense(200, activation='sigmoid'),
      tf.keras.layers.Dense(60, activation='sigmoid'),
      tf.keras.layers.Dense(10, activation='softmax')
  ])

اطّلِع على "ملخّص" النموذج. ويحتوي الآن على 10 أضعاف عدد المَعلمات على الأقل. يجب أن يكون أفضل 10 مرات! ولكن لسبب ما، لم يتم ذلك ...

يبدو أنّ الخسارة قد ارتفعت بشكل كبير أيضًا. هناك خطأ ما.

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

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

تفعيل RELU

relu.png

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

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

أداة تحسين أفضل

في المساحات العالية الأبعاد، مثل المساحة هنا التي تضمّ حوالي 10 آلاف وزن وانحياز، تكون "نقاط السرج" شائعة. هذه نقاط ليست الحد الأدنى المحلي، ولكن يكون فيها التدرّج التكراري صفرًا، ويبقى محسِّن التدرّج التكراري عالقًا فيها. تتضمّن TensorFlow مجموعة كاملة من أدوات التحسين المتاحة، بما في ذلك بعض الأدوات التي تعمل مع مقدار من القصور الذاتي وستتجاوز نقاط السرج بأمان.

عمليات التهيئة العشوائية

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

ليس عليك اتخاذ أي إجراء، لأنّ Keras يتّخذ الإجراء المناسب تلقائيًا.

NaN ???

تتضمّن صيغة الإنتروبيا المتقاطعة لوغاريتمًا، وقيمة log(0) هي "ليس رقمًا" (NaN، وهو خطأ عددي إذا كنت تفضّل ذلك). هل يمكن أن يكون الإدخال إلى الإنتروبيا المتقاطعة 0؟ تأتي المدخلات من دالة softmax التي تكون في الأساس دالة أسية، والدالة الأسية لا تساوي صفرًا أبدًا. لذا، نحن بأمان.

حقًا؟ في عالم الرياضيات الجميل، سنكون في أمان، ولكن في عالم الكمبيوتر، فإنّ exp(-150) الممثَّل بتنسيق float32 هو صفر تمامًا، وبالتالي يتعطّل حساب الإنتروبيا المتقاطعة.

لحسن الحظ، ليس عليك اتّخاذ أي إجراء هنا أيضًا، لأنّ Keras يتولّى ذلك ويحسب دالة softmax متبوعة بدالة الإنتروبيا المتقاطعة بطريقة دقيقة للغاية لضمان الاستقرار العددي وتجنُّب قيم NaN غير المرغوب فيها.

تم بنجاح؟

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

إذا واجهت صعوبة، إليك الحلّ في هذه المرحلة:

keras_02_mnist_dense.ipynb

هل يمكننا محاولة التدريب بشكل أسرع؟ معدّل التعلّم التلقائي في محسِّن Adam هو 0.001. لنحاول زيادته.

لا يبدو أنّ زيادة السرعة تساعد كثيرًا، وما كل هذه الضوضاء؟

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

slow down.png

الحلّ الجيّد هو البدء بسرعة وتقليل معدّل التعلّم بشكل كبير. في Keras، يمكنك إجراء ذلك باستخدام دالة الاستدعاء tf.keras.callbacks.LearningRateScheduler.

رمز مفيد للنسخ واللصق:

# lr decay function
def lr_decay(epoch):
  return 0.01 * math.pow(0.6, epoch)

# lr schedule callback
lr_decay_callback = tf.keras.callbacks.LearningRateScheduler(lr_decay, verbose=True)

# important to see what you are doing
plot_learning_rate(lr_decay, EPOCHS)

لا تنسَ استخدام lr_decay_callback الذي أنشأته. أضِفها إلى قائمة الدوالّ التي يتم استدعاؤها في model.fit:

model.fit(...,  callbacks=[plot_training, lr_decay_callback])

ويُحدث هذا التغيير البسيط تأثيرًا مذهلاً. تلاحظ أنّ معظم التشويش قد اختفى وأنّ دقة الاختبار أصبحت الآن أعلى من% 98 بشكل مستمر.

يبدو أنّ النموذج يتلاقى بشكل جيد الآن. لنحاول التوغّل أكثر في التفاصيل.

هل يساعد ذلك؟

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

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

dropout.png

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

هل نجح الأمر؟

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

يبدو أنّ عملية الحذف لم تكن الحلّ المناسب، أو ربما يكون مفهوم "التطابق الزائد" أكثر تعقيدًا ولا يمكن حلّ بعض أسبابه من خلال عملية الحذف.

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

overfitting.png

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

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

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

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

إذا واجهت صعوبة، إليك الحلّ في هذه المرحلة:

keras_03_mnist_dense_lrdecay_dropout.ipynb

باختصار

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

convolutional.gif

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

إليك الشكل الذي تبدو عليه شبكة عصبونية التفافية بسيطة في Keras:

model = tf.keras.Sequential([
    tf.keras.layers.Reshape(input_shape=(28*28,), target_shape=(28, 28, 1)),
    tf.keras.layers.Conv2D(kernel_size=3, filters=12, activation='relu'),
    tf.keras.layers.Conv2D(kernel_size=6, filters=24, strides=2, activation='relu'),
    tf.keras.layers.Conv2D(kernel_size=6, filters=32, strides=2, activation='relu'),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(10, activation='softmax')
])

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

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

Screen Shot 2016-07-29 at 16.02.37.png

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

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

الالتفافات المخطَّطة، والتجميع الأقصى

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

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

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

الطبقة النهائية

بعد آخر طبقة التفافية، تكون البيانات على شكل "مكعّب". هناك طريقتان لتغذيتها من خلال الطبقة الكثيفة النهائية.

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

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

انتقِل إلى القسم التالي لإنشاء شبكة عصبية التفافية للمشكلة المطروحة.

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

لاحظ أنّ الطبقتَين الالتفافيتَين الثانية والثالثة تتضمّنان خطوة بمقدار اثنَين، ما يفسّر سبب خفض عدد قيم الإخراج من 28×28 إلى 14×14 ثم إلى 7×7.

لنكتب رمز Keras البرمجي.

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

tf.keras.layers.Reshape(input_shape=(28*28,), target_shape=(28, 28, 1))

يمكنك استخدام هذا الخط بدلاً من طبقة tf.keras.layers.Input التي استخدمتها حتى الآن.

في Keras، يكون بناء الجملة لطبقة التفافية مُنشَّطة باستخدام "relu" على النحو التالي:

tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu')

بالنسبة إلى الالتفاف بخطوات متقطّعة، يمكنك كتابة:

tf.keras.layers.Conv2D(kernel_size=6, filters=24, padding='same', activation='relu', strides=2)

لتسوية مكعّب بيانات في متجه كي تتمكّن طبقة كثيفة من استخدامه، اتّبِع الخطوات التالية:

tf.keras.layers.Flatten()

بالنسبة إلى الطبقة الكثيفة، لم يتغير بناء الجملة:

tf.keras.layers.Dense(200, activation='relu')

هل تجاوز نموذجك حاجز الدقة البالغ% 99؟ قريب جدًا... ولكن انظر إلى منحنى فقدان صحة البيانات. هل يبدو ذلك مألوفًا؟

اطّلِع أيضًا على التوقّعات. للمرة الأولى، من المفترض أن تلاحظ أنّه تم الآن التعرّف على معظم الأرقام العشرة آلاف التجريبية بشكل صحيح. يتبقى حوالي 4 صفوف ونصف من عمليات الرصد الخاطئة (حوالي 110 أرقام من أصل 10,000)

إذا واجهت صعوبة، إليك الحلّ في هذه المرحلة:

keras_04_mnist_convolutional.ipynb

يُظهر التدريب السابق علامات واضحة على الإفراط في التكيّف (ولا يزال أقل من 99% من الدقة). هل يجب أن نعيد تجربة التسرب؟

كيف سارت الأمور هذه المرة؟

يبدو أنّ ميزة "التوقف عن المشاهدة" قد نجحت هذه المرة. لم يعُد معدّل الخطأ في بيانات التحقّق يرتفع، ومن المفترض أن تكون الدقة النهائية أعلى من %99. تهانينا!

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

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

أخيرًا، لنحاول إضافة تسوية الدفعات.

هذه هي النظرية، ولكن في الواقع، ما عليك سوى تذكُّر قاعدتين:

لنلتزم بالأساسيات في الوقت الحالي ونضيف طبقة تسوية الدفعات إلى كل طبقة من طبقات الشبكة العصبية باستثناء الطبقة الأخيرة. لا تُضِفها إلى طبقة "softmax" الأخيرة. ولن يكون مفيدًا هناك.

# Modify each layer: remove the activation from the layer itself.
# Set use_bias=False since batch norm will play the role of biases.
tf.keras.layers.Conv2D(..., use_bias=False),
# Batch norm goes between the layer and its activation.
# The scale factor can be turned off for Relu activation.
tf.keras.layers.BatchNormalization(scale=False, center=True),
# Finish with the activation.
tf.keras.layers.Activation('relu'),

ما مدى دقة المعلومات الآن؟

مع بعض التعديلات (BATCH_SIZE=64، ومعلَمة انخفاض معدل التعلّم 0.666، ومعدل التسرب في الطبقة الكثيفة 0.3) وبعض الحظ، يمكنك الوصول إلى ‎99.5%. تم إجراء تعديلات على معدّل التعلّم ومعدّل التسرب وفقًا "لأفضل الممارسات" لاستخدام ميزة "التسوية الدفعية":

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

يتضمّن دفتر ملاحظات الحلّ عملية تدريب بنسبة% 99.5:

keras_05_mnist_batch_norm.ipynb

ستجد نسخة من الرمز البرمجي جاهزة للاستخدام على السحابة الإلكترونية في مجلد mlengine على GitHub، بالإضافة إلى تعليمات لتشغيلها على Google Cloud AI Platform. قبل أن تتمكّن من تنفيذ هذا الجزء، عليك إنشاء حساب على Google Cloud وتفعيل الفوترة. يجب أن تكون الموارد اللازمة لإكمال المختبر أقل من بضعة دولارات (بافتراض ساعة واحدة من وقت التدريب على وحدة معالجة رسومات واحدة). لإعداد حسابك، اتّبِع الخطوات التالية:

  1. أنشئ مشروعًا على Google Cloud Platform (http://cloud.google.com/console).
  2. فعِّل الفوترة.
  3. ثبِّت أدوات سطر الأوامر في Google Cloud Platform (GCP SDK هنا).
  4. أنشئ حزمة في Google Cloud Storage (ضَعها في المنطقة us-central1)، وسيتم استخدامها لتنظيم رمز التدريب وتخزين النموذج المدرَّب.
  5. فعِّل واجهات برمجة التطبيقات اللازمة واطلب الحصص اللازمة (نفِّذ أمر التدريب مرة واحدة وستتلقّى رسائل خطأ تخبرك بما يجب تفعيله).

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

cliffs notes tensorflow lab.png

الخطوات التالية

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

HR.png

Martin Görner ID small.jpg

المؤلف: "مارتن غورنر"

‫Twitter: @martin_gorner

جميع صور الرسوم المتحركة في هذا المختبر محمية بموجب حقوق الطبع والنشر: alexpokusay / 123RF stock photos