Conversion du tenseur TensorFlow en tableau Numpy
Description du problème
J'essaie d'écrire une fonction de perte personnalisée dans TensorFlow 2.3.0. Pour calculer la perte, j'ai besoin que le y_predparamètre soit converti en un tableau numpy. Cependant, je ne trouve pas de moyen de le convertir <class 'tensorflow.python.framework.ops.Tensor'>en tableau numpy, même s'il semble que des fonctions TensorFlow le permettent.
Exemple de code
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)
donne le message d'erreur: AttributeError: 'Tensor' object has no attribute 'make_ndarrayaprès l'impression du type du y_predparamètre:<class 'tensorflow.python.framework.ops.Tensor'>
Ce que j'ai essayé jusqu'à présent
À la recherche d'une solution, j'ai trouvé que cela semble être un problème courant et il y a quelques suggestions, mais elles n'ont pas fonctionné pour moi jusqu'à présent:
1. "... alors appelez simplement .numpy () sur l'objet Tensor.": Comment puis-je convertir un tenseur en un tableau numpy dans TensorFlow?
alors j'ai essayé:
def custom_loss(y_true, y_pred):
npa = y_pred.numpy()
...
me donnant AttributeError: 'Tensor' object has no attribute 'numpy'
2. "Utilisez tensorflow.Tensor.eval () pour convertir un tenseur en tableau": Comment convertir un tenseur TensorFlow en tableau NumPy en Python
alors j'ai essayé:
def custom_loss(y_true, y_pred):
npa = y_pred.eval(session=tf.compat.v1.Session())
...
me donnant l'une des plus longues traces de messages d'erreur que j'ai jamais vues avec le noyau étant:
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) ]]
devoir également appeler les fonctions de compatibilité TensorFlow à partir de la version 1.x ne me semble pas très à l'épreuve du temps, donc je n'aime pas trop cette approche de toute façon.
3. En regardant les documents TensorFlow, il semblait y avoir la fonction dont j'avais besoin juste en attente: tf.make_ndarray Créer un ndarray numpy à partir d'un tenseur.
alors j'ai essayé:
def custom_loss(y_true, y_pred):
npa = tf.make_ndarray(y_pred)
...
me donnant AttributeError: 'Tensor' object has no attribute 'tensor_shape'
En regardant l'exemple dans la documentation TF, ils l'utilisent sur un proto_tensor, alors j'ai d'abord essayé de convertir en proto:
def custom_loss(y_true, y_pred):
proto_tensor = tf.make_tensor_proto(y_pred)
npa = tf.make_ndarray(proto_tensor)
...
mais déjà le tf.make_tensor_proto(y_pred)soulève l'erreur:TypeError: Expected any non-tensor type, got a tensor instead.
Essayer également de créer un tenseur const donne d'abord la même erreur:
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)
...
Il y a beaucoup plus de messages à ce sujet, mais il semble qu'ils reviennent tous à ces trois idées de base. Nous attendons vos suggestions avec plaisir!
Réponses
y_pred.numpy()fonctionne dans TF 2 mais AttributeError: 'Tensor' object has no attribute 'make_ndarrayindique qu'il y a des parties de votre code que vous n'exécutez pas en mode Eager car vous n'auriez pas autrement un Tensorobjet mais un EagerTensor.
Pour activer le mode Eager, placez ceci au début de votre code avant que quoi que ce soit dans le graphique ne soit construit:
tf.config.experimental_run_functions_eagerly(True)
Deuxièmement, lorsque vous compilez votre modèle, ajoutez ce paramètre:
model.compile(..., run_eagerly=True, ...)
Maintenant, vous exécutez en mode Eager et toutes les variables contiennent en fait des valeurs que vous pouvez à la fois imprimer et travailler. Sachez que le passage en mode Eager peut nécessiter des ajustements supplémentaires de votre code (voir ici pour un aperçu).