Sesión de TensorFlow dentro de la función de pérdida personalizada de

Sesión de TensorFlow dentro de la función de pérdida personalizada de Keras

Después de revisar algunas preguntas de Stack y la documentación de Keras, logré escribir un código tratando de evaluar el gradiente de la salida de una red neuronal con respecto a sus entradas, el propósito es un simple ejercicio de aproximación de una función bivariada (f(x,y) = x^2+y^2) utilizando como pérdida la diferencia entre diferenciación analítica y automática.

Combinando respuestas de dos preguntas (Función de pérdida personalizada de Keras: Acceso al patrón de entrada actual y Obtención del gradiente de los pesos w.r.t de salida del modelo usando Keras ), se me ocurrió esto:

import tensorflow as tf
from keras import backend as K
from keras.models import Model
from keras.layers import Dense, Activation, Input

def custom_loss(input_tensor):

    outputTensor = model.output       
    listOfVariableTensors = model.input      
    gradients = K.gradients(outputTensor, listOfVariableTensors)

    sess = tf.InteractiveSession()
    sess.run(tf.initialize_all_variables())
    evaluated_gradients = sess.run(gradients,feed_dict={model.input:input_tensor})

    grad_pred = K.add(evaluated_gradients[0], evaluated_gradients[1])
    grad_true = k.add(K.scalar_mul(2, model.input[0][0]), K.scalar_mul(2, model.input[0][1])) 

    return K.square(K.subtract(grad_pred, grad_true))

input_tensor = Input(shape=(2,))
hidden = Dense(10, activation='relu')(input_tensor)
out = Dense(1, activation='sigmoid')(hidden)
model = Model(input_tensor, out)
model.compile(loss=custom_loss_wrapper(input_tensor), optimizer='adam')

Lo que produce el error: TypeError: The value of a feed cannot be a tf.Tensor object. debido a feed_dict={model.input:input_tensor}. Entiendo el error, pero no sé cómo solucionarlo.

Por lo que he recopilado, no puedo simplemente pasar datos de entrada a la función de pérdida, debe ser un tensor. Me di cuenta de que Keras lo 'entendería' cuando llamo a input_tensor. Todo esto me lleva a pensar que estoy haciendo las cosas de manera incorrecta, tratando de evaluar el gradiente de esa manera. Realmente agradecería un poco de iluminación.

Mostrar la mejor respuesta

Una pérdida de Keras debe tener y_true y y_pred como entradas. Puede intentar agregar su objeto de entrada como x y y durante el ajuste:

def custom_loss(y_true,y_pred):
    ...
    return K.square(K.subtract(grad_true, grad_pred))

...
model.compile(loss=custom_loss, optimizer='adam')

model.fit(X, X, ...)

De esta manera, y_true será el lote que se procesará en cada iteración desde la entrada X, mientras que y_pred será la salida del modelo para ese lote en particular.

da el mismo error, feed_dict no recibirá tensores; y_pred es uno. ¡gracias de cualquier manera!

Realmente no entiendo por qué desea esta función de pérdida, pero le proporcionaré una respuesta de todos modos. Además, no es necesario evaluar el gradiente dentro de la función (de hecho, estaría "desconectando" el gráfico computacional). La función de pérdida podría implementarse de la siguiente manera:

from keras import backend as K
from keras.models import Model
from keras.layers import Dense, Input

def custom_loss(input_tensor, output_tensor):
    def loss(y_true, y_pred):
        gradients = K.gradients(output_tensor, input_tensor)
        grad_pred = K.sum(gradients, axis=-1)
        grad_true = K.sum(2*input_tensor, axis=-1)
        return K.square(grad_pred - grad_true)
    return loss

input_tensor = Input(shape=(2,))
hidden = Dense(10, activation='relu')(input_tensor)
output_tensor = Dense(1, activation='sigmoid')(hidden)
model = Model(input_tensor, output_tensor)
model.compile(loss=custom_loss(input_tensor, output_tensor), optimizer='adam')

Como dije, es solo un ejemplo de juguete que sigue, más o menos, la misma estructura de un problema más complejo. ¡Muchas gracias por ayudar!

Por cierto, ¿existe realmente la necesidad de ajustar la función de pérdida y_true/y_pred?

Sí, esto es necesario porque model.compile espera una cadena (nombre de la función objetivo) o una función objetivo con estos argumentos. ¡Estoy feliz de ayudarte!