10

I am training a CovNet with two outputs. My training samples look like this:

[0, value_a1], [0, value_a2], ...

and

[value_b1, 0], [value_b2, 0], ....

I want to generate my own loss function and mask pairs that contain the mask_value = 0. I have this function, though I am not sure whether it really does what I want. So, I want to write some tests.

from tensorflow.python.keras import backend as K
from tensorflow.python.keras import losses

def masked_loss_function(y_true, y_pred, mask_value=0):
    '''
    This model has two target values which are independent of each other.
    We mask the output so that only the value that is used for training 
    contributes to the loss.
        mask_value : is the value that is not used for training
    '''
    mask = K.cast(K.not_equal(y_true, mask_value), K.floatx())
    return losses.mean_squared_error(y_true * mask, y_pred * mask)

Though, I don't know how I can test this function with keras? Usually, this would be passed to model.compile(). Something like along these lines:

x = [1, 0]
y = [1, 1]
assert masked_loss_function(x, y, 0) == 0
today
  • 32,602
  • 8
  • 95
  • 115
Soerendip
  • 7,684
  • 15
  • 61
  • 128
  • Just out of curiosity, why did you rolled back the edit of tags? Your question is concerned with Keras and clearly you want an answer in Python. Therefore adding Python tag is the reasonable thing to do. Further, this has been discussed previously in Meta [here](https://meta.stackoverflow.com/a/276057/2099607), [here](https://meta.stackoverflow.com/a/269593/2099607) and [here](https://meta.stackoverflow.com/a/293880/2099607). All of them recommend to add language tags of frameworks or libraries as well. – today Jul 09 '18 at 20:09
  • Plus, since you have not accepted any answer, it seems that you are looking for another or better solution. Therefore that edit had two benefits: 1. Those people who are tracking python tag will see your question and may provide another answer and 2. It made your question to go to the top of the "Active" tab of questions (and hence increases the chance of being seen by others). All in all, it was just some suggestions and you can do whatever you want. I just asked for the reason out of curiosity since I have done this many times before but never saw such a thing. – today Jul 09 '18 at 20:17
  • Oh, I am sorry about that. When I was reviewing the changes it looked like you copy pasted the exact same content. Everything was highlighted as removed and reinserted. So, I did not see your changes at all. – Soerendip Jul 09 '18 at 21:17
  • No problem. That's because I removed the syntax highlighting directive (i.e. ``); since adding the Python tag automatically highlights the syntax and there was no need for the directive anymore. – today Jul 09 '18 at 21:24

2 Answers2

8

I think one way of achieving that is using a Keras backend function. Here we define a function that takes as input two tensors and returns as output a tensor:

from keras import Model
from keras import layers

x = layers.Input(shape=(None,))
y = layers.Input(shape=(None,))
loss_func = K.function([x, y], [masked_loss_function(x, y, 0)])

And now we can use loss_func to run the computation graph we have defined:

assert loss_func([[[1,0]], [[1,1]]]) == [[0]]

Note that keras backend function, i.e. function, expects that the input and output arguments be an array of tensors. Additionally, x and y takes a batch of tensors, i.e. an array of tensors, with undefined shape.

today
  • 32,602
  • 8
  • 95
  • 115
  • I am getting ``AttributeError: module 'keras.backend' has no attribute 'Function'``, what are you importing? – GuySoft Jul 28 '20 at 15:37
  • @GuySoft Probably you are using the recent versions of Keras. In versions before 2.3.0, there used to be a `Function` class that did the real job (see [here](https://github.com/keras-team/keras/blob/f78d417f948cdfaaca22fabf90e01a76db126237/keras/backend/tensorflow_backend.py#L2029)) and `function` (with lowercase "f") was just a functional interface to that. Now, in both `keras` and `tf.keras` only the lowercase version is working. So you can use the lowercase version. Updated my answer to reflect that. Thanks for mentioning this. – today Jul 28 '20 at 16:23
1

This is another workaround,

x = [1, 0]
y = [1, 1]
F = masked_loss_function(K.variable(x), K.variable(y), K.variable(0))
assert K.eval(F) == 0 
Mehdi
  • 11
  • 2