我正在尝试使用 Deepmind 在 tensorflow 中自己实现 DQN 论文,并且在裁剪损失函数时遇到了困难。
以下是描述损失剪裁的自然论文的摘录:
(全文链接:http://www.nature.com/nature/journal/v518/n7540/full/nature14236.html)
到目前为止我尝试过的是使用
clipped_loss_vec = tf.clip_by_value(loss, -1, 1)
削减我在 -1 和 +1 之间计算的损失。在这种情况下,代理没有学习正确的策略。我打印出网络的梯度,并意识到如果损失低于 -1,梯度会突然变成 0!
我对这种情况的推理是,裁剪损失是 (-inf,-1) U (1,inf) 中的一个常数函数,这意味着它在这些区域的梯度为零。这反过来又确保了整个网络的梯度为零(想象一下,无论我向网络提供什么输入图像,本地邻域的损失都保持在 -1,因为它已被剪裁)。
所以,我的问题是两部分:
谢谢!
最佳答案
我怀疑他们的意思是你应该将梯度剪裁为 [-1,1],而不是剪裁损失函数。因此,您像往常一样计算梯度,然后将梯度的每个分量剪裁在 [-1,1] 范围内(因此,如果它大于 +1,则将其替换为 +1;如果它小于-1,您将其替换为 -1);然后在梯度下降更新步骤中使用结果而不是使用未修改的梯度。
等价于: 定义一个函数 f
如下:
f(x) = x^2 if x in [-0.5,0.5]
f(x) = |x| - 0.25 if x < -0.5 or x > 0.5
他们建议使用
s^2
作为损失函数,而不是使用 s
形式的东西作为损失函数(其中 f(s)
是一些复杂的表达式)。这是平方损失和绝对值损失之间的某种混合:当 s^2
很小时,它将表现得像 s
,但是当 s
变大时,它将表现得像绝对值 (0x232413)。请注意,
|s|
的导数具有很好的属性,即它的导数将始终在 [-1,1] 范围内:f'(x) = 2x if x in [-0.5,0.5]
f'(x) = +1 if x > +1
f'(x) = -1 if x < -1
因此,当您采用这个基于
f
的损失函数的梯度时,结果将与计算平方损失的梯度然后裁剪它的结果相同。因此,他们正在做的是有效地用 Huber loss 替换平方损失。函数
f
只是 delta = 0.5 时 Huber 损失的两倍。现在的重点是以下两种选择是等价的:
前者很容易实现。后者具有很好的特性(提高稳定性;它比绝对值损失更好,因为它避免了在最小值附近振荡)。因为两者是等价的,这意味着我们得到了一个易于实现的方案,它具有平方损失的简单性和 Huber 损失的稳定性和鲁棒性。
关于neural-network - tensorflow 中的损失裁剪(在 DeepMind 的 DQN 上),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36462962/