Keras:定制损失函数,训练数据与模型不直接相关

时间:2020-02-04 10:11:27

标签: tensorflow keras tf.keras

我正在尝试将使用tensorflow层编写的CNN转换为在tensorflow中使用keras api(我正在使用TF 1.x提供的keras api),并且在编写自定义损失函数来训练模型时遇到问题

根据本指南,在定义损失函数时,它需要参数(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都与模型直接相关(在简单情况下,它是网络的输出)。在我的问题中,事实并非如此。如果我的损失函数依赖于一些与模型张量无关的训练数据,该如何实现?

具体来说,这是我的问题:

我正在尝试学习训练成对的图像嵌入图像。我的训练数据包括图像对和图像对之间的匹配点注释(图像坐标)。输入功能仅是图像对,并且网络以暹罗配置进行训练。

我能够使用tensorflow层成功实现此目标,并使用tensorflow估计器对其进行成功培训。 我目前的实现是从tf Records的大型数据库中构建tf数据集,其中的功能是包含图像和匹配点数组的字典。在我可以轻松地将这些图像坐标数组提供给损失函数之前,但是目前尚不清楚如何做到这一点。

1 个答案:

答案 0 :(得分:6)

我经常使用一种技巧,即通过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)

创建一个虚拟的keras损失函数进行编译:

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,)), ...)

另一种方法是使用自定义训练循环。

这还需要更多工作。

尽管您使用的是TF1,但是仍然可以在代码的开始处打开eager execution,并像在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