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

السؤال

Recommended Posts

  • 2
نشر

هذه الطبقة كما يشير اسمها هي طبقة تسطيح (أو تسوية أو إعادة تشكيل) المدخلات. نستخدمها عادة مع النماذج عندما نستخدم طبقات RNN و CNN. ولفهمها جيداً سأشرحها مع المثالين التاليين، الأول مع مهمة تحليل مشاعر imdb أي مع مهمة NLP وسنستخدم طبقات RNN وسنتحتاج إلى الطبقة flatten:

from keras.datasets import imdb
from keras import preprocessing
max_features = 10000
maxlen = 20
(x_train, y_train), (x_test, y_test) = imdb.load_data(
num_words=max_features)
x_train = preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen)
# بناء النموذج
from keras.models import Sequential
from keras.layers import Flatten, Dense
model = Sequential()
model.add(Embedding(10000, 8, input_length=maxlen))
# هنا سنتحتاج لإضافة طبقة تسطيح
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
model.summary()
history = model.fit(x_train, y_train,
epochs=10,
batch_size=32,
validation_split=0.2)

حسناً  هنا قمنا بتسطيح الخرج الناتج من طبقة التضمين Embedding أي قمنا بتسطيح (تحويل) ال 3D tensor التي أنتجتها طبقة التضمين إلى 2Dtensor بالشكل التالي (samples,maxlen * 8)( أي عدد العينات أو الباتشز لايتأثر كما أشرنا في التعريف وإنما يتم إعادة تشكيل الفيتشرز). لقد قمنا  هضه العملية لأن الطبقة التي تلي طبقة التضمين هي طبقة من نوع Dense وهي طبقة تستقبل 2D tensor ولاتستقبل 3D وبالتالي وجب علينا تسطيح مخرجات طبقة التضمين.
مثال آخر:

def lstm_model_flatten():
    embedding_dim = 128
    model = Sequential()
    model.add(layers.Embedding(vocab_size, embedding_dim, input_length=maxlen))
    model.add(layers.LSTM(128, return_sequences = True,  dropout=0.2)) 
    # Flatten layer هنا أيضاً سنحتاج
    model.add(layers.Flatten())
    model.add(layers.Dense(1,activation='sigmoid'))
    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
    model.summary()
    return model

هنا استخدمنا طبقة التسطيح لأن مخرجات طبقة lstm هي 3D كما نعلم وذلك لأننا ضبطنا return_sequences على true، والطبقة التالية هي dense وبالتالي لابد من تسطيح المخرجات بنفس الطريقة.
الآن حالة آخرى مع الطبقات التلاففية حيث أنني بنيت نموذج لتصنيف الأرقام المكتوبة بخط اليد:

from keras import layers
from keras import models
from keras.datasets import mnist
from keras.utils import to_categorical
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images.astype('float32') / 255
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
# بناء النموذج
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
# هنا سنتحتاجها
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
# تدريب النموذج
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=5, batch_size=64)

حسناً، إن خرج كل طبقة Conv2D و MaxPooling2D هو 3D Tensor من الشكل (height, width, channels). إن آخر خطوة من بناء الشبكة التلاففية هو إضافة طبقة أو مجموعة طبقات dense وبالتالي تتم تغذية هذه الطبقة بآخر tensor أنتجتها طبقاتنا التلاففية (هنا (64, 3, 3))  وكما ذكرنا فإن dense لاتستقبل 3D وبالتالي يجب تسطيحها، ,وبالتالي هنا سيكون ناتج تسطيح الخرج هو شعاع 1D أبعاده 64*3*3 وهذا ماسوف تتغذى  به طبقات ال dense.

  • 2
نشر

Flatten تستقبل أي tensor بأي شكل (multi-dimensional tensor) و تحوله إلى 1D tensor بالإضافة لعدد العينات. مثلاً إذا كان مدخل الدالة عبارة عن (عدد العينات، 10،20) الناتج سيكون (عدد العينات، 10*20) وبالتالي (عدد العينات، 200).

لاحظ المثال التالي و الذي يقوم بتطبيق التسطيح على عدد 32 عينة مكونة من 5 صفوف للطول و 5 أعمدة في العرض و هي عبارة عن صورة ملونة مكونة من 3 قنوات Red, Green, Blue:

import numpy as np
from tensorflow.keras.layers import *

n_samples, H, W, n_channels = 32, 5, 5, 3

# إنشاء قيم كمدخلات للدالة
X = np.random.uniform(0,1, (n_samples,H,W,n_channels)).astype('float32')

# تطبيق عملية التسطيح بإستخدام طريقتين
np_flatten = X.reshape(batch_dim, -1) 
tf_flatten = Flatten()(X).numpy() 

#طباعة الشكل الناتج
print(np_flatten.shape, tf_flatten.shape)

#التأكد من أن الشكل الناتج هو نفسه للطريقتين
(tf_flatten == np_flatten).all() # True

يمكننا تطبيق التسطيح بإستخدام الدالة flatten أو بإستخدام الدالة reshape في كل من الطريقتين يتم تحويل المدخل إلى (n_samples, H*W*n_channels) وبالتالي يكون الخرج عبارة عن عدد العينات و حاصل ضرب كل من الطول في العرض في عدد القنوات.

عادة ما يتم إستخدام flatten مع CNN, RNN,LSTM حسب القيم الممررة و التي توضع قبل عملية نداء الدالة Dense لأنها تستقبل عدد العينات بالإضافة لقيم المدخلات مجموعة في شكل 1D tensor.

 

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

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

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

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

  • إعلانات

  • تابعنا على



×
×
  • أضف...