准确地说,当绝对误差小于0.5时,我要寻找的损失函数是平方误差,当绝对误差大于0.5时,它是绝对误差本身。这样,误差函数的梯度不会超过 1,因为一旦平方误差函数的梯度达到 1,绝对误差函数就会启动,并且梯度保持恒定为 1。我在下面列出了我当前的实现。由于某种原因,它给我带来的性能比平方误差更差。
fn_choice_maker1 = (tf.to_int32(tf.sign(y - y_ + 0.5)) + 1)/2
fn_choice_maker2 = (tf.to_int32(tf.sign(y_ - y + 0.5)) + 1)/2
choice_maker_sqr = tf.to_float(tf.mul(fn_choice_maker1, fn_choice_maker2))
sqr_contrib = tf.mul(choice_maker_sqr, tf.square(y - y_))
abs_contrib = tf.abs(y - y_)-0.25 - tf.mul(choice_maker_sqr, tf.abs(y - y_)-0.25)
loss = tf.reduce_mean(sqr_contrib + abs_contrib)
train_step = tf.train.AdamOptimizer(1e-4).minimize(loss)
choice_maker_sqr
是一个列张量,只要误差在 0.5 到 -0.5 之间,它就为 1。这些名称非常不言自明。
这是我在 python 张量流中实现的 Huber 损失函数:
def huber_loss(y_true, y_pred, max_grad=1.):
"""Calculates the huber loss.
Parameters
----------
y_true: np.array, tf.Tensor
Target value.
y_pred: np.array, tf.Tensor
Predicted value.
max_grad: float, optional
Positive floating point value. Represents the maximum possible
gradient magnitude.
Returns
-------
tf.Tensor
The huber loss.
"""
err = tf.abs(y_true - y_pred, name='abs')
mg = tf.constant(max_grad, name='max_grad')
lin = mg*(err-.5*mg)
quad=.5*err*err
return tf.where(err < mg, quad, lin)
您可以使用
tf.select
在一次调用中实现它:
err = y - y_
huber_loss = tf.select(tf.abs(err) < 1.0,
0.5 * tf.square(err),
tf.abs(err) - 0.5) # if, then, else
err = tf.subtract(x,y)
huber_loss = tf.where(tf.less(x,y),
tf.sqrt(tf.square(err)),
tf.abs(err))
with tf.Session() as sess:
print(sess.run(tf.reduce_mean(huber_loss)))
不确定这是否仍然相关,但我想向那些将来寻求这一点的人指出。张量流研究损失脚本具有用于对象检测的 Huber 损失的实现(如 FasterRCNN 论文中的实现)
这是方法的链接
有这样的代码:
def huber_loss_with_threshold (t = 𝛿):
def huber_loss (y_true, y_pred):
error = y_true - y_pred
within_threshold = tf.abs(error) <= t
small_error = tf.square(error)
large_error = t * (tf.abs(error) - (0.5*t))
if within_threshold:
return small_error
else:
return large_error
return huber_loss
或这里 将张量流导入为 tf
def huber_loss(y_pred, y_true, delta=1.0):
error = y_pred - y_true
abs_error = tf.abs(error)
quadratic = tf.minimum(abs_error, delta)
linear = (abs_error - quadratic)
return tf.reduce_mean(0.5 * quadratic ** 2 + delta * linear)
该函数采用预测值 y_pred、真实值 y_true、 和 delta 超参数作为输入,并返回 Huber 损失。