我正试图在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)
在训练期间,我交错 discriminator
的 discriminator
和 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 回答
Keras型号支持多种输出 . 因此,如果不应训练鉴别器,只需将您的discirminator包含在您的keras模型和freeze判别层中 .
接下来的问题是如何组合自动编码器丢失和鉴别器丢失 . 幸运的是keras model.compile支持减重 . 如果autoencoder是你的第一个输出,鉴别器是你的第二个你可以做
loss_weights=[1, -1]
之类的事情 . 因此,对于自动编码器,更好的鉴别器更糟糕 .编辑:以下是一个如何实施对手网络的示例:
正如你所看到的那样, Build 一个带有keras的对手模型背后没有太大的魔力 .
除非你决定深入研究keras源代码,否则我认为你不能轻易做到这一点 . 在编写自己的对抗模块之前,您应该仔细检查现有的工作 . 据我所知,keras-adversarial仍被许多人使用 . 当然,它只支持旧的keras版本,例如2.0.8 .
其他几件事:
冻结模型权重时要小心 . 如果您首先编译模型然后冻结一些权重,则这些权重仍然可以训练,因为在编译期间生成训练函数时 . 所以你应该首先冻结权重然后编译 .
keras-adversarial
以更优雅的方式完成这项工作 . 它不是制作两个模型,共享权重,而是以不同方式冻结一些权重,而是创建两个列车功能,每个玩家一个 .