web-dev-qa-db-fra.com

Impossible d'enregistrer le modèle de sous-classe personnalisé

Inspiré par tf.keras.Model subclassing J'ai créé un modèle personnalisé.
Je peux l'entraîner et obtenir des résultats réussis, mais je ne peux pas l'enregistrer .
J'utilise python3.6 avec tensorflow v1.10 (ou v1.9)

Exemple de code complet minimal ici:

import tensorflow as tf
from tensorflow.keras.datasets import mnist


class Classifier(tf.keras.Model):
    def __init__(self):
        super().__init__(name="custom_model")

        self.batch_norm1 = tf.layers.BatchNormalization()
        self.conv1 = tf.layers.Conv2D(32, (7, 7))
        self.pool1 = tf.layers.MaxPooling2D((2, 2), (2, 2))

        self.batch_norm2 = tf.layers.BatchNormalization()
        self.conv2 = tf.layers.Conv2D(64, (5, 5))
        self.pool2 = tf.layers.MaxPooling2D((2, 2), (2, 2))

    def call(self, inputs, training=None, mask=None):
        x = self.batch_norm1(inputs)
        x = self.conv1(x)
        x = tf.nn.relu(x)
        x = self.pool1(x)

        x = self.batch_norm2(x)
        x = self.conv2(x)
        x = tf.nn.relu(x)
        x = self.pool2(x)

        return x


if __name__ == '__main__':
    (x_train, y_train), (x_test, y_test) = mnist.load_data()

    x_train = x_train.reshape(*x_train.shape, 1)[:1000]
    y_train = y_train.reshape(*y_train.shape, 1)[:1000]

    x_test = x_test.reshape(*x_test.shape, 1)
    y_test = y_test.reshape(*y_test.shape, 1)

    y_train = tf.keras.utils.to_categorical(y_train)
    y_test = tf.keras.utils.to_categorical(y_test)

    model = Classifier()

    inputs = tf.keras.Input((28, 28, 1))

    x = model(inputs)
    x = tf.keras.layers.Flatten()(x)
    x = tf.keras.layers.Dense(10, activation="sigmoid")(x)

    model = tf.keras.Model(inputs=inputs, outputs=x)
    model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
    model.fit(x_train, y_train, epochs=1, shuffle=True)

    model.save("./my_model")

Message d'erreur:

1000/1000 [==============================] - 1s 1ms/step - loss: 4.6037 - acc: 0.7025
Traceback (most recent call last):
  File "/home/user/Data/test/python/mnist/mnist_run.py", line 62, in <module>
    model.save("./my_model")
  File "/home/user/miniconda3/envs/ml3.6/lib/python3.6/site-packages/tensorflow/python/keras/engine/network.py", line 1278, in save
    save_model(self, filepath, overwrite, include_optimizer)
  File "/home/user/miniconda3/envs/ml3.6/lib/python3.6/site-packages/tensorflow/python/keras/engine/saving.py", line 101, in save_model
    'config': model.get_config()
  File "/home/user/miniconda3/envs/ml3.6/lib/python3.6/site-packages/tensorflow/python/keras/engine/network.py", line 1049, in get_config
    layer_config = layer.get_config()
  File "/home/user/miniconda3/envs/ml3.6/lib/python3.6/site-packages/tensorflow/python/keras/engine/network.py", line 1028, in get_config
    raise NotImplementedError
NotImplementedError

Process finished with exit code 1

J'ai regardé dans la ligne d'erreur et j'ai découvert que get_config vérifie la méthode self._is_graph_network

Quelqu'un s'occupe-t-il de ce problème?

Merci!

Mise à jour 1:
Sur les keras 2.2.2 (pas tf.keras)
Commentaire trouvé (pour l'enregistrement du modèle)
Fichier : keras/engine/network.py
Fonction: get_config

# Les réseaux sous-classés ne sont pas sérialisables
# (sauf si la sérialisation est implémentée par
# l'auteur du réseau sous-classé).

Alors, évidemment, ça ne marchera pas ...
Je me demande, pourquoi ne le signalent-ils pas dans la documentation (comme: "Utiliser le sous-classement sans possibilité de sauvegarde!")

Mise à jour 2:
Trouvé dans documentation keras :

Dans les modèles sous-classés, la topologie du modèle est définie comme Python
(plutôt que comme un graphique statique de couches). Cela signifie que le modèle est
La topologie ne peut pas être inspectée ou sérialisée. En conséquence, les éléments suivants
Les méthodes et attributs ne sont pas disponibles pour les modèles sous-classés:

model.inputs et model.outputs.
model.to_yaml () et model.to_json ()
model.get_config () et model.save ().

Il n'y a donc aucun moyen d'enregistrer le modèle en utilisant le sous-classement.
Il est possible d'utiliser uniquement Model.save_weights()

13
RedEyed

Cette réponse est pour Tensorflow 2.0

TL; DR:

  1. n'utilisez pas model.save() pour le modèle de keras de sous-classe personnalisé;
  2. utilisez à la place save_weights() et load_weights().

Avec l'aide de l'équipe Tensorflow, il s'avère que la meilleure pratique pour enregistrer un modèle Keras de sous-classe personnalisé consiste à enregistrer ses poids et à le recharger en cas de besoin.

La raison pour laquelle nous ne pouvons pas simplement enregistrer un modèle de sous-classe personnalisé Keras est qu'il contient des codes personnalisés, qui ne peuvent pas être sérialisés en toute sécurité. Cependant, les poids peuvent être enregistrés/chargés lorsque nous avons la même structure de modèle et les codes personnalisés sans aucun problème.

Il y a un excellent tutoriel écrit par François Chollet qui est l'auteur de Keras, pour savoir comment enregistrer/charger des modèles de sous-classe séquentiels/fonctionnels/Keras/personnalisés dans Tensorflow 2.0 dans Colab à ici . Dans la section Enregistrement des modèles sous-classés , il est indiqué que:

Les modèles séquentiels et les modèles fonctionnels sont des infrastructures de données qui représentent un DAG de couches. En tant que tels, ils peuvent être sérialisés et désérialisés en toute sécurité.

Un modèle sous-classé diffère en ce qu'il n'est pas une structure de données, c'est un morceau de code. L'architecture du modèle est définie via le corps de la méthode d'appel. Cela signifie que l'architecture du modèle ne peut pas être sérialisée en toute sécurité. Pour charger un modèle, vous devez avoir accès au code qui l'a créé (le code de la sous-classe de modèle). Alternativement, vous pouvez sérialiser ce code en bytecode (par exemple via le décapage), mais ce n'est pas sûr et généralement pas portable.

14
Huan

Cela sera corrigé dans une prochaine version selon les 1.13 notes de mise à jour pré-version :

  • Keras & Python:
    • Les modèles Keras sous-classés peuvent désormais être enregistrés via tf.contrib.saved_model.save_keras_model.

EDIT: Il semble que ce ne soit pas aussi fini que les notes le suggèrent. Les documents pour cette fonction pour v1.1 indiquent:

Limitations du modèle: - Les modèles séquentiels et fonctionnels peuvent toujours être enregistrés. - Les modèles sous-classés ne peuvent être enregistrés que lorsque serve_only = True. Cela est dû à l'implémentation actuelle qui copie le modèle afin d'exporter les graphiques de formation et d'évaluation. Étant donné que la topologie des modèles sous-classés ne peut pas être déterminée, les modèles sous-classés ne peuvent pas être clonés. Les modèles sous-classés seront entièrement exportables à l'avenir.

6
qwitwa

utilisation model.predict avant tf.saved_model.save

0
Antoine Liutkus