自定义损失函数,用于Keras中的顺序输出

时间:2018-08-30 09:50:16

标签: tensorflow keras

我需要为我的keras模型编写自定义损失。由于我需要使用Keras函数编写函数进行自动反向传播,因此我不确定如何实现此功能,因为这可能需要一些循环操作-

Target[1*300] - [...0 0 0 1 0 0 0 0 0 1 0 0 0...]

Output[1*300] - [...0 0 1 0 0 0 0 0 0 0 1 0 0...]

我需要的是,在计算损失时,我不需要完全匹配。 即使我的输出与+/- 3 个位置存在差异。我希望它进行标记以将其视为正确的预测。

例如,这两个都应视为正确的预测-

Output[1*300] - [...0 0 1 0 0 0 0 0 0 0 1 0 0...]

Output[1*300] - [...0 1 0 0 0 0 0 0 0 0 0 1 0...]

我到目前为止编写的代码-

import tensorflow as tf
tar = tf.placeholder(tf.float32, shape=(1, 10))
tar_unpacked = tf.unstack(tar) 

pred = tf.placeholder(tf.float32, shape=(1, 10))
pred_unpacked = tf.unstack(pred) 


for t in tar_unpacked:
    result_tensor = tf.equal(t,1)

tar_ind = tf.where(result_tensor)

with tf.Session() as sess:
    print(sess.run([tar_ind], feed_dict={tar:np.asarray([[0, 0,1, 0,0,0,1,0,0,0]]),pred:np.asarray([[0, 0,1, 0,0,0,1,0,0,0]])}))

现在,我接下来要做的是通过添加来自每个对象的有效索引

[-3,-2,-1,0,1,2,3]

tar_ind中的元素,然后将索引与pred_unstacked进行比较。

我天真的损失将是1 - (NUM_MATCHED/TOTAL)

但是问题是tar_ind是一个大小可变的张量,我无法在下一个操作中对其进行循环。

Update-1。

如@ user36624所建议,我尝试了另一种方法,即让tf.py_func给出更新后的y_pred,然后将更新后的值用于binary cross-entropy.

由于我已经使用py_func,实现了该功能,因此给我的错误是ValueError: An operation hasfor the gradient. Please make sure that all of your ops have a gradient defined (i.e., are differentiable). Common ops without gradient: K.argmax, K.round, K.eval.

他还建议我需要手动停止不知道该怎么做的渐变?

def specificity_loss_wrapper():
    def specificity_loss(y_true, y_pred):

        y_pred = tf.py_func(best_match,[y_true,y_pred],(tf.float32))

        y_pred = tf.stop_gradient(y_pred)
        y_pred.set_shape(y_true.get_shape())


        return K.binary_crossentropy(y_true, y_pred)

    return specificity_loss    

spec_loss = specificity_loss_wrapper()

...
model.compile(loss=spec_loss, optimizer='adam', metrics=['accuracy'])
...

据我了解,binary_crossentropy应该是可区分的。

谢谢

1 个答案:

答案 0 :(得分:0)

您的建议是计算

ind[-1]

我建议以其他方式解决它。

1. offsets = compute_index_offsets( y_true, y_pred )
2. loss = 1 - num(offsets <= 3)/total

修改1. y_true_mod = DP_best_match( y_true, y_pred ) 2. loss = 1 - num(y_true_mod==y_pred)/total 的优势在于它等效于提供新的目标值,因此它不是模型图优化或损失计算的一部分。

y_true应该做的是根据DP_best_match( y_true, y_pred )修改y_true

例如给予

y_pred

然后y_true[1*300] - [...0 0 0 1 0 0 0 0 0 1 0 0 0...] y_pred[1*300] - [...0 0 1 0 0 0 0 0 0 0 1 0 0...] 应该指定新的目标

DP_best_match( y_true, y_pred )

请注意,y_true_mod[1*300] - [...0 0 1 0 0 0 0 0 0 0 1 0 0...] 旨在修改DP_best_match( y_true, y_pred )以使其最佳匹配y_true,因此它是确定性的,无可优化。因此,不需要反向传播。这意味着,如果您在y_pred中实现DP_best_match( y_true, y_pred ),则需要手动停止渐变。否则,您可以在numpy中实现它,并通过tf包装函数,这可能会更容易实现。

最后一点,您应该确保建议的损失函数有意义。对我来说,在找到最佳的tf.py_func之后使用binary_crossentropymse更有意义。