我正在使用Tensorflow创建一个自定义的损失函数,这个关于通用机器学习的问题突然出现在我的脑海中。
我的理解是,优化算法需要一个可导的代价函数来寻找/接近最小值,但是我们可以使用不可导的函数,如绝对函数(当x=0时没有导数)。一个更极端的例子是,我这样定义我的成本函数:
def customLossFun(x,y):
return tf.sign(x)我预计在运行代码时会出现错误,但它实际上起作用了(它没有学到任何东西,但没有崩溃)。
我是不是遗漏了什么?
发布于 2018-01-07 17:52:36
您忽略了这样一个事实,即sign函数的梯度是在Tensorflow源代码中手动定义的。
如您所见,here
def _SignGrad(op, _):
"""Returns 0."""
x = op.inputs[0]
return array_ops.zeros(array_ops.shape(x), dtype=x.dtype)tf.sign的梯度被定义为始终为零。当然,这是导数存在的梯度,因此是无处不在的,而不是零。
tensorflow的作者决定不检查输入是否为零,并在该特定情况下抛出异常
发布于 2018-01-07 17:53:16
为了防止TensorFlow抛出错误,唯一的实际要求是对于输入变量的任何值,您的成本函数的计算结果都是一个数字。从纯粹的“它会运行”的角度来看,它并不知道/关心它试图最小化的函数的形式。
为了让你的成本函数在TensorFlow使用它来训练模型时为你提供有意义的结果,它还需要1)随着你的模型做得更好而变得更小,2)从下面开始有界(即它不能达到负无穷大)。它通常不需要平滑(例如,abs(x)在符号翻转的地方有一个扭结)。Tensorflow总是能够使用自动微分(https://en.wikipedia.org/wiki/Automatic_differentiation,https://www.tensorflow.org/versions/r0.12/api_docs/python/train/gradient_computation)在任何位置计算梯度。
当然,如果你选择了一个有意义的成本函数,而不是太平坦,那么这些梯度更有用。
发布于 2018-01-07 17:55:35
理想情况下,要应用基于梯度的优化方法(SGD,Momentum,Adam等),成本函数需要在任何地方都是平滑的。但如果不是这样,没有什么会崩溃,你可能只会遇到收敛到局部最小值的问题。
当函数在某一点不可微时,如果神经网络收敛到这个x,就有可能得到很大的振荡。例如,如果损失函数为tf.abs(x),则网络权重可能大部分为正,因此推断x > 0在任何时候都是正的,因此网络不会注意到tf.abs。然而,更有可能的是,x会在0周围反弹,因此梯度是任意正负的。如果学习率没有衰减,优化就不会收敛到局部最小值,而是会围绕它。
在你的特殊情况下,梯度总是为零,所以什么都不会改变。
https://stackoverflow.com/questions/48134194
复制相似问题