Conversión del tensor de TensorFlow en una matriz Numpy
Descripción del problema
Estoy tratando de escribir una función de pérdida personalizada en TensorFlow 2.3.0. Para calcular la pérdida, necesito que el y_predparámetro se convierta en una matriz numpy. Sin embargo, no puedo encontrar una manera de convertirlo <class 'tensorflow.python.framework.ops.Tensor'>en una matriz numpy, aunque parece que hay funciones de TensorFlow para hacerlo.
Ejemplo de código
def custom_loss(y_true, y_pred):
print(type(y_pred))
npa = y_pred.make_ndarray()
...
if __name__ == '__main__':
...
model.compile(loss=custom_loss, optimizer="adam")
model.fit(x=train_data, y=train_data, epochs=10)
da el mensaje de error: AttributeError: 'Tensor' object has no attribute 'make_ndarraydespués de imprimir el tipo de y_predparámetro:<class 'tensorflow.python.framework.ops.Tensor'>
Lo que he probado hasta ahora
Buscando una solución, encontré que esto parece ser un problema común y hay un par de sugerencias, pero hasta ahora no me han funcionado:
1. "... así que simplemente llame a .numpy () en el objeto Tensor": ¿Cómo puedo convertir un tensor en una matriz numpy en TensorFlow?
así que intenté:
def custom_loss(y_true, y_pred):
npa = y_pred.numpy()
...
dando me AttributeError: 'Tensor' object has no attribute 'numpy'
2. "Use tensorflow.Tensor.eval () para convertir un tensor en una matriz": Cómo convertir un tensor de TensorFlow en una matriz NumPy en Python
así que intenté:
def custom_loss(y_true, y_pred):
npa = y_pred.eval(session=tf.compat.v1.Session())
...
dándome uno de los mensajes de error más largos que he visto, siendo el núcleo:
InvalidArgumentError: 2 root error(s) found.
(0) Invalid argument: You must feed a value for placeholder tensor 'functional_1/conv2d_2/BiasAdd/ReadVariableOp/resource' with dtype resource
[[node functional_1/conv2d_2/BiasAdd/ReadVariableOp/resource (defined at main.py:303) ]]
[[functional_1/cropping2d/strided_slice/_1]]
(1) Invalid argument: You must feed a value for placeholder tensor 'functional_1/conv2d_2/BiasAdd/ReadVariableOp/resource' with dtype resource
[[node functional_1/conv2d_2/BiasAdd/ReadVariableOp/resource (defined at main.py:303) ]]
Además, tener que llamar a las funciones de compatibilidad de TensorFlow desde la versión 1.x no parece muy preparado para el futuro, por lo que de todos modos no me gusta demasiado este enfoque.
3. Mirando los documentos de TensorFlow, parecía que había la función que necesitaba esperando: tf.make_ndarray Crea un ndarray numpy a partir de un tensor.
así que intenté:
def custom_loss(y_true, y_pred):
npa = tf.make_ndarray(y_pred)
...
dando me AttributeError: 'Tensor' object has no attribute 'tensor_shape'
Mirando el ejemplo en la documentación de TF, usan esto en un proto_tensor, así que intenté convertirlo a un proto primero:
def custom_loss(y_true, y_pred):
proto_tensor = tf.make_tensor_proto(y_pred)
npa = tf.make_ndarray(proto_tensor)
...
pero ya tf.make_tensor_proto(y_pred)surge el error:TypeError: Expected any non-tensor type, got a tensor instead.
También intentar hacer un tensor constante primero da el mismo error:
def custom_loss(y_true, y_pred):
a = tf.constant(y_pred)
proto_tensor = tf.make_tensor_proto(a)
npa = tf.make_ndarray(proto_tensor)
...
Hay muchas más publicaciones en torno a esto, pero parece que todas están volviendo a estas tres ideas básicas. ¡Esperamos sus sugerencias!
Respuestas
y_pred.numpy()funciona en TF 2 pero AttributeError: 'Tensor' object has no attribute 'make_ndarrayindica que hay partes de su código que no está ejecutando en modo Eager ya que de otra manera no tendría un Tensorobjeto sino un EagerTensor.
Para habilitar el modo ansioso, coloque esto al principio de su código antes de que se construya cualquier cosa en el gráfico:
tf.config.experimental_run_functions_eagerly(True)
En segundo lugar, cuando compile su modelo, agregue este parámetro:
model.compile(..., run_eagerly=True, ...)
Ahora está ejecutando en modo ansioso y todas las variables contienen valores con los que puede imprimir y trabajar. Tenga en cuenta que cambiar al modo Eager puede requerir ajustes adicionales en su código (consulte aquí para obtener una descripción general).