在自定义 keras.Model 类中定义模型时,为什么 keras.models.save_model() 方法不保存权重?

问题描述 投票:0回答:1

我正在尝试训练、保存和加载在继承自 keras.Model 的自定义类中定义的模型。 定义和训练运行良好。我将训练后的模型保存为“.keras”格式。当我加载模型时,架构被保留,但每层的权重丢失。这是重现该问题的代码示例:

import tensorflow as tf
import numpy as np

@tf.keras.utils.register_keras_serializable()
class dummyModel(tf.keras.Model):

    def __init__(self, dense_size, **kwargs):
        
        self.dense_size = dense_size
        super().__init__(**kwargs) 

  
    def build(self):
        self.layer1 = tf.keras.layers.Dense(self.dense_size) 
        self.layer2 = tf.keras.layers.Dense(self.dense_size)

    def call(self, inputs):
        x = self.layer1(inputs)
        out = self.layer2(x)
        return out
    
        
    def get_config(self):
        config = super().get_config()
        config.update({
            'dense_size': self.dense_size
        }) 
        return config
      

input = tf.random.normal((100,100,1))
output = tf.random.normal((100,100,1))

model = dummyModel(10) 

model.compile(optimizer='adam', loss='mse')
model.fit(input, output, epochs=10, batch_size=10)

tf.keras.models.save_model(model, 'dummy.keras')

modelSaved = tf.keras.models.load_model('dummy.keras')

assert model.to_json() == modelSaved.to_json(), "Model architectures are different"

for layer1, layer2 in zip(model.layers, modelSaved.layers):
    weights1 = layer1.get_weights()
    weights2 = layer2.get_weights()
    if weights1 != []: 
        assert weights2, f"{layer2.name} of loaded model has empty weight list" 
    for w1, w2 in zip(weights1, weights2):
        assert np.array_equal(w1, w2), f"Weigths of {layer1.name} are different."

print("Models are identical (architecture and weigths).")

代码抛出此断言错误:

AssertionError                            Traceback (most recent call last)

<ipython-input-10-3ff24dc35a83> in <cell line: 46>()
     48     weights2 = layer2.get_weights()
     49     if weights1 != []:
---> 50         assert weights2, f"{layer2.name} of loaded model has empty weight list"
     51     for w1, w2 in zip(weights1, weights2):
     52         assert np.array_equal(w1, w2), f"Weigths of {layer1.name} are different."

AssertionError: dense_2 of loaded model has empty weight list

我尝试使用 keras.Sequential 模型或功能 API,并且权重已正确保存。当使用适当的

get_config()
方法在自定义类中定义模型时,不会保存任何权重。我对 keras 框架相对较新,我可能会错过这里的一个关键概念。

这是具有相同代码的协作链接:

https://colab.research.google.com/drive/1H47N77k5skn9CXp4ijx3sMhGy2EL5iAd#scrollTo=0xy_DDNNO2So

python tensorflow keras
1个回答
0
投票

嗨,我之前在自定义层/模型的序列化方面也遇到过类似的问题。

我不知道您使用的是哪个 tf 版本,但在某些版本中您无法使用 .keras 扩展名来保存整个模型,而应该使用另一个扩展名,例如 .ml 。我还建议,如果您使用 ModelCheckpoint,请始终将标志 save_weights_only 设置为 True 或 False,以便您确定保存的内容。

序列化始终是一个令人头疼的问题,因此我过去几个月所做的和一直在努力的就是仅保存模型的权重(这里没有序列化问题),然后创建模型的新实例任何我想要的地方并导入权重。

如果您确实想出于某种原因保存整个模型,我发现您没有进行任何序列化,也没有显式的反序列化 from_config() 类方法。

任何非经典类型,例如 int、float...都需要序列化/反序列化,这包括您的 Dense 层。

有关更多信息,请访问 https://keras.io/guides/serialization_and_ saving/

© www.soinside.com 2019 - 2024. All rights reserved.