I am dealing with a regression problem where given an image, I want to predict the value of 3 parameters (cartesian coordinates) . For the same image I can have several acceptable coordinates. To do this, I use a neural network using keras. To train my network, I want to implement a custom loss function that will calculate the euclidian distance between the prediction and the closest acceptable value. In mathematical term it can be expressed like that :
The shape of is and the shape of my target is .
To calculate this loss, I first reshape to have the correct shape. Then I perform the loss calculation (using tensorflow 1.13):
import tensorflow as tf
import tensorflow.keras.backend as K
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
K.set_session(tf.Session(config=config))
from tensorflow.python.keras.applications import ResNet50
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense, Dropout
import numpy as np
def min_mse(y_pred, y_true):
y_pred_temp = K.repeat(y_pred, K.shape(y_true)[1])
return K.min(K.sum(K.sqrt(y_pred_temp-y_true), axis=-1), axis=-1)
def resnet_model():
model = Sequential()
model.add(ResNet50(include_top=False, pooling='avg', weights='imagenet'))
model.add(Dense(1024, activation='relu'))
model.add(Dropout(rate=0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(rate=0.2))
model.add(Dense(3, activation='linear'))
model.layers[0].trainable = False
model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.001), loss=min_mse)
return model
X = np.random.random((200, 224, 224, 3))
Y = np.random.random((200, 10, 3))
model = resnet_model()
model.fit(X, Y)
However, this code outputs an error
tensorflow.python.framework.errors_impl.InvalidArgumentError: Expected multiples argument to be a vector of length 4 but got length 3 [[{{node loss/dense_2_loss/Tile}}]]
I have some trouble solving it as I can not easily print the shape of my different tensors to understand the problem. Do you have any clue of how to solve this problem (by fixing my code or using another method) ? Thanks in advance.
From Kera's documentation you can see that when you define a custom metric, labels come as the first argument and prediction as the second argument of the custom loss.
Just swap y_true and y_pred and your code should run :
def min_mse(y_true, y_pred):
y_pred_temp = K.repeat(y_pred, K.shape(y_true)[1])
return K.min(K.sum(K.sqrt(y_pred_temp-y_true), axis=-1), axis=-1)