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

استبدال طبقة الدخل input layer في كيراس keras وتنسرفلو Tensorflow

عامر ابراهيم

السؤال

لدي نموذج مدرب قمت بحفظه سابقاً:

model.save('my_model.h5')

 وأريد الآن تحميله لكن أريد استبدال طبقة الدخل فيه (input layer). النموذج بامتداد h5. فهل هذا ممكن؟

رابط هذا التعليق
شارك على الشبكات الإجتماعية

Recommended Posts

  • 1

نعم ممكن. عندما نقوم بحفظ النموذج من خلال:

model.save('my_model.h5')

يتم حفظ معماريته (هيكليته) مما يسمح لنا بإنشاء النموذج. ويتم حفظ أوزان النموذج المدربة و ال loss وال optimizer (وحالته أيضاً) مما يمكننا من استكمال التدريب لاحقاً. وبالتالي عند تحميل النموذج:

load_model('my_model.h5')

 يمكننا الحصول على معماريته وأوزانه من خلال:

model.summary() # ملخص بطبقات النموذج وأوزانه
model.get_weights() # (قيم الأوزان) أوزان النموذج

ثم يمكنك القيام بحذف طبقة الدخل من خلال الدالة pop حيث نمرر لها رقم الطبقة المراد حذفها ثم إضافة الطبقة الجديدة التي تريدها:

model.layers.pop(0) # حذف الطبقة الأولى
# تعريف طبقة الدخل الجديدة وتعديل النموذج
Input = Input(batch_shape=(0,300,300,3))  # مثلاً
# الخرج الجديد
newOutputs = model(Input)
newModel = Model(Input, newOutputs)
# عرض هيكلية النموذج بعد التعديل
newModel.summary()

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

# استخراج تكوين النموذج
config = model.get_config()
# نسخ التكوين
input_layer_name = config['layers'][0]['name']
config['layers'][0] = {
                      'name': 'new_input',
                      'class_name': 'InputLayer',
                      'config': {
                          'batch_input_shape': (None, 300, 300),
                          'dtype': 'float32',
                          'sparse': False,
                          'name': 'new_input'
                      },
                      'inbound_nodes': []
                  }
config['layers'][1]['inbound_nodes'] = [[['new_input', 0, 0, {}]]]
config['input_layers'] = [['new_input', 0, 0]]
# النموذج الجديد
model = model.__class__.from_config(model_config, custom_objects={})
# نسخ الأوزان
weights = [layer.get_weights() for layer in model.layers[1:]]
for layer, weight in zip(new_model.layers[1:], weights):
    layer.set_weights(weight)
رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 1

دعنا نشرحها في هيئة خطوات بسيطة:

  • تقوم باستخراج معلومات النموذج الذي تم تحميله:
model_config = model.get_config()
  • تبديل الطبقة التي تريد تغييرها:
input_layer_name = model_config['layers'][0]['name']
model_config['layers'][0] = {
                      'name': 'new_input',
                      'class_name': 'InputLayer',
                      'config': {
                          'batch_input_shape': (None, 300, 300),
                          'dtype': 'float32',
                          'sparse': False,
                          'name': 'new_input'
                      },
                      'inbound_nodes': []
                  }
model_config['layers'][1]['inbound_nodes'] = [[['new_input', 0, 0, {}]]]
model_config['input_layers'] = [['new_input', 0, 0]]
  • ثم تقوم بانشاء النموذج الجديد:
new_model = model.__class__.from_config(model_config, custom_objects={}) 
  • ثم نسخ الأوزان من النموذج القديم للجديد:
# iterate over all the layers that we want to get weights from
weights = [layer.get_weights() for layer in model.layers[1:]]
for layer, weight in zip(new_model.layers[1:], weights):
    layer.set_weights(weight)
  • بعد ذلك اضافة الطبقات التي تريد:
from kerassurgeon.operations import delete_layer, insert_layer

model = delete_layer(model, layer_1)
# insert new_layer_1 before layer_2 in a model
model = insert_layer(model, layer_2, new_layer_3)

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

import keras
import numpy as np

def get_model():
    old_input_shape = (20, 20, 3)
    model = keras.models.Sequential()
    model.add(keras.layers.Conv2D(9, (3, 3), padding="same", input_shape=old_input_shape))
    model.add(keras.layers.MaxPooling2D((2, 2)))
    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(1, activation="sigmoid"))
    model.compile(loss='binary_crossentropy', optimizer=keras.optimizers.Adam(lr=0.0001), metrics=['acc'], )
    model.summary()
    return model

def change_model(model, new_input_shape=(None, 40, 40, 3)):
    # تغيير شكل الدخل لاول طبقة
    model._layers[1].batch_input_shape = new_input_shape

    #استبدال وتعديل الطبقات التي تريد
    model._layers[2].pool_size = (8, 8)
    model._layers[2].strides = (8, 8)

    # اعادة بناء شكل النموذج
    new_model = keras.models.model_from_json(model.to_json())
    new_model.summary()

    # نسخ الأوزان
    for layer in new_model.layers:
        try:
            layer.set_weights(model.get_layer(name=layer.name).get_weights())
        except:
            print("Could not transfer weights for layer {}".format(layer.name))

    # تجربة النموذج الجديد
    X = np.random.rand(10, 40, 40, 3)
    y_pred = new_model.predict(X)
    print(y_pred)

    return new_model

if __name__ == '__main__':
    model = get_model()
    new_model = change_model(model)

 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

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

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

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

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

  • إعلانات

  • تابعنا على



×
×
  • أضف...