1
votes

Erreur "La couche n'est pas connectée, aucune entrée à renvoyer" lors de la tentative d'obtention de la prédiction de couche intermédiaire à l'aide du rappel personnalisé tensorflow

J'essaie d'accéder aux prédictions des couches intermédiaires d'un modèle pendant l'entraînement à l'aide d'un rappel personnalisé. La version simplifiée suivante du code actuel illustre le problème.

<ipython-input-3-635fd53dbffc> in on_epoch_end(self, epoch, logs)
     12     def on_epoch_end(self, epoch, logs=None):
     13         get_output = tf.keras.backend.function(
---> 14             inputs = self.model.layers[0].input,
     15             outputs = self.model.layers[0].output
     16         )
.
.
AttributeError: Layer dense is not connected, no input to return.

Le rappel est écrit comme suggéré dans ce réponse . Obtention de l'erreur suivante:

import tensorflow as tf
import numpy as np

class Model(tf.keras.Model):
    def __init__(self, input_shape=None, name="cus_model", **kwargs):
        super(Model, self).__init__(name=name, **kwargs)
        
    def build(self, input_shape):
        self.dense1 = tf.keras.layers.Dense(input_shape=input_shape, units=32)
        
    def call(self, input_tensor):
        return self.dense1(input_tensor)

class CustomCallback(tf.keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs=None):
        get_output = tf.keras.backend.function(
            inputs = self.model.layers[0].input,
            outputs = self.model.layers[0].output
        )
        print("Layer output: ",get_output.outputs)

X = np.ones((8,16))
y = np.sum(X, axis=1)

model = Model()
model.compile(optimizer='adam',loss='mean_squared_error', metrics='accuracy')
model.fit(X,y, epochs=8, callbacks=[CustomCallback()])

Qu'est-ce qui en est la cause? Comment le résoudre?


1 commentaires

L'approche fonctionnelle suggérée par @Marco Cerliani semble fonctionner correctement, mais j'aimerais savoir quel est le problème avec l'approche de sous-classification présentée dans la question.


3 Réponses :


1
votes

Je n'ai aucun problème à exécuter ceci:

import tensorflow as tf
import numpy as np

X = np.ones((8,16))
y = np.sum(X, axis=1)


class CustomCallback(tf.keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs=None):
        get_output = tf.keras.backend.function(
            inputs = self.model.layers[0].input,
            outputs = self.model.layers[1].output # return output of first dense
        )
        print("\nLayer output: ", get_output(X))


inp = tf.keras.layers.Input((16,))
dense1 = tf.keras.layers.Dense(units=32)(inp)
dense2 = tf.keras.layers.Dense(units=20)(dense1)
model = tf.keras.Model(inp, dense2)

model.compile(optimizer='adam',loss='mean_squared_error', metrics='accuracy')
model.fit(X,y, epochs=8, callbacks=[CustomCallback()])


0 commentaires

1
votes

Je ne peux pas non plus obtenir le self.layers [0] .input à cause de la même erreur, mais peut-être que vous pouvez appeler directement la fonction définie dans Model comme ceci: < pré> XXX


0 commentaires

0
votes

Je suppose qu'il y a une différence entre l ' API fonctionnelle et la sous-classification tf.keras.Model . Une réécriture de Dense serait également nécessaire. Au moins, cela fonctionne maintenant. Quiconque sait pourquoi, veuillez expliquer.

import tensorflow as tf
import numpy as np

class Model(tf.keras.Model):
    def __init__(self, inputs=None, name="cus_model", **kwargs):
        super(Model, self).__init__(name=name, **kwargs)
        self.inputs= inputs
        self.output_dim = 8

    def build(self, input_shape):
        #tf.keras.layers.Dense(input_shape=input_shape, units=32)
        self.dense1 = self.add_weight(name='weight_vector', shape=(input_shape[1], self.output_dim),
                                      initializer='glorot_uniform', trainable=True,
                                      regularizer=None)

    def call(self, input_tensor):
        return tf.matmul(self.dense1, input_tensor)

class CustomCallback(tf.keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs=None):
        get_output = tf.keras.backend.function(
            inputs = self.model.layers[0].input,
            outputs = self.model.layers[0].output
        )
        print("Layer output: ",get_output.outputs)

X = np.ones((10,8,16))
y = np.sum(X, axis=1)

print(X.shape,y.shape)

inp = tf.keras.layers.Input((8, 16))
model = Model(inp)
# model.compile(optimizer='adam',loss='mean_squared_error', metrics='accuracy')
# model.fit(X,y, epochs=8, callbacks=[CustomCallback()])

optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
loss_fn = tf.keras.losses.BinaryCrossentropy(from_logits=False)

for i in range(X.shape[0]):
    with tf.GradientTape() as tape:
        out = model(X[i, :])
        label = tf.cast(y[i], dtype=tf.float32)
        loss = loss_fn(label, out)
        grads = tape.gradient(loss, model.trainable_weights)
        optimizer.apply_gradients(zip(grads, model.trainable_weights))
        print("step: ", i, "loss:", loss.numpy())


0 commentaires