TensorFlow: почему значение моего монитора обратного вызова Keras недоступно?

Я использую TensorFlow 1.12. Я пытаюсь подобрать модель, используя обратные вызовы Keras:

checkpoint_full = tf.keras.callbacks.ModelCheckpoint(filepath='model/dir/model.{epoch:02d}.hdf5', monitor='val_dice_loss', save_best_only=True, mode = "min")
tensorboard = tf.keras.callbacks.TensorBoard(log_dir='/media/nfs/7_raid/ebos/models/fcn/logs/', write_graph=False)
history = model.fit(train,
                    steps_per_epoch=int(np.ceil(num_samples / float(BATCH_SIZE))),
                    epochs=NUM_EPOCHS,
                    validation_data=val,
                    verbose=0,
                    callbacks=[checkpoint_full, tensorboard])

Однако это вызывает следующую ошибку:

WARNING:tensorflow:Can save best model only with val_dice_loss available, skipping.

Во-первых, я не понимаю, как разрешается строка, переданная monitor. Я следую двум руководствам по Keras (1, 2), и оба предоставляют имена строк, которые больше нигде не упоминаются в их коде. Я предполагаю, что они указывают строки, которые пользователь может позже использовать для получения данных о развитии производительности после обучения, а не указывают, какой показатель fit должен отслеживаться? Если да, то почему он говорит, что значение недоступно?

Во-вторых, все ответы на подобные вопросы указывают на то, что проблема заключается в отсутствии проверочных данных. Тем не менее, я почти уверен, что предоставляю fit данные, о чем свидетельствует цикл val и подсчет количества записей. Что я делаю неправильно?

Для справки, мои наборы данных генерируются следующим образом:

def train_sample_fetcher():
    return sample_fetcher()

def val_sample_fetcher():
    return sample_fetcher(is_validations=True)

def sample_fetcher(is_validations=False):
    sample_names = [filename[:-4] for filename in os.listdir(DIR_DATASET + "ndarrays/")]
    if not is_validations: sample_names = sample_names[:int(len(sample_names) * TRAIN_VAL_SPLIT)]
    else: sample_names = sample_names[int(len(sample_names) * TRAIN_VAL_SPLIT):]
    for sample_name in sample_names:
        rgb = tf.image.decode_jpeg(tf.read_file(DIR_DATASET + sample_name + ".jpg"))
        rgb = tf.image.resize_images(rgb, (HEIGHT, WIDTH))
        #d = tf.image.decode_jpeg(tf.read_file(DIR_DATASET + "depth/" + sample_name + ".jpg"))
        #d = tf.image.resize_images(d, (HEIGHT, WIDTH))
        #rgbd = tf.concat([rgb,d], axis=2)
        onehots = tf.convert_to_tensor(np.load(DIR_DATASET + "ndarrays/" + sample_name + ".npy"), dtype=tf.float32)
        yield rgb, onehots

train = tf.data.Dataset.from_generator(generator=train_sample_fetcher, output_types=(tf.uint8, tf.uint8))
#train = train.repeat()
train = train.batch(BATCH_SIZE)
#train = train.shuffle(10)
val = tf.data.Dataset.from_generator(generator=val_sample_fetcher, output_types=(tf.uint8, tf.uint8))

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

def dice_loss(y_true, y_pred):
    smooth = 1.
    y_true_f = tf.reshape(y_true, [-1]) # Flatten
    y_pred_f = tf.reshape(y_pred, [-1]) # Flatten
    intersection = tf.reduce_sum(y_true_f * y_pred_f)
    dice_coefficient = (2. * intersection + smooth) / (tf.reduce_sum(y_true_f) + tf.reduce_sum(y_pred_f) + smooth)
    loss = 1 - dice_coefficient
    return loss

Я выполняю семантическую сегментацию, и потери в кости рассчитываются на пиксель.

Какие потери и показатели вы указываете для своей модели?

Dr. Snoopy 27.05.2019 15:16
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
1 137
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Следите за 'val_loss', так как ваша функция потери уже настроена на вашу пользовательскую функцию потери кубиков.

Параметр monitor ожидает метрику. 'loss' всегда доступен, и если у вас есть данные проверки, то и 'val_loss'. Некоторым людям нравится использовать 'accuracy' и его валидацию. Если бы у вас была пользовательская функция метрики, такая как чувствительность, называемая (например) sensitivity_deluxe(), вы могли бы включить sensitivity_deluxe в массив метрик в compile(), и она была бы доступна для любых обратных вызовов, ссылающихся на нее в своем поле monitor. Каждый раз, когда у вас есть данные проверки, вы можете добавить к строке метрики префикс «val_».

Пример:

model.compile(loss=my_loss_function(), optimizer='Adam', metrics=[sensitivity_deluxe])
reduce_lr = ReduceLROnPlateau(monitor='val_loss', patience=3, mode='min')
earlystop = EarlyStopping(monitor='val_sensitivity_deluxe', patience=5, mode='max')
model.fit(X, y, validation_split=0.5, callbacks=[earlystop, reduce_lr])

Я не могу ответить на ваш второй вопрос о проверке, не увидев вашу функцию fit(), но похоже, что вы, вероятно, в порядке, поскольку вы настроили отдельные генераторы.

Спасибо за разъяснение(я)! Я до сих пор не понимаю, почему функция потерь передается непосредственно в поле метрик в .compile(), а обратные вызовы ссылаются на эти функции в строках. Разбирает ли TensorFlow эти строки и каким-то образом связывает их с правильной функцией потерь?

EmielBoss 28.05.2019 01:52

Да! Вы правильно поняли, и вы также правы, что это не интуитивно. В случае потери строковое представление остается «потерей», независимо от того, пользовательское оно или нет, потому что в compile(loss=...) оно стало известно под этим именем. В противном случае для пользовательских метрик имя строки является конкретным, как в случае теоретической пользовательской метрической функции sensitivity_deluxe() выше. Нелогичная часть заключается в том, что имя функции становится строкой под капотом,, но так оно и работает. Я подозреваю, что причина, по которой loss отделена от массива metrics, заключается в том, что он (в отличие от любых других) является обязательным.

TheLoneDeranger 28.05.2019 17:11

Другие вопросы по теме