zoukankan      html  css  js  c++  java
  • 人工智能深度学习入门练习之(23)TensorFlow2教程-keras模型保存和序列化

     

    1 保存序列模型或函数式模型

    In [1]:
    # 构建一个简单的模型并训练
    from __future__ import absolute_import, division, print_function
    import tensorflow as tf
    tf.keras.backend.clear_session()
    from tensorflow import keras
    from tensorflow.keras import layers
    
    inputs = keras.Input(shape=(784,), name='digits')
    x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
    x = layers.Dense(64, activation='relu', name='dense_2')(x)
    outputs = layers.Dense(10, activation='softmax', name='predictions')(x)
    
    model = keras.Model(inputs=inputs, outputs=outputs, name='3_layer_mlp')
    model.summary()
    (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='sparse_categorical_crossentropy',
                  optimizer=keras.optimizers.RMSprop())
    history = model.fit(x_train, y_train,
                        batch_size=64,
                        epochs=1)
    
    predictions = model.predict(x_test)
    
     
    /home/doit/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
      from ._conv import register_converters as _register_converters
    
     
    Model: "3_layer_mlp"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    digits (InputLayer)          [(None, 784)]             0         
    _________________________________________________________________
    dense_1 (Dense)              (None, 64)                50240     
    _________________________________________________________________
    dense_2 (Dense)              (None, 64)                4160      
    _________________________________________________________________
    predictions (Dense)          (None, 10)                650       
    =================================================================
    Total params: 55,050
    Trainable params: 55,050
    Non-trainable params: 0
    _________________________________________________________________
    Train on 60000 samples
    60000/60000 [==============================] - 2s 28us/sample - loss: 0.3133
    
     

    1.1 保存整个模型

    可以对整个模型进行保存,其保持的内容包括:

    • 该模型的架构
    • 模型的权重(在训练期间学到的)
    • 模型的训练配置(传递给编译的)
    • 优化器及其状态(这使您可以从中断的地方重新启动训练)
    In [2]:
    import numpy as np
    # 模型保存
    model.save('the_save_model.h5')
    # 导入模型
    new_model = keras.models.load_model('the_save_model.h5')
    new_prediction = new_model.predict(x_test)
    np.testing.assert_allclose(predictions, new_prediction, atol=1e-6) # 预测结果一样
    
     

    1.2 导出为SavedModel文件

    SavedModel是Tensorflow对象的独立序列化格式,支持使用Tensorflow Serving server来部署模型,支持其他语言读取。

    In [4]:
    # 导出为tf的SavedModel文件
    model.save('save_model', save_format='tf')
    # 从SavedModel文件中导入模型
    new_model = keras.models.load_model('save_model')
    
    new_prediction = new_model.predict(x_test)
    np.testing.assert_allclose(predictions, new_prediction, atol=1e-6) # 预测结果一样
    
     
    W1013 16:41:11.934549 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.decay
    W1013 16:41:11.935179 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.learning_rate
    W1013 16:41:11.935569 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.momentum
    W1013 16:41:11.935910 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.rho
    W1013 16:41:11.936488 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-0.kernel
    W1013 16:41:11.937078 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-0.bias
    W1013 16:41:11.937702 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-1.kernel
    W1013 16:41:11.938094 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-1.bias
    W1013 16:41:11.938518 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-2.kernel
    W1013 16:41:11.938826 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-2.bias
    W1013 16:41:11.939161 140085562951488 util.py:152] A checkpoint was restored (e.g. tf.train.Checkpoint.restore or tf.keras.Model.load_weights) but not all checkpointed values were used. See above for specific issues. Use expect_partial() on the load status object, e.g. tf.train.Checkpoint.restore(...).expect_partial(), to silence these warnings, or use assert_consumed() to make the check explicit. See https://www.tensorflow.org/alpha/guide/checkpoints#loading_mechanics for details.
    W1013 16:41:11.940948 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer
    W1013 16:41:11.941336 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.iter
    W1013 16:41:11.941909 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.decay
    W1013 16:41:11.944620 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.learning_rate
    W1013 16:41:11.945564 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.momentum
    W1013 16:41:11.946080 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.rho
    W1013 16:41:11.946562 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-0.kernel
    W1013 16:41:11.946892 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-0.bias
    W1013 16:41:11.947290 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-1.kernel
    W1013 16:41:11.947617 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-1.bias
    W1013 16:41:11.947977 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-2.kernel
    W1013 16:41:11.948273 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-2.bias
    W1013 16:41:11.948586 140085562951488 util.py:152] A checkpoint was restored (e.g. tf.train.Checkpoint.restore or tf.keras.Model.load_weights) but not all checkpointed values were used. See above for specific issues. Use expect_partial() on the load status object, e.g. tf.train.Checkpoint.restore(...).expect_partial(), to silence these warnings, or use assert_consumed() to make the check explicit. See https://www.tensorflow.org/alpha/guide/checkpoints#loading_mechanics for details.
    
     

    SaveModel创建的文件包含:

    • 权重
    • 网络图
     

    1.3 仅保存网络结构

    仅保持网络结构,这样导出的模型并未包含训练好的参数

    In [5]:
    # 获取网络结构配置
    config = model.get_config()
    reinitialized_model = keras.Model.from_config(config)
    
    new_prediction = reinitialized_model.predict(x_test)
    assert abs(np.sum(predictions-new_prediction)) >0
    
     

    也可以使用json保存网络结构

    In [6]:
    # 将网络结构导出为json格式
    json_config = model.to_json()
    reinitialized_model = keras.models.model_from_json(json_config)
    
    new_prediction = reinitialized_model.predict(x_test)
    assert abs(np.sum(predictions-new_prediction)) >0
    
     

    1.4 仅保存网络权重参数

    In [7]:
    # 获取网络权重
    weights = model.get_weights()
    # 对网络权重进行赋值
    model.set_weights(weights)
    
     

    可以把结构和参数保存结合起来

    In [8]:
    config = model.get_config()
    weights = model.get_weights()
    
    new_model = keras.Model.from_config(config) # config只能用keras.Model的这个api
    new_model.set_weights(weights)
    
    new_predictions = new_model.predict(x_test)
    np.testing.assert_allclose(predictions, new_predictions, atol=1e-6)
    
     

    1.5 完整的模型保存方法

    In [10]:
    # 导出网络结构和权重
    json_config = model.to_json()
    with open('model_config.json', 'w') as json_file:
        json_file.write(json_config)
    model.save_weights('path_to_my_weights.h5')
    # 载入网络结构和权重
    with open('model_config.json') as json_file:
        json_config = json_file.read()
    new_model = keras.models.model_from_json(json_config)
    new_model.load_weights('path_to_my_weights.h5')
    
    new_predictions = new_model.predict(x_test)
    np.testing.assert_allclose(predictions, new_predictions, atol=1e-6)
    
    In [11]:
    # 当然也可以一步到位
    model.save('path_to_my_model.h5')
    del model
    model = keras.models.load_model('path_to_my_model.h5')
    
     
    W1013 16:49:21.690537 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer
    W1013 16:49:21.691003 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.iter
    W1013 16:49:21.691583 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.decay
    W1013 16:49:21.691886 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.learning_rate
    W1013 16:49:21.692354 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.momentum
    W1013 16:49:21.692843 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer.rho
    W1013 16:49:21.693265 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-0.kernel
    W1013 16:49:21.693663 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-0.bias
    W1013 16:49:21.693997 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-1.kernel
    W1013 16:49:21.694370 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-1.bias
    W1013 16:49:21.694779 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-2.kernel
    W1013 16:49:21.695171 140085562951488 util.py:144] Unresolved object in checkpoint: (root).optimizer's state 'rms' for (root).layer_with_weights-2.bias
    W1013 16:49:21.695466 140085562951488 util.py:152] A checkpoint was restored (e.g. tf.train.Checkpoint.restore or tf.keras.Model.load_weights) but not all checkpointed values were used. See above for specific issues. Use expect_partial() on the load status object, e.g. tf.train.Checkpoint.restore(...).expect_partial(), to silence these warnings, or use assert_consumed() to make the check explicit. See https://www.tensorflow.org/alpha/guide/checkpoints#loading_mechanics for details.
    
     

    1.6 权重保存格式

    有.h5或.keras后缀时保存为keras HDF5格式文件,否则默认为TensorFlow Checkpoint格式文件。可以使用save_format显式确定。

    In [12]:
    model.save_weights('weight_tf_savedmodel')
    model.save_weights('weight_tf_savedmodel.h5')
    
    In [13]:
    model.save_weights('weight_tf_savedmodel_tf', save_format='tf')
    model.save_weights('weight_tf_savedmodel_h5', save_format='h5')
    
     

    1.7 子类模型权重保存

    子类模型的结构无法保存和序列化,只能保持参数

    In [16]:
    # 构建模型
    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, activation='softmax', 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()
    
     

    首先,无法保存从未使用过的子类模型。

    这是因为需要在某些数据上调用子类模型才能创建其权重。

    In [17]:
    # 训练模型
    (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='sparse_categorical_crossentropy',
                  optimizer=keras.optimizers.RMSprop())
    history = model.fit(x_train, y_train,
                        batch_size=64,
                        epochs=1)
    
     
    Train on 60000 samples
    60000/60000 [==============================] - 2s 26us/sample - loss: 0.3128
    
     

    推荐的保存子类模型的方法是使用save_weights创建TensorFlow SavedModel检查点。

    该检查点将包含与模型关联的所有变量的值:

    • 图层的权重
    • 优化器的状态
    • 与有状态模型指标关联的任何变量
    In [18]:
    # 保持权重参数
    model.save_weights('my_model_weights', save_format='tf')
    
    # 输出结果,供后面对比
    
    predictions = model.predict(x_test)
    first_batch_loss = model.train_on_batch(x_train[:64], y_train[:64])
    
     

    要还原模型,将需要访问创建模型对象的代码。

    请注意,为了恢复优化器状态和任何有状态度量的状态,应该先编译模型(使用与以前完全相同的参数)。

    In [19]:
    # 读取保存的模型参数
    new_model = get_model()
    new_model.compile(loss='sparse_categorical_crossentropy',
                      optimizer=keras.optimizers.RMSprop())
    
    #new_model.train_on_batch(x_train[:1], y_train[:1])
    
    new_model.load_weights('my_model_weights')
    
    new_predictions = new_model.predict(x_test)
    np.testing.assert_allclose(predictions, new_predictions, atol=1e-6)
    
    
    new_first_batch_loss = new_model.train_on_batch(x_train[:64], y_train[:64])
    assert first_batch_loss == new_first_batch_loss
    
    In [ ]:
     
    作者:大码王

    -------------------------------------------

    个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!

    如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!

    万水千山总是情,打赏一分行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•?ω•?)っ???!

  • 相关阅读:
    输入和输出--java的NIO
    Java的NIO
    Java的nio
    输入和输出--java序列化机制
    输入和输出--javase中的路径
    输入和输出--重定向标准输入和输出
    输入和输出--RandomAccessFile类
    输入和输出--IO流
    输入和输出--File类
    无废话XML--DOM4J
  • 原文地址:https://www.cnblogs.com/huanghanyu/p/13845157.html
Copyright © 2011-2022 走看看