【问题标题】:keras loss function for 360 degree prediction用于 360 度预测的 keras 损失函数
【发布时间】:2018-03-03 11:07:35
【问题描述】:

我正在尝试使用 keras/tensorflow 预测方位角。 y_true 的范围为 0-359,但我需要一个损失函数来处理已经环绕并超出该范围的预测。不幸的是,当我尝试任何类型的模块化除法tf.mod()% 时,我得到一个错误...

LookupError: No gradient defined for operation 'FloorMod' (op type: FloorMod)

所以我想我已经通过以下方式解决了这个问题......

def mean_squared_error_360(y_true, y_pred):
  delta = K.minimum(K.minimum(K.abs(y_pred - y_true),
                              K.abs(y_pred - (360+y_true))),
                              K.abs(y_true - (360+y_pred)))
  return K.mean(K.square(delta), axis=-1)

def rmse_360(y_true, y_pred):
  return K.sqrt(mean_squared_error_360(y_true, y_pred))


model.compile(loss=mean_squared_error_360,
              optimizer=rmsprop(lr=0.0001),
              metrics=[rmse_360])

这处理以下边缘情况...我没有遇到预测

y =   1  y_pred = 361  err = 0
y = 359  y_pred =   1  err = 2
y = 359  y_pred = 361  err = 2

问题

  • 这感觉很笨拙;有更智能的解决方案吗?
  • 直观地说,我认为使用 mean_squared_error 和 root_mean_squared_error 作为损失之间的结果没有区别...梯度会有所不同,但相同的最佳权重可以解决两者,对吧?有什么理由选择一个而不是另一个吗?我猜 mse 比 rmse 稍微简单一些,但这应该是微不足道的。我已经尝试了这两种方法,并且使用 rmse '感觉' 比 mse 更有序的下降......这些平方误差的大小是否会使其跳跃更多?

提前致谢。

编辑

无论出于何种原因......我最初的 mse 似乎适合训练集,但验证集似乎非常嘈杂,经过几个 epoch 后没有任何真正的改进。 rmse 似乎是一个更有序的下降......直到在改进了几十个 epoch 后损失变为 inf。我可能有比损失函数更大的问题。

编辑 2 - 在下面添加我的实现@Patwie 答案

啊……触发!!当然!!不幸的是,我使用的 tf v1.0 似乎没有 tf.atan2()。奇怪的是,我在 tf 存储库中找不到 atan2 实现,但我认为 asos-ben 在 issue 6095 中的建议可以解决问题。看这里:https://github.com/tensorflow/tensorflow/issues/6095

def atan2(x, y, epsilon=1.0e-12):
  x = tf.where(tf.equal(x, 0.0), x+epsilon, x)
  y = tf.where(tf.equal(y, 0.0), y+epsilon, y)    
  angle = tf.where(tf.greater(x,0.0), tf.atan(y/x), tf.zeros_like(x))
  angle = tf.where(tf.logical_and(tf.less(x,0.0),  tf.greater_equal(y,0.0)), tf.atan(y/x) + np.pi, angle)
  angle = tf.where(tf.logical_and(tf.less(x,0.0),  tf.less(y,0.0)), tf.atan(y/x) - np.pi, angle)
  angle = tf.where(tf.logical_and(tf.equal(x,0.0), tf.greater(y,0.0)), 0.5*np.pi * tf.ones_like(x), angle)
  angle = tf.where(tf.logical_and(tf.equal(x,0.0), tf.less(y,0.0)), -0.5*np.pi * tf.ones_like(x), angle)
  angle = tf.where(tf.logical_and(tf.equal(x,0.0), tf.equal(y,0.0)), tf.zeros_like(x), angle)
  return angle

# y in radians
def rmse_360_2(y_true, y_pred):
  return K.mean(K.abs(atan2(K.sin(y_true - y_pred), K.cos(y_true - y_pred))))

测试运行只进行了大约 7 个 epoch,但看起来很有希望。

【问题讨论】:

  • 是否有一个特定的角度不太可能,甚至无效?如果是这样,您可以将此角度居中为零 ....
  • 我认为使用单位圆中的点并使用 mse 会产生更好的结果。使用点 (cos(a), sin(a)),而不是给模型提供角度。

标签: tensorflow keras conv-neural-network


【解决方案1】:

将我的评论转化为答案。给定两个角度 a (gt), b (预测) 作为 弧度 你得到角度差

tf.atan2(tf.sin(a - b), tf.cos(a - b))

根据定义,tf.atan2 在闭区间[-pi, +pi](即[-180 degrees, +180 degrees])中自动给出差异。

因此,您可以使用

tf.reduce_mean(tf.abs(tf.atan2(tf.sin(a - b), tf.cos(a - b))))

我认为 Keras 理解这段 TensorFlow 代码。

【讨论】:

  • 这个解决方案效果很好,但为了清楚起见,atan2 返回区间 [-pi, pi] 弧度的最小差异。
猜你喜欢
  • 1970-01-01
  • 2019-08-30
  • 2019-07-20
  • 2020-12-02
  • 2019-04-14
  • 2021-02-24
  • 2018-10-10
  • 2018-10-21
  • 1970-01-01
相关资源
最近更新 更多