正确的排名损失实施

时间:2019-08-04 23:06:58

标签: python tensorflow machine-learning loss-function multilabel-classification

我有一个多标签问题,我正在尝试将TensorFlow中的排名损失实现为自定义损失。 (https://arxiv.org/pdf/1312.4894.pdf

我制作了一个带有最后一个Sigmoid激活层的简单CNN,以使每个类具有独立的分布。
数学公式将标签分为正负两个标签。

rankloss

我的问题是,实现它的正确方法是什么?

def ranking_loss(y_true, y_pred):    
    pos = tf.where(tf.equal(y_true, 1), y_pred, tf.zeros_like(y_pred))
    neg = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))

    loss = tf.maximum(1.0 - tf.math.reduce_sum(pos) + tf.math.reduce_sum(neg), 0.0)
    return tf.math.reduce_sum(loss)

结果是,对于每个样本,来自正类别和负类别的激活分数将独立求和。

tr = [1, 0, 0, 1]
pr = [0, 0.6, 0.55, 0.9]
t =  tf.constant([tr])
p =  tf.constant([pr])

print(ranking_loss(t, p))

tf.Tensor([[0.  0.  0.  0.9]], shape=(1, 4), dtype=float32) #Pos
tf.Tensor([[0.   0.6  0.55 0.  ]], shape=(1, 4), dtype=float32) #Neg
tf.Tensor(1.2500001, shape=(), dtype=float32) #loss

CNN的准确度,召回率和F1性能确实很差。
改用标准的二进制交叉熵损失会产生良好的性能,这让我认为我的实现存在问题。

1 个答案:

答案 0 :(得分:1)

我认为,根据公式,总和的扩展是错误的,并且总和tf.math.reduce_sum(pos)tf.math.reduce_sum(neg)不能推入tf.maximum中。如我所见,您的示例公式将扩展为:

max(0,1-0 + 0.6)+ max(0,1-0 + 0.55)+ max(0,1-0.9 + 0.6)+ max(0,1-0.9 + 0.55)= 4.5

您在注释部分中提供的第二种实现对我来说似乎很明智,并且产生了我期望的结果。但是,让我提供一种替代方法:

def ranking_loss(y_true, y_pred):
    y_true_ = tf.cast(y_true, tf.float32)
    partial_losses = tf.maximum(0.0, 1 - y_pred[:, None, :] + y_pred[:, :, None])
    loss = partial_losses * y_true_[:, None, :] * (1 - y_true_[:, :, None])
    return tf.reduce_sum(loss)

此实现可能更快。