Keras: пользовательская функция потерь с данными обучения, не имеющими прямого отношения к модели - PullRequest
1 голос
/ 04 февраля 2020

Я пытаюсь преобразовать свой CNN, написанный слоями тензорного потока, чтобы использовать keras api в тензорном потоке (я использую keras api, предоставленный TF 1.x), и у меня возникают проблемы при написании пользовательской функции потерь для обучения модели .

Согласно этому руководству, при определении функции потерь он ожидает аргументы (y_true, y_pred) https://www.tensorflow.org/guide/keras/train_and_evaluate#custom_losses

def basic_loss_function(y_true, y_pred):
    return ...

Однако в каждом примере, который я видел y_true как-то напрямую связано с моделью (в простом случае это выход сети). В моей проблеме это не тот случай. Как реализовать это, если моя функция потерь зависит от некоторых обучающих данных, которые не связаны с тензорами модели?

Если говорить конкретно, вот моя проблема:

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

Я могу успешно реализовать это с слоями тензорного потока и успешно обучить с помощью оценок тензорного потока. Мои текущие реализации создают набор данных tf из большой базы данных tf Records, где функциями является словарь, содержащий изображения и массивы совпадающих точек. Раньше я мог легко подавать эти массивы координат изображения в функцию потерь, но здесь неясно, как это сделать.

1 Ответ

4 голосов
/ 06 февраля 2020

Я часто использую хак, который рассчитывает потери в модели с помощью Lambda слоев. (Например, когда потеря не зависит от истинных данных и модель не имеет выходных данных для сравнения)

В функциональной модели API:

def loss_calc(x):
    loss_input_1, loss_input_2 = x #arbirtray inputs, you choose
                                   #according to what you gave to the Lambda layer

    #here you use some external data that doesn't relate to the samples
    externalData = K.constant(external_numpy_data)


    #calculate the loss
    return the loss

Использование выходные данные самой модели (тензор (ы), которые используются в вашей потере)

loss = Lambda(loss_calc)([model_output_1, model_output_2])

Создайте модель, выводящую потери вместо выходных:

model = Model(inputs, loss)

Создайте функция потери фиктивных керасов для компиляции:

def dummy_loss(y_true, y_pred):
    return y_pred #where y_pred is the loss itself, the output of the model above

model.compile(loss = dummy_loss, ....)

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

model.fit(your_inputs, np.zeros((number_of_samples,)), ...)

Другой способ сделать это, использует пользовательское обучение l oop.

Это гораздо больше работы.

Хотя вы используете TF1, вы все равно можете включить нетерпеливое выполнение в самом начале вашего кода и делать вещи, как это сделано в TF2. (tf.enable_eager_execution())

Следуйте инструкциям для пользовательских циклов обучения: https://www.tensorflow.org/tutorials/customization/custom_training_walkthrough

Здесь вы сами рассчитываете градиенты, любого результата относительно того, что вы хотите. Это означает, что вам не нужно следовать стандартам обучения Keras.


Наконец, вы можете использовать предложенный вами подход model.add_loss. В этом случае вы точно рассчитываете потери так же, как и в первом ответе. И передайте этот тензор потерь на add_loss.

Вы, вероятно, можете затем скомпилировать модель с loss=None (не уверен), потому что вы будете использовать другие потери, не стандартные.

В этом случае выходные данные вашей модели вероятно будет тоже None, и вы должны соответствовать y=None.

...