تنفيذ بنیة ResNet-50 في Keras (الشبكات المتبقية| Residual Networks)

تنفيذ بنیة ResNet-50

في هذه المقالة، سنتعرف على البرنامج التعليمي لتطبيق Keras لهندسة ResNet-50 من البداية. ResNet-50 (الشبكات المتبقية) عبارة عن شبكة عصبية عميقة (deep neural network) تُستخدم كعمود فقري للعديد من تطبيقات رؤية الحاسوبیة مثل اكتشاف الاشیاء وتجزئة الصور وما إلى ذلك. كما وجدت حلاً لمشكلة التدرج المتلاشي (vanishing gradient) التي كانت شائعة في الشبكات العصبية العميقة جدًا مثلها.

في تطبيق Keras لهندسة ResNet-50، سنستخدم مجموعة بيانات Dogs Vs Cats الشهيرة من Kaggle.

بنیة ResNet-50

في السنوات الأخيرة من ثورة التعلم العميق (deep learning)، أصبحت الشبكات العصبية أعمق، حيث انتقلت الشبكات الحديثة من طبقات قليلة فقط (على سبيل المثال، VGG16) إلى أكثر من مائة طبقة. الفائدة الرئيسية للشبكة العميقة هي أنها يمكن أن تمثل وظائف معقدة للغاية. يمكنه أيضًا التعرف على ميزات في العديد من مستويات التجريد المختلفة، على سبيل المثال، الحواف (في الطبقات السفلية (low layers)) إلى الخصائص المعقدة جدًا (في الطبقات العميقة (deep layers)) في حالة الصورة.

تنفيذ بنیة ResNet-50 فی Keras

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

اتصال التخطي (skip connection)

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

هناك نوعان رئيسيان من الكتل المستخدمة في شبكة ResNet، اعتمادًا بشكل أساسي على ما إذا كانت أبعاد الإدخال/ الإخراج هي نفسها أو مختلفة.

كتلة الهوية (identity block)

كتلة الهوية (identity block) هي الكتلة القياسية المستخدمة في ResNets وتتوافق مع الحالة التي يكون فيها تفعیل الإدخال له نفس أبعاد تنشيط الإخراج.

تنفيذ بنیة ResNet-50 فی Keras

الكتلة التلافيفية (convolutional block)

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

تنفيذ بنیة ResNet-50 فی Keras

ResNet-50

يتكون نموذج ResNet-50 من 5 مراحل لكل منها كتلة التفاف (convolutional) وهوية (identity). تحتوي كل كتلة التفاف على 3 طبقات التفاف ولكل كتلة هوية أيضًا 3 طبقات التفاف. يحتوي ResNet-50 على أكثر من 23 مليون معلمة قابلة للتدريب.

تنفيذ بنیة ResNet-50 فی Keras

تنفيذ ResNet-50 فی keras

استيراد المكتبات وإعداد GPU:

import cv2
import numpy as np
import os
from keras.preprocessing.image import ImageDataGenerator
from keras import backend as K
import keras
from keras.models import Sequential, Model,load_model
from keras.optimizers import SGD
from keras.callbacks import EarlyStopping,ModelCheckpoint
from google.colab.patches import cv2_imshow
from keras.layers import Input, Add, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D, AveragePooling2D, MaxPooling2D, GlobalMaxPooling2D,MaxPool2D
from keras.preprocessing import image
from keras.initializers import glorot_uniform

يستخدم الكود أدناه لتحديد GPU:

K.tensorflow_backend._get_available_gpus()

تحديد مسار التدريب والاختبار لمجموعة البيانات

من الضروري وضع صور كلا الفئتين في مجلدات فرعية منفصلة ضمن مجلد التدريب والاختبار كما هو موضح أدناه:

train_path="/content/gdrive/My Drive/datasets/train"
test_path="/content/gdrive/My Drive/datasets/test"
class_names=os.listdir(train_path)
class_names_test=os.listdir(test_path)

دعنا نتحقق من أسماء فئات المجلدات عن طريق طباعتها:

الإدخال:

print(class_names)
print(class_names_test)

الإخراج:

['cat', 'dog']
['Cat', 'Dog']

دعنا نقرأ فقط بعض الصور العشوائية لمجموعة البيانات لنرى أنواع الصور التي لدينا. تم تعطيل استخدام cv2.imshow في Colab لأنه يتسبب في تعطل جلسات Jupyter، لذلك كبديل، نستخدم ()cv2_imshow.

#Sample datasets images
image_dog=cv2.imread("/content/gdrive/My Drive/datasets/test/Dog/4.jpg")
cv2_imshow(image_dog)
image_cat=cv2.imread("/content/gdrive/My Drive/datasets/test/Cat/5.jpg")
cv2_imshow(image_cat)

تحضير مجموعات البيانات (data preparation)

في بعض الأحيان نواجه مشكلات حيث نحاول تحميل مجموعة بيانات حیث لا توجد ذاكرة كافية في جهازك. يوفر Keras فئة ImageDataGenerator التي تحدد التكوين لإعداد بيانات الصورة وزيادتها. يقوم المُنشئ (generator) بتحميل الصور بشكل تدريجي في مجموعة البيانات الخاصة بك، مما يسمح لك بالعمل مع مجموعات بيانات كبيرة جدًا تحتوي على آلاف أو ملايين الصور التي قد لا تتناسب مع ذاكرة النظام.

train_datagen = ImageDataGenerator(zoom_range=0.15,width_shift_range=0.2,height_shift_range=0.2,shear_range=0.15)
test_datagen = ImageDataGenerator()
train_generator = train_datagen.flow_from_directory("/content/gdrive/My Drive/datasets/train",target_size=(224, 224),batch_size=32,shuffle=True,class_mode='binary')
test_generator = test_datagen.flow_from_directory("/content/gdrive/My Drive/datasets/test",target_size=(224,224),batch_size=32,shuffle=False,class_mode='binary')

الإخراج:

Found 25000 images belonging to 2 classes.
Found 627 images belonging to 2 classes.

تنفيذ كتلة الهوية (identity block)

دعونا ننفذ كتلة الهوية في keras:

def identity_block(X, f, filters, stage, block):
   
    conv_name_base = 'res' + str(stage) + block + '_branch'
    bn_name_base = 'bn' + str(stage) + block + '_branch'
    F1, F2, F3 = filters

    X_shortcut = X
   
    X = Conv2D(filters=F1, kernel_size=(1, 1), strides=(1, 1), padding='valid', name=conv_name_base + '2a', kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3, name=bn_name_base + '2a')(X)
    X = Activation('relu')(X)

    X = Conv2D(filters=F2, kernel_size=(f, f), strides=(1, 1), padding='same', name=conv_name_base + '2b', kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3, name=bn_name_base + '2b')(X)
    X = Activation('relu')(X)

    X = Conv2D(filters=F3, kernel_size=(1, 1), strides=(1, 1), padding='valid', name=conv_name_base + '2c', kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3, name=bn_name_base + '2c')(X)

    X = Add()([X, X_shortcut])# SKIP Connection
    X = Activation('relu')(X)

    return X

تنفيذ الكتلة التلافيفية (convolutional block)

دعونا ننفذ الكتلة التلافيفية في keras:

def convolutional_block(X, f, filters, stage, block, s=2):
   
    conv_name_base = 'res' + str(stage) + block + '_branch'
    bn_name_base = 'bn' + str(stage) + block + '_branch'

    F1, F2, F3 = filters

    X_shortcut = X

    X = Conv2D(filters=F1, kernel_size=(1, 1), strides=(s, s), padding='valid', name=conv_name_base + '2a', kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3, name=bn_name_base + '2a')(X)
    X = Activation('relu')(X)

    X = Conv2D(filters=F2, kernel_size=(f, f), strides=(1, 1), padding='same', name=conv_name_base + '2b', kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3, name=bn_name_base + '2b')(X)
    X = Activation('relu')(X)

    X = Conv2D(filters=F3, kernel_size=(1, 1), strides=(1, 1), padding='valid', name=conv_name_base + '2c', kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3, name=bn_name_base + '2c')(X)

    X_shortcut = Conv2D(filters=F3, kernel_size=(1, 1), strides=(s, s), padding='valid', name=conv_name_base + '1', kernel_initializer=glorot_uniform(seed=0))(X_shortcut)
    X_shortcut = BatchNormalization(axis=3, name=bn_name_base + '1')(X_shortcut)

    X = Add()([X, X_shortcut])
    X = Activation('relu')(X)

    return X

تنفيذ ResNet-50

في تطبيق Keras هذا لـ ResNet -50، لم نحدد الطبقة المتصلة بالكامل (fully connected layer) في الشبكة. سنرى لاحقا لماذا.

def ResNet50(input_shape=(224, 224, 3)):

    X_input = Input(input_shape)

    X = ZeroPadding2D((3, 3))(X_input)

    X = Conv2D(64, (7, 7), strides=(2, 2), name='conv1', kernel_initializer=glorot_uniform(seed=0))(X)
    X = BatchNormalization(axis=3, name='bn_conv1')(X)
    X = Activation('relu')(X)
    X = MaxPooling2D((3, 3), strides=(2, 2))(X)

    X = convolutional_block(X, f=3, filters=[64, 64, 256], stage=2, block='a', s=1)
    X = identity_block(X, 3, [64, 64, 256], stage=2, block='b')
    X = identity_block(X, 3, [64, 64, 256], stage=2, block='c')


    X = convolutional_block(X, f=3, filters=[128, 128, 512], stage=3, block='a', s=2)
    X = identity_block(X, 3, [128, 128, 512], stage=3, block='b')
    X = identity_block(X, 3, [128, 128, 512], stage=3, block='c')
    X = identity_block(X, 3, [128, 128, 512], stage=3, block='d')

    X = convolutional_block(X, f=3, filters=[256, 256, 1024], stage=4, block='a', s=2)
    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='b')
    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='c')
    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='d')
    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='e')
    X = identity_block(X, 3, [256, 256, 1024], stage=4, block='f')

    X = X = convolutional_block(X, f=3, filters=[512, 512, 2048], stage=5, block='a', s=2)
    X = identity_block(X, 3, [512, 512, 2048], stage=5, block='b')
    X = identity_block(X, 3, [512, 512, 2048], stage=5, block='c')

    X = AveragePooling2D(pool_size=(2, 2), padding='same')(X)
    
    model = Model(inputs=X_input, outputs=X, name='ResNet50')

    return model
base_model = ResNet50(input_shape=(224, 224, 3))

مفهوم سريع حول تعلم النقل (transfer learning)

تستغرق الشبكة العصبية التلافيفية العميقة أيامًا للتدريب ويتطلب تدريبها الكثير من الموارد الحسابية. لذلك للتغلب على هذا، نستخدم التعلم بالنقل في تطبيق Keras هذا لـ ResNet 50.

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

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

هنا، سنعيد استخدام أوزان النموذج من النماذج المدربة مسبقًا التي تم تطويرها لمجموعات البيانات المعيارية لقياس رؤية الحاسوبیة مثل ImageNet. لذلك قمنا بتنزيل الأوزان المدربة مسبقًا التي لا تحتوي على أوزان طبقات عليا. لقد استبدلنا الطبقة الأخيرة بطبقتنا الخاصة ولا تحتوي الأوزان المدربة مسبقًا على أوزان ثلاث طبقات الكثيفة (dense layers) الحدیثة. لهذا السبب يتعين علينا تنزيل طبقة مُدربة مسبقًا بدون أعلى.

headModel = base_model.output
headModel = Flatten()(headModel)
headModel=Dense(256, activation='relu', name='fc1',kernel_initializer=glorot_uniform(seed=0))(headModel)
headModel=Dense(128, activation='relu', name='fc2',kernel_initializer=glorot_uniform(seed=0))(headModel)
headModel = Dense( 1,activation='sigmoid', name='fc3',kernel_initializer=glorot_uniform(seed=0))(headModel)

أخيرًا، لنقم بإنشاء النموذج الذي يأخذ المدخلات من الطبقة الأخيرة من طبقة الإدخال والمخرجات من الطبقة الأخيرة من نموذج الرأس.

model = Model(inputs=base_model.input, outputs=headModel)

هنا ملخص النموذج:

model.summary()

الإخراج:

Model: "model_1"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            (None, 224, 224, 3)  0                                            
__________________________________________________________________________________________________
zero_padding2d_1 (ZeroPadding2D (None, 230, 230, 3)  0           input_1[0][0]                    
__________________________________________________________________________________________________
conv1 (Conv2D)                  (None, 112, 112, 64) 9472        zero_padding2d_1[0][0]           
__________________________________________________________________________________________________
bn_conv1 (BatchNormalization)   (None, 112, 112, 64) 256         conv1[0][0]                      
__________________________________________________________________________________________________
activation_1 (Activation)       (None, 112, 112, 64) 0           bn_conv1[0][0]                   
__________________________________________________________________________________________________
max_pooling2d_1 (MaxPooling2D)  (None, 55, 55, 64)   0           activation_1[0][0]               
__________________________________________________________________________________________________
res2a_branch2a (Conv2D)         (None, 55, 55, 64)   4160        max_pooling2d_1[0][0]            
__________________________________________________________________________________________________
bn2a_branch2a (BatchNormalizati (None, 55, 55, 64)   256         res2a_branch2a[0][0]             
__________________________________________________________________________________________________
activation_2 (Activation)       (None, 55, 55, 64)   0           bn2a_branch2a[0][0]              
__________________________________________________________________________________________________
res2a_branch2b (Conv2D)         (None, 55, 55, 64)   36928       activation_2[0][0]               
__________________________________________________________________________________________________
bn2a_branch2b (BatchNormalizati (None, 55, 55, 64)   256         res2a_branch2b[0][0]             
__________________________________________________________________________________________________
activation_3 (Activation)       (None, 55, 55, 64)   0           bn2a_branch2b[0][0]              
__________________________________________________________________________________________________
res2a_branch2c (Conv2D)         (None, 55, 55, 256)  16640       activation_3[0][0]               
__________________________________________________________________________________________________
res2a_branch1 (Conv2D)          (None, 55, 55, 256)  16640       max_pooling2d_1[0][0]            
__________________________________________________________________________________________________
bn2a_branch2c (BatchNormalizati (None, 55, 55, 256)  1024        res2a_branch2c[0][0]             
__________________________________________________________________________________________________
bn2a_branch1 (BatchNormalizatio (None, 55, 55, 256)  1024        res2a_branch1[0][0]              
__________________________________________________________________________________________________
add_1 (Add)                     (None, 55, 55, 256)  0           bn2a_branch2c[0][0]              
                                                                 bn2a_branch1[0][0]               
__________________________________________________________________________________________________
activation_4 (Activation)       (None, 55, 55, 256)  0           add_1[0][0]                      
__________________________________________________________________________________________________
res2b_branch2a (Conv2D)         (None, 55, 55, 64)   16448       activation_4[0][0]               
__________________________________________________________________________________________________
bn2b_branch2a (BatchNormalizati (None, 55, 55, 64)   256         res2b_branch2a[0][0]             
__________________________________________________________________________________________________
activation_5 (Activation)       (None, 55, 55, 64)   0           bn2b_branch2a[0][0]              
__________________________________________________________________________________________________
res2b_branch2b (Conv2D)         (None, 55, 55, 64)   36928       activation_5[0][0]               
__________________________________________________________________________________________________
bn2b_branch2b (BatchNormalizati (None, 55, 55, 64)   256         res2b_branch2b[0][0]             
__________________________________________________________________________________________________
activation_6 (Activation)       (None, 55, 55, 64)   0           bn2b_branch2b[0][0]              
__________________________________________________________________________________________________
res2b_branch2c (Conv2D)         (None, 55, 55, 256)  16640       activation_6[0][0]               
__________________________________________________________________________________________________
bn2b_branch2c (BatchNormalizati (None, 55, 55, 256)  1024        res2b_branch2c[0][0]             
__________________________________________________________________________________________________
add_2 (Add)                     (None, 55, 55, 256)  0           bn2b_branch2c[0][0]              
                                                                 activation_4[0][0]               
__________________________________________________________________________________________________
activation_7 (Activation)       (None, 55, 55, 256)  0           add_2[0][0]                      
__________________________________________________________________________________________________
res2c_branch2a (Conv2D)         (None, 55, 55, 64)   16448       activation_7[0][0]               
__________________________________________________________________________________________________
bn2c_branch2a (BatchNormalizati (None, 55, 55, 64)   256         res2c_branch2a[0][0]             
__________________________________________________________________________________________________
activation_8 (Activation)       (None, 55, 55, 64)   0           bn2c_branch2a[0][0]              
__________________________________________________________________________________________________
res2c_branch2b (Conv2D)         (None, 55, 55, 64)   36928       activation_8[0][0]               
__________________________________________________________________________________________________
bn2c_branch2b (BatchNormalizati (None, 55, 55, 64)   256         res2c_branch2b[0][0]             
__________________________________________________________________________________________________
activation_9 (Activation)       (None, 55, 55, 64)   0           bn2c_branch2b[0][0]              
__________________________________________________________________________________________________
res2c_branch2c (Conv2D)         (None, 55, 55, 256)  16640       activation_9[0][0]               
__________________________________________________________________________________________________
bn2c_branch2c (BatchNormalizati (None, 55, 55, 256)  1024        res2c_branch2c[0][0]             
__________________________________________________________________________________________________
add_3 (Add)                     (None, 55, 55, 256)  0           bn2c_branch2c[0][0]              
                                                                 activation_7[0][0]               
__________________________________________________________________________________________________
activation_10 (Activation)      (None, 55, 55, 256)  0           add_3[0][0]                      
__________________________________________________________________________________________________
res3a_branch2a (Conv2D)         (None, 28, 28, 128)  32896       activation_10[0][0]              
__________________________________________________________________________________________________
bn3a_branch2a (BatchNormalizati (None, 28, 28, 128)  512         res3a_branch2a[0][0]             
__________________________________________________________________________________________________
activation_11 (Activation)      (None, 28, 28, 128)  0           bn3a_branch2a[0][0]              
__________________________________________________________________________________________________
res3a_branch2b (Conv2D)         (None, 28, 28, 128)  147584      activation_11[0][0]              
__________________________________________________________________________________________________
bn3a_branch2b (BatchNormalizati (None, 28, 28, 128)  512         res3a_branch2b[0][0]             
__________________________________________________________________________________________________
activation_12 (Activation)      (None, 28, 28, 128)  0           bn3a_branch2b[0][0]              
__________________________________________________________________________________________________
res3a_branch2c (Conv2D)         (None, 28, 28, 512)  66048       activation_12[0][0]              
__________________________________________________________________________________________________
res3a_branch1 (Conv2D)          (None, 28, 28, 512)  131584      activation_10[0][0]              
__________________________________________________________________________________________________
bn3a_branch2c (BatchNormalizati (None, 28, 28, 512)  2048        res3a_branch2c[0][0]             
__________________________________________________________________________________________________
bn3a_branch1 (BatchNormalizatio (None, 28, 28, 512)  2048        res3a_branch1[0][0]              
__________________________________________________________________________________________________
add_4 (Add)                     (None, 28, 28, 512)  0           bn3a_branch2c[0][0]              
                                                                 bn3a_branch1[0][0]               
__________________________________________________________________________________________________
activation_13 (Activation)      (None, 28, 28, 512)  0           add_4[0][0]                      
__________________________________________________________________________________________________
res3b_branch2a (Conv2D)         (None, 28, 28, 128)  65664       activation_13[0][0]              
__________________________________________________________________________________________________
bn3b_branch2a (BatchNormalizati (None, 28, 28, 128)  512         res3b_branch2a[0][0]             
__________________________________________________________________________________________________
activation_14 (Activation)      (None, 28, 28, 128)  0           bn3b_branch2a[0][0]              
__________________________________________________________________________________________________
res3b_branch2b (Conv2D)         (None, 28, 28, 128)  147584      activation_14[0][0]              
__________________________________________________________________________________________________
bn3b_branch2b (BatchNormalizati (None, 28, 28, 128)  512         res3b_branch2b[0][0]             
__________________________________________________________________________________________________
activation_15 (Activation)      (None, 28, 28, 128)  0           bn3b_branch2b[0][0]              
__________________________________________________________________________________________________
res3b_branch2c (Conv2D)         (None, 28, 28, 512)  66048       activation_15[0][0]              
__________________________________________________________________________________________________
bn3b_branch2c (BatchNormalizati (None, 28, 28, 512)  2048        res3b_branch2c[0][0]             
__________________________________________________________________________________________________
add_5 (Add)                     (None, 28, 28, 512)  0           bn3b_branch2c[0][0]              
                                                                 activation_13[0][0]              
__________________________________________________________________________________________________
activation_16 (Activation)      (None, 28, 28, 512)  0           add_5[0][0]                      
__________________________________________________________________________________________________
res3c_branch2a (Conv2D)         (None, 28, 28, 128)  65664       activation_16[0][0]              
__________________________________________________________________________________________________
bn3c_branch2a (BatchNormalizati (None, 28, 28, 128)  512         res3c_branch2a[0][0]             
__________________________________________________________________________________________________
activation_17 (Activation)      (None, 28, 28, 128)  0           bn3c_branch2a[0][0]              
__________________________________________________________________________________________________
res3c_branch2b (Conv2D)         (None, 28, 28, 128)  147584      activation_17[0][0]              
__________________________________________________________________________________________________
bn3c_branch2b (BatchNormalizati (None, 28, 28, 128)  512         res3c_branch2b[0][0]             
__________________________________________________________________________________________________
activation_18 (Activation)      (None, 28, 28, 128)  0           bn3c_branch2b[0][0]              
__________________________________________________________________________________________________
res3c_branch2c (Conv2D)         (None, 28, 28, 512)  66048       activation_18[0][0]              
__________________________________________________________________________________________________
bn3c_branch2c (BatchNormalizati (None, 28, 28, 512)  2048        res3c_branch2c[0][0]             
__________________________________________________________________________________________________
add_6 (Add)                     (None, 28, 28, 512)  0           bn3c_branch2c[0][0]              
                                                                 activation_16[0][0]              
__________________________________________________________________________________________________
activation_19 (Activation)      (None, 28, 28, 512)  0           add_6[0][0]                      
__________________________________________________________________________________________________
res3d_branch2a (Conv2D)         (None, 28, 28, 128)  65664       activation_19[0][0]              
__________________________________________________________________________________________________
bn3d_branch2a (BatchNormalizati (None, 28, 28, 128)  512         res3d_branch2a[0][0]             
__________________________________________________________________________________________________
activation_20 (Activation)      (None, 28, 28, 128)  0           bn3d_branch2a[0][0]              
__________________________________________________________________________________________________
res3d_branch2b (Conv2D)         (None, 28, 28, 128)  147584      activation_20[0][0]              
__________________________________________________________________________________________________
bn3d_branch2b (BatchNormalizati (None, 28, 28, 128)  512         res3d_branch2b[0][0]             
__________________________________________________________________________________________________
activation_21 (Activation)      (None, 28, 28, 128)  0           bn3d_branch2b[0][0]              
__________________________________________________________________________________________________
res3d_branch2c (Conv2D)         (None, 28, 28, 512)  66048       activation_21[0][0]              
__________________________________________________________________________________________________
bn3d_branch2c (BatchNormalizati (None, 28, 28, 512)  2048        res3d_branch2c[0][0]             
__________________________________________________________________________________________________
add_7 (Add)                     (None, 28, 28, 512)  0           bn3d_branch2c[0][0]              
                                                                 activation_19[0][0]              
__________________________________________________________________________________________________
activation_22 (Activation)      (None, 28, 28, 512)  0           add_7[0][0]                      
__________________________________________________________________________________________________
res4a_branch2a (Conv2D)         (None, 14, 14, 256)  131328      activation_22[0][0]              
__________________________________________________________________________________________________
bn4a_branch2a (BatchNormalizati (None, 14, 14, 256)  1024        res4a_branch2a[0][0]             
__________________________________________________________________________________________________
activation_23 (Activation)      (None, 14, 14, 256)  0           bn4a_branch2a[0][0]              
__________________________________________________________________________________________________
res4a_branch2b (Conv2D)         (None, 14, 14, 256)  590080      activation_23[0][0]              
__________________________________________________________________________________________________
bn4a_branch2b (BatchNormalizati (None, 14, 14, 256)  1024        res4a_branch2b[0][0]             
__________________________________________________________________________________________________
activation_24 (Activation)      (None, 14, 14, 256)  0           bn4a_branch2b[0][0]              
__________________________________________________________________________________________________
res4a_branch2c (Conv2D)         (None, 14, 14, 1024) 263168      activation_24[0][0]              
__________________________________________________________________________________________________
res4a_branch1 (Conv2D)          (None, 14, 14, 1024) 525312      activation_22[0][0]              
__________________________________________________________________________________________________
bn4a_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096        res4a_branch2c[0][0]             
__________________________________________________________________________________________________
bn4a_branch1 (BatchNormalizatio (None, 14, 14, 1024) 4096        res4a_branch1[0][0]              
__________________________________________________________________________________________________
add_8 (Add)                     (None, 14, 14, 1024) 0           bn4a_branch2c[0][0]              
                                                                 bn4a_branch1[0][0]               
__________________________________________________________________________________________________
activation_25 (Activation)      (None, 14, 14, 1024) 0           add_8[0][0]                      
__________________________________________________________________________________________________
res4b_branch2a (Conv2D)         (None, 14, 14, 256)  262400      activation_25[0][0]              
__________________________________________________________________________________________________
bn4b_branch2a (BatchNormalizati (None, 14, 14, 256)  1024        res4b_branch2a[0][0]             
__________________________________________________________________________________________________
activation_26 (Activation)      (None, 14, 14, 256)  0           bn4b_branch2a[0][0]              
__________________________________________________________________________________________________
res4b_branch2b (Conv2D)         (None, 14, 14, 256)  590080      activation_26[0][0]              
__________________________________________________________________________________________________
bn4b_branch2b (BatchNormalizati (None, 14, 14, 256)  1024        res4b_branch2b[0][0]             
__________________________________________________________________________________________________
activation_27 (Activation)      (None, 14, 14, 256)  0           bn4b_branch2b[0][0]              
__________________________________________________________________________________________________
res4b_branch2c (Conv2D)         (None, 14, 14, 1024) 263168      activation_27[0][0]              
__________________________________________________________________________________________________
bn4b_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096        res4b_branch2c[0][0]             
__________________________________________________________________________________________________
add_9 (Add)                     (None, 14, 14, 1024) 0           bn4b_branch2c[0][0]              
                                                                 activation_25[0][0]              
__________________________________________________________________________________________________
activation_28 (Activation)      (None, 14, 14, 1024) 0           add_9[0][0]                      
__________________________________________________________________________________________________
res4c_branch2a (Conv2D)         (None, 14, 14, 256)  262400      activation_28[0][0]              
__________________________________________________________________________________________________
bn4c_branch2a (BatchNormalizati (None, 14, 14, 256)  1024        res4c_branch2a[0][0]             
__________________________________________________________________________________________________
activation_29 (Activation)      (None, 14, 14, 256)  0           bn4c_branch2a[0][0]              
__________________________________________________________________________________________________
res4c_branch2b (Conv2D)         (None, 14, 14, 256)  590080      activation_29[0][0]              
__________________________________________________________________________________________________
bn4c_branch2b (BatchNormalizati (None, 14, 14, 256)  1024        res4c_branch2b[0][0]             
__________________________________________________________________________________________________
activation_30 (Activation)      (None, 14, 14, 256)  0           bn4c_branch2b[0][0]              
__________________________________________________________________________________________________
res4c_branch2c (Conv2D)         (None, 14, 14, 1024) 263168      activation_30[0][0]              
__________________________________________________________________________________________________
bn4c_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096        res4c_branch2c[0][0]             
__________________________________________________________________________________________________
add_10 (Add)                    (None, 14, 14, 1024) 0           bn4c_branch2c[0][0]              
                                                                 activation_28[0][0]              
__________________________________________________________________________________________________
activation_31 (Activation)      (None, 14, 14, 1024) 0           add_10[0][0]                     
__________________________________________________________________________________________________
res4d_branch2a (Conv2D)         (None, 14, 14, 256)  262400      activation_31[0][0]              
__________________________________________________________________________________________________
bn4d_branch2a (BatchNormalizati (None, 14, 14, 256)  1024        res4d_branch2a[0][0]             
__________________________________________________________________________________________________
activation_32 (Activation)      (None, 14, 14, 256)  0           bn4d_branch2a[0][0]              
__________________________________________________________________________________________________
res4d_branch2b (Conv2D)         (None, 14, 14, 256)  590080      activation_32[0][0]              
__________________________________________________________________________________________________
bn4d_branch2b (BatchNormalizati (None, 14, 14, 256)  1024        res4d_branch2b[0][0]             
__________________________________________________________________________________________________
activation_33 (Activation)      (None, 14, 14, 256)  0           bn4d_branch2b[0][0]              
__________________________________________________________________________________________________
res4d_branch2c (Conv2D)         (None, 14, 14, 1024) 263168      activation_33[0][0]              
__________________________________________________________________________________________________
bn4d_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096        res4d_branch2c[0][0]             
__________________________________________________________________________________________________
add_11 (Add)                    (None, 14, 14, 1024) 0           bn4d_branch2c[0][0]              
                                                                 activation_31[0][0]              
__________________________________________________________________________________________________
activation_34 (Activation)      (None, 14, 14, 1024) 0           add_11[0][0]                     
__________________________________________________________________________________________________
res4e_branch2a (Conv2D)         (None, 14, 14, 256)  262400      activation_34[0][0]              
__________________________________________________________________________________________________
bn4e_branch2a (BatchNormalizati (None, 14, 14, 256)  1024        res4e_branch2a[0][0]             
__________________________________________________________________________________________________
activation_35 (Activation)      (None, 14, 14, 256)  0           bn4e_branch2a[0][0]              
__________________________________________________________________________________________________
res4e_branch2b (Conv2D)         (None, 14, 14, 256)  590080      activation_35[0][0]              
__________________________________________________________________________________________________
bn4e_branch2b (BatchNormalizati (None, 14, 14, 256)  1024        res4e_branch2b[0][0]             
__________________________________________________________________________________________________
activation_36 (Activation)      (None, 14, 14, 256)  0           bn4e_branch2b[0][0]              
__________________________________________________________________________________________________
res4e_branch2c (Conv2D)         (None, 14, 14, 1024) 263168      activation_36[0][0]              
__________________________________________________________________________________________________
bn4e_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096        res4e_branch2c[0][0]             
__________________________________________________________________________________________________
add_12 (Add)                    (None, 14, 14, 1024) 0           bn4e_branch2c[0][0]              
                                                                 activation_34[0][0]              
__________________________________________________________________________________________________
activation_37 (Activation)      (None, 14, 14, 1024) 0           add_12[0][0]                     
__________________________________________________________________________________________________
res4f_branch2a (Conv2D)         (None, 14, 14, 256)  262400      activation_37[0][0]              
__________________________________________________________________________________________________
bn4f_branch2a (BatchNormalizati (None, 14, 14, 256)  1024        res4f_branch2a[0][0]             
__________________________________________________________________________________________________
activation_38 (Activation)      (None, 14, 14, 256)  0           bn4f_branch2a[0][0]              
__________________________________________________________________________________________________
res4f_branch2b (Conv2D)         (None, 14, 14, 256)  590080      activation_38[0][0]              
__________________________________________________________________________________________________
bn4f_branch2b (BatchNormalizati (None, 14, 14, 256)  1024        res4f_branch2b[0][0]             
__________________________________________________________________________________________________
activation_39 (Activation)      (None, 14, 14, 256)  0           bn4f_branch2b[0][0]              
__________________________________________________________________________________________________
res4f_branch2c (Conv2D)         (None, 14, 14, 1024) 263168      activation_39[0][0]              
__________________________________________________________________________________________________
bn4f_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096        res4f_branch2c[0][0]             
__________________________________________________________________________________________________
add_13 (Add)                    (None, 14, 14, 1024) 0           bn4f_branch2c[0][0]              
                                                                 activation_37[0][0]              
__________________________________________________________________________________________________
activation_40 (Activation)      (None, 14, 14, 1024) 0           add_13[0][0]                     
__________________________________________________________________________________________________
res5a_branch2a (Conv2D)         (None, 7, 7, 512)    524800      activation_40[0][0]              
__________________________________________________________________________________________________
bn5a_branch2a (BatchNormalizati (None, 7, 7, 512)    2048        res5a_branch2a[0][0]             
__________________________________________________________________________________________________
activation_41 (Activation)      (None, 7, 7, 512)    0           bn5a_branch2a[0][0]              
__________________________________________________________________________________________________
res5a_branch2b (Conv2D)         (None, 7, 7, 512)    2359808     activation_41[0][0]              
__________________________________________________________________________________________________
bn5a_branch2b (BatchNormalizati (None, 7, 7, 512)    2048        res5a_branch2b[0][0]             
__________________________________________________________________________________________________
activation_42 (Activation)      (None, 7, 7, 512)    0           bn5a_branch2b[0][0]              
__________________________________________________________________________________________________
res5a_branch2c (Conv2D)         (None, 7, 7, 2048)   1050624     activation_42[0][0]              
__________________________________________________________________________________________________
res5a_branch1 (Conv2D)          (None, 7, 7, 2048)   2099200     activation_40[0][0]              
__________________________________________________________________________________________________
bn5a_branch2c (BatchNormalizati (None, 7, 7, 2048)   8192        res5a_branch2c[0][0]             
__________________________________________________________________________________________________
bn5a_branch1 (BatchNormalizatio (None, 7, 7, 2048)   8192        res5a_branch1[0][0]              
__________________________________________________________________________________________________
add_14 (Add)                    (None, 7, 7, 2048)   0           bn5a_branch2c[0][0]              
                                                                 bn5a_branch1[0][0]               
__________________________________________________________________________________________________
activation_43 (Activation)      (None, 7, 7, 2048)   0           add_14[0][0]                     
__________________________________________________________________________________________________
res5b_branch2a (Conv2D)         (None, 7, 7, 512)    1049088     activation_43[0][0]              
__________________________________________________________________________________________________
bn5b_branch2a (BatchNormalizati (None, 7, 7, 512)    2048        res5b_branch2a[0][0]             
__________________________________________________________________________________________________
activation_44 (Activation)      (None, 7, 7, 512)    0           bn5b_branch2a[0][0]              
__________________________________________________________________________________________________
res5b_branch2b (Conv2D)         (None, 7, 7, 512)    2359808     activation_44[0][0]              
__________________________________________________________________________________________________
bn5b_branch2b (BatchNormalizati (None, 7, 7, 512)    2048        res5b_branch2b[0][0]             
__________________________________________________________________________________________________
activation_45 (Activation)      (None, 7, 7, 512)    0           bn5b_branch2b[0][0]              
__________________________________________________________________________________________________
res5b_branch2c (Conv2D)         (None, 7, 7, 2048)   1050624     activation_45[0][0]              
__________________________________________________________________________________________________
bn5b_branch2c (BatchNormalizati (None, 7, 7, 2048)   8192        res5b_branch2c[0][0]             
__________________________________________________________________________________________________
add_15 (Add)                    (None, 7, 7, 2048)   0           bn5b_branch2c[0][0]              
                                                                 activation_43[0][0]              
__________________________________________________________________________________________________
activation_46 (Activation)      (None, 7, 7, 2048)   0           add_15[0][0]                     
__________________________________________________________________________________________________
res5c_branch2a (Conv2D)         (None, 7, 7, 512)    1049088     activation_46[0][0]              
__________________________________________________________________________________________________
bn5c_branch2a (BatchNormalizati (None, 7, 7, 512)    2048        res5c_branch2a[0][0]             
__________________________________________________________________________________________________
activation_47 (Activation)      (None, 7, 7, 512)    0           bn5c_branch2a[0][0]              
__________________________________________________________________________________________________
res5c_branch2b (Conv2D)         (None, 7, 7, 512)    2359808     activation_47[0][0]              
__________________________________________________________________________________________________
bn5c_branch2b (BatchNormalizati (None, 7, 7, 512)    2048        res5c_branch2b[0][0]             
__________________________________________________________________________________________________
activation_48 (Activation)      (None, 7, 7, 512)    0           bn5c_branch2b[0][0]              
__________________________________________________________________________________________________
res5c_branch2c (Conv2D)         (None, 7, 7, 2048)   1050624     activation_48[0][0]              
__________________________________________________________________________________________________
bn5c_branch2c (BatchNormalizati (None, 7, 7, 2048)   8192        res5c_branch2c[0][0]             
__________________________________________________________________________________________________
add_16 (Add)                    (None, 7, 7, 2048)   0           bn5c_branch2c[0][0]              
                                                                 activation_46[0][0]              
__________________________________________________________________________________________________
activation_49 (Activation)      (None, 7, 7, 2048)   0           add_16[0][0]                     
__________________________________________________________________________________________________
average_pooling2d_1 (AveragePoo (None, 4, 4, 2048)   0           activation_49[0][0]              
__________________________________________________________________________________________________
flatten_1 (Flatten)             (None, 32768)        0           average_pooling2d_1[0][0]        
__________________________________________________________________________________________________
fc1 (Dense)                     (None, 256)          8388864     flatten_1[0][0]                  
__________________________________________________________________________________________________
fc2 (Dense)                     (None, 128)          32896       fc1[0][0]                        
__________________________________________________________________________________________________
fc3 (Dense)                     (None, 1)            129         fc2[0][0]                        
==================================================================================================
Total params: 32,009,601
Trainable params: 31,956,481
Non-trainable params: 53,120
__________________________________________________________________________________________________

سنقم بتحميل أوزان النموذج المدربة مسبقًا:

(انقر هنا لتنزيل الأوزان المدربة مسبقًا.)

base_model.load_weights("/content/gdrive/My Drive/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5")

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

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

في حالتنا، نقوم بتجميد كل الكتلة التلافيفية (convolutional block) للنموذج.

for layer in base_model.layers:
    layer.trainable = False

دعونا نطبع كل الطبقات في نموذج ResNet 50 الخاص بنا. كما ترى هنا حتى آخر طبقة Maxpooling، فهذا False، وهذا يعني أنه أثناء التدريب لن يتم تحديث معلمات (parameters) هذه الطبقة وأن الطبقات الثلاث الأخيرة لديها مجموعات معلمات قابلة للتدريب إلى True، وبالتالي أثناء التدريب يتم تحديث معلمة هذه الطبقة.

for layer in model.layers:
    print(layer, layer.trainable)

الإخراج:

<keras.engine.input_layer.InputLayer object at 0x7f5bdd4602e8> False
<keras.layers.convolutional.ZeroPadding2D object at 0x7f5bd41ecfd0> False
<keras.layers.convolutional.Conv2D object at 0x7f5bc042f048> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c7f5390> False
<keras.layers.core.Activation object at 0x7f5b6c7f5e80> False
<keras.layers.pooling.MaxPooling2D object at 0x7f5bc043db00> False
<keras.layers.convolutional.Conv2D object at 0x7f5c349fc198> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cf9ee80> False
<keras.layers.core.Activation object at 0x7f5b6cf9ee48> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cf47a90> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cf4f080> False
<keras.layers.core.Activation object at 0x7f5b6cf5f518> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cf08a90> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cf3b7f0> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cf0f160> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cecb8d0> False
<keras.layers.merge.Add object at 0x7f5b6ced15f8> False
<keras.layers.core.Activation object at 0x7f5b6cee9860> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6ce83898> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6ce8ca90> False
<keras.layers.core.Activation object at 0x7f5b6ce8ccf8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6ce3ef60> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6ce3efd0> False
<keras.layers.core.Activation object at 0x7f5b6ce4c6d8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6ce78e80> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cdfe3c8> False
<keras.layers.merge.Add object at 0x7f5b6ce06b38> False
<keras.layers.core.Activation object at 0x7f5b6ce1d898> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6ce3b898> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6ce3b9b0> False
<keras.layers.core.Activation object at 0x7f5b6cdc0b70> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cdf2f98> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cdf2d30> False
<keras.layers.core.Activation object at 0x7f5b6cd826a0> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cdade48> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cdb6390> False
<keras.layers.merge.Add object at 0x7f5b6cdbdb00> False
<keras.layers.core.Activation object at 0x7f5b6cd52860> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cd6f898> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cd78a90> False
<keras.layers.core.Activation object at 0x7f5b6cd78c88> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cd2bf98> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cd2bd30> False
<keras.layers.core.Activation object at 0x7f5b6cd3b6a0> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cce3e80> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cc989b0> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cced3c8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cca4a90> False
<keras.layers.merge.Add object at 0x7f5b6ccad7b8> False
<keras.layers.core.Activation object at 0x7f5b6cc45a20> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cc60a58> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cc67c50> False
<keras.layers.core.Activation object at 0x7f5b6cc67eb8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cc1a9b0> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cc20080> False
<keras.layers.core.Activation object at 0x7f5b6cc28898> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cbd4ba8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cbdb588> False
<keras.layers.merge.Add object at 0x7f5b6cbe3cf8> False
<keras.layers.core.Activation object at 0x7f5b6cbf8a58> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cb96a90> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cb9ec88> False
<keras.layers.core.Activation object at 0x7f5b6cb9ee48> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cb509b0> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cb59080> False
<keras.layers.core.Activation object at 0x7f5b6cb5e898> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cb0dba8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cb115c0> False
<keras.layers.merge.Add object at 0x7f5b6cb1cd30> False
<keras.layers.core.Activation object at 0x7f5b6cb2ea58> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6cacda90> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6cad5a58> False
<keras.layers.core.Activation object at 0x7f5b6cad5ac8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6ca869b0> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6ca90080> False
<keras.layers.core.Activation object at 0x7f5b6ca98898> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6ca41ba8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6ca4a5c0> False
<keras.layers.merge.Add object at 0x7f5b6ca52d30> False
<keras.layers.core.Activation object at 0x7f5b6ca66a58> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6ca02a90> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6ca09c88> False
<keras.layers.core.Activation object at 0x7f5b6ca09e80> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6ca3d9b0> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c9c4080> False
<keras.layers.core.Activation object at 0x7f5b6c9cc898> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c9f8ba8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c9acb70> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c97e5c0> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c9bac50> False
<keras.layers.merge.Add object at 0x7f5b6c941978> False
<keras.layers.core.Activation object at 0x7f5b6c95bc50> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c971b70> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c979e48> False
<keras.layers.core.Activation object at 0x7f5b6c8ff5f8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c92edd8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c934320> False
<keras.layers.core.Activation object at 0x7f5b6c93ca90> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c8e8c88> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c8ee7b8> False
<keras.layers.merge.Add object at 0x7f5b6c8f7f28> False
<keras.layers.core.Activation object at 0x7f5b6c894c88> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c8a9ba8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c8afe80> False
<keras.layers.core.Activation object at 0x7f5b6c8bb5f8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c865dd8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c86d320> False
<keras.layers.core.Activation object at 0x7f5b6c873a90> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c822c88> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c8257b8> False
<keras.layers.merge.Add object at 0x7f5b6c82def0> False
<keras.layers.core.Activation object at 0x7f5b6c789c88> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c7a0b70> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c7a8e48> False
<keras.layers.core.Activation object at 0x7f5b6c7af5c0> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c758da0> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c7602e8> False
<keras.layers.core.Activation object at 0x7f5b6c768a58> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c714c88> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c71b7b8> False
<keras.layers.merge.Add object at 0x7f5b6c722f28> False
<keras.layers.core.Activation object at 0x7f5b6c6bfc88> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c6d4ba8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c6dae80> False
<keras.layers.core.Activation object at 0x7f5b6c6e35f8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c68cdd8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c696320> False
<keras.layers.core.Activation object at 0x7f5b6c69fa58> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c649c88> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c6507b8> False
<keras.layers.merge.Add object at 0x7f5b6c658f28> False
<keras.layers.core.Activation object at 0x7f5b6c675c88> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c60cba8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c613e80> False
<keras.layers.core.Activation object at 0x7f5b6c61c5f8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c5c8dd8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c5cf320> False
<keras.layers.core.Activation object at 0x7f5b6c5d7a90> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c57fc88> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c5897b8> False
<keras.layers.merge.Add object at 0x7f5b6c58ff28> False
<keras.layers.core.Activation object at 0x7f5b6c5adc88> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c542ba8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c547e80> False
<keras.layers.core.Activation object at 0x7f5b6c5535f8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c57cdd8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c505320> False
<keras.layers.core.Activation object at 0x7f5b6c50ca90> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c537c88> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c4e8da0> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c4bd7b8> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c4f8c88> False
<keras.layers.merge.Add object at 0x7f5b6c47fba8> False
<keras.layers.core.Activation object at 0x7f5b6c49ee80> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c4b3d68> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c4b8cf8> False
<keras.layers.core.Activation object at 0x7f5b6c4427f0> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c46e7f0> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c474518> False
<keras.layers.core.Activation object at 0x7f5b6c3fec88> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c426e80> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c42a9b0> False
<keras.layers.merge.Add object at 0x7f5b6c42aac8> False
<keras.layers.core.Activation object at 0x7f5b6c3d2eb8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c3e8d68> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c3f1cf8> False
<keras.layers.core.Activation object at 0x7f5b6c3f97b8> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c3a6f98> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c3aa4e0> False
<keras.layers.core.Activation object at 0x7f5b6c3b6c50> False
<keras.layers.convolutional.Conv2D object at 0x7f5b6c35de48> False
<keras.layers.normalization.BatchNormalization object at 0x7f5b6c365978> False
<keras.layers.merge.Add object at 0x7f5b6c365a90> False
<keras.layers.core.Activation object at 0x7f5b6c30aeb8> False
<keras.layers.pooling.AveragePooling2D object at 0x7f5b6c311fd0> False
<keras.layers.core.Flatten object at 0x7f5b6c2c22b0> True
<keras.layers.core.Dense object at 0x7f5b6c2c2c18> True
<keras.layers.core.Dense object at 0x7f5b6c2c7b00> True
<keras.layers.core.Dense object at 0x7f5b6c2d6780> True

ثم نقوم بتجميع (compile) النموذج باستخدام دالة التجمیع. تتوقع هذه دالة ثلاث معلمات: المُحسِّن (optimizer) ودالة التکلفه (loss function) ومقاييس الأداء. المُحسِّن (optimizer) هو خوارزمية نزول التدرج العشوائي (stochastic gradient descent) التي سنستخدمها. نستخدم دالة التکلفة binary_crossentropy لأننا نقوم بتصنيف ثنائي.

EarlyStopping

تتمثل المشكلة الأساسية التي تنشأ في تدريب الشبكة العصبية في تحديد عدد الحقب (epochs) التي يجب تدريب النموذج فيها. قد يؤدي عدد كبير جدًا من العهود إلى overfitting النموذج وقد يؤدي عدد قليل جدًا من الepochs إلى underfitting.

لذلك للتغلب على هذه المشكلة، يتم استخدام مفهوم EarlyStopping.

في هذه التقنية، يمكننا تحديد عدد كبير بشكل تعسفي من حقب (epochs) التدريب والتوقف عن التدريب بمجرد توقف أداء النموذج عن التحسن في مجموعة بيانات التحقق (validation dataset). يدعم Keras هاذ المفهوم للتدريب عن طريق callback يسمى EarlyStopping.

فيما يلي الحجج (arguments) المختلفة في EarlyStopping.

  1. monitor – يسمح لنا ذلك بتحديد مقياس الأداء من أجل إنهاء التدريب.
  2. mode – يُستخدم لتحديد ما إذا كان الهدف من المقياس المختار هو زيادة التكبير أو التصغير.
  3. verbose – لاكتشاف حقبة التدريب التي توقف فيها التدريب، يمكن ضبط وسيطة “verbose” على 1. بمجرد التوقف، ستطبع callback رقم الحقبة.
  4. patience – قد لا تكون أولى علامات عدم التحسن هو أفضل وقت للتوقف عن التدريب. هذا لأن النموذج قد يتجه نحو هضبة لا يوجد بها تحسن أو حتى يزداد سوءًا قليلاً قبل أن يتحسن كثيرًا. هذا هو عدد الحقب التي لم نرا فی النموذج ای تحسن. يمكن القيام بذلك عن طريق وضع حجة ” patience”.
es=EarlyStopping(monitor='val_accuracy', mode='max', verbose=1, patience=20)

ModelCheckpoint

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

mc = ModelCheckpoint('/content/gdrive/My Drive/best_model.h5', monitor='val_accuracy', mode='

تدريب النموذج

H = model.fit_generator(train_generator,validation_data=test_generator,epochs=100,verbose=1,callbacks=[mc,es])
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/keras/backend/tensorflow_backend.py:422: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead.

Epoch 1/100
785/785 [==============================] - 12435s 16s/step - loss: 0.1190 - accuracy: 0.9516 - val_loss: 1.2386 - val_accuracy: 0.9394
Epoch 2/100
785/785 [==============================] - 360s 459ms/step - loss: 0.0804 - accuracy: 0.9678 - val_loss: 1.2215 - val_accuracy: 0.9601
Epoch 3/100
785/785 [==============================] - 363s 462ms/step - loss: 0.0697 - accuracy: 0.9725 - val_loss: 1.3172 - val_accuracy: 0.9601
Epoch 4/100
785/785 [==============================] - 364s 463ms/step - loss: 0.0628 - accuracy: 0.9750 - val_loss: 1.3791 - val_accuracy: 0.9617
Epoch 5/100
785/785 [==============================] - 365s 465ms/step - loss: 0.0564 - accuracy: 0.9775 - val_loss: 1.4478 - val_accuracy: 0.9569
Epoch 6/100
785/785 [==============================] - 364s 463ms/step - loss: 0.0544 - accuracy: 0.9793 - val_loss: 1.5138 - val_accuracy: 0.9569
Epoch 7/100
785/785 [==============================] - 366s 467ms/step - loss: 0.0511 - accuracy: 0.9806 - val_loss: 1.4760 - val_accuracy: 0.9537
Epoch 8/100
785/785 [==============================] - 377s 480ms/step - loss: 0.0472 - accuracy: 0.9817 - val_loss: 1.5260 - val_accuracy: 0.9601
Epoch 9/100
785/785 [==============================] - 378s 481ms/step - loss: 0.0450 - accuracy: 0.9824 - val_loss: 1.5810 - val_accuracy: 0.9601
Epoch 10/100
785/785 [==============================] - 383s 488ms/step - loss: 0.0437 - accuracy: 0.9832 - val_loss: 1.5863 - val_accuracy: 0.9585
Epoch 11/100
785/785 [==============================] - 382s 487ms/step - loss: 0.0402 - accuracy: 0.9845 - val_loss: 1.5143 - val_accuracy: 0.9601
Epoch 12/100
785/785 [==============================] - 389s 496ms/step - loss: 0.0368 - accuracy: 0.9867 - val_loss: 1.5643 - val_accuracy: 0.9601
Epoch 13/100
785/785 [==============================] - 383s 488ms/step - loss: 0.0341 - accuracy: 0.9870 - val_loss: 1.5968 - val_accuracy: 0.9601
Epoch 14/100
785/785 [==============================] - 385s 490ms/step - loss: 0.0332 - accuracy: 0.9878 - val_loss: 1.6893 - val_accuracy: 0.9601
Epoch 15/100
785/785 [==============================] - 385s 490ms/step - loss: 0.0302 - accuracy: 0.9891 - val_loss: 1.8144 - val_accuracy: 0.9617
Epoch 16/100
785/785 [==============================] - 387s 494ms/step - loss: 0.0296 - accuracy: 0.9891 - val_loss: 1.6615 - val_accuracy: 0.9601
Epoch 17/100
785/785 [==============================] - 386s 492ms/step - loss: 0.0297 - accuracy: 0.9898 - val_loss: 1.8563 - val_accuracy: 0.9569
Epoch 18/100
785/785 [==============================] - 385s 490ms/step - loss: 0.0291 - accuracy: 0.9888 - val_loss: 1.9082 - val_accuracy: 0.9617
Epoch 19/100
785/785 [==============================] - 384s 490ms/step - loss: 0.0284 - accuracy: 0.9894 - val_loss: 1.8754 - val_accuracy: 0.9665
Epoch 20/100
785/785 [==============================] - 384s 489ms/step - loss: 0.0277 - accuracy: 0.9890 - val_loss: 1.8689 - val_accuracy: 0.9633
Epoch 21/100
785/785 [==============================] - 381s 486ms/step - loss: 0.0247 - accuracy: 0.9913 - val_loss: 1.8928 - val_accuracy: 0.9617
Epoch 22/100
785/785 [==============================] - 381s 485ms/step - loss: 0.0230 - accuracy: 0.9917 - val_loss: 1.9322 - val_accuracy: 0.9617
Epoch 23/100
785/785 [==============================] - 378s 481ms/step - loss: 0.0224 - accuracy: 0.9912 - val_loss: 1.8897 - val_accuracy: 0.9633
Epoch 24/100
785/785 [==============================] - 378s 482ms/step - loss: 0.0203 - accuracy: 0.9928 - val_loss: 2.0867 - val_accuracy: 0.9585
Epoch 25/100
785/785 [==============================] - 378s 482ms/step - loss: 0.0220 - accuracy: 0.9916 - val_loss: 2.0524 - val_accuracy: 0.9617
Epoch 26/100
785/785 [==============================] - 379s 483ms/step - loss: 0.0209 - accuracy: 0.9926 - val_loss: 1.8708 - val_accuracy: 0.9601
Epoch 27/100
785/785 [==============================] - 375s 478ms/step - loss: 0.0195 - accuracy: 0.9929 - val_loss: 1.9471 - val_accuracy: 0.9617
Epoch 28/100
785/785 [==============================] - 376s 480ms/step - loss: 0.0154 - accuracy: 0.9946 - val_loss: 2.0850 - val_accuracy: 0.9601
Epoch 29/100
785/785 [==============================] - 376s 479ms/step - loss: 0.0205 - accuracy: 0.9930 - val_loss: 2.0068 - val_accuracy: 0.9665
Epoch 30/100
785/785 [==============================] - 377s 480ms/step - loss: 0.0173 - accuracy: 0.9936 - val_loss: 2.0252 - val_accuracy: 0.9617
Epoch 31/100
785/785 [==============================] - 379s 483ms/step - loss: 0.0203 - accuracy: 0.9930 - val_loss: 2.2049 - val_accuracy: 0.9585
Epoch 32/100
785/785 [==============================] - 375s 478ms/step - loss: 0.0158 - accuracy: 0.9939 - val_loss: 2.2168 - val_accuracy: 0.9617
Epoch 33/100
785/785 [==============================] - 377s 480ms/step - loss: 0.0150 - accuracy: 0.9949 - val_loss: 2.1689 - val_accuracy: 0.9649
Epoch 34/100
785/785 [==============================] - 382s 486ms/step - loss: 0.0155 - accuracy: 0.9945 - val_loss: 2.3065 - val_accuracy: 0.9649
Epoch 35/100
442/785 [===============>..............] - ETA: 2:42 - loss: 0.0158 - accuracy: 0.9945

كما يمكننا أن نرى هنا أن تدريب النموذج قد توقف مبكرًا وفقًا لما كنا نتوقعه. نحفظ الأوزان في ملف “best_model.h5”. في المستقبل، لسنا مطالبين بتدريب النموذج مرة أخرى، يمكننا فقط تحميل الوزن في النموذج باستخدام الأمر أدناه.

model.load_weights("/content/gdrive/My Drive/best_model.h5")

تقييم نموذج ResNet 50 على مجموعات بيانات الاختبار

دعونا الآن نقيم أداء نموذجنا على مجموعة بيانات الاختبار غير المرئية. يمكننا أن نرى دقة تصل إلى 99٪.

model.evaluate_generator(test_generator)
[0.0068423871206876, 0.9931576128793124]

تسلسل نموذج ResNet

إنها أفضل ممارسة لتحويل النموذج إلى تنسيق JSON لحفظه لبرنامج الاستدلال (inference program) في المستقبل. لذلك سنحفظ نموذج ResNet الخاص بنا على النحو التالي:

model_json = model.to_json()
with open("/content/gdrive/My Drive/model.json","w") as json_file:
  json_file.write(model_json)

برنامج استدلال تصنيف dogs مقابل cats

لتلخيص ما فعلناه حتى الآن:

  1. قمنا بتنفيذ نموذج ResNet-50 مع Keras.
  2. قمنا بحفظ أفضل أوزان تدريبية للنموذج في ملف لاستخدامها في المستقبل.
  3. قمنا بحفظ النموذج بتنسيق JSON لإعادة استخدامه.

حان الوقت الآن لكتابة برنامج استنتاج (inference program) يقوم بما يلي:

  1. قم بتحميل النموذج الذي حفظناه بتنسيق JSON سابقًا.
  2. قم بتحميل الوزن الذي وفرناه بعد تدريب النموذج مسبقًا.
  3. تجميع (compile) النموذج.
  4. قم بتحميل الصورة التي نريد تصنيفها.
  5. أداء التصنيف.

لتنفيذ هذه الخطوات، قمنا بكتابة وظيفة تنبأ على النحو التالي:

from keras.models import model_from_json
 def predict_(image_path):
    #Load the Model from Json File
    json_file = open('/content/gdrive/My Drive/model.json', 'r')
    model_json_c = json_file.read()
    json_file.close()
    model_c = model_from_json(model_json_c)
    #Load the weights
    model_c.load_weights("/content/gdrive/My Drive/best_model.h5")
    #Compile the model
    opt = SGD(lr=1e-4, momentum=0.9)
    model_c.compile(loss="categorical_crossentropy", optimizer=opt,metrics=["accuracy"])
    #load the image you want to classify
    image = cv2.imread(image_path)
    image = cv2.resize(image, (224,224))
    cv2_imshow(image)
    #predict the image
    preds = model_c.predict(np.expand_dims(image, axis=0))[0]
    if preds==0:
        print("Predicted Label:Cat")
    else:
        print("Predicted Label: Dog")

أداء التصنيف

سنقدم الآن بعض الصور العشوائية من مجلد Dog and Cat لوظيفة التنبؤ ونرى كيف كان أداء تطبيق Keras لـ ResNet 50.

يمكن ملاحظة أن ملصق التنبؤ يتطابق بدقة مع نموذج ResNet الخاص بنا. تهانينا على تنفيذ Keras لـ ResNet 50 بنجاح.

predict_("/content/gdrive/My Drive/datasets/test/Dog/4.jpg")
predict_("/content/gdrive/My Drive/datasets/test/Cat/10.jpg")
predict_("/content/gdrive/My Drive/datasets/test/Cat/7.jpg")

الاستنتاج

بنهاية مقال طويل، نأمل أن تعرف الآن كيفية تنفيذ ResNet 50 مع Keras. استخدمنا مجموعة بيانات Dog vs Cat، ولكن يمكنك استخدام أي مجموعة بيانات فقط لإنشاء نموذج ResNet 50 الخاص بك باستخدام Keras.

المصدر

منشور ذات صلة
تقنية CCA 4 Minutes

تقنیة تحليل الارتباط الكنسي (Canonical Correlation Analysis) وتنفیذها في بايثون

حسن خنفري

تحليل الارتباط الكنسي (Canonical Correlation Analysis) هو أسلوب إحصائي متعدد المتغيرات يسمح لك بتحليل الارتباطات بين مجموعتي بيانات. يمكن استخدام تحليل الارتباط الكنسي لنمذجة الارتباطات بين مجموعتي بيانات.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

السلة