前向传播后的 KL 损失究竟用在哪里?
Where exactly are the KL losses used after the forward pass?
我注意到损失的 KL 部分被添加到 DenseVariational
的列表 self._losses
of the Layer
class when self.add_loss
is called from the call
method 中(即在前向传递期间)。
但是这个列表self._losses
(或者同Layer
class的方法losses
)在训练过程中是如何处理的呢?训练时从哪里调用?例如,在将它们添加到最终损失之前,它们是相加还是平均?我想查看实际代码。
我想知道这些损失如何与您在 fit
方法中指定的损失相结合。你能给我提供结合它们的代码吗?请注意,我对 TensorFlow 附带的 Keras 很感兴趣(因为我正在使用它)。
其实计算total loss的部分在Model
class的compile
方法中,具体在this line:
# Compute total loss.
# Used to keep track of the total loss value (stateless).
# eg., total_loss = loss_weight_1 * output_1_loss_fn(...) +
# loss_weight_2 * output_2_loss_fn(...) +
# layer losses.
self.total_loss = self._prepare_total_loss(masks)
_prepare_total_loss
方法将正则化和层损失添加到总损失(即所有损失加在一起),然后在 these lines 中的批处理轴上对它们进行平均:
# Add regularization penalties and other layer-specific losses.
for loss_tensor in self.losses:
total_loss += loss_tensor
return K.mean(total_loss)
其实self.losses
并不是Model
的属性class;相反,它是 attribute of the parent class,即 Network
,其中 return 将所有特定于层的损失列为一个列表。此外,为了解决任何混淆,上面代码中的 total_loss
是单个张量,它等于模型中所有损失的 总和 (即损失函数值和层-特定损失)。请注意,根据定义 必须 return 每个输入样本(而不是整个批次)的单个损失值。因此,K.mean(total_loss)
会将批处理轴上的所有这些值平均为一个最终损失值,优化器应将其最小化。
至于tf.keras
这个和原生的差不多keras
;但是,事物的结构和流程有点不同,如下所述。
首先,在Model
classa loss container is created的compile
方法中保存和计算损失函数的值:
self.compiled_loss = compile_utils.LossesContainer(
loss, loss_weights, output_names=self.output_names)
接下来,在Model
class这个容器is called的train_step
方法中计算一个batch的损失值:
loss = self.compiled_loss(
y, y_pred, sample_weight, regularization_losses=self.losses)
正如您在上面看到的那样,self.losses
已传递到此容器。 self.losses
,与原生 Keras 实现一样,包含所有特定于层的损失值,唯一的区别是 tf.keras
it's implemented in Layer
class (instead of Network
class as in native Keras). Note that Model
is a subclass of Network
which itself is a subclass of Layer
. Now, let's see how regularization_losses
would be treated in the __call__
method of LossesContainer
(these lines):
if (loss_obj.reduction == losses_utils.ReductionV2.SUM_OVER_BATCH_SIZE or
loss_obj.reduction == losses_utils.ReductionV2.AUTO):
loss_value = losses_utils.scale_loss_for_distribution(loss_value)
loss_values.append(loss_value)
loss_metric_values.append(loss_metric_value)
if regularization_losses:
regularization_losses = losses_utils.cast_losses_to_common_dtype(
regularization_losses)
reg_loss = math_ops.add_n(regularization_losses)
loss_metric_values.append(reg_loss)
loss_values.append(losses_utils.scale_loss_for_distribution(reg_loss))
if loss_values:
loss_metric_values = losses_utils.cast_losses_to_common_dtype(
loss_metric_values)
total_loss_metric_value = math_ops.add_n(loss_metric_values)
self._loss_metric.update_state(
total_loss_metric_value, sample_weight=batch_dim)
loss_values = losses_utils.cast_losses_to_common_dtype(loss_values)
total_loss = math_ops.add_n(loss_values)
return total_loss
如您所见,regularization_losses
将被添加到 total_loss
中,该 total_loss
将包含层特定损失的总和以及批处理轴上所有损失函数的平均值之和(因此,这将是一个单一的价值)。
我注意到损失的 KL 部分被添加到 DenseVariational
的列表 self._losses
of the Layer
class when self.add_loss
is called from the call
method 中(即在前向传递期间)。
但是这个列表self._losses
(或者同Layer
class的方法losses
)在训练过程中是如何处理的呢?训练时从哪里调用?例如,在将它们添加到最终损失之前,它们是相加还是平均?我想查看实际代码。
我想知道这些损失如何与您在 fit
方法中指定的损失相结合。你能给我提供结合它们的代码吗?请注意,我对 TensorFlow 附带的 Keras 很感兴趣(因为我正在使用它)。
其实计算total loss的部分在Model
class的compile
方法中,具体在this line:
# Compute total loss.
# Used to keep track of the total loss value (stateless).
# eg., total_loss = loss_weight_1 * output_1_loss_fn(...) +
# loss_weight_2 * output_2_loss_fn(...) +
# layer losses.
self.total_loss = self._prepare_total_loss(masks)
_prepare_total_loss
方法将正则化和层损失添加到总损失(即所有损失加在一起),然后在 these lines 中的批处理轴上对它们进行平均:
# Add regularization penalties and other layer-specific losses.
for loss_tensor in self.losses:
total_loss += loss_tensor
return K.mean(total_loss)
其实self.losses
并不是Model
的属性class;相反,它是 attribute of the parent class,即 Network
,其中 return 将所有特定于层的损失列为一个列表。此外,为了解决任何混淆,上面代码中的 total_loss
是单个张量,它等于模型中所有损失的 总和 (即损失函数值和层-特定损失)。请注意,根据定义 必须 return 每个输入样本(而不是整个批次)的单个损失值。因此,K.mean(total_loss)
会将批处理轴上的所有这些值平均为一个最终损失值,优化器应将其最小化。
至于tf.keras
这个和原生的差不多keras
;但是,事物的结构和流程有点不同,如下所述。
首先,在Model
classa loss container is created的compile
方法中保存和计算损失函数的值:
self.compiled_loss = compile_utils.LossesContainer(
loss, loss_weights, output_names=self.output_names)
接下来,在Model
class这个容器is called的train_step
方法中计算一个batch的损失值:
loss = self.compiled_loss(
y, y_pred, sample_weight, regularization_losses=self.losses)
正如您在上面看到的那样,self.losses
已传递到此容器。 self.losses
,与原生 Keras 实现一样,包含所有特定于层的损失值,唯一的区别是 tf.keras
it's implemented in Layer
class (instead of Network
class as in native Keras). Note that Model
is a subclass of Network
which itself is a subclass of Layer
. Now, let's see how regularization_losses
would be treated in the __call__
method of LossesContainer
(these lines):
if (loss_obj.reduction == losses_utils.ReductionV2.SUM_OVER_BATCH_SIZE or
loss_obj.reduction == losses_utils.ReductionV2.AUTO):
loss_value = losses_utils.scale_loss_for_distribution(loss_value)
loss_values.append(loss_value)
loss_metric_values.append(loss_metric_value)
if regularization_losses:
regularization_losses = losses_utils.cast_losses_to_common_dtype(
regularization_losses)
reg_loss = math_ops.add_n(regularization_losses)
loss_metric_values.append(reg_loss)
loss_values.append(losses_utils.scale_loss_for_distribution(reg_loss))
if loss_values:
loss_metric_values = losses_utils.cast_losses_to_common_dtype(
loss_metric_values)
total_loss_metric_value = math_ops.add_n(loss_metric_values)
self._loss_metric.update_state(
total_loss_metric_value, sample_weight=batch_dim)
loss_values = losses_utils.cast_losses_to_common_dtype(loss_values)
total_loss = math_ops.add_n(loss_values)
return total_loss
如您所见,regularization_losses
将被添加到 total_loss
中,该 total_loss
将包含层特定损失的总和以及批处理轴上所有损失函数的平均值之和(因此,这将是一个单一的价值)。