web-dev-qa-db-fra.com

Ce modèle n'a pas encore été construit d'erreur sur model.summary ()

J'ai un modèle de keras défini comme suit

class ConvLayer(Layer) :
    def __init__(self, nf, ks=3, s=2, **kwargs):
        self.nf = nf
        self.grelu = GeneralReLU(leak=0.01)
        self.conv = (Conv2D(filters     = nf,
                            kernel_size = ks,
                            strides     = s,
                            padding     = "same",
                            use_bias    = False,
                            activation  = "linear"))
        super(ConvLayer, self).__init__(**kwargs)

    def rsub(self): return -self.grelu.sub
    def set_sub(self, v): self.grelu.sub = -v
    def conv_weights(self): return self.conv.weight[0]

    def build(self, input_shape):
        # No weight to train.
        super(ConvLayer, self).build(input_shape)  # Be sure to call this at the end

    def compute_output_shape(self, input_shape):
        output_shape = (input_shape[0],
                        input_shape[1]/2,
                        input_shape[2]/2,
                        self.nf)
        return output_shape

    def call(self, x):
        return self.grelu(self.conv(x))

    def __repr__(self):
        return f'ConvLayer(nf={self.nf}, activation={self.grelu})'
class ConvModel(tf.keras.Model):
    def __init__(self, nfs, input_shape, output_shape, use_bn=False, use_dp=False):
        super(ConvModel, self).__init__(name='mlp')
        self.use_bn = use_bn
        self.use_dp = use_dp
        self.num_classes = num_classes

        # backbone layers
        self.convs = [ConvLayer(nfs[0], s=1, input_shape=input_shape)]
        self.convs += [ConvLayer(nf) for nf in nfs[1:]]
        # classification layers
        self.convs.append(AveragePooling2D())
        self.convs.append(Dense(output_shape, activation='softmax'))

    def call(self, inputs):
        for layer in self.convs: inputs = layer(inputs)
        return inputs

Je peux compiler ce modèle sans aucun problème

>>> model.compile(optimizer=tf.keras.optimizers.Adam(lr=lr), 
              loss='categorical_crossentropy',
              metrics=['accuracy'])

Mais quand je demande le résumé de ce modèle, je vois cette erreur

>>> model = ConvModel(nfs, input_shape=(32, 32, 3), output_shape=num_classes)
>>> model.summary()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-220-5f15418b3570> in <module>()
----> 1 model.summary()

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/network.py in summary(self, line_length, positions, print_fn)
   1575     """
   1576     if not self.built:
-> 1577       raise ValueError('This model has not yet been built. '
   1578                        'Build the model first by calling `build()` or calling '
   1579                        '`fit()` with some data, or specify '

ValueError: This model has not yet been built. Build the model first by calling `build()` or calling `fit()` with some data, or specify an `input_shape` argument in the first layer(s) for automatic build.

Je fournis input_shape pour la première couche de mon modèle, pourquoi lance cette erreur?

11
bachr
# X is a train dataset with features excluding a target variable

input_shape = X.shape  
model.build(input_shape) 
model.summary()
0
B. Kanani

Il existe une très grande différence entre le modèle de sous-classes de kéros et les autres modèles de kéros (séquentiel et fonctionnel).

Les modèles séquentiels et les modèles fonctionnels sont des infrastructures de données qui représentent un DAG de couches. En termes simples, le modèle fonctionnel ou séquentiel sont des graphiques statiques de couches construites en empilant les unes sur les autres comme LEGO. Ainsi, lorsque vous fournissez input_shape à la première couche, ces modèles (fonctionnels et séquentiels) peuvent déduire la forme de toutes les autres couches et créer un modèle. Vous pouvez ensuite imprimer des formes d'entrée/sortie à l'aide de model.summary ().

D'autre part, le modèle sous-classé est défini via le corps (une méthode d'appel) de Python. Pour le modèle sous-classé, il n'y a pas de graphique de couches ici. Nous ne pouvons pas savoir comment les couches sont connectées à les uns les autres (car cela est défini dans le corps de l'appel, pas comme une structure de données explicite), donc nous ne pouvons pas déduire les formes d'entrée/sortie. Donc, pour un modèle de sous-classe, la forme d'entrée/sortie nous est inconnue jusqu'à ce qu'elle soit testée avec données appropriées. Dans la méthode compile (), nous allons effectuer une compilation différée et attendre des données correctes. Pour qu'il puisse déduire la forme des couches intermédiaires, nous devons exécuter avec des données appropriées, puis utiliser model.summary () . Sans exécuter le modèle avec des données, il générera une erreur comme vous l'avez remarqué. Veuillez vérifier GitHub Gist pour le code complet.

Voici un exemple du site Web Tensorflow.

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

class ThreeLayerMLP(keras.Model):

  def __init__(self, name=None):
    super(ThreeLayerMLP, self).__init__(name=name)
    self.dense_1 = layers.Dense(64, activation='relu', name='dense_1')
    self.dense_2 = layers.Dense(64, activation='relu', name='dense_2')
    self.pred_layer = layers.Dense(10, name='predictions')

  def call(self, inputs):
    x = self.dense_1(inputs)
    x = self.dense_2(x)
    return self.pred_layer(x)

def get_model():
  return ThreeLayerMLP(name='3_layer_mlp')

model = get_model()

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255

model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              optimizer=keras.optimizers.RMSprop())

model.summary() # This will throw an error as follows
# ValueError: This model has not yet been built. Build the model first by calling `build()` or calling `fit()` with some data, or specify an `input_shape` argument in the first layer(s) for automatic build.

# Need to run with real data to infer shape of different layers
history = model.fit(x_train, y_train,
                    batch_size=64,
                    epochs=1)

model.summary()

J'espère que cela t'aides. Merci!