我正在玩Tensorflow创建一个定制的损失功能,这个关于一般机器学习的问题出现在我脑海里。
我的理解是优化算法需要一个可导出的代价函数来找到/接近最小值,但是我们可以使用不可导出的函数,例如绝对函数(当x = 0时没有导数)。一个更极端的例子,我定义了我的成本函数:
def customLossFun(x,y):
return tf.sign(x)
我在运行代码时遇到了一个错误,但它实际上有效(它没有学到任何东西,但它并没有崩溃)。
我错过了什么吗?
答案 0 :(得分:1)
您错过了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作者决定不检查输入是否为零并在特定情况下抛出异常
答案 1 :(得分:1)
为了防止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)计算任何位置的渐变。
当然,如果你选择了一个有意义的成本函数,这些渐变更有用。
答案 2 :(得分:0)
理想情况下,成本函数在任何地方都需要平滑才能应用基于梯度的优化方法(SGD,Momentum,Adam等)。但如果不是,那么没有任何事情会崩溃,你可能会遇到融合到当地最低限度的问题。
当函数在某个点x
处不可微分时,如果神经网络收敛到此x
,则可能会出现大的振荡。例如,如果损失函数为tf.abs(x)
,则网络权重可能大部分为正,因此推断x > 0
始终为tf.abs
,因此网络不会注意到{{} 1}}。但是,x
更有可能在0
周围反弹,因此渐变是任意正面和负面的。如果学习率没有衰减,则优化不会收敛到局部最小值,但会围绕它进行限制。
在您的特定情况下,渐变始终为零,因此根本不会发生任何变化。
答案 3 :(得分:0)
如果没有学到任何东西,你获得了什么?你的损失函数几乎无处不在,但它几乎是平坦的,所以最小化器无法找出最小的方向。
如果你从一个正值开始,即使左侧的最小值更好(具有更低的值),它也很可能在正面被卡在随机值上。
Tensorflow可用于进行一般的计算,它提供了一种机制,可以自动查找给定表达式的派生,并且可以跨不同的计算平台(CPU,GPU)执行此操作,并在需要时分布在多个GPU和服务器上。
但是你在Tensorflow中实现的并不一定是最小化的目标函数。你可以使用它,例如抛出随机数并执行给定函数的蒙特卡洛积分。