Keras 中 GAN 损失的指标名称

Metric names for the GANs loss in Keras

我正在使用 Wasserstein GAN 的改进版本,用于在将一些特征 X_{S} 与噪声向量 z 结合在一起作为输入时生成的图像。此外,我想从特定 类 生成样本。因此,在整个系统的标准训练中加入了一个分类器。我构建整个系统的代码如下:

class WGANGP():
def __init__(self):

    self.target_mod = ".."
    self.learning_param = 0.0001
    self.no_input_feats = ...

    # Following parameter and optimizer set as recommended in paper
    self.n_critic = 15
    optimizer = RMSprop(lr=self.learning_param)

    self.img_rows = ...
    self.img_cols = ...
    self.channels = 3
    self.img_shape = (self.img_rows, self.img_cols, self.channels)
    self.latent_dim = ...

    # Build the generator and critic
    self.generator = build_generator(self.latent_dim, self.channels)
    #self.generator = self.build_generator_old()
    self.critic = build_critic(self.img_shape)

    #-------------------------------
    # Construct Computational Graph
    #       for the Critic
    #-------------------------------

    # Freeze generator's layers while training critic
    self.generator.trainable = False

    # Image input (real sample)
    real_img = Input(shape=self.img_shape)

    # Noise input
    z_disc = Input(shape=(self.latent_dim,))
    # Generate image based of noise (fake sample)
    fake_img = self.generator(z_disc)

    # Discriminator determines validity of the real and fake images
    fake, aux1 = self.critic(fake_img)
    valid, aux2 = self.critic(real_img)

    # Construct weighted average between real and fake images
    interpolated_img = RandomWeightedAverage()([real_img, fake_img])
    # Determine validity of weighted sample
    validity_interpolated, aux3 = self.critic(interpolated_img)

    # Use Python partial to provide loss function with additional
    # 'averaged_samples' argument
    partial_gp_loss = partial(self.gradient_penalty_loss,
                      averaged_samples=interpolated_img)

    partial_gp_loss.__name__ = 'gradient_penalty' 
    # Keras requires function names

    self.critic_model = Model(inputs=[real_img, z_disc],
                        outputs=[valid, fake, validity_interpolated, aux1])

    self.critic_model.compile(loss=[self.wasserstein_loss,
            self.wasserstein_loss,
            partial_gp_loss,
            'categorical_crossentropy'],
        optimizer=optimizer,
        metrics=['accuracy'],
        loss_weights=[1, 1, 5, 1])
    #-------------------------------
    # Construct Computational Graph
    #         for Generator
    #-------------------------------

    # For the generator we freeze the critic's layers
    self.critic.trainable = False
    self.generator.trainable = True

    # Sampled noise for input to generator
    z_gen = Input(shape=(self.latent_dim,))
    # Generate images based of noise
    img = self.generator(z_gen)
    # Discriminator determines validity
    valid = self.critic(img)
    # Defines generator model
    self.generator_model = Model(z_gen, valid)
    self.generator_model.compile(loss=self.wasserstein_loss, optimizer=optimizer)

当我打印 critic_model.metric_names 时,我收到以下信息:

['loss', 'model_2_loss', 'model_2_loss', 'model_2_loss', 'model_2_loss', 'model_2_acc', 'model_2_acc_1', 'model_2_acc_2', 'model_2_acc_3']

谁能帮我理解这些名字代表什么?

您有两个指标,损失和准确性,keras 从最后定义模型输出的层生成指标名称。 你的模型的输出是 outputs=[valid, fake, validity_interpolated, aux1] 所以你有四个并且都是用评论模型定义的:

 fake, aux1 = self.critic(fake_img)
 valid, aux2 = self.critic(real_img)
 validity_interpolated, aux3 = self.critic(interpolated_img)

所以都命名为 name_of_the_model_name_of_the_loss -> Model_2_loss

这显示了如何将名称参数添加到图层以更改为指标指定的名称:

编辑评论:

keras 的源代码在这里: https://github.com/tensorflow/tensorflow/blob/v2.1.0/tensorflow/python/keras/engine/training.py#L81-L2865

如下面的metrics_names函数所示,名字默认硬编码为'loss',可能是因为他们总是至少输,然后自动加上name属性:

     @property
      def metrics_names(self):
        """Returns the model's display labels for all outputs."""

        # This property includes all output names including `loss` and per-output
        # losses for backward compatibility.
        metrics_names = ['loss']
        if self._is_compiled:
          # Add output loss metric names to the metric names list.
          if len(self._training_endpoints) > 1:
            metrics_names.extend([
                e.loss_name()
                for e in self._training_endpoints
                if not e.should_skip_target()
            ])

        # Add all metric names.
        metrics_names += [m.name for m in self.metrics]
        return metrics_names

方法 return 损失的 self.name 属性而不是可用于调用它们的变量名

您也可以使用这个简单的代码来查看 metrics_names 取决于模型输出的最后定义:

input_ =  keras.layers.Input(shape=(8,))
x =  keras.layers.Dense(16)(input_)
output1 = keras.layers.Dense(32)(x)
output2 = keras.layers.Dense(32, name="output2")(x)
model = keras.models.Model(inputs=input_, outputs=[output1, output2])
model.compile(loss=["mse", "mae"], optimizer="adam", metrics={"output2":"accuracy"})
print(model.metrics_names)

>>> ['loss', 'dense_3_loss', 'output2_loss', 'output2_acc']

答案就在这里:

self.critic_model = Model(inputs=[real_img, z_disc],
                        outputs=[valid, fake, validity_interpolated, aux1]) #<- 4 outputs

                                                              #4 model losses + 1 total loss:
self.critic_model.compile(loss=[self.wasserstein_loss,        #loss for output 0
                                self.wasserstein_loss,        #loss for output 1
                                partial_gp_loss,              #loss for output 2
                                'categorical_crossentropy']   #loss for output 3
                          optimizer=optimizer,
                          metrics=['accuracy'],           #replicated, one for each output
                          loss_weights=[1, 1, 5, 1])

您的模型显然有 4 个输出,并且您为每个输出定义了一个损失。每当你有多个损失时,Keras 会为你计算总损失,所以:

  • 'loss' 是总损失(该模型所有损失的总和)

另外4个'model_2_loss'依次是:

  • self.wasserstein_loss,第一个输出valid
  • self.wasserstein_loss,对于第二个输出fake
  • partial_gp_loss, validity_interpolated
  • 'categorical_crossentropy' 对于 aux1

对于指标,由于您只定义了一个指标,系统会为每个模型的输出复制相同的指标:

  • 'model_2_acc'valid
  • 的指标
  • 'model_2_acc_1'fake
  • 的指标
  • 'model_2_acc_2'validity_interpolated
  • 的指标
  • 'model_2_acc_3'aux1
  • 的指标

为了获得更好的损失名称,您应该将名称添加到模型的输出、损失等,只要有可能添加 name 参数。

有些操作接受名称,例如:How can I set the name of my loss operation in Tensorflow?

新版本中的损失,创建为对象,也接受名称:https://www.tensorflow.org/api_docs/python/tf/keras/losses/CategoricalCrossentropy

模型接受名称,例如:

self.critic_model = Model(inputs=[real_img, z_disc],
                          outputs=[valid, fake, validity_interpolated, aux1], 
                          name='critic_model')

层接受名称,因此您应该为每个模型的输出层命名,以便更好地跟踪事物。

我对新的急切模式执行概念并不完全熟悉,但您也可以尝试在调用模型时添加一个名称……不确定这是否可行。