我需要为我的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 has
无for 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
应该是可区分的。
谢谢
答案 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_crossentropy
或mse
更有意义。