Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keras: how to get tensor dimensions inside custom loss?

Tags:

I'm trying to write my custom loss function: I want to apply categorical_crossentropy to the parts of input vector and then sum.

Assume y_true, y_pred are 1D vectors.

Code:

def custom_loss(y_true, y_pred):      loss_sum= 0.0     for i in range(0,y_true.shape[0],dictionary_dims):         loss_sum+= keras.backend.categorical_crossentropy(y_true[i*dictionary_dims:(i+1)*dictionary_dims], y_pred[i*dictionary_dims:(i+1)*dictionary_dims])      return loss_sum 

But I get an error:

    for i in range(0,y_true.shape[0],dictionary_dims): TypeError: __index__ returned non-int (type NoneType) 

So how to access shape of input tensors to get subset of tensor?

Update: Also tried to write loss via tensorflow directly:

def custom_loss_tf(y_true, y_pred):      print('tf.shape(y_true)',tf.shape(y_true)) #     print('type(tf.shape(y_true))',type(tf.shape(y_true))) #      sys.exit()      loss_sum= 0.0     for i in range(0,y_true.shape[0],dictionary_dims):         loss_sum+= keras.backend.categorical_crossentropy(y_true[i*dictionary_dims:(i+1)*dictionary_dims], y_pred[i*dictionary_dims:(i+1)*dictionary_dims])      return loss_sum 

Output:

tf.shape(y_true) Tensor("Shape:0", shape=(2,), dtype=int32) type(tf.shape(y_true)) <class 'tensorflow.python.framework.ops.Tensor'> 

Not sure what is shape=(2,) mean, but this is not what I'm expecting, because model.summary() shows that last layer is (None, 26):

_________________________________________________________________ Layer (type)                 Output Shape              Param # ================================================================= input_1 (InputLayer)         (None, 80, 120, 3)        0 _________________________________________________________________ conv2d_1 (Conv2D)            (None, 80, 120, 32)       896 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 40, 60, 32)        0 _________________________________________________________________ activation_1 (Activation)    (None, 40, 60, 32)        0 _________________________________________________________________ conv2d_2 (Conv2D)            (None, 40, 60, 32)        9248 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 20, 30, 32)        0 _________________________________________________________________ activation_2 (Activation)    (None, 20, 30, 32)        0 _________________________________________________________________ conv2d_3 (Conv2D)            (None, 20, 30, 64)        18496 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 10, 15, 64)        0 _________________________________________________________________ activation_3 (Activation)    (None, 10, 15, 64)        0 _________________________________________________________________ conv2d_4 (Conv2D)            (None, 10, 15, 64)        36928 _________________________________________________________________ max_pooling2d_4 (MaxPooling2 (None, 5, 7, 64)          0 _________________________________________________________________ activation_4 (Activation)    (None, 5, 7, 64)          0 _________________________________________________________________ flatten_1 (Flatten)          (None, 2240)              0 _________________________________________________________________ head (Dense)                 (None, 26)                58266 ================================================================= 
like image 390
mrgloom Avatar asked Aug 03 '17 09:08

mrgloom


1 Answers

Two things here:

  1. If you want to get a tensor shape you should use int_shape function from keras.backend.
  2. The first dimension is set to be a batch dimension so int_shape(y_true)[0] will return you a batch size. You should use int_shape(y_true)[1].
like image 135
Marcin Możejko Avatar answered Nov 28 '22 09:11

Marcin Możejko