即使尺寸不匹配,自定义损失函数也能工作

Mar*_*mba 5 keras tensorflow loss-function


我正在使用 Keras/TF 和以下模型:

conv = Conv2D(4, 3, activation = None, use_bias=True)(inputs)   
conv = Conv2D(2, 1, activation = None, use_bias=True)(conv)
model = Model(input = inputs, output = conv)
model.compile(optimizer=Adam(lr=1e-4), loss=keras.losses.mean_absolute_error)
Run Code Online (Sandbox Code Playgroud)

在 model.fit 中,我收到一条错误消息:

ValueError:检查目标时出错:预期 conv2d_2 的形状为 (300, 320, 2),但得到的数组形状为 (300, 320, 1)

这是符合预期的,因为目标是单通道图像,而模型的最后一层有 2 个通道。

我不明白的是为什么当我使用自定义损失函数时:

def my_loss2(y_true, y_pred):
    return keras.losses.mean_absolute_error(y_true, y_pred)
Run Code Online (Sandbox Code Playgroud)

并编译模型:

model.compile(optimizer = Adam(lr=1e-4), loss=my_loss2)
Run Code Online (Sandbox Code Playgroud)

确实有效(或者至少没有给出错误)。是否有任何类型的自动转换/截断正在进行?

我正在使用 TF (CPU) 1.12.0 和 Keras 2.2.2

此致,埃拉德

seb*_*ckm 4

为什么内置损失和自定义损失的行为不同?

事实证明,Keras 正在对损失模块中定义的内置函数执行预先形状检查。

Model._standardize_user_data在被调用的 的源代码中fit,我发现了这样的注释:

# If `loss_fn` is not a function (e.g. callable class)
# or if it not in the `losses` module, then
# it is a user-defined loss and we make no assumptions
# about it.
Run Code Online (Sandbox Code Playgroud)

在该注释周围的代码中,您可以看到,实际上,根据损失函数的类型(内置或自定义),输出形状要么传递给内部调用,要么standardize_input_data不传递给内部调用。如果输出形状通过,standardize_input_data则会引发您收到的错误消息。

我认为这种行为是有道理的:如果不知道损失函数的实现,你就无法知道它的形状要求。有人可能会发明一些需要不同形状的损失函数。另一方面,文档明确指出损失函数的参数必须具有相同的形状:

y_true:真实标签。TensorFlow/Theano 张量。

y_pred:预测。与 y_true 形状相同的 TensorFlow/Theano 张量。

所以我觉得这有点不一致......

为什么您的自定义损失函数适用于不兼容的形状?

如果您提供自定义损失,即使形状不完全匹配,它仍然可能有效。在你的情况下,只有最后一个维度不同,我很确定广播就是正在发生的事情。您的目标的最后一个维度将被复制。

在许多情况下,广播非常有用。然而,这里可能不是,因为它隐藏了逻辑错误。