代码之家  ›  专栏  ›  技术社区  ›  RedEyed

无法保存自定义子类模型

  •  9
  • RedEyed  · 技术社区  · 8 年前

    灵感来自 tf.keras.Model subclassing
    我可以训练它并获得成功的结果,但是 .
    我用python3.6和tensorflow v1.10(或v1.9)

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

    错误消息:

    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
    

    我查了一下错误线,发现 获取配置 自我是图形网络

    有人处理这个问题吗?

    更新1:

    找到注释(用于模型保存)
    文件:keras/engine/network.py

    #子类网络不可序列化
    #(除非序列化是由
    #子类网络的作者)。


    我想知道,为什么他们不在 documentation (例如:“使用没有保存能力的子类!”)


    发现于 keras documentation

    在子类模型中,模型的拓扑被定义为Python代码
    (而不是静态的图层图)。也就是说模特
    无法检查或序列化拓扑。因此,以下
    方法和属性不可用于子类模型:


    model.to_yaml()和model.to_json()
    model.get_config()和model.save()。

    所以,没有办法通过使用子类来保存模型。
    Model.save_weights()

    2 回复  |  直到 8 年前
        1
  •  18
  •   Huan    7 年前

    这个答案适用于Tensorflow 2.0

    TL;博士:

    1. 不使用 model.save()
    2. 使用 save_weights() 和 load_weights()

    在Tensorflow团队的帮助下,保存自定义子类Keras模型的最佳实践是保存其权重,并在需要时将其重新加载。

    我们不能简单地保存Keras自定义子类模型的原因是它包含自定义代码,这些代码不能安全地序列化。但是,当我们拥有相同的模型结构和自定义代码时,权重可以被保存/加载,没有任何问题。

    关于如何在Colab的Tensorflow 2.0中保存/加载Sequential/Functional/Keras/Custom子类模型,Keras的作者Francois Chollet编写了一个很棒的教程 here . 在 保存子类模型 它说:

    序列模型和功能模型是表示层的DAG的数据结构。因此,它们可以安全地序列化和反序列化。

    一段代码。模型的体系结构是通过主体定义的 调用方法的。这意味着模型的架构 无法安全序列化。要加载模型,您需要 或者,可以将此代码序列化为字节码(例如。 但这是不安全的,而且通常不便于携带。

        2
  •  6
  •   qwitwa    7 年前

    1.13 pre-release patch notes :

      • 子类Keras模型现在可以通过 tf.contrib.saved_model.save_keras_model

    编辑: 这件事似乎没有笔记上说的那么彻底。这个 docs for that function for v1.13

    模型限制:始终可以保存顺序和功能模型。-子类模型只能在服务于'u only=True时保存。这是由于当前的实现为了导出培训和评估图而复制了模型。由于无法确定子类模型的拓扑,因此无法克隆子类模型。子类模型将来将完全可导出。

        3
  •  0
  •   Antoine Liutkus    6 年前

    model.predict 之前 tf.saved_model.save