简体   繁体   English

如何访问生成器提供的 Keras 自定义损失函数中的样本权重?

[英]How to access sample weights in a Keras custom loss function supplied by a generator?

I have a generator function that infinitely cycles over some directories of images and outputs 3-tuples of batches the form我有一个生成器函数,它在某些图像目录上无限循环并输出批量的 3 元组表单

[img1, img2], label, weight

where img1 and img2 are batch_size x M x N x 3 tensors, and label and weight are each batch_size x 1 tensors.其中img1img2batch_size x M x N x 3张量, labelweight分别是batch_size x 1 张量。

I provide this generator to the fit_generator function when training a model with Keras.在使用fit_generator训练模型时,我将此生成器提供给fit_generator函数。

For this model I have a custom cosine contrastive loss function,对于这个模型,我有一个自定义的余弦对比损失函数,

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)

Structurally everything runs OK with my model.从结构上讲,我的模型一切正常。 There are no errors and it is consuming the inputs and labels from the generator as expected.没有错误,它正在按预期消耗来自生成器的输入和标签。

But now I am seeking to directly use the weights parameter per each batch and perform some customized logic inside of cosine_contrastive_loss based on the sample-specific weight.但是现在我正在寻求直接使用每个批次的权重参数,并根据特定于样本的权cosine_contrastive_loss内部执行一些自定义逻辑。

How can I access this parameter from the structure of a batch of samples at the moment of the loss function being executed?如何在执行损失函数时从一批样本的结构中访问此参数?

Note that since it is an infinitely cycling generator, it is not possible to precompute weights or compute them on the fly to either curry the weights into the loss function or generate them.请注意,由于它是一个无限循环的生成器,因此无法预先计算权重或动态计算它们以将权重归入损失函数或生成它们。

They have to be generated in unison with the samples being generated, and indeed there is custom logic in my data generator that determines the weights dynamically from properties of img1 , img2 and label at the moment they are generated for a batch.它们必须与正在生成的样本一致生成,并且确实在我的数据生成器中有自定义逻辑,可以在为批处理生成时根据img1img2label属性动态确定权重。

Manual training loop alternative手动训练循环替代

The only thing I can think of is a manual training loop where you get the weights yourself.我唯一能想到的是手动训练循环,您可以自己获得重量。

Have a weights tensor and a non variable batch size:有一个权重张量和一个不可变的批量大小:

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

Use them in your custom loss:在您的自定义损失中使用它们:

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

For a "generator":对于“生成器”:

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)

For a keras.utils.Sequence :对于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)

I know this answer is not optimal because it does not parallelize getting data from the generator as it happens with fit_generator .我知道这个答案不是最优的,因为它不会像fit_generator那样并行从生成器获取数据。 But it's the best easy solution I can think of.但这是我能想到的最好的简单解决方案。 Keras didn't expose the weights, they are applied automatically in some hidden source code. Keras 没有公开权重,它们会自动应用在一些隐藏的源代码中。


Let the model calculate the weights alternative让模型计算权重替代方案

If calculating the weights can be done from x and y , you can delegate this task to the loss function itself.如果可以从xy计算权重,您可以将此任务委托给损失函数本身。

This is sort of hacky, but may work:这有点hacky,但可能有效:

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

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

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

Let the loss have access to input1 and input2 :让损失可以访问input1input2

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

The issue here is whether you can or not calculate the weigths as a tensor from the inputs.这里的问题是您是否可以根据输入将权重计算为张量。

The loss function in Keras Tensorflow v2 is called with the sample weighs使用样本权重调用 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 https://github.com/keras-team/keras/blob/tf-2/keras/engine/training.py


You can use GradientTape for custom training, see https://www.tensorflow.org/guide/keras/train_and_evaluate#part_ii_writing_your_own_training_evaluation_loops_from_scratch您可以使用 GradientTape 进行自定义训练,请参阅https://www.tensorflow.org/guide/keras/train_and_evaluate#part_ii_writing_your_own_training_evaluation_loops_from_scratch

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM