5
$\begingroup$

I'm looking for a way to create a conditional loss function that looks like this: there is a vector of labels, say l (l has the same length as the input x), then for a given input (y_true, y_pred, l) the loss should be:

def conditional_loss_function(y_true, y_pred, l):
    loss = if l is 0: loss_funtion1
           if l is 1: loss_funtion2
    return loss

It is like a kind of semi-supervised loss funtion.

$\endgroup$
1

1 Answer 1

1
$\begingroup$

You should be able to solve this with currying. Make a function that takes the label as input and returns a function which takes y_true and y_pred as input. Note that the label needs to be a constant or a tensor for this to work.

def conditional_loss_function(l):
    def loss(y_true, y_pred):
        if l == 0: 
            return loss_funtion1(y_true, y_pred)
        else: 
            return loss_funtion2(y_true, y_pred)
    return loss

model.compile(loss=conditional_loss_function(l), optimizer=...)

Small working example with different loss function depending on the label:

# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
data = dataset[:,0:8]
label = dataset[:,8]

X = Input(shape=(8,))
Y = Input(shape=(1,))
x = Dense(12, input_dim=8, activation='relu')(X)
x = Dense(8, activation='relu')(x)
predictions = Dense(1, activation='sigmoid')(x)

def custom_loss(l):
    def loss(y_true, y_pred):
        if l == 0:
            return binary_crossentropy(y_true, y_pred)
        else: 
            return mean_squared_error(y_true, y_pred)
    return loss    

# Compile model
model = Model(inputs=[X, Y], outputs=predictions)
model.compile(loss=custom_loss(Y), optimizer='adam', metrics=['accuracy'])

# Fit the model
model.fit(x=[data, label], y=label, epochs=150)

# evaluate the model
scores = model.evaluate([data, label], label)
print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
$\endgroup$
7
  • 1
    $\begingroup$ I think you may have missed the point. The vector l is almost certainly dynamically changing. $\endgroup$
    – kbrose
    Commented Mar 1, 2018 at 15:11
  • $\begingroup$ @kbrose: I believe it should work for your case. This github issue have a similar solution github.com/keras-team/keras/issues/2121 $\endgroup$
    – Shaido
    Commented Mar 1, 2018 at 15:43
  • $\begingroup$ @kbrose You are right, l is a vector which has the same length as the input. $\endgroup$
    – Tian
    Commented Mar 1, 2018 at 16:31
  • $\begingroup$ @Tian: I added a small working example that should better illustrate the idea $\endgroup$
    – Shaido
    Commented Mar 2, 2018 at 1:31
  • $\begingroup$ @Shaido I am confused that should "label" here be a tensor? If "label" is a tensor, can we do like "if label == 0:"? $\endgroup$
    – Tian
    Commented Mar 2, 2018 at 4:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.