即使尺寸不匹配,自定义损失函数也能正常工作
Custom loss function works even though dimensions mismatch
我将 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)
在 model.fit 中,我收到一条错误消息:
ValueError: Error when checking target: expected conv2d_2 to have
shape (300, 320, 2) but got array with shape (300, 320, 1)
这是预期的,因为目标是单通道图像,而模型中的最后一层有 2 个通道。
我不明白的是为什么当我使用自定义损失函数时:
def my_loss2(y_true, y_pred):
return keras.losses.mean_absolute_error(y_true, y_pred)
并编译模型:
model.compile(optimizer = Adam(lr=1e-4), loss=my_loss2)
它确实有效(或者至少,不给出错误)。是否有某种自动 conversion/truncation 正在进行?
我正在使用 TF (CPU) 1.12.0 和 Keras 2.2.2
真诚的,
埃拉德
为什么内置损失和自定义损失的行为不同?
事实证明,Keras 正在对损失模块中定义的内置函数执行前期形状检查。
在fit
调用的Model._standardize_user_data
的源代码中,我发现了这个注释:
# 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.
在该评论周围的代码中,您确实可以看到,根据损失函数的类型(内置或自定义),输出形状要么传递给 standardize_input_data
的内部调用,要么不传递.如果输出形状通过,standardize_input_data
会引发您收到的错误消息。
而且我认为这种行为是有道理的:不知道损失函数的实现,就无法知道它的形状要求。有人可能会发明一些需要不同形状的损失函数。另一方面,docs 明确表示损失函数的参数必须具有相同的形状:
y_true: True labels. TensorFlow/Theano tensor.
y_pred: Predictions. TensorFlow/Theano tensor of the same shape as y_true.
所以我觉得这有点不一致...
为什么您的自定义损失函数适用于不兼容的形状?
如果您提供自定义损失,它可能仍然有效,即使形状不完全匹配。在您的情况下,只有最后一个维度不同,我很确定 broadcasting 是正在发生的事情。您的目标的最后一个维度将被复制。
在很多情况下广播非常有用。然而,这里可能不是,因为它隐藏了一个逻辑错误。
我将 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)
在 model.fit 中,我收到一条错误消息:
ValueError: Error when checking target: expected conv2d_2 to have shape (300, 320, 2) but got array with shape (300, 320, 1)
这是预期的,因为目标是单通道图像,而模型中的最后一层有 2 个通道。
我不明白的是为什么当我使用自定义损失函数时:
def my_loss2(y_true, y_pred):
return keras.losses.mean_absolute_error(y_true, y_pred)
并编译模型:
model.compile(optimizer = Adam(lr=1e-4), loss=my_loss2)
它确实有效(或者至少,不给出错误)。是否有某种自动 conversion/truncation 正在进行?
我正在使用 TF (CPU) 1.12.0 和 Keras 2.2.2
真诚的, 埃拉德
为什么内置损失和自定义损失的行为不同?
事实证明,Keras 正在对损失模块中定义的内置函数执行前期形状检查。
在fit
调用的Model._standardize_user_data
的源代码中,我发现了这个注释:
# 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.
在该评论周围的代码中,您确实可以看到,根据损失函数的类型(内置或自定义),输出形状要么传递给 standardize_input_data
的内部调用,要么不传递.如果输出形状通过,standardize_input_data
会引发您收到的错误消息。
而且我认为这种行为是有道理的:不知道损失函数的实现,就无法知道它的形状要求。有人可能会发明一些需要不同形状的损失函数。另一方面,docs 明确表示损失函数的参数必须具有相同的形状:
y_true: True labels. TensorFlow/Theano tensor.
y_pred: Predictions. TensorFlow/Theano tensor of the same shape as y_true.
所以我觉得这有点不一致...
为什么您的自定义损失函数适用于不兼容的形状?
如果您提供自定义损失,它可能仍然有效,即使形状不完全匹配。在您的情况下,只有最后一个维度不同,我很确定 broadcasting 是正在发生的事情。您的目标的最后一个维度将被复制。
在很多情况下广播非常有用。然而,这里可能不是,因为它隐藏了一个逻辑错误。