首页 文章

在Keras实施对抗性损失

提问于
浏览
1

我正试图在keras中实施对抗性损失 . 该模型由两个网络组成,一个自动编码器(目标模型)和一个鉴别器 . 两种型号共用编码器 .

我通过设置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)

在训练期间,我交错 discriminatordiscriminatorautoencoder 来更新 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

    Keras型号支持多种输出 . 因此,如果不应训练鉴别器,只需将您的discirminator包含在您的keras模型和freeze判别层中 .

    接下来的问题是如何组合自动编码器丢失和鉴别器丢失 . 幸运的是keras model.compile支持减重 . 如果autoencoder是你的第一个输出,鉴别器是你的第二个你可以做 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)
    

    正如你所看到的那样, Build 一个带有keras的对手模型背后没有太大的魔力 .

  • 0

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

    其他几件事:

    • 冻结模型权重时要小心 . 如果您首先编译模型然后冻结一些权重,则这些权重仍然可以训练,因为在编译期间生成训练函数时 . 所以你应该首先冻结权重然后编译 .

    • keras-adversarial 以更优雅的方式完成这项工作 . 它不是制作两个模型,共享权重,而是以不同方式冻结一些权重,而是创建两个列车功能,每个玩家一个 .

相关问题