前向传播后的 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(或者同Layerclass的方法losses)在训练过程中是如何处理的呢?训练时从哪里调用?例如,在将它们添加到最终损失之前,它们是相加还是平均?我想查看实际代码。

我想知道这些损失如何与您在 fit 方法中指定的损失相结合。你能给我提供结合它们的代码吗?请注意,我对 TensorFlow 附带的 Keras 很感兴趣(因为我正在使用它)。

其实计算total loss的部分在Modelclass的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;但是,事物的结构和流程有点不同,如下所述。

首先,在Modelclassa loss container is createdcompile方法中保存和计算损失函数的值:

  self.compiled_loss = compile_utils.LossesContainer(
      loss, loss_weights, output_names=self.output_names)

接下来,在Modelclass这个容器is calledtrain_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 将包含层特定损失的总和以及批处理轴上所有损失函数的平均值之和(因此,这将是一个单一的价值)。