问题描述
我正在尝试使用keras/tensorflow预测方位角. y_true的范围是0-359,但我需要一个损失函数来处理围绕该范围且超出该范围的预测.不幸的是,当我尝试任何类型的模块化除法tf.mod()
或%
时,我得到一个错误...
I'm trying to predict azimuths using keras/tensorflow. y_true ranges from 0-359, but I need a loss function that handles predictions that have wrapped around and are outside that range. Unfortunately, when I try any kind of modular division tf.mod()
or %
, i get an error...
LookupError: No gradient defined for operation 'FloorMod' (op type: FloorMod)
所以我想我已经通过以下方法解决了这个问题……
so I think I've worked around this with the following...
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])
这可以处理以下几种极端情况...我还没有遇到预测< 0,所以我没有解决.
this handles the following edge cases... I haven't come across predictions < 0, so I'm not addressing.
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更像一个有序的下降...那些平方误差的大小是否使它跳得更多?
谢谢.
编辑
无论出于什么原因……我最初的女士似乎都适合训练集,但是验证集似乎在每个时期都非常嘈杂,经过几个时期后并没有任何实质性的改进. rmse似乎是有序下降的...直到改善了几十个纪元之后,损失才降到了inf.我可能会遇到比损失函数更大的问题.
for whatever reason... my original mse seemed to be fitting the training set, but the validation set seemed pretty noisy epoch to epoch, without any real improvement after a few epochs. rmse seemed like a more orderly descent... until the loss went to inf after improving for a couple dozen epochs. I might have bigger issues than the loss function.
编辑2-在下面添加我的实现@Patwie答案
啊...当然!!不幸的是,我使用的是tf v1.0,它似乎没有tf.atan2().奇怪的是,我在tf存储库中找不到atan2实现,但是我认为asos-ben在问题6095中的建议可以解决问题.参见此处: https://github.com/tensorflow/tensorflow/issues/6095
ah... trig!! of course!! unfortunately, I'm using tf v1.0 which doesn't seem to have tf.atan2(). strangely, I couldn't find atan2 implementation in tf repository, but I think asos-ben's suggestion in issue 6095 does the trick. see here: 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个纪元,但这似乎很有希望.
Only about 7 epochs in on a test run, but it seems promising.
推荐答案
将我的评论转换为答案.给定两个角度a(gt),b(预测)为弧度,您将获得
Converting my comment into an answer. Given two angles a (gt), b (prediction) as radians you get the angle difference by
tf.atan2(tf.sin(a - b), tf.cos(a - b))
根据定义tf.atan2
在闭合间隔[-pi, +pi]
(即[-180 degrees, +180 degrees]
)中自动给出差值.
By definition tf.atan2
gives the difference automatically in the closed interval [-pi, +pi]
(that is, [-180 degrees, +180 degrees]
).
因此,您可以使用
tf.reduce_mean(tf.abs(tf.atan2(tf.sin(a - b), tf.cos(a - b))))
我认为Keras可以理解TensorFlow代码.
I think Keras understand this TensorFlow code.
这篇关于用于360度预测的keras损失函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!