Keras/Tensorflow: Combined Loss function for single output

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Keras/Tensorflow: Combined Loss function for single output



I have only one output for my model, but I would like to combine two different loss functions:


def get_model():
# create the model here
model = Model(inputs=image, outputs=output)

alpha = 0.2
model.compile(loss=[mse, gse],
loss_weights=[1-alpha, alpha]
, ...)



but it complains that I need to have two outputs because I defined two losses:


ValueError: When passing a list as loss, it should have one entry per model outputs.
The model has 1 outputs, but you passed loss=[<function mse at 0x0000024D7E1FB378>, <function gse at 0x0000024D7E1FB510>]



Can I possibly write my final loss function without having to create another loss function (because that would restrict me from changing the alpha outside the loss function)?



How do I do something like (1-alpha)*mse + alpha*gse?


(1-alpha)*mse + alpha*gse



Update:



Both my loss functions are equivalent to the function signature of any builtin keras loss function, takes in y_true and y_pred and gives a tensor back for loss (which can be reduced to a scalar using K.mean()), but I believe, how these loss functions are defined shouldn't affect the answer as long as they return valid losses.


y_true


y_pred


K.mean()


def gse(y_true, y_pred):
# some tensor operation on y_pred and y_true
return K.mean(K.square(y_pred - y_true), axis=-1)





could you add your gse function?
– Ioannis Nasios
Aug 6 at 10:46




3 Answers
3



Specify a custom function for the loss:


model = Model(inputs=image, outputs=output)

alpha = 0.2
model.compile(
loss=lambda y_true, y_pred: (1 - alpha) * mse(y_true, y_pred) + alpha * gse(y_true, y_pred),
...)



Or if you don't want an ugly lambda make it into an actual function:


def my_loss(y_true, y_pred):
return (1 - alpha) * mse(y_true, y_pred) + alpha * gse(y_true, y_pred)

model = Model(inputs=image, outputs=output)

alpha = 0.2
model.compile(loss=my_loss, ...)



EDIT:



If your alpha is not some global constant, you can have a "loss function factory":


alpha


def make_my_loss(alpha):
def my_loss(y_true, y_pred):
return (1 - alpha) * mse(y_true, y_pred) + alpha * gse(y_true, y_pred)
return my_loss

model = Model(inputs=image, outputs=output)

alpha = 0.2
my_loss = make_my_loss(alpha)
model.compile(loss=my_loss, ...)





usually when I define custom losses, I will have to pass that in the dict when loading the model, but if I pass a lambda, do I need to pass that somehow or will it work just right?
– Saravanabalagi Ramachandran
Aug 6 at 10:38





@SaravanabalagiRamachandran Not sure what dict you are referring to... Are you talking about the model definition part, or checkpointing, or something else? Where exactly would you usually need to put the custom loss you define?
– jdehesa
Aug 6 at 10:40





if I save a model with custom losses I will have to tell keras what they are when loading the same. So import gse from somewhere and then load_model(model_file, custom_objects='gse':gse. custom_objects dict...!
– Saravanabalagi Ramachandran
Aug 6 at 10:42



import gse from somewhere


load_model(model_file, custom_objects='gse':gse


custom_objects





@SaravanabalagiRamachandran Ahh I see, sorry I was not aware of this API of Keras models. I have only saved and restored models using TensorFlow tooling, I'm not sure how Keras mechanism works, so I wouldn't know for sure, but it does seem that all non-standard functions (including lambdas, I'd suspect) have to be passed as custom_objects or provided by a CustomObjectScope...
– jdehesa
Aug 6 at 10:49


custom_objects


CustomObjectScope





Yep, it can't seem to get the anonymous function as expected. Throws ValueError: Unknown loss function:<lambda> error when loading the model after saving.
– Saravanabalagi Ramachandran
Aug 6 at 10:56


ValueError: Unknown loss function:<lambda>



Yes, define your own custom loss function and pass that to the loss argument upon compiling:


loss


def custom_loss(y_true, y_pred):
return (1-alpha) * K.mean(K.square(y_true-y_pred)) + alpha * gse



(Not sure what you mean with gse). It can be helpful to have a look at how the vanilla losses are implemented in Keras: https://github.com/keras-team/keras/blob/master/keras/losses.py


gse





gse is a function just like mse (Updated the question), so we would have to pass in y_true and y_pred to it when calling, we can't do alpha * gse.
– Saravanabalagi Ramachandran
Aug 6 at 10:59


gse


mse


y_true


y_pred


alpha * gse





Because gse is a function. Try writing it out as a single custom loss function as above.
– sdcbr
Aug 6 at 11:02



gse





sorry if I misunderstood you, but alpha would be a scalar like 0.1 or 0.2 and keras wouldn't know how to multiply a function gse or mse with a scalar alpha and would throw TypeError: unsupported operand type(s) for *: 'function' and 'float', wouldn't it?
– Saravanabalagi Ramachandran
Aug 6 at 11:05



alpha


0.1


0.2


gse


mse


alpha


TypeError: unsupported operand type(s) for *: 'function' and 'float'





Sorry, I meant that gse is a function. If you write it out as a single custom loss function like above, with gse replace by it's definition, do you still get the error?
– sdcbr
Aug 6 at 11:08


gse





gotcha, you suggest to create another loss function incorporating both the losses inside. But alpha can't be changed when I define the model :(
– Saravanabalagi Ramachandran
Aug 6 at 11:10



loss function should be one function.You are giving your model a list of two functions


loss



try:


def mse(y_true, y_pred):
return K.mean(K.square(y_pred - y_true), axis=-1)

model.compile(loss= (mse(y_true, y_pred)*(1-alpha) + gse(y_true, y_pred)*alpha),
, ...)





You mean to say loss=(mse*(1-alpha) + gse*alpha)?
– Saravanabalagi Ramachandran
Aug 6 at 10:34


loss=(mse*(1-alpha) + gse*alpha)





I don't think we can do arithmetic on functions in Python, but anyway I tried but got TypeError: unsupported operand type(s) for *: 'function' and 'float'
– Saravanabalagi Ramachandran
Aug 6 at 10:34



TypeError: unsupported operand type(s) for *: 'function' and 'float'





what is gse function?
– Ioannis Nasios
Aug 6 at 10:38





it is exactly like how you have defined mse in your answer. the problem is it doesn't know what function * float means, so it just complains unsupported operand
– Saravanabalagi Ramachandran
Aug 6 at 10:39



mse


function * float


unsupported operand






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

make 2 or more post in bootsrap

Store custom data using WC_Cart add_to_cart() method in Woocommerce 3

Firebase Auth - with Email and Password - Check user already registered