Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keras custom function: implementing Jaccard

I am trying to apply the Jaccard coefficient as customised loss function in a Keras LSTM, using Tensorflow as backend.

I know the I have to call the following:

model.compile(optimizer='rmsprop', loss=[jaccard_similarity])

where jaccard_similarity function should be the keras.backend implementation of the below:

def jaccard_similarity(doc1, doc2):
   intersection =set(doc1).intersection(set(doc2))
   union = set(doc1).union(set(doc2))
   return len(intersection)/len(union)

The problem is that I cannot find methods to implement intersection and union functions on tensors using tensorflow as backend.

Any suggestion?

like image 509
Mauro Gentile Avatar asked Jul 13 '26 06:07

Mauro Gentile


2 Answers

Careful with Artur's answer!

intersection = K.sum(K.abs(y_true * y_pred), axis=-1)
sum_ = K.sum(K.abs(y_true) + K.abs(y_pred), axis=-1)

Loss function in the link is incorrect! |X| denotes the cardinality of the set, not the absolute value! Also the summation runs through classes ?

The corrected version should look something like this: (tensorflow version, not tested yet)

def jaccard_distance(y_true, y_pred, smooth=100):
    """ Calculates mean of Jaccard distance as a loss function """
    intersection = tf.reduce_sum(y_true * y_pred, axis=(1,2))
    sum_ = tf.reduce_sum(y_true + y_pred, axis=(1,2))
    jac = (intersection + smooth) / (sum_ - intersection + smooth)
    jd =  (1 - jac) * smooth
    return tf.reduce_mean(jd)

Inputs are image tensors of shape (batch, width, height, classes). Calculates the jaccard distance for each batch and class (shape=(batch, classes)) and returns mean value as a loss scalar.

like image 95
JBWKy Avatar answered Jul 15 '26 21:07

JBWKy


I've used the jaccard distance to train a semantic segmentation network in keras. The loss function I used is identidical to this one. I'll paste it here:

from keras import backend as K
def jaccard_distance(y_true, y_pred, smooth=100):
    intersection = K.sum(K.abs(y_true * y_pred), axis=-1)
    sum_ = K.sum(K.abs(y_true) + K.abs(y_pred), axis=-1)
    jac = (intersection + smooth) / (sum_ - intersection + smooth)
    return (1 - jac) * smooth

Notice that this one minus the jaccard similarity (which you want to maximize). In fact, it's a continuous approximation of the jaccard distance, so it's derivative is well defined.

like image 28
Artur Lacerda Avatar answered Jul 15 '26 20:07

Artur Lacerda