当在Keras模型中定义自定义损失时,在线资源似乎表明该损失应返回一个值数组(批次中每个样品的损失)。像这样
def custom_loss_function(y_true, y_pred):
squared_difference = tf.square(y_true - y_pred)
return tf.reduce_mean(squared_difference, axis=-1)
model.compile(optimizer='adam', loss=custom_loss_function)
在上面的示例中,我不知道该模型何时或是否采用tf.reduce_sum()
或tf.reduce_mean()
的批次总和或均值
在另一种情况下,当我们想使用自定义功能实现自定义训练循环时,根据Keras文档,要遵循的模板是
for epoch in range(epochs):
for step, (x_batch_train, y_batch_train) in enumerate(train_dataset):
with tf.GradientTape() as tape:
y_batch_pred = model(x_batch_train, training=True)
loss_value = custom_loss_function(y_batch_train, y_batch_pred)
grads = tape.gradient(loss_value, model.trainable_weights)
optimizer.apply_gradients(zip(grads, model.trainable_weights))
因此,根据书中的内容,如果我理解正确,我们应该采用批次梯度的平均值。因此,上述损失值应为每批次单一值。
但是,该示例将适用于以下两种变体:
tf.reduce_mean(squared_difference, axis=-1) # array of loss for each sample
tf.reduce_mean(squared_difference) # mean loss for batch
那么,为什么上面的第一个选项(阵列丢失)仍然有效? apply_gradients
是否对每个值依次应用小的更改?尽管有效,这是错误的吗?
没有自定义循环和有自定义循环的正确方法是什么?
答案 0 :(得分:1)
好问题。我认为,这在TensorFlow / Keras API中没有得到很好的记录。默认情况下,如果您不提供标量loss_value
,TensorFlow将add them up(并且更新不是连续的)。从本质上讲,这等效于沿批处理轴求和。
当前,TensorFlow API中的损失包括一个reduction
参数(例如tf.losses.MeanSquaredError),该参数允许指定如何沿批处理轴汇总损失。