4
$\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
$\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))
| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ I think you may have missed the point. The vector l is almost certainly dynamically changing. $\endgroup$ – kbrose Mar 1 '18 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 Mar 1 '18 at 15:43
  • $\begingroup$ @kbrose You are right, l is a vector which has the same length as the input. $\endgroup$ – Tian Mar 1 '18 at 16:31
  • $\begingroup$ @Tian: I added a small working example that should better illustrate the idea $\endgroup$ – Shaido Mar 2 '18 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 Mar 2 '18 at 4:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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