在Keras中实施对抗性损失

时间:2018-08-28 11:06:13

标签: python keras deep-learning generative-adversarial-network

我正在尝试在喀拉拉邦实行对抗性损失。 该模型由两个网络组成,一个是自动编码器(目标模型),另一个是鉴别器。两种型号共享编码器。

我通过设置keras变量来创建自动编码器的对抗性损失

def get_adv_loss(d_loss):
    def loss(y_true, y_pred):
        return some_loss(y_true, y_pred) - d_loss
    return loss

discriminator_loss = K.variable()
L = get_adv_loss(discriminator_loss)
autoencoder.compile(..., loss=L)

在训练期间,我交错插入train_on_batchdiscriminator中的autoencoder来更新discriminator_loss

d_loss = disciminator.train_on_batch(x, y_domain)
discriminator_loss.assign(d_loss)
a_loss, ... = self.segmenter.train_on_batch(x, y_target)

但是,我发现在编译模型时这些变量的值被冻结了。我尝试在训练过程中重新编译模型,但这会引发错误

  

节点'IsVariableInitialized_13644':未知输入节点   'training_12 / Adam / Variable'

我猜这意味着我在训练期间无法重新编译?关于如何在自动编码器中注入鉴别器损耗的任何建议?

2 个答案:

答案 0 :(得分:0)

Keras模型支持多个输出。因此,如果不应该对鉴别器进行训练,只需将其添加到keras模型和freeze鉴别器层中即可。

下一个问题将是如何结合自动编码器损耗和鉴别器损耗。幸运的是,keras model.compile支持减肥。如果自动编码器是您的第一个输出,而鉴别器是您的第二个输出,则可以执行类似loss_weights=[1, -1]的操作。因此,更好的鉴别器对自动编码器来说更糟。

编辑:这是一个示例,说明如何实施对手网络:

# Build your architecture
auto_encoder_input = Input((5,))
auto_encoder_net = Dense(10)(auto_encoder_input)
auto_encoder_output = Dense(5)(auto_encoder_net)

discriminator_net = Dense(20)(auto_encoder_output)
discriminator_output = Dense(5)(discriminator_net)

# Define outputs of your model
train_autoencoder_model = Model(auto_encoder_input, [auto_encoder_output, discriminator_output])
train_discriminator_model = Model(auto_encoder_input, discriminator_output)

# Compile the models (compile the first model and then change the trainable attribute for the second)
for layer_index, layer in enumerate(train_autoencoder_model.layers):
    layer.trainable = layer_index < 3

train_autoencoder_model.compile('Adam', loss=['mse', 'mse'], loss_weights=[1, -1])        

for layer_index, layer in enumerate(train_discriminator_model.layers):
    layer.trainable = layer_index >= 3

train_discriminator_model.compile('Adam', loss='mse')

# A simple example how a training can look like
for i in range(10):
    auto_input = np.random.sample((10,5))
    discrimi_output = np.random.sample((10,5))
    train_discriminator_model.fit(auto_input, discrimi_output, steps_per_epoch=5, epochs=1)
    train_autoencoder_model.fit(auto_input, [auto_input, discrimi_output], steps_per_epoch=1, epochs=1)  

如您所见,使用keras构建对抗模型并没有太多魔力。

答案 1 :(得分:0)

除非您决定深入研究keras源代码,否则我认为您不容易做到这一点。在编写自己的对抗模块之前,您应该仔细检查现有的作品。据我所知,keras-adversarial仍然被许多人使用。当然,它仅支持旧的keras版本,例如2.0.8。

其他几件事:

  1. 冻结模型权重时要小心。如果先编译模型然后冻结一些权重,则这些权重仍然是可训练的,因为在编译期间会生成训练函数。因此,您应该先冻结权重然后再编译。
  2. keras-adversarial以更优雅的方式完成了这项工作。它没有创建两个模型,而是共享权重而是以不同的方式冻结一些权重,而是创建了两个训练函数,每个球员一个。