编译时清除添加到tensorflow 2中自定义层的损失

Loss added to custom layer in tensorflow 2 is cleared when compiling

我正在尝试将 https://github.com/yaringal/ConcreteDropout/blob/master/concrete-dropout-keras.ipynb 中 keras 中的具体 dropout 实现移植到 tensorflow 2。这基本上很简单,因为 tf 2 内置了大部分 keras API。不过,海关损失正在装修前清算。

定义模型后,在编译之前,我可以看到每个具体的 dropout 层的损失已通过行 self.layer.add_loss(regularizer) 运行 添加到模型损失中建成:

>>> print(model.losses)
[<tf.Tensor: id=64, shape=(), dtype=float32, numpy=-8.4521576e-05>, <tf.Tensor: id=168, shape=(), dtype=float32, numpy=-0.000650166>, <tf.Tensor: id=272, shape=(), dtype=float32, numpy=-0.000650166>, <tf.Tensor: id=376, shape=(), dtype=float32, numpy=-0.000650166>, <tf.Tensor: id=479, shape=(), dtype=float32, numpy=-0.000650166>]

编译后,model.losses变为空列表,断言assert len(model.losses) == 5失败。如果我选择忽略断言,层损失被忽略的事实会在训练模型时显示在警告 WARNING:tensorflow:Gradients do not exist for variables ['concrete_dropout/p_logit:0', 'concrete_dropout_1/p_logit:0', 'concrete_dropout_2/p_logit:0', 'concrete_dropout_3/p_logit:0', 'concrete_dropout_4/p_logit:0'] when minimizing the loss. 中。

深入研究 https://github.com/tensorflow/tensorflow/blob/r2.0/tensorflow/python/keras/engine/training.py#L184 中的编译代码后,我认为有问题的行是

    # Clear any `_eager_losses` that was added.
    self._clear_losses()

为什么要在模型编译时完成?如果这不是方法,我如何在 tensorflow 2 中添加每层损失?

由于自定义损失不依赖于模型的输入,您应该使用零参数调用来添加它,如下所示:

self.layer.add_loss(lambda: regularizer)