Python 使用自定义图层保存Keras模型

Python 使用自定义图层保存Keras模型,python,tensorflow,keras,save,Python,Tensorflow,Keras,Save,我正在尝试将Keras模型保存在H5文件中。Keras模型有一个自定义层。 当我尝试恢复模型时,出现以下错误: --------------------------------------------------------------------------- ValueError回溯(最近一次调用上次) 在() 1.save型号('model.h5') 2-del模型 ---->3模型=tf.keras.models.load_模型('model.h5')) 8帧 /usr/local/li

我正在尝试将Keras模型保存在H5文件中。Keras模型有一个自定义层。 当我尝试恢复模型时,出现以下错误:

---------------------------------------------------------------------------
ValueError回溯(最近一次调用上次)
在()
1.save型号('model.h5')
2-del模型
---->3模型=tf.keras.models.load_模型('model.h5'))
8帧
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/utils/generic_utils.py类中的usr/local/lib/python3.6/dist-packages
319 cls=获取注册对象(类名称、自定义对象、模块对象)
320如果cls为无:
-->321提升值错误('Unknown'+可打印模块名称+':'+类名称)
322
323 cls_config=config['config']
ValueError:未知图层:CustomLayer
您能告诉我如何保存和加载所有自定义Keras层的重量吗?(另外,保存时没有警告,是否可以从我已经保存但现在无法加载的H5文件加载模型?)

以下是此错误的最小工作代码示例(MCVE)以及完整的扩展消息:

为了完整起见,这是我用来制作自定义图层的代码。
get_config
from_config
都工作正常

class自定义层(tf.keras.layers.Layer):
定义初始化(self,k,name=None):
超级(CustomLayer,self)。\uuuuu init\uuuuuu(name=name)
self.k=k
def get_配置(自身):
返回{'k':self.k}
def呼叫(自我,输入):
返回tf.multiply(输入,2)
模型=tf.keras.models.Sequential([
tf.keras.Input(name='Input_layer',shape=(10,),
CustomLayer(10,name='custom_layer'),
致密(1,激活='sigmoid',名称='output\u layer')
])
model.save('model.h5')
model=tf.keras.models.load_model('model.h5'))

更正编号1是在
加载
保存的模型时使用
自定义对象
,即更换代码

new_model = tf.keras.models.load_model('model.h5') 

由于我们使用
自定义层
构建
模型
,在
保存它之前,我们应该在
加载它时使用
自定义对象

修正号2是在自定义层的
\uuuuu init\uuuuu
函数中添加
**kwargs
,如

def __init__(self, k, name=None, **kwargs):
        super(CustomLayer, self).__init__(name=name)
        self.k = k
        super(CustomLayer, self).__init__(**kwargs)
完整的工作代码如下所示:

import tensorflow as tf

class CustomLayer(tf.keras.layers.Layer):
    def __init__(self, k, name=None, **kwargs):
        super(CustomLayer, self).__init__(name=name)
        self.k = k
        super(CustomLayer, self).__init__(**kwargs)


    def get_config(self):
        config = super(CustomLayer, self).get_config()
        config.update({"k": self.k})
        return config

    def call(self, input):
        return tf.multiply(input, 2)

model = tf.keras.models.Sequential([
    tf.keras.Input(name='input_layer', shape=(10,)),
    CustomLayer(10, name='custom_layer'),
    tf.keras.layers.Dense(1, activation='sigmoid', name='output_layer')
])
tf.keras.models.save_model(model, 'model.h5')
new_model = tf.keras.models.load_model('model.h5', custom_objects={'CustomLayer': CustomLayer})

print(new_model.summary())
WARNING:tensorflow:No training configuration found in the save file, so the model was *not* compiled. Compile it manually.
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
custom_layer_1 (CustomLayer) (None, 10)                0         
_________________________________________________________________
output_layer (Dense)         (None, 1)                 11        
=================================================================
Total params: 11
Trainable params: 11
Non-trainable params: 0
上述代码的输出如下所示:

import tensorflow as tf

class CustomLayer(tf.keras.layers.Layer):
    def __init__(self, k, name=None, **kwargs):
        super(CustomLayer, self).__init__(name=name)
        self.k = k
        super(CustomLayer, self).__init__(**kwargs)


    def get_config(self):
        config = super(CustomLayer, self).get_config()
        config.update({"k": self.k})
        return config

    def call(self, input):
        return tf.multiply(input, 2)

model = tf.keras.models.Sequential([
    tf.keras.Input(name='input_layer', shape=(10,)),
    CustomLayer(10, name='custom_layer'),
    tf.keras.layers.Dense(1, activation='sigmoid', name='output_layer')
])
tf.keras.models.save_model(model, 'model.h5')
new_model = tf.keras.models.load_model('model.h5', custom_objects={'CustomLayer': CustomLayer})

print(new_model.summary())
WARNING:tensorflow:No training configuration found in the save file, so the model was *not* compiled. Compile it manually.
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
custom_layer_1 (CustomLayer) (None, 10)                0         
_________________________________________________________________
output_layer (Dense)         (None, 1)                 11        
=================================================================
Total params: 11
Trainable params: 11
Non-trainable params: 0

希望这有帮助。学习愉快

您可以在回答中提到的
load\u model
方法中手动提供映射
custom\u对象
,但当您有许多自定义层(或定义了任何自定义可调用项,例如度量、损失、优化器等)时,这可能会很繁琐

Tensorflow提供了一个utils函数来自动执行此操作:

您必须按如下方式更新
CustomLayer

将tensorflow导入为tf
@tf.keras.utils.register_keras_serializable()
类CustomLayer(tf.keras.layers.Layer):
定义初始值(self,k,**kwargs):
self.k=k
超级(自定义层,自我)。\uuuuu初始化(**kwargs)
def get_配置(自身):
config=super()
config[“k”]=self.k
返回配置
def呼叫(自我,输入):
返回tf.multiply(输入,2)

以下是完整的工作代码:

import tensorflow as tf


@tf.keras.utils.register_keras_serializable()
class CustomLayer(tf.keras.layers.Layer):
    def __init__(self, k, **kwargs):
        self.k = k
        super(CustomLayer, self).__init__(**kwargs)

    def get_config(self):
        config = super().get_config()
        config["k"] = self.k
        return config

    def call(self, input):
        return tf.multiply(input, 2)


def main():
    model = tf.keras.models.Sequential(
        [
            tf.keras.Input(name='input_layer', shape=(10,)),
            CustomLayer(10, name='custom_layer'),
            tf.keras.layers.Dense(1, activation='sigmoid', name='output_layer')
        ]
    )
    print("SUMMARY OF THE MODEL CREATED")
    print("-" * 60)
    print(model.summary())
    model.save('model.h5')

    del model

    print()
    print()

    model = tf.keras.models.load_model('model.h5')
    print("SUMMARY OF THE MODEL LOADED")
    print("-" * 60)
    print(model.summary())

if __name__ == "__main__":
    main()
以及相应的输出:

SUMMARY OF THE MODEL CREATED
------------------------------------------------------------
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
custom_layer (CustomLayer)   (None, 10)                0         
_________________________________________________________________
output_layer (Dense)         (None, 1)                 11        
=================================================================
Total params: 11
Trainable params: 11
Non-trainable params: 0
_________________________________________________________________
None


WARNING:tensorflow:No training configuration found in the save file, so the model was *not* compiled. Compile it manually.
SUMMARY OF THE MODEL LOADED
------------------------------------------------------------
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
custom_layer (CustomLayer)   (None, 10)                0         
_________________________________________________________________
output_layer (Dense)         (None, 1)                 11        
=================================================================
Total params: 11
Trainable params: 11
Non-trainable params: 0
_________________________________________________________________
None

是的,我看到了,我照上面说的做了,对吧?我已经实现了
get_config
from_config
函数。但是他们从不保存整个模型,他们总是只保存权重。@AnimeshSinha,这个错误可以通过将
model=tf.keras.models.load\u model('model.h5')
替换为
tf.keras.models.load\u model('model.h5',custom\u objects={'CustomLayer':CustomLayer})
来解决。但是,这会导致其他错误。您的Google Colab无法访问。请你提供访问权限,以便我可以帮助你。谢谢抱歉@TensorflowWarriors,修复了链接。我将尝试自定义对象。@AnimeshSinha,请确认使用
自定义对象
是否解决了您的问题。您好,使用给定的自定义层保存模型是否需要更正2?谢谢