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

السؤال

Recommended Posts

  • 2
نشر (معدل)

تستخدم بشكل أساسي مع الشبكات العصبية التلاففية CNN حيث غالباً ماتتبع طبقة ال CNN طبقة MaxPooling.  مبدأياً تأمل الصورة التالية:
maxpool.png.30aeafee31dea5043834d8df1f5f5513.png هنا لدينا مصفوفة 4*4 ونافذة حجمها 2*2 تمر على المصفوفة (لاحظ أن النافذة التي حجمها2*2 تتحرك بمقدار خطوتين) في البداية كانت النافذة موضوعة على المربع الأحمر وبالتالي ستأخذ أكبر قيمة فيه هي 20، ثم ستمشي على  المصفوفة أفقياً بمقدار خطوتين (أي بكسلين أفقياً) وبالتالي ستصيح النافذة موجودة على المربع الأصفر وبالتالي ستأخذ أكبر قيمة فيه وهي 30 ، الآن وصلنا لنهاية حدود المصفوفة وبالتالي ننزل بمقدار خطوتين (أي بكسلين عمودياً) وبالتالي تصبح النافذة على  المربع الأزرق وأكبر قيمة هي 112 وهكذا..
لاحظ كيف تم اختزال أبعاد المصفوفة من 4*4 إلى 2*2. حسناً لماذا نستخدم هذه الطبقة؟ السبب الأول هو أنها تقوم بتخفيف العبء الحسابي "Reducing computational load" فنظراً لأن MaxPooling يقلل من دقة الإخراج المعطى من الطبقة التلافيفية، وبالتالي ستنظر الشبكة في مناطق أكبر من الصورة في وقت واحد ، مما يقلل من كمية المعلمات في الشبكة وبالتالي يقلل من الحمل الحسابي. والسبب الثاني هو "Reducing overfitting" فهي تساعد في محاربة الضبط الزائد، حيث أن الفكرة وراء عمل max pooling هو أنها بالنسبة لصورة معينة، ستبحث شبكتنا لاستخراج بعض الميزات الخاصة. فهي تبحث عن الحواف والمنحنيات والدوائر وما إلى ذلك من السمات التي تميز الصورة (يمكننا التفكير في وحدات البكسل الأعلى قيمة على أنها الأكثر نشاطاً). وبالتلي فهي تركز على البكسلات الأعلى قيمة وتتجاهل البكسلات الأقل قيمة. طبعاُ يمكننا أن نغير حجم النافذة وأن نغير حجم الخطوات أو أن نقوم بخطوة نسميها الحشو padding التي تقوم بحشو حدود المصفوفة  بأصفار لكي تحافظ على أبعاد المصفوفة (الصورة). كيراس أو تنسرفلو تؤمن لك طريقة سهلة للقيام بهذا. لها الشكل التالي:

tf.keras.layers.MaxPooling2D(
    pool_size=(2, 2), strides=None, padding="valid", data_format=None
)
# الوسيط الأخير سأتحدث عنه في النهاية

pool_size: يمثل حجم النافذة، ويمكنك إسناد عدد صحيح أو tuple بحيث إذا استخدمت عدد صحيح مثلاً 2 فهذا يعني أنك سوف تستخدم  نافذة بحجم 2*2 وإما إذا استخدمت tuple فمثلاً (2,2) فهذا يعني أن حجم النافذة سيكون 2*2. الوسيط الثاني strides هو حجم الخطوة أي مقدار إزاحة النافذة، فمثلاً إذا اخترت (1,1) هذا يعني أنه ستتم إزاحة النافذة بمقدار 1 بكسل في العرض و 1 بكسل في الطول (النافذة تمشي على طول سطر المصفوفة بمقدار بكسل واحد وعندما تصل لنهاية أول سطر ستنزل للسطر التالي بمقدار بكسل واحد). أما بالنسبة لآخر وسيط فهو يمثل ال padding أي الحشو ففي حال استخدمت vaild فلن يتم حشو حدود المصفوفة بأصفار (أي لن يتم الحفاظ على أبعاد المصفوفة أي كما في المثال في الأعلى ويجب أن تعلم أن عملية الحشو هذه تتم بما يتلائم مع المصفوفة ولاتقلق فكيراس تتكفل بكل هذا الأمر) والمصفوفة الناتجة في هذه الحالة:

output_shape = math.floor((input_shape - pool_size) / strides) + 1 (when input_shape >= pool_size)

أما في حالة استخدمت same فسوف يقوم بعملية الحشو. والمصفوفة الناتجة في هذه الحالة:

output_shape = math.floor((input_shape - 1) / strides) + 1

الآن انظر للأمثلة التالية:

# مصفوفة بحجم 3*3
# حجم الخطوة هنا اخترناه بمقدار بكسل واحد
# حجم النافذة اخترناها 2*2
#valid الحشو
x = tf.constant([[1., 2., 3.],
                [4., 5., 6.],
                [7., 8., 9.]])
# قمت بتحويل مصفوفة ال 3*3 إلى مصفوفة ب 4 أبعاد لأن هذه الطبقة لاتستقبل إلى مصفوفة بأربع أبعاد كما سأوضح بعد قليل
x = tf.reshape(x, [1, 3, 3, 1])
max_pool_2d = tf.keras.layers.MaxPooling2D(pool_size=(2, 2),
  strides=(1, 1), padding='valid')
c=max_pool_2d(x)
# هنا قمت بتحويل الخرج من رباعي إلى ثنائي الأبعاد لتسهل قراءة الخرج
tf.reshape(c, [ 2, 2])
# الخرج
"""
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[5., 6.],
       [8., 9.]], dtype=float32)>
"""

مثال آخر:

# مصفوفة بحجم 3*3
# حجم الخطوة هنا اخترناه بمقدار بكسل واحد
# حجم النافذة اخترناها 2*2
#same الحشو
x = tf.constant([[1., 2., 3.],
                [4., 5., 6.],
                [7., 8., 9.]])

x = tf.reshape(x, [1, 3, 3, 1])
max_pool_2d = tf.keras.layers.MaxPooling2D(pool_size=(2, 2),
  strides=(1, 1), padding='same') # تمت إضافةعمود بأصفار وسطر بأصفار للحفاظ على الأبعاد
c=max_pool_2d(x)
c
tf.reshape(c, [ 3, 3])
"""
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[5., 6., 6.],
       [8., 9., 9.],
       [8., 9., 9.]], dtype=float32)>
"""

يمكنك الآن التلاعب بقيم الوسطاء لتفهم أكثر. الآن سأستخدم لك هذه الطبقة في نموذج يحتوي على طبقة إدخال تقبل إدخال أبعاده 20 × 20 × 3 ، ثم طبقة كثيفة تليها طبقة تلافيفية تليها طبقة تجميع قصوى ، ثم طبقة تلافيفية أخرى ، تليها طبقة مخرجات.، ونظراً لأن الطبقات التلافيفية هنا ثنائية الأبعاد ، فإننا نستخدم طبقة MaxPooling2D من Keras ، لكن Keras لديها أيضًا طبقات تجميع 1d و 3 d max أيضاً.:

import keras
from keras.models import Sequential
from keras.layers import Activation
from keras.layers.core import Dense, Flatten
from keras.layers.convolutional import *
from keras.layers.pooling import *
# بناء نموذج
model_valid = Sequential([
	# الدخل هو صورة بأبعاد 20 ب 20 و 3 قنوات لونية أي صورة ملونة
    Dense(16, input_shape=(20,20,3), activation='relu'),
    Conv2D(32, kernel_size=(3,3), activation='relu', padding='same'),
    MaxPooling2D(pool_size=(2, 2), strides=2, padding='valid'),
    Conv2D(64, kernel_size=(5,5), activation='relu', padding='same'),
    Flatten(),
    Dense(2, activation='softmax')
])
# هكذا سيكون شكل النموذج
"""

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_2 (Dense)              (None, 20, 20, 16)        64        
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 20, 20, 32)        4640      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 10, 10, 32)        0     
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 10, 10, 64)        51264    
_________________________________________________________________
flatten_1 (Flatten)          (None, 6400)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 2)                 12802     
=================================================================
Total params: 68,770
Trainable params: 68,770
Non-trainable params: 0
_________________________________________________________________
"""

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

# الدخل
data_format='channels_last': 4D tensor with shape (batch_size, rows, cols, channels).
data_format='channels_first': 4D tensor with shape (batch_size, channels, rows, cols).
# الخرج
data_format='channels_last': 4D tensor with shape (batch_size, pooled_rows, pooled_cols, channels).
data_format='channels_first': 4D tensor with shape (batch_size, channels, pooled_rows, pooled_cols).

 

تم التعديل في بواسطة Ali Haidar Ahmad
  • 1
نشر

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

التجميع المكاني أو كما يعرف ايضا ب اخذ عينات فرعية subsampling أو الاختزال downsampling يقوم بتقليص الأبعاد لكل خريطة خصائص مع اعتبار الإبقاء على المعلومات المهمة. التجميع المكاني له عدة انواع مثل: Max (اعلى قيمة)، Average (حساب المتوسط)، Sum (المجموع) . في حالة التجميع باستخدام اعلى قيمة Max Pooling فإننا نقوم بتحديد المنطقة المكانية المتجاورة (نافذة بحجم ٢x٢ على سبيل المثال) ونقوم باستخراج العنصر (البكسل) صاحب اعلى قيمة في النافذة المحددة من خريطة الخصائص المصححة. وبنفس الطريقة لو استخدمنا المتوسط Average فسنقوم بحساب متوسط الاعداد في تلك النافذة فقط او مجموعهم في حال Sum. بشكل عام فإن التجميع باستخدام اعلى قيمة Max Pooling قد اظهر اداء افضل. الشكل البياني التفاعلي الأتي يستعرض مثال لاستخدام التجميع باستخدام اعلى قيمة Max Pooling على خريطة الخصائص المصححة المستخرجة بعد عملية الالتفاف convolution بالاضافة لعملية الريلو ReLU باستخدام نافذة ذات حجم ٢x٢

1_gpkHl16U7ppl4-lBlnAYqw.thumb.gif.ba3827ef37cd3434888ae504d8da8aff.gif

وتستخدم ال maxpooling في تقليص حجم البيانات باستخراج الاكبر منها كقيمه عددية، وتستخدم بشده مع الشبكات العصبية التلاففية CNN وتستطيع تحديد حجم النافذة والحركات التي تقوم بها بسهولة في بايثون.

اما عن maxpooling في keras فهي كالتالي:

tf.keras.layers.MaxPooling2D(
    pool_size=(2, 2), strides=None, padding="valid", data_format=None )

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

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

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

الكود التالي يوضح كيف يمكن أستخدامها داخل موديل باستخدام keras.

import keras
from keras.models import Sequential
from keras.layers import Activation
from keras.layers.core import Dense, Flatten
from keras.layers.convolutional import *
from keras.layers.pooling import *

model_valid = Sequential([
    Dense(16, input_shape=(20,20,3), activation='relu'),
    Conv2D(32, kernel_size=(3,3), activation='relu', padding='same'),
    MaxPooling2D(pool_size=(2, 2), strides=2, padding='valid'), #هنا نستخدم maxpooling
    Conv2D(64, kernel_size=(5,5), activation='relu', padding='same'),
    Flatten(),
    Dense(2, activation='softmax')
])

وتكون نتيجة تشغيل الكود اذا اردنا استخراج ابعاد الصوره بعد كل عملية كاتالي:

> model_valid.summary()

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_2 (Dense)              (None, 20, 20, 16)        64        
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 20, 20, 32)        4640      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 10, 10, 32)        0     
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 10, 10, 64)        51264    
_________________________________________________________________
flatten_1 (Flatten)          (None, 6400)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 2)                 12802     
=================================================================
Total params: 68,770
Trainable params: 68,770
Non-trainable params: 0
_________________________

يمكننا أن نلاحظ من خلال الخرج output_shape أن حجم الصورة قد قل للنصف بعد استخدام ال maxpooling، وذلك لاننا وضعنا حجم النافذة (2,2) وكذلك حجم الخطوة stride =2، حيناها ساخذ قيمه واحده من كل مربع به عنصرين فتقل حجم الصورة للنصف.

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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.

  • إعلانات

  • تابعنا على



×
×
  • أضف...