我正在使用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:检查目标时出错:应为conv2d_2形状(300320,2),但得到具有形状(3003201)的阵列
这是预期的,因为目标是单通道图像,而模型中的最后一层有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)
它确实工作(或者至少没有给出错误)。是否正在进行任何类型的自动转换/截断?
我使用的是TF(CPU)1.12.0和Keras 2.2.2
真诚地,Elad
为什么内置损失和自定义损失的行为不同
事实证明,Keras正在为loss模块中定义的内置函数执行前期形状检查。
在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
将引发您得到的错误消息。
我认为这种行为是有道理的:如果不知道损失函数的实现,你就不可能知道它的形状要求。有人可能会发明一些需要不同形状的损失函数。另一方面,文件明确表示,损失函数的参数必须具有相同的形状:
y_true:true标签。TensorFlow/Theano张量。
y_pred:预测。张量流/与y_true形状相同的雷诺张量。
所以我觉得这有点不一致。。。
为什么您的自定义损失函数适用于不兼容的形状
如果提供自定义损失,即使形状不完全匹配,它也可能仍然有效。在你的情况下,只有最后一个维度不同,我很确定广播就是正在发生的事情。目标的最后一个维度将被复制。
在许多情况下,广播是非常有用的。然而,在这里,它可能不是,因为它隐藏了一个逻辑错误。