我正在尝试使用 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,因为它已被剪裁)。

所以,我的问题是两部分:
  • Deepmind 在摘录中究竟是什么意思?他们的意思是低于 -1 的损失被限制为 -1,高于 +1 的损失被限制为 +1。如果是这样,他们是如何处理梯度的(即关于绝对值函数的所有部分是什么?)
  • 我应该如何在 tensorflow 中实现损失裁剪,以便梯度在裁剪范围外不会变为零(但可能保持在 +1 和 -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 损失的两倍。

    现在的重点是以下两种选择是等价的:
  • 使用平方损失函数。计算此损失函数的梯度,但在执行梯度下降的更新步骤之前将梯度变为 [-1,1]。
  • 使用 Huber 损失函数而不是平方损失函数。在梯度下降中直接(不变)计算这个损失函数的梯度。

  • 前者很容易实现。后者具有很好的特性(提高稳定性;它比绝对值损失更好,因为它避免了在最小值附近振荡)。因为两者是等价的,这意味着我们得到了一个易于实现的方案,它具有平方损失的简单性和 Huber 损失的稳定性和鲁棒性。

    关于neural-network - tensorflow 中的损失裁剪(在 DeepMind 的 DQN 上),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36462962/

    10-14 16:05