اذهب إلى المحتوى

السؤال

Recommended Posts

  • 1
نشر

الطبقة Conv2D هي الطبقة التي يمكننا من خلالها بناء شبكة CNN في كيراس وتنسرفلو.. وسأشرح كيف نستخدمها.. أولاً الشكل العام لها:

tf.keras.layers.Conv2D(
    filters,
    kernel_size,
    strides=(1, 1),
    padding="valid",
    data_format=None,
    activation=None,
    use_bias=True,
    kernel_initializer="glorot_uniform",
    bias_initializer="zeros",
    kernel_regularizer=None,
    bias_regularizer=None,
    input_shape,
    **kwargs
)

 الوسيط الأول filters يمثل عدد المرشحات التي تريد أن يتم تطبيقها على مجموعة بياناتك (الصور). حيث يتم تطبيق كل فلتر على كل صورة لاستخراج السمات المميزة فيها (حواف زوايا نقاط..إلخ) عن طريق تنفيذ عملية "التفاف" convolution عليها. وعدد هذه الفلاتر سيمثل عدد القنوات التي سيتم إخراجها من هذه الطبقة (ستفهم أكثر في المثال بعد قليل).
الوسيط الثاني kernel_size يمثل حجم النواة (حجم المرشحات التي سيتم تطبيقها) حيث نمرر tuble يحوي قيمتين تمثلان طول وعرض المرشح، على سبيل المثال إذا قمنا بتمرير (3,3) فهذا يعني أن المرشحات التي سيتم تطبيقها ستكون أبعادها 3*3. كما يمكننا أن نمرر قيمة واحدة بدلاً من ال tuble، على سبيل المثال يمكن أن نمرر 5 وبالتالي سيفهم تلقائياً أن حجم المرشح الذي تريده هو 5*5. كما يجب أن نعلم أن أبعاد هذا المرشح يجب أن تكون أعداداً فردية لأن الأرقام الزوجية تعطي أداء ضعيف لأنك ستعاني مما يسمى بال aliasing error وهي عبارة عن تشوهات غير مرغوبة.
الوسيط الثالث هو strides أي عدد الخطوات، فكما نعلم إن عملية ال convolution هي عملية مرور مرشح على الصورة بدءاً من أعلى اليسار وصولاً لأسفل اليمين من الصورة. والوسيط strides يقوم بتحيد عدد الخطوات (عدد البكسلات).
الوسيط الرابع padding لتحيد فيما إذا كنت تريد تنفيذ عملية حشو للصورة أو لا (حشو جوانب الصورة بأصفار). ويأخذ قيمتان same لتنفيذ عملية الحشو و valid لعدم تنفيذها. ويكون الحشو في يمين ويسار أو أسفل وأعلى الصورة حسبما تحتاجه الصورة وذلك للحفاظ على نفس الأبعاد للصورة.
الوسيط الخامس data_format لتحديد شكل أبعاد الصور في بياناتك فمثلاً إذا كان عدد القنوات اللونية للصور في مجموعة بياناتك يتم تمثيلها في البعد الأخير (أي الثالث) فهنا نضع channels_last  (وهي الحالة الافتراضية حيث أن أغلب الصور يتم تمثيل القنوات اللونية فيها كآخر بعد (batch_size, height, width, channels) ). أو channels_first في حال كان عدد القنوات اللونية ممثل في أول بعد (batch_size, channels, height, width).
الوسيط السادس activation هو دالة التنشيط التي سيتم استخدامها (افتراضياُ لن يتم استخدام أي دالة تنشيط) حيث يتم تطبيقها على مخرجات الطبقة. أما الوسيط السابع use_bias ويأخذ إما True أو False لتحديد فيما إذا كنت تريد إضافة وزن يمثل ال bias بحيث يتم جمعه على ناتج تطبيق الفلتر. أما الوسيط الثامن فهو kernel_initializer وهو لتحديد نوع التهيئة التي سيتم فيها تهيئة الفلاتر (افتراضياً يكون "glorot_uniform") والوسيط التاسع  bias_initializer وافتراضياً يكون التهيئة بأصفار"zeros". وأخيراً input_shape لتحديد حجم الصور التي سيتم تقديمها للطبقة حيث نحدد لها طول وعرض وعدد القنوات اللونية للصورة وهو يضيف تلقائياُ البعد الرابع الذي يمثل حجم الباتش أي: batch_shape + (channels, rows, cols) أو batch_shape + (rows, cols, channels)  حسب موضع القناة اللونية.
خرج هذه الطبقة هو:
batch_shape + (filters, new_rows, new_cols) في حالة كانت القناة اللونية في البداية. أو batch_shape + (new_rows, new_cols, filters) في حالة كانت القناة اللونية في النهاية.
ال new_rows و ال new_cols يتم حسابهم من المعادلة:

new_col=(col-2*p+f)/strides + 1
new_row=(row-2*p+f)/strides + 1
{{{{{{{{{وعدد الخطوات هو 1  p=0 في حالة كان بدون حشو يكون }}}}}}}}}}
new_col=(col-f) + 1
new_row=(row-f + 1

الأمثلة التالية ستوضح الأمر أكثر:

# سنقوم بإنشاء 4 صور طولها 28 وعرضها 28 وملونة أي لها 3 قنوات لونية
# سنقوم بتوليد هذه الصور بقيم عشوائية 
import tensorflow as tf
x = tf.random.normal((4, 28, 28, 3))
#Conv2D الآن سنطبق عليها ال 
# سنستخدم مرشحين بحجم 3*3
#p=0 لن نستخدم حشو أي 
# وعدد الخطوات هو (1, 1)
y = tf.keras.layers.Conv2D(2, 3,padding="valid",strides=(1, 1), activation='relu', input_shape=(28, 28, 3))(x)
# الآن لنعرض أبعاد الخرج
print(y.shape)
(4, 26, 26, 2)
# لاحظ أن الخرج ينتج من المعدلات السابقة كالتالي
# new_col=new_row=28-3+1=26
# وعدد الفلاتر يصبح عدد القنوات

في حالة كان ال padding=same:

y = tf.keras.layers.Conv2D(2, 3, activation='relu', padding="same", input_shape=input_shape[1:])(x)
print(y.shape)
# (4, 28, 28, 2)
# لاحظ أن الخرج لم يتغير حيث أنه يقوم هنا بعملية حشو بأصفار بحيث تحافظ الصورة على أبعادها

مثال عملي، حيث سأقوم باستخدامها مع مجموعة البيانات التالية لتصنيف صور القطط والكلاب (يمكنك الحصول على مجموعة البيانات من هنا https://www.kaggle.com/c/dogs-vs-cats/data):

from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
# نحدد مسارات البيانات
train_data_dir = 'data/train'
validation_data_dir = 'data/validation'
nb_train_samples = 2000 # عدد عينات التدريب
nb_validation_samples = 800 # التحقق
epochs = 50
batch_size = 16 # عدد الباتشات
# أبعاد الصور
img_width, img_height = 150, 150
# نحدد طبقة الادخال
input_shape = (img_width, img_height, 3)

#DataAugmentation الآن سنقوم بعملية 
# إن لم يكن لديك معرفة بها فلقد تركت لك رابط في الأسفل
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

# نبدأ ببناء النموذج
model = Sequential()
# نعرف أول طبقة التفاف
model.add(Conv2D(32, (3, 3),activation='relu', input_shape=input_shape))
#وذلك لتقليل أبعاد الصورة Conv2Dبعد كل طبقة  MaxPooling2D غالباً مانستخدم طبقة تسمى 
# إن لم يكن لديك معرفة بها فلقد تركت لك رابطاً في الأسفل لتوضيها
model.add(MaxPooling2D(pool_size=(2, 2)))
# ثاني طبقة التفاف
model.add(Conv2D(32, (3, 3),activation='relu', ))
model.add(MaxPooling2D(pool_size=(2, 2)))
# ثالث طبقة 
model.add(Conv2D(64, (3, 3),activation='relu', ))
model.add(MaxPooling2D(pool_size=(2, 2)))
# نقوم بتسطيح المخرجات
model.add(Flatten())
# fully-connected نبني الكلاسيفير الآن وهنا سنستخدم الطبقات المتصلة بالكامل 
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5)) #لمنع الأوفرفيت
model.add(Dense(1)) # طبقة الخرج
model.add(Activation('sigmoid'))
# تجميع النموذج
model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['acc'])
# تدريب النموذج
model.fit_generator(
    train_generator,
    steps_per_epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size)

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...