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

У меня есть функция генератора, которая бесконечно циклически перебирает некоторые каталоги изображений и выводит 3-х кортежи пакетов в форме

[img1, img2], label, weight

где img1 и img2 - это batch_size x M x N x 3 тензоры, а label и weight - каждый batch_size x 1 тензоры.

Я предоставляю этот генератор функции fit_generator при обучении модели с помощью Keras.

Для этой модели у меня есть настраиваемая функция косинусных контрастных потерь,

def cosine_constrastive_loss(y_true, y_pred):
    cosine_distance = 1 - y_pred
    margin = 0.9
    cdist = y_true * y_pred + (1 - y_true) * keras.backend.maximum(margin - y_pred, 0.0)
    return keras.backend.mean(cdist)

Конструктивно с моей моделью все работает нормально. Ошибок нет, и он, как и ожидалось, использует входные данные и метки от генератора.

Но теперь я пытаюсь напрямую использовать параметр весов для каждой партии и выполнять некоторую настраиваемую логику внутри cosine_contrastive_loss на основе веса конкретного образца.

Как мне получить доступ к этому параметру из структуры пакета образцов в момент выполнения функции потерь?

Обратите внимание, что, поскольку это генератор с бесконечным циклом, невозможно предварительно вычислить веса или вычислить их на лету, чтобы преобразовать веса в функцию потерь или сгенерировать их.

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


person ely    schedule 18.09.2019    source источник


Ответы (2)


Альтернатива ручного цикла обучения

Единственное, что я могу придумать, - это цикл ручных тренировок, когда вы сами поднимаете веса.

Имейте тензор весов и неизменяемый размер партии:

weights = K.variable(np.zeros((batch_size,)))

Используйте их в своем индивидуальном проигрыше:

def custom_loss(true, pred):
    return someCalculation(true, pred, weights)

Для генератора:

for e in range(epochs):
    for s in range(steps_per_epoch):
        x, y, w = next(generator) #or generator.next(), not sure
        K.set_value(weights, w)

        model.train_on_batch(x, y)

Для keras.utils.Sequence:

for e in range(epochs):
    for s in range(len(generator)):
        x,y,w = generator[s]

        K.set_value(weights, w)
        model.train_on_batch(x,y)

Я знаю, что этот ответ не оптимален, потому что он не распараллеливает получение данных от генератора, как это происходит с fit_generator. Но это лучшее простое решение, которое я могу придумать. Керас не раскрыл веса, они автоматически применяются в каком-то скрытом исходном коде.


Пусть модель вычислит альтернативу весов

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

Это вроде взлома, но может сработать:

input1 = Input(shape1)
input2 = Input(shape2)

# .... model creation .... #

model = Model([input1, input2], outputs)

Пусть у проигрыша будет доступ к input1 и input2:

def custom_loss(y_true, y_pred):
    w = calculate_weights(input1, input2, y_pred)
    # .... rest of the loss .... #

Проблема здесь в том, можете ли вы вычислить веса как тензор из входных данных.

person Daniel Möller    schedule 19.09.2019
comment
Благодарность! Это определенно не идеально - вручную вызывать train_on_batch таким образом, но он предлагает надежную работу, очень признателен! - person ely; 19.09.2019
comment
В конце добавлен альтернативный ответ, который может быть интересно проверить. - person Daniel Möller; 19.09.2019
comment
Добавленный ответ - хорошая идея, но, к сожалению, в моем случае веса зависят от метаданных о входных данных, к которым осуществляется доступ в то время, когда входные данные генерируются и загружаются в кишечник пакетного генератора. По сути, пакетный генератор перебирает манифесты файлов и метаданные об этих файлах, чтобы определить, как отбирать положительные и отрицательные пары изображений. В зависимости от других метаданных, некоторые положительные и отрицательные изображения получают больший вес для обучения, потому что модель должна хорошо работать с ними во время прогнозирования после обучения. - person ely; 19.09.2019
comment
Понятно ... если вам действительно нужна лучшая производительность, вы можете попробовать передать эти метаданные в модель в качестве дополнительных входных данных. Затем умножьте его на ноль и добавьте к основному входу (просто для связи с выходом). Это может показаться слишком сложным, но в зависимости от времени загрузки пакета это может значительно увеличить скорость обучения. - person Daniel Möller; 19.09.2019
comment
Метаданные - это множество строковых данных, которые представляют собой метаданные файла (временная метка создания, кто их создал, свойства об обстоятельствах, когда они были созданы). Большая часть из них предварительно вычисляется до простого набора критериев, которые могут быть проверены внутренностями генератора данных, который затем должен фактически загрузить пакетное значение пар изображений, меток и т. Д. Скорость обучения была довольно высокой. для этого и не сильно ограничивается временем загрузки партии. Я думаю, что найти структурированный способ для всех этих строковых данных, которые будут приняты в тензоры в модели, действительно сделало бы сложность кода очень проблематичной. - person ely; 19.09.2019
comment
Можно ли каким-либо образом встроить весовые коэффициенты выборки (или любое другое значение генератора) в y_pred для последующего извлечения в функции потерь. Единственная сложность, которую я могу придумать, заключается в том, что это снизит размеры вашей сети. - person seeiespi; 26.05.2020

Функция потерь в Keras Tensorflow v2 вызывается с весом образца

output_loss = loss_fn(y_true, y_pred, sample_weight=sample_weight)

https://github.com/keras-team/keras/blob/tf-2/keras/engine/training.py


Вы можете использовать GradientTape для пользовательского обучения, см. https://www.tensorflow.org/guide/keras/train_and_evaluate#part_ii_writing_your_own_training_evaluation_loops_from_scratch

person Gary Fibiger    schedule 28.10.2019
comment
Любые API-подобные абстракции непосредственно в Tensorflow, такие как API-интерфейс Estimator, набор данных или GradientTape, обязательно должны игнорироваться. Это слишком небезопасно и подвержено ошибкам, чтобы полагаться на то, что разработчики Tensorflow выбирают для этих абстракций. - person ely; 29.10.2019