Разные результаты при многократном оценивании на GPU и загрузке модели

Я только что впервые использовал функцию ModelCheckpoint для сохранения лучшей модели (best_model = True) и хотел проверить ее производительность. Когда модель была сохранена, было сказано, что val_acc было на уровне 83,3% перед сохранением. Я загрузил модель и использовал Assessment_generator для validation_generator, но результат для val_acc был 0,639. Я запутался, использовал его снова и получил 0,654, а затем 0,647, 0,744 и так далее. Я протестировал ту же конфигурацию на своем ПК (без графических процессоров), и она постоянно показывает одинаковые результаты (иногда могут быть небольшие ошибки округления).

Результат Val_acc после сохранения

  1. Почему результаты между разными запусками Assessment_generator различаются только на графическом процессоре?
  2. Почему модель val_acc отличается от указанной?

Я использую реализацию Keras Tensorflows.

model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])
checkpointer = ModelCheckpoint(filepath='/tmp/weights.hdf5', monitor = "val_acc", verbose=1, save_best_only=True)
# prepare data augmentation configuration
train_datagen = ImageDataGenerator(
    rescale = 1./ 255,
    shear_range = 0.2,
    zoom_range = 0.2,
    horizontal_flip = True)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size = (img_height, img_width),
    batch_size = batch_size)
validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size = (img_height, img_width),
    batch_size = batch_size)
# fine-tune the model
model.fit_generator(
    train_generator,
    steps_per_epoch = math.ceil(train_samples/batch_size),
    epochs=100,
    workers = 120,
    validation_data=validation_generator,
    validation_steps=math.ceil(val_samples/batch_size),
    callbacks=[checkpointer])
model.load_weights(filepath='/tmp/weights.hdf5')
model.predict_generator(validation_generator, steps = math.ceil(val_samples/batch_size) )
temp_model = load_model('/tmp/weights.hdf5')
temp_model.evaluate_generator(validation_generator, steps = math.ceil(val_samples/batch_size), workers = 120)
>>> [2.1996076788221086, 0.17857142857142858]
temp_model.evaluate_generator(validation_generator, steps = math.ceil(val_samples/batch_size), workers = 120)
>>> [2.2661823204585483, 0.25]

person Centar 15    schedule 01.09.2017    source источник
comment
Ваш генератор каждый раз возвращает один и тот же набор проверки? Есть ли случайность в том, как он выбирает образцы?   -  person gionni    schedule 01.09.2017
comment
Как и в коде, я использую встроенный файл flow_from_directory. Две папки train и test разделены. Я думаю, что он использует все => никакой случайности. train_data_dir = '/data/datasets/NAME/train' validation_data_dir = '/data/datasets/NAME/test'   -  person Centar 15    schedule 01.09.2017
comment
Равно ли val_samples общему количеству файлов изображений в разделе validation_data_dir?   -  person Yu-Yang    schedule 01.09.2017
comment
Это на самом деле ошибка, которую я сделал, но ошибки остаются даже с train_generator, где все в порядке.   -  person Centar 15    schedule 01.09.2017
comment
После исправления ошибки остались   -  person Centar 15    schedule 01.09.2017
comment
Что, если вы будете вызывать validation_generator.reset() после каждого вызова функции fit_generator()/predict_generator()/evaluate_generator()?   -  person Yu-Yang    schedule 01.09.2017
comment
К сожалению без изменений. Небольшое редактирование заключается в том, что я использую реализацию Keras Tensorflows.   -  person Centar 15    schedule 04.09.2017
comment
Очень сложно отлаживать такие вещи, просто проверяя код. Однако разница в поведении процессора и графического процессора удивительна — разницы быть не должно. Если вы можете сделать небольшой, воспроизводимый, автономный пример, который по-разному работает между ЦП и ГП в актуальной версии TensorFlow, вероятно, стоит зарегистрировать проблему TensorFlow на github.   -  person Peter Hawkins    schedule 07.09.2017


Ответы (2)


Это потому, что вы сохраняете только вес модели. Это означает, что вы не сохраняете состояние оптимизатора, что объясняет разницу в точности при перезагрузке модели. Если вы добавите save_weights_only=False при создании ModelCheckpoint, проблема будет решена:

Если вы перезагрузите модель, используйте функцию load_model из Keras. В противном случае вы все равно будете загружать только веса.

checkpointer = ModelCheckpoint(filepath='/tmp/full_model.hdf5', monitor = "val_acc", verbose=1, save_best_only=True, save_weights_only=False)

#reload model
from keras.models import load_model
model = load_model('/tmp/full_model.hdf5')
person Wilmar van Ommeren    schedule 01.09.2017
comment
Спасибо за ответ. Сейчас я использовал ту же переменную модели и импортировал только веса с помощью load_weights. Результаты по-прежнему различаются между оценками и сильно отличаются от того, что, по сообщениям, было спасено. - person Centar 15; 01.09.2017
comment
не только импортируйте веса, вам также необходимо импортировать состояние оптимизатора. Проверьте мой обновленный ответ - person Wilmar van Ommeren; 01.09.2017
comment
Спасибо! Было бы слишком сложно объяснить, почему состояние оптимизатора имеет значение, разве это не просто способ... ну... оптимизировать? Я попробую это сейчас и надеюсь получить тот же результат — точность довольно сильно колеблется из-за относительно небольшого набора —> она достигает 79,1, а затем падает до 0,667, я должен еще больше снизить скорость обучения. - person Centar 15; 01.09.2017
comment
К сожалению, не работал. ››› checkpointer = ModelCheckpoint(filepath='/tmp/weights4.hdf5', monitor = val_acc, verbose=1, ... save_best_only=True, save_weights_only=False) ››› model.load_weights(/tmp/weights4.hdf5 ) оценить1 => 0,75 оценить2 => 0,625 - person Centar 15; 01.09.2017
comment
Этого не должно быть. Продолжала ли ваша модель тренироваться после того, как она сохранила лучшую модель? Например, лучшая модель находится в 90-й эпохе, но ваша модель продолжала тренироваться до 100-й эпохи. В этом случае оценка1 дает точность модели в 100-ю эпоху, а оценка2 — в 90-ю эпоху. - person Wilmar van Ommeren; 01.09.2017
comment
Оптимизаторы обновляются во время обучения, чтобы минимизировать потери (medium.com/towards-data-science/). - person Wilmar van Ommeren; 01.09.2017
comment
Между двумя оценками не происходит обучения. Evaluate1 и 2 — это просто два раза подряд я набираю Evaluate_generator. Я также попытался предсказать и получил разные результаты между двумя прогнозами подряд (проверено, даже при случайном сборе образцов не удается найти совпадения) и нашел этот драгоценный камень: stackoverflow.com/questions/43938176/ Мне бы очень не хотелось писать свой собственный генератор с аугментациями... - person Centar 15; 01.09.2017
comment
Я понимаю, что обучения не происходит, но может случиться так, что модель, которую вы используете в оценке 1, отличается от той модели, которая была сохранена. Потому что последняя эпоха не привела к «лучшей» модели. - person Wilmar van Ommeren; 01.09.2017
comment
Вы можете проверить это, используя model.save после вашего evaluate1. Это определенно спасет ту же модель (которая может быть не самой лучшей) - person Wilmar van Ommeren; 01.09.2017
comment
Я это понимаю, я даже попробовал ваш подход, и все равно результаты разные. model.evaluate_generator(validation_generator, steps = math.ceil(val_samples/batch_size), workers = 120) [1.4041728178660076, 0.66666666666666663] ››› model.evaluate_generator(validation_generator, steps = math.ceil(val_samples/batch_size), workers = 120 [1.1987533519665401, 0.70833333333333337] ››› model.save(/tmp/saved.hdf5) ››› temp_model = model.load(/tmp/saved.hdf5) ››› temp_model = load_model(/tmp/saved.hdf5) › ›› temp_model.evaluate_generator(...) [0,81864879528681433, 0,8125] - person Centar 15; 01.09.2017
comment
Единственное, что я могу придумать, это то, что validation_generator генерирует разные входные данные. Можете ли вы установить numpy.random.seed(42) перед каждым вызовом model.evaluate_generator? - person Wilmar van Ommeren; 01.09.2017
comment
Вы также можете найти больше информации по этой проблеме здесь: github.com/fchollet/keras/issues/6499< /а> - person Wilmar van Ommeren; 01.09.2017
comment
Жаль, что это как-то связано с генератором. В статье, которую я опубликовал, последний комментатор утверждает, что он использует max_queue_size=1 для получения правильных результатов. Это мой последний вариант, иначе, к сожалению, я не смог бы вам помочь (за исключением части оптимизатора, которая все еще важна, если вы сохраняете модель). - person Wilmar van Ommeren; 01.09.2017

Ок, проблема была в следующем - batch_size ! Мне потребовались годы, чтобы понять это -

steps = math.ceil(val_samples/batch_size)

Из-за того, что batch_size не был делителем number_of_samples, это создавало проблемы. Небольшие ошибки возникли и при установке переменной workers - на GPU нет смысла ее использовать.

person Centar 15    schedule 13.09.2017