I am having a problem when trying to implement the pairwise ranking loss mentioned in this paper "Deep Convolutional Ranking for Multilabel Image Annotation". When I defined the pairwise ranking function, I found that y_true and y_predict are actually Tensors, which means that we do not know which are positive labels and which are negative labels according to y_true. And I cannot transform this loss into a tensor operation. Could anybody solve this problem?
Thanks in advance!
You can use simple equality statements to find the positive/negative values of an array.
Example:
import numpy as np
import keras.backend as K
def postive_values(yt, yp):
return (yp > 0.) #return a mask of Truth values indicating which elements are positive
def negative_values(yt, yp):
return (yp < 0.) #return a mask of Truth values indicating which elements are nmegative
y_true = K.placeholder(shape=(10,), dtype='int32')
y_pred = K.placeholder(shape=(10,), dtype='float32')
pos = postive_values(y_true, y_pred)
neg = negative_values(y_true, y_pred)
loss1 = K.function([y_true, y_pred], pos)
loss2 = K.function([y_true, y_pred], neg)
tmp = np.eye(10)[0] * 2.0 - 1.0 #sum of positive elements == 1.0; negative elements == -9.0
print(tmp)
# array([ 1., -1., -1., -1., -1., -1., -1., -1., -1., -1.])
print(loss1([tmp, tmp]))
# [1 0 0 0 0 0 0 0 0 0]
print(loss2([tmp, tmp]))
# [0 1 1 1 1 1 1 1 1 1]
# Apply the masks to get only the positive (or negative) values
print(tmp * loss1([tmp, tmp]))
print(tmp * loss2([tmp, tmp]))
# [ 1. -0. -0. -0. -0. -0. -0. -0. -0. -0.]
# [ 0. -1. -1. -1. -1. -1. -1. -1. -1. -1.]
@patyork Thank you very much for your quick response. Yes, this indeed can find the positive/negative values of an array. But it still doesn't solve the pairwise ranking loss. The main idea of pairwise ranking loss is to let positive labels have higher scores than negative labels.
For instance, y_true = [1 0 0 1] (1 is positive label and 0 is negative label), y_pred = [0.3 0.1 0.2 0.4] (y_pred can be considered as scores), thus the pairwise ranking loss = max(0, m-0.3+0.1) + max(0, m-0.3+0.2) + max(0, m-0.4+0.1) + max(0, m-0.4+0.2) (here m is the margin).
The difficulty is how to use Tensor operation to calculate this pairwise ranking loss? It needs to iterate the positive labels and negative labels.
@guxiaoling Do you find the solution?
No, I have not found solution. Maybe the backend file should be modified.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 30 days if no further activity occurs, but feel free to re-open a closed issue if needed.
@patyork Thank you very much for your quick response. Yes, this indeed can find the positive/negative values of an array. But it still doesn't solve the pairwise ranking loss. The main idea of pairwise ranking loss is to let positive labels have higher scores than negative labels.
For instance, y_true = [1 0 0 1] (1 is positive label and 0 is negative label), y_pred = [0.3 0.1 0.2 0.4] (y_pred can be considered as scores), thus the pairwise ranking loss = max(0, m-0.3+0.1) + max(0, m-0.3+0.2) + max(0, m-0.4+0.1) + max(0, m-0.4+0.2) (here m is the margin).
The difficulty is how to use Tensor operation to calculate this pairwise ranking loss? It needs to iterate the positive labels and negative labels.
I've implemented pairwise loss in pytorch but not in Keras still i think it shouldn't matter. The way i utilized tensor operations is like the following:
filter these two tensors by masking
neg_preds = [0.1, 0.2]
pos_preds = [0.3, 0.4]
use vectorization
loss = max(0, (margin + neg_preds[:, None] - pos_preds[None, :]).view(-1) ) # view() is flatten() for pytorch
Hope this helps. But i found it very unstable to optimize, though it's another issue or research.
@KeremTurgutlu did you develop a Keras version?
Most helpful comment
I've implemented pairwise loss in pytorch but not in Keras still i think it shouldn't matter. The way i utilized tensor operations is like the following:
filter these two tensors by masking
neg_preds = [0.1, 0.2]
pos_preds = [0.3, 0.4]
use vectorization
loss = max(0, (margin + neg_preds[:, None] - pos_preds[None, :]).view(-1) ) # view() is flatten() for pytorch
Hope this helps. But i found it very unstable to optimize, though it's another issue or research.