自定义损失在Keras中分散损失

时间:2019-09-27 11:52:45

标签: python keras deep-learning

我有一个用Keras实现的完全连接的前馈网络。最初,我使用二进制交叉熵作为损耗和度量,然后使用Adam优化器,如下所示:

adam = keras.optimizers.Adam(lr=0.01, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
model.compile(optimizer=adam, loss='binary_crossentropy', metrics=['binary_crossentropy']) 

此模型训练良好,并给出了良好的结果。为了获得更好的结果,我想使用以下其他损失函数和指标,

import keras.backend as K

def soft_bit_error_loss(yTrue, yPred):
    loss = K.pow(1 - yPred, yTrue) * K.pow(yPred, 1-yTrue)
    return K.mean(loss)

def ber(yTrue, yPred):
    x_hat_train = K.cast(K.greater(yPred, 0.5), 'uint8')
    train_errors = K.cast(K.not_equal(K.cast(yTrue, 'uint8'), x_hat_train), 'float32')
    train_ber = K.mean(train_errors)
    return train_ber

我用它来编译我的模型,如下所示

model.compile(optimizer=adam, loss=soft_bit_error_loss, metrics=[ber])

但是,当我这样做时,每次经过以下训练后,损失和度量就会发生变化。

custom loss

ber

这可能是什么原因?

1 个答案:

答案 0 :(得分:1)

您的损失函数非常不稳定,请看一下它:

enter image description here

为简单起见,在这里我将y_pred(变量)替换为x,将y_true(常数)替换为c

随着您的预测接近零,至少一项操作将趋于1/0,这是无限的。尽管根据极限理论,您可以知道结果是可以的,但Keras并不知道“整数”函数是一个整数,但它会基于使用的基本运算来计算导数。

因此,一种简单的解决方案是@today指出的解决方案:

loss = K.switch(yTrue == 1, 1 - yPred, yPred)

它是完全相同的函数(仅当c不为零或1时才不同)。

对于c=0c=1,甚至更简单,它只是普通的loss='mae'