Keras ModelCheckpoint вводит дополнительные слои при сохранении модели - PullRequest
1 голос
/ 08 января 2020

Я пытаюсь сохранить модель, используя ModelCheckpoint в Keras. Я сохраняю модель, используя следующий фрагмент кода.

model = load_vgg()
parallel_model = keras.utils.multi_gpu_model(model_1, gpus=2)
parallel_model.compile(loss="binary_crossentropy", metrics=['accuracy'], optimizer=Adam())
early_stopping = EarlyStopping(monitor='val_loss', min_delta=0, patience=5, verbose=1, mode='min')
checkpoint = ModelCheckpoint(os.path.join(ouput_dir, "model.h5"), monitor='val_loss', verbose=1, save_best_only=True, mode='auto')
history = parallel_model.fit_generator(train_gen, steps_per_epoch=math.ceil(num_train_samples / batch_size), validation_data=val_gen, validation_steps=math.ceil(num_val_samples / batch_size), epochs=200, verbose=1, class_weight=class_weights, callbacks=[checkpoint, early_stopping])
model.save(os.path.join(ouput_dir, 'model_2.h5'))

Модель определяется с использованием следующего кода:

def load_vgg(in_shape=(x, y), n_classes=1, n_stages_per_blocks=[2, 2, 2, 2, 2]):
  in_layer = keras.layers.Input(in_shape)
  block1 = _block(in_layer, 64, n_stages_per_blocks[0])
  pool1 = keras.layers.MaxPool1D()(block1)
  block2 = _block(pool1, 128, n_stages_per_blocks[1])
  pool2 = keras.layers.MaxPool1D()(block2)
  block3 = _block(pool2, 256, n_stages_per_blocks[2])
  pool3 = keras.layers.MaxPool1D()(block3)
  block4 = _block(pool3, 512, n_stages_per_blocks[3])
  pool4 = keras.layers.MaxPool1D()(block4)
  block5 = _block(pool4, 512, n_stages_per_blocks[4])
  pool5 = keras.layers.MaxPool1D()(block5)
  flattened = keras.layers.Flatten()(pool5)
  dense1 = keras.layers.Dense(2048, activation='relu')(flattened)
  dense2 = keras.layers.Dense(1024, activation='relu')(dense1)
  preds = keras.layers.Dense(n_classes, activation='sigmoid')(dense2)
  model = keras.models.Model(in_layer, preds)
  model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
  return model

convBlock = partial(keras.layers.Conv1D, kernel_size=3, strides=1, padding='same', activation='relu')

def _block(in_tensor, filters, n_convs):
  conv_block = in_tensor
  for _ in range(n_convs):
    conv_block = convBlock(filters=filters)(conv_block)
  return conv_block

Проблема: Когда мы загружаем модель, сохраненную с помощью ModelCheckpoint, и модель сохраняется напрямую используя функцию сохранения, они предоставляют нам различные сводки моделей.

Сводка модели, сохраненной с помощью ModelCheckpoint: 1] Сводка модели, сохраненной с помощью функции сохранения модели: 2]

Почему ModelCheckpoint вводит три дополнительных слоя и перемещает модель в слой model_1? Какие изменения нужно сделать, чтобы модель, сохраненная в ModelCheckpoint, имела ту же структуру, что и модель, полученная с помощью функции сохранения? Любая помощь будет высоко ценится. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

1 Ответ

1 голос
/ 14 января 2020

Согласно документации Keras:

Чтобы сохранить модель с несколькими графическими процессорами, используйте .save(fname) или .save_weights(fname) с моделью шаблона (аргумент, который вы передали multi_gpu_model), а не с моделью. возвращается multi_gpu_model.

Когда мы используем ModelCheckpoint, возникает та же проблема. Обратный вызов вызывается на модели графического процессора, что не правильно.

Существует два решения: 1) вы реализуете версию ModelCheckpoint, в которой вы передаете модель шаблона в качестве аргумента (код приведен ниже), или 2) вы следуете этому предложению реализует класс это гарантирует, что любой вызов функции сохранения будет использовать модель шаблона.

Реализация ModelCheckpoint для multi_gpu_model:

import keras
import numpy as np 
import warnings

class ModelCheckpoint(keras.callbacks.Callback):

    def __init__(self, filepath, ser_model, monitor='val_loss', verbose=0,
                 save_best_only=False, save_weights_only=False,
                 mode='auto', period=1):
        super(ModelCheckpoint, self).__init__()
        self.monitor = monitor
        self.verbose = verbose
        self.filepath = filepath
        self.save_best_only = save_best_only
        self.save_weights_only = save_weights_only
        self.period = period
        self.epochs_since_last_save = 0
        self.ser_model = ser_model

        if mode not in ['auto', 'min', 'max']:
            warnings.warn('ModelCheckpoint mode %s is unknown, '
                          'fallback to auto mode.' % (mode),
                          RuntimeWarning)
            mode = 'auto'

        if mode == 'min':
            self.monitor_op = np.less
            self.best = np.Inf
        elif mode == 'max':
            self.monitor_op = np.greater
            self.best = -np.Inf
        else:
            if 'acc' in self.monitor or self.monitor.startswith('fmeasure'):
                self.monitor_op = np.greater
                self.best = -np.Inf
            else:
                self.monitor_op = np.less
                self.best = np.Inf

    def on_epoch_end(self, epoch, logs=None):
        logs = logs or {}
        self.epochs_since_last_save += 1
        if self.epochs_since_last_save >= self.period:
            self.epochs_since_last_save = 0
            filepath = self.filepath.format(epoch=epoch + 1, **logs)
            if self.save_best_only:
                current = logs.get(self.monitor)
                if current is None:
                    warnings.warn('Can save best model only with %s available, '
                                  'skipping.' % (self.monitor), RuntimeWarning)
                else:
                    if self.monitor_op(current, self.best):
                        if self.verbose > 0:
                            print('\nEpoch %05d: %s improved from %0.5f to %0.5f,'
                                  ' saving model to %s'
                                  % (epoch + 1, self.monitor, self.best,
                                     current, filepath))
                        self.best = current
                        if self.save_weights_only:
                            self.ser_model.save_weights(filepath, overwrite=True)
                        else:
                            self.ser_model.save(filepath, overwrite=True)
                    else:
                        if self.verbose > 0:
                            print('\nEpoch %05d: %s did not improve from %0.5f' %
                                  (epoch + 1, self.monitor, self.best))
            else:
                if self.verbose > 0:
                    print('\nEpoch %05d: saving model to %s' % (epoch + 1, filepath))
                if self.save_weights_only:
                    self.ser_model.save_weights(filepath, overwrite=True)
                else:
                    self.ser_model.save(filepath, overwrite=True)

Не стесняйтесь давать любые комментарии и предложения, которые у вас есть!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...