如何在keras损失函数中使用tf.nn.top_k?

时间:2017-02-28 15:41:21

标签: python tensorflow neural-network keras

我在制作此自定义丢失函数时遇到了一些问题(它检查y_pred数据是否与y_true)工作提供的实际排序索引一致地排序:

def custom_objective(y_true, y_pred):
    y_true = tf.cast(y_true, tf.float32)
    ordered_output = tf.cast(tf.nn.top_k(-y_pred, k=5)[1], tf.float32)
    return tf.sqrt(tf.reduce_mean(tf.square(ordered_output - y_true), axis=-1))

我可以使用示例数据正确运行它:

with tf.Session() as sess:
    print(custom_objective(tf.constant([0, 1, 2, 3, 4, 5]), 
                           tf.constant([0.0, 0.9, 0.2, 0.3, 0.5, 0.8])).eval())  # 1.82574

但是如果我在model.compile中使用它,它会以某种方式起作用,因为它会引发:

/Users/luca/.virtualenvs/python3/lib/python3.6/site-packages/tensorflow/python/framework/tensor_util.py in make_tensor_proto(values, dtype, shape, verify_shape)
    358   else:
    359     if values is None:
--> 360       raise ValueError("None values not supported.")
    361     # if dtype is provided, forces numpy array to be the type
    362     # provided if possible.

ValueError: None values not supported.

请注意,没有"无"我的训练测试集中的值如果我将ordered_output = tf.cast(tf.nn.top_k(-y_pred, k=5)[1], tf.float32)更改为ordered_output = -y_pred,则模型编译正常并开始正确训练(但它显然不是我想要的损失函数)。

我有一种微妙的感觉,即在损失函数中使用top_k可能有问题,因为我不知道它是如何可以区分的,但我没有更好的想法评估预测排序的差异。提示/创意/纸/引用? :)

1 个答案:

答案 0 :(得分:4)

这可能会被拒绝,因为我不会真正修复你的代码,但这里什么都没有:

我确实不相信你可以使用top_k作为目标函数。就像你不能将精确度用作目标函数一样。

原因是数学。即使keras,tensorflow,theano和co。是人工智能的绝佳工具,允许每个人都使用神经网络,后者仍然是非常复杂的数学工具。这些数学很好地隐藏在引擎盖下,但是当你试图比预制工具更进一步时,你应该意识到它们。

当您训练网络时会发生的事情是您计算网络在一个示例中的错误,并且您反向传播该错误以从中学习。反向传播背后的算法是优化器,更准确地说,它们是基于梯度的优化器。计算梯度需要区分我们正在优化的功能,损失/目标函数。这意味着目标必须是可区分的。精度不是可微分函数,它将0和1之间的实数作为输入并输出阶梯状函数:如果x <0.5则为0,如果x> 0.5则为1。该函数不可微分,因为我们无法在0.5中得到它的梯度。 top_k函数是某种精度函数。所以我确实不能在目标中使用它,因为在引擎盖下,智能张量流必须计算函数的渐变。

我希望这会有所帮助:)