如何使用 MSE 创建损失函数,使用 tf.where() 忽略某些元素
How To Create A Loss Function with MSE that Uses tf.where() to ignore certain elements
这是目前的功能。在这里,它从 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]
您似乎对 tf.where
用法感到困惑。从 documentation 可以看出 tf.where 应该采用三个参数,否则它将简单地 return None
如此处所述
tf.where(
condition, x=None, y=None, name=None
)
这就是为什么你的损失无助于学习任何东西,因为无论如何,它总是 returns None
。
对于你的问题,如果你想检查这两个条件然后暗示损失,你应该这样做。
假设你想为 y_true!=0
和 y_pred!=0
分别给出损失,some_loss1
和 some_loss2
,那么可以通过嵌套 [=12] 来计算总损失=]作为
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 值重新分配给此掩码损失。
如果您在转换为图形模式的代码中使用 python 短路 and
运算符,大多数情况下会导致不良行为或错误,因为 python 短路 - circuit 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)
这是目前的功能。在这里,它从 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]
您似乎对 tf.where
用法感到困惑。从 documentation 可以看出 tf.where 应该采用三个参数,否则它将简单地 return None
如此处所述
tf.where(
condition, x=None, y=None, name=None
)
这就是为什么你的损失无助于学习任何东西,因为无论如何,它总是 returns None
。
对于你的问题,如果你想检查这两个条件然后暗示损失,你应该这样做。
假设你想为 y_true!=0
和 y_pred!=0
分别给出损失,some_loss1
和 some_loss2
,那么可以通过嵌套 [=12] 来计算总损失=]作为
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 值重新分配给此掩码损失。
如果您在转换为图形模式的代码中使用 python 短路 and
运算符,大多数情况下会导致不良行为或错误,因为 python 短路 - circuit 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)