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

السؤال

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.

  • إعلانات

  • تابعنا على



×
×
  • أضف...