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?
# X is a train dataset with features excluding a target variable
input_shape = X.shape
model.build(input_shape)
model.summary()
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!