شعار زيفيرنت

فهم التجهيز الزائد في ConvNets

التاريخ:

المُقدّمة

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

أوصي بقراءة هذه المقالات لفهم أساسيات overfitting، underfitting و مقايضة التباين التحيز.

تعلم الأهداف

  • فهم أسباب وعواقب وسيناريوهات التجاوز شبكات التحويل.
  • تفسير منحنيات التعلم للكشف عن التجاوز والنقص في نماذج الشبكات العصبية.
  • تعلم تقنيات مختلفة للتخفيف من التجاوز، مثل الإيقاف المبكر، والتسرب، وتسوية الدفعة، والتنظيم، وزيادة البيانات.
  • تنفيذ هذه التقنيات باستخدام TensorFlow وKeras لتدريب ConvNets على مجموعة بيانات CIFAR-10.
  • تحليل تأثير التقنيات المختلفة على أداء النموذج وتعميمه.

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

السيناريوهات الشائعة للتركيب الزائد في ConvNet

دعونا نلقي نظرة على بعض السيناريوهات الشائعة للتركيب الزائد في ConvNet:

السيناريو 1: نموذج معقد للغاية مع بيانات غير كافية

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

نتيجة

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

كيف يمكن حل هذه القضية؟

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

السيناريو 2: التدريب المفرط

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

نتيجة

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

كيف يمكن حل هذه القضية؟

استخدم الإيقاف المبكر لتجنب زيادة ملاءمة النموذج وحفظ النموذج الأفضل. 

السيناريو 3: تجاهل التنظيم

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

نتيجة

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

كيف يمكن حل هذه القضية؟

تنفيذ التنظيم والتحقق المتبادل وضبط المعلمات المفرطة. 

ما هي قدرة النموذج؟

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

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

تفسير منحنيات التعلم

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

يتم إرجاع كائن السجل من الاستدعاءات إلى الدالة fit() المستخدمة لتدريب النموذج. يتم تخزين المقاييس في القاموس في عضو محفوظات الكائن الذي تم إرجاعه.

على سبيل المثال، يمكنك سرد المقاييس المجمعة في كائن السجل باستخدام مقتطف التعليمات البرمجية التالي بعد تدريب النموذج:

# list all data in history
print(history.history.keys())

الإخراج:

['الدقة'، 'الخسارة'، 'val_accuracy'، 'val_loss']

نوع المعلومات

قد تفكر في المعلومات الموجودة في بيانات التدريب على أنها من نوعين:

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

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

منحنيات التعلم

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

طرق لتجنب الإفراط في التجهيز

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

الطريقة الأولى: استخدام المزيد من البيانات

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

الطريقة الثانية: التوقف المبكر

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

نقص التجهيز والإفراط في التجهيز

الطريقة الثالثة: التسرب

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

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

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

التجهيز الزائد في ConvNets

الطريقة الرابعة: تطبيع الدفعة

الطريقة الخاصة التالية التي سنلقي نظرة عليها تؤدي "تسوية الدُفعة" (أو ""batchnorm")، والتي يمكن أن تساعد في تصحيح التدريب البطيء أو غير المستقر.

مع الشبكات العصبية، من الجيد عمومًا وضع جميع بياناتك على نطاق مشترك، ربما باستخدام شيء مثل StandardScaler أو MinMaxScaler من scikit-learn. والسبب هو أن SGD سيغير أوزان الشبكة بما يتناسب مع حجم التنشيط الذي تنتجه البيانات. الميزات التي تميل إلى إنتاج عمليات تنشيط بأحجام مختلفة جدًا يمكن أن تؤدي إلى سلوك تدريبي غير مستقر.

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

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

الطريقة الخامسة: تسوية L5 وL1

يعد تنظيم L1 وL2 من التقنيات المستخدمة لمنع التجهيز الزائد عن طريق معاقبة الأوزان الكبيرة في الشبكة العصبية. يضيف تنظيم L1 حدًا جزائيًا إلى دالة الخسارة بما يتناسب مع القيمة المطلقة للأوزان. إنه يشجع على التناثر في الأوزان ويمكن أن يؤدي إلى اختيار الميزات. يضيف تنظيم L2، المعروف أيضًا باسم تسوس الوزن، حدًا جزائيًا يتناسب مع مربع الأوزان إلى دالة الخسارة. فهو يمنع الأوزان من أن تصبح كبيرة جدًا ويشجع على توزيع الأوزان بشكل متساوٍ.

غالبًا ما يعتمد الاختيار بين ضبط L1 وL2 على المشكلة المحددة والخصائص المطلوبة للنموذج.

سيؤدي وجود قيم كبيرة لضبط L1/L2 إلى عدم تعلم النموذج بسرعة والوصول إلى مرحلة الاستقرار في التعلم مما يؤدي إلى عدم ملائمة النموذج. 

الطريقة السادسة: زيادة البيانات

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

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

وهذه هي الفكرة الكاملة وراء زيادة البيانات: أضف بعض البيانات المزيفة الإضافية التي تبدو بشكل معقول مثل البيانات الحقيقية وسيتحسن مصنفك. 

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

تنفيذ الأساليب المذكورة أعلاه مع البيانات

دعونا نستكشف خطوات التنفيذ للطرق المذكورة أعلاه:

الخطوة 1: تحميل المكتبات اللازمة

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import ModelCheckpoint
import keras
from keras.preprocessing import image
from keras import models, layers, regularizers
from tqdm import tqdm
import warnings
warnings.filterwarnings(action='ignore')

الخطوة 2: تحميل مجموعة البيانات والمعالجة المسبقة

#Here all the images are in the form of a numpy array
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train / 255.0
x_test = x_test / 255.0

الخطوة 3: تعلم مجموعة البيانات

x_train.shape, y_train.shape, x_test.shape, y_test.shape 

الإخراج:

الناتج
np.unique(y_train)

الإخراج:

الناتج
#These labels are in the order and taken from the documentaion
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
               'dog', 'frog', 'horse', 'ship', 'truck']

الخطوة 4: تصور الصورة من مجموعة البيانات

def show_image(IMG_INDEX):
    plt.imshow(x_train[20] ,cmap=plt.cm.binary)
    plt.xlabel(class_names[y_train[IMG_INDEX][0]])
    plt.show()
show_image(20)
التجهيز الزائد في ConvNets
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))
model.summary()

دعونا الآن نقوم بتهيئة المعلمات الفائقة وتجميع النموذج باستخدام المُحسِّن ووظيفة الخسارة ومقياس التقييم.


train_hyperparameters_config={'optim':keras.optimizers.Adam(learning_rate=0.001),
                             'epochs':20,
                              'batch_size':16
                             }
model.compile(optimizer=train_hyperparameters_config['optim'],
                  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                  metrics=['accuracy'])

الخطوة 6: نموذج التدريب

history = model.fit(x_train, y_train, 
                        epochs=train_hyperparameters_config['epochs'], 
                        batch_size=train_hyperparameters_config['batch_size'], 
                        verbose=1,
                        validation_data=(x_test, y_test))

الخطوة 7: تقييم النموذج

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

print(history.history.keys()) 
def learning_curves(history):
# Plotting Accuracy
    plt.figure(figsize=(14, 5))  # Adjust the figure size as needed
    plt.subplot(1, 2, 1)  # Subplot with 1 row, 2 columns, and index 1
    plt.plot(history.history['accuracy'], label='train_accuracy', marker='s', markersize=4)
    plt.plot(history.history['val_accuracy'], label='val_accuracy', marker='*', markersize=4)
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend(loc='lower right')

    # Plotting Loss
    plt.subplot(1, 2, 2)  # Subplot with 1 row, 2 columns, and index 2
    plt.plot(history.history['loss'], label='train_loss', marker='s', markersize=4)
    plt.plot(history.history['val_loss'], label='val_loss', marker='*', markersize=4)
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend(loc='lower right')

    plt.show()
learning_curves(history)
التجهيز الزائد في ConvNets

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

الخطوة الثامنة: تنفيذ الإيقاف المبكر

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

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))
model.summary()

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)

def model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config):
    model.compile(optimizer=train_hyperparameters_config['optim'],
                      loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                      metrics=['accuracy'])
    ht = model.fit(x_train, y_train, 
                            epochs=train_hyperparameters_config['epochs'], 
                            batch_size=train_hyperparameters_config['batch_size'],
                            callbacks=[callback],
                            verbose=1,
                            validation_data=(x_test, y_test))
    return ht

ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
التجهيز الزائد في ConvNets

لمعرفة أفضل الأوزان التي أخذها النموذج لدينا. 

print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

الخطوة 9: زيادة تعقيد النموذج

نظرًا لأن نموذجنا لا يعمل بشكل جيد وغير مناسب لأنه غير قادر على التقاط بيانات كافية. يجب علينا زيادة تعقيد نموذجنا وتقييمه. 

model = models.Sequential()

model.add(layers.Conv2D(128, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
model.summary()
الناتج

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

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)

learning_curves(ht)
التجهيز الزائد في ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

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

الخطوة 10: استخدام الطبقات المتسربة وطبقات التسوية المجمعة

model = models.Sequential()

model.add(layers.Conv2D(128, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.3))

model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.3))

model.add(layers.Dense(10, activation='softmax'))
model.summary()
الناتج
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
التجهيز الزائد في ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

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

الخطوة 11: زيادة طبقات الالتواء

قم بتقليل المعلمة القابلة للتدريب ولكن قم بزيادة طبقات الالتواء لاستخراج المزيد من الميزات.

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))

model.add(layers.Dense(10, activation='softmax'))

model.summary()
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
الناتج
learning_curves(ht)
التجهيز الزائد في ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

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

الخطوة 12: استخدام تسوية L1/L2

from tensorflow.keras import regularizers

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l2(0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu', kernel_regularizer=regularizers.l1_l2(0.0005, 0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(10, activation='softmax'))

model.summary()
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 7,
    'epochs': 70,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
التجهيز الزائد في ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

يمكننا الآن أن نرى أن تنظيم L1/L2 حتى بعد استخدام درجة جزاء منخفضة تبلغ 0.0001، جعل نموذجنا غير ملائم بنسبة 4%. ومن ثم فمن المستحسن استخدام جميع الطرق معًا بحذر. نظرًا لأن تسوية الدفعة وتنظيمها يؤثران على النموذج بطريقة مماثلة، فلن نحتاج إلى تسوية L1/L2. 

الخطوة 13: زيادة البيانات

سوف نستخدم ImageDataGenerator من Tensorflow keras.

# creates a data generator object that transforms images
datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')

# pick an image to transform
test_img = x_train[20]
img = image.img_to_array(test_img)  # convert image to numpy arry
img = img.reshape((1,) + img.shape)  # reshape image

i = 0

for batch in datagen.flow(img, save_prefix='test', save_format='jpeg'):  # this loops runs forever until we break, saving images to current directory with specified prefix
    plt.figure(i)
    plot = plt.imshow(image.img_to_array(batch[0]))
    i += 1
    if i > 4:  # show 4 images
        break

plt.show()
التجهيز الزائد في ConvNets

هذه أربع صور مدمجة وصورة أصلية واحدة.

# Create an instance of the ImageDataGenerator
datagen = ImageDataGenerator(
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode='nearest'
)

# Create an iterator for the data generator
data_generator = datagen.flow(x_train, y_train, batch_size=32)

# Create empty lists to store the augmented images and labels
augmented_images = []
augmented_labels = []

# Loop over the data generator and append the augmented data to the lists
num_batches = len(x_train) // 32
progress_bar = tqdm(total=num_batches, desc="Augmenting data", unit="batch")

for i in range(num_batches):
    batch_images, batch_labels = next(data_generator)
    augmented_images.append(batch_images)
    augmented_labels.append(batch_labels)
    progress_bar.update(1)

progress_bar.close()

# Convert the lists to NumPy arrays
augmented_images = np.concatenate(augmented_images, axis=0)
augmented_labels = np.concatenate(augmented_labels, axis=0)

# Combine the original and augmented data
x_train_augmented = np.concatenate((x_train, augmented_images), axis=0)
y_train_augmented = np.concatenate((y_train, augmented_labels), axis=0)
الناتج

لقد استخدمنا مكتبة tqdm لمعرفة مدى تقدم عملية التعزيز لدينا.

x_train_augmented.shape, y_train_augmented.shape
الناتج

هذه هي مجموعة البيانات لدينا بعد التعزيز. الآن دعونا نستخدم مجموعة البيانات هذه وندرب نموذجنا.

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))

model.add(layers.Dense(10, activation='softmax'))

model.summary()

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 10,
    'epochs': 70,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)

ht=model_train(model, x_train_augmented, y_train_augmented, x_test, y_test, train_hyperparameters_config)


learning_curves(ht)
التجهيز الزائد في ConvNets
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

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

وفي الختام

يعد التجاوز مشكلة شائعة في التعلم العميق، خاصة مع بنيات الشبكات العصبية المعقدة مثل ConvNets. يمكن للممارسين منع التجهيز الزائد في ConvNets من خلال فهم أسبابه الجذرية والتعرف على السيناريوهات التي يحدث فيها. يمكن أن تساعد تقنيات مثل الإيقاف المبكر، والتسرب، وتسوية الدُفعات، والتنظيم، وزيادة البيانات في تخفيف هذه المشكلة. أظهر تنفيذ هذه التقنيات على مجموعة بيانات CIFAR-10 تحسينات كبيرة في تعميم النموذج والأداء. إن إتقان هذه التقنيات وفهم مبادئها يمكن أن يؤدي إلى نماذج شبكات عصبية قوية وموثوقة.

الأسئلة المتكررة

س1. ما هو التجهيز الزائد، ولماذا يمثل مشكلة في التعلم العميق؟ 

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

س2. كيف يمكنني اكتشاف التجاوز في نموذج الشبكة العصبية الخاص بي؟

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

س3. ما هو التوقف المبكر، وكيف يساعد في منع الإفراط في التجهيز؟

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

س 4. كيف تساعد زيادة البيانات في التخفيف من التجاوز؟ 

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

بقعة_صورة

أحدث المعلومات الاستخباراتية

بقعة_صورة