Keras/Tensorflow: Combined Loss function for single output

Clash 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)
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.
could you add your gse function?
– Ioannis Nasios
Aug 6 at 10:46