【问题标题】:How To Create A Loss Function with MSE that Uses tf.where() to ignore certain elements如何使用 MSE 创建使用 tf.where() 忽略某些元素的损失函数
【发布时间】:2021-10-13 13:56:59
【问题描述】:

这是目前的功能。在这里,它会从 MSE 中删除 y_true 小于阈值(此处为 0.1)的任何值。

def my_loss(y_true,y_pred):
    loss = tf.square(y_true-y_pred)
    # if any y_true is less than a threshold (say 0.1) 
    # the element is removed from loss, and does not affect MSE
    loss = tf.where(y_true<0.1)
    # return mean of losses
    return tf.reduce_mean(loss)

这个可以编译,但是网络从来没有学会很好地预测 0。相反,我只想消除那些 y_true 和 y_pred 都小于某个阈值的值。这是因为它需要首先学习如何预测 0,然后在稍后的训练中忽略这些点。

然而,这并不能编译。

def my_better_loss(y_true,y_pred):
    loss = tf.square(y_true-y_pred)
    # remove all elements where BOTH y_true & y_pred < threshold
    loss = tf.where(y_true<0.1 and y_pred<0.1)
    # return mean of losses
    return tf.reduce_mean(loss)

导致如下错误。


  (0) Invalid argument:  The second input must be a scalar, but it has shape [25,60,60]
         [[{{node replica_1/customMSE/cond/switch_pred/_51}}]]
  (1) Invalid argument:  The second input must be a scalar, but it has shape [25,60,60]
         [[{{node replica_1/customMSE/cond/switch_pred/_51}}]]
         [[customMSE/cond/Squeeze/_59]]
  (2) Invalid argument:  The second input must be a scalar, but it has shape [25,60,60]
         [[{{node replica_1/customMSE/cond/replica_1/customMSE/Less/_55}}]]
0 successful operations.
0 derived errors ignored. [Op:__inference_train_function_4715]

Function call stack:
train_function -> train_function -> train_function

编辑:

更具体一点。假设我们的阈值是 0.5:

y_true = [0.3, 0.4, 0.6, 0.7]
y_pred = [0.2, 0.7, 0.5, 1]

然后损失函数将在删除第一个元素的情况下计算 mse,因为 y_pred[0] 和 y_true[0] 都小于阈值。

# MSE would be computed between
y_true = [0.4, 0.6, 0.7]
#and
y_pred = [0.7, 0.5, 1]

【问题讨论】:

  • 你可以轻松做到这一点,但如果批次中 y_pred 和 y_true 的所有元素都小于阈值,则损失将是 nan
  • 真的!有什么办法吗?我可以检查if loss == np.nan 然后loss = 0 这是可以接受的,因为它可以正确预测该图像。您想到了什么实现方式?
  • 您可以简单地将所有低于等于零的阈值(如 relu 实现)这样计算损失时没有 nan 问题
  • @MarcoCerliani 但是,我希望truth &lt;= thresholdpred &gt; threshold 时有非零损失。没有它,网络不会因为在任何地方都放置非零值而受到惩罚

标签: python tensorflow keras neural-network


【解决方案1】:

如果您在转换为图形模式的代码中使用 python 短路 and 运算符,大多数情况下会导致不良行为或错误,因为无法重载 python 短路 and 运算符。要对张量进行逐元素和运算,请使用tf.math.logical_and

此外,tf.where 在这里不是必需的,它可能会更慢。掩蔽是优选的。示例代码:

@tf.function
def better_loss(y_true,y_pred):
  loss = tf.square(y_true - y_pred)
  # ignore elements where BOTH y_true & y_pred < 0.1
  mask = tf.cast(tf.logical_or(y_true >= 0.1, y_pred >= 0.1) ,tf.float32)
  loss *= mask
  return tf.reduce_sum(loss) / tf.reduce_sum(mask)

【讨论】:

  • 有没有办法在 y_true > 0.1 & y_pred
【解决方案2】:

您似乎对 tf.where 的用法感到困惑。从documentation 可以看出 tf.where 应该采用三个参数,否则它将简单地返回None,如此处所述

tf.where(
    condition, x=None, y=None, name=None
)

这就是为什么你的损失对学习任何东西都没有帮助,因为无论如何它总是返回None

对于您的问题,如果您想检查两个条件,然后暗示损失,这是您应该这样做的。

假设 y_true!=0y_pred!=0 你想分别给出损失,some_loss1some_loss2,那么总损失可以通过嵌套 tf.where 来计算

some_loss1=tf.constant(1000.0) #say
some_loss12=tf.constant(1000.0) #say

loss = tf.where(y_pred<0.1,tf.where(y_true<0.1,tf.constant(0.0),some_loss1),some_loss2)

这将同时惩罚y_pred and y_true

此外,如果您想将此损失添加到您的 MSE 损失中,则创建不同的变量名称,因为它将已经获得的 MSE 值重新分配给此掩码损失。

【讨论】:

  • 来自 tensorflow.org:此运算符有两种模式:在一种模式下,x 和 y 都提供,在另一种模式下,两者都不提供。条件总是期望是一个布尔类型的 tf.Tensor。
猜你喜欢
  • 2021-01-24
  • 2020-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-28
  • 1970-01-01
  • 1970-01-01
  • 2011-03-26
  • 2020-10-29
相关资源
最近更新 更多