我正在尝试训练、保存和加载在继承自 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
嗨,我之前在自定义层/模型的序列化方面也遇到过类似的问题。
我不知道您使用的是哪个 tf 版本,但在某些版本中您无法使用 .keras 扩展名来保存整个模型,而应该使用另一个扩展名,例如 .ml 。我还建议,如果您使用 ModelCheckpoint,请始终将标志 save_weights_only 设置为 True 或 False,以便您确定保存的内容。
序列化始终是一个令人头疼的问题,因此我过去几个月所做的和一直在努力的就是仅保存模型的权重(这里没有序列化问题),然后创建模型的新实例任何我想要的地方并导入权重。
如果您确实想出于某种原因保存整个模型,我发现您没有进行任何序列化,也没有显式的反序列化 from_config() 类方法。
任何非经典类型,例如 int、float...都需要序列化/反序列化,这包括您的 Dense 层。
有关更多信息,请访问 https://keras.io/guides/serialization_and_ saving/