【问题标题】:Keras throws a DisconnectedInputError due to custom loss function由于自定义损失函数,Keras 抛出 DisconnectedInputError
【发布时间】:2017-08-31 12:33:59
【问题描述】:

我正在尝试使用 theano 后端在 Keras 中为 improved WGAN training 实现梯度范数的正则化项。基本上我想根据它与 1 的距离来惩罚梯度的 l2 范数。

我正在实现这样的自定义损失:

def get_gradient_norm(model, y_pred):
    weights = model.trainable_weights
    gradients = model.optimizer.get_gradients(K.mean(y_pred), weights)
    acc = None
    for g in gradients:
        s = K.sum(K.square(g))
        if acc == None:
            acc = s
        else:
            acc = s + acc
    return K.sqrt(acc)

def make_w_reg_loss(model):
    lvar = K.variable(lamb, name="Lambda")

    def foo(y_true, y_pred):
        gnorm = get_gradient_norm(model, y_pred)
        return lvar * K.square(gnorm - 1)

return foo

[...]

critic.compile(loss=make_w_reg_loss(critic), optimizer=RMSprop(learn_rate))

一旦训练过程尝试获取我的自定义损失函数的梯度,它就会抛出 DisconnectedInputError。

为什么?

用一些标准的损失代替损失是可行的。错误与我定义的损失函数有关。

请参阅此要点以了解我的尝试a minimal not-working example

编辑:

所以我想我现在知道如何让它工作了。 首先,我只是在从 foo(y_true, y_pred) 返回之前直接将这个术语随机添加到我的损失中:

K.mean(y_pred) - K.mean(y_pred)

显然是一个恒定的零,如果我只使用这个术语作为我的损失,我确实得到一个零。 但是,如果我将这个“恒定零”添加到我的正则化损失中,它会突然正常工作。我得到了一个非零的损失,因此来自正则化,并且对许多 train_on_batch 的优化也确实减少了损失。

那么,theano 在抛出异常时有点过分热心,这是一个奇怪的问题吗?我的问题仍然存在:为什么它会抛出原始代码。由于添加一个常数零项可以修复它,所以对我来说它看起来像是一个错误?

【问题讨论】:

    标签: neural-network theano keras


    【解决方案1】:

    我真的很想在 keras 中实现这个改进的 wgan,看到你如何解决你的“问题”我很惊讶。您是否验证了您的 wgan-gp 损失按预期工作的 trought 实验? 它应该很容易检查,它是一种非常稳定的训练,使您能够使用非常深的鉴别器;) 我想做与您相同的工作,但使用 tensorflow 后端,我将尝试查看您的代码和此处的代码:keras improved wgan

    我很高兴听到你的更新,一旦我在 keras/tensorflow 中有 wgan-gp 的工作代码,我会在这里再次写信! 附言上面的链接是在 tensorflow 代码中实现所有过程,强制使用 tf 训练函数。我真的很喜欢你的方法,我们可以简单地定义一个 keras 损失,使用我们所有常用的 keras 高级 API 进行训练;)

    编辑:从您的代码看来,您似乎完全可以使用 K 后端,因此您的代码也应该可以轻松地使用 tensorflow 后端运行。您是否尝试更改后端以检查问题/错误是否与 Theano 真正相关?

    第二次编辑:您正在计算梯度 w.r.t 权重,但在 wgan-gp 论文中,梯度惩罚是从梯度 w.r.t 开始计算的,即生成样本和真实样本之间的平均样本。这会带来截然不同的结果。 在以下链接中,您可以找到一个非常好的改进的 wgan loss 实现,也可以在 theano 上工作: https://github.com/farizrahman4u/keras-contrib/

    【讨论】:

    • 我发布的代码是一个残酷的缩减版本,当然没有正确实现任何东西,它只是为了显示问题。我的真实代码通过在真实样本和虚假样本之间传递插值数据点来实现采样。到目前为止,我只测试了玩具示例,但它们对我来说看起来很有希望。然而,因为更多“真实”的工作而偏离了方向,所以我无法测试更复杂的数据集。
    • 我没有用 tensorflow 进行测试,这里没有安装它,因为最终的损失函数包含更多的术语,无论哪种方式,异常问题都不是真正的问题。这让我很困惑。我猜你发布的 wgan 实现可能是由在 keras 方面有更多经验并且有更好记录的人编写的。当我回到那个时候我可能会使用那个,因为它似乎是在 GPU 上实现插值部分,我是在 CPU 中做的。酷!
    • 我最终在调试上浪费了 12 个小时,试图修改我链接的代码,以便作为单独的梯度惩罚损失(而不是集成到鉴别器中)工作,我很快就卡在墙上了“tensorflow正在获取 None 作为损失”类型的错误。我突然想起了你的修复,好吧,在我的情况下也修复了。如果没有您的修复,如果我通过 model.summary() 可视化模型,则没有输入层。通过您的简单修复,输入层突然显示为输入(并且梯度惩罚损失可以正常工作而不会给出 None 错误)
    • 那么,theano 和 Keras 似乎正在发生的事情(根据我有限的后端知识),图形编译器没有正确链接所有的 dumbo 许可证变量,以 a 结尾断开的图。将 y_pred 放在损失函数“return”行上可以难以置信地解决问题,因为图形是正确构建的。这可能是我一生中最奇怪的错误/问题(并修复!)!
    猜你喜欢
    • 2020-12-19
    • 2017-12-18
    • 2020-03-27
    • 1970-01-01
    • 2018-10-28
    • 2017-12-29
    • 1970-01-01
    • 2020-02-27
    • 2018-12-26
    相关资源
    最近更新 更多