Conversione del tensore TensorFlow in un array Numpy

Sep 13 2020

Descrizione del problema

Sto cercando di scrivere una funzione di perdita personalizzata in TensorFlow 2.3.0. Per calcolare la perdita, ho bisogno che il y_predparametro venga convertito in un array numpy. Tuttavia, non riesco a trovare un modo per convertirlo da <class 'tensorflow.python.framework.ops.Tensor'>a numpy array, anche se sembra che le funzioni TensorFlow lo facciano.

Esempio di codice

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)

dà il messaggio di errore: AttributeError: 'Tensor' object has no attribute 'make_ndarraydopo aver stampato il tipo di y_predparametro:<class 'tensorflow.python.framework.ops.Tensor'>

Quello che ho provato finora

Alla ricerca di una soluzione ho scoperto che questo sembra essere un problema comune e ci sono un paio di suggerimenti, ma finora non hanno funzionato per me:

1. "... quindi chiama .numpy () sull'oggetto Tensor.": Come posso convertire un tensore in un array numpy in TensorFlow?

quindi ho provato:

def custom_loss(y_true, y_pred):
    npa = y_pred.numpy()
    ...

dandomi AttributeError: 'Tensor' object has no attribute 'numpy'

2. "Usa tensorflow.Tensor.eval () per convertire un tensore in un array": Come convertire un tensore TensorFlow in un array NumPy in Python

quindi ho provato:

def custom_loss(y_true, y_pred):
    npa = y_pred.eval(session=tf.compat.v1.Session())
    ...

dandomi una delle tracce più lunghe di messaggi di errore che abbia mai visto con il nucleo di:

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) ]]

anche dover chiamare le funzioni di compatibilità TensorFlow dalla versione 1.x non sembra molto a prova di futuro, quindi non mi piace molto questo approccio comunque.

3. Guardando i documenti di TensorFlow sembrava esserci la funzione di cui avevo bisogno solo in attesa: tf.make_ndarray Crea un numpy ndarray da un tensore.

quindi ho provato:

def custom_loss(y_true, y_pred):
    npa = tf.make_ndarray(y_pred)
    ...

dandomi AttributeError: 'Tensor' object has no attribute 'tensor_shape'

Guardando l'esempio nella documentazione di TF lo usano su un proto_tensor, quindi ho provato prima a convertirlo in un proto:

def custom_loss(y_true, y_pred):
    proto_tensor = tf.make_tensor_proto(y_pred)
    npa = tf.make_ndarray(proto_tensor)
    ...

ma già il tf.make_tensor_proto(y_pred)solleva l'errore:TypeError: Expected any non-tensor type, got a tensor instead.

Anche provare a creare prima un tensore const dà lo stesso errore:

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)
    ...

Ci sono molti altri post su questo argomento, ma sembra che stiano tutti tornando su queste tre idee di base. In attesa dei tuoi suggerimenti!

Risposte

runDOSrun Sep 13 2020 at 17:11

y_pred.numpy()funziona in TF 2 ma AttributeError: 'Tensor' object has no attribute 'make_ndarrayindica che ci sono parti del codice che non stai eseguendo in modalità Eager poiché altrimenti non avresti un Tensoroggetto ma un file EagerTensor.

Per abilitare la modalità Eager, inseriscilo all'inizio del codice prima di creare qualsiasi cosa nel grafico:

tf.config.experimental_run_functions_eagerly(True)

Secondo, quando compili il tuo modello, aggiungi questo parametro:

model.compile(..., run_eagerly=True, ...)

Ora stai eseguendo in modalità Eager e tutte le variabili contengono effettivamente valori che puoi sia stampare che lavorare. Tieni presente che il passaggio alla modalità Eager potrebbe richiedere ulteriori modifiche al tuo codice (vedi qui per una panoramica).