我有一个使用新的tensorflow 2.0并混合keras和tensorflow制作的大型自定义模型。我要保存它(体系结构和权重)。 复制的确切命令:
import tensorflow as tf
OUTPUT_CHANNELS = 3
def downsample(filters, size, apply_batchnorm=True):
initializer = tf.random_normal_initializer(0., 0.02)
result = tf.keras.Sequential()
result.add(
tf.keras.layers.Conv2D(filters, size, strides=2, padding='same',
kernel_initializer=initializer, use_bias=False))
if apply_batchnorm:
result.add(tf.keras.layers.BatchNormalization())
result.add(tf.keras.layers.LeakyReLU())
return result
def upsample(filters, size, apply_dropout=False):
initializer = tf.random_normal_initializer(0., 0.02)
result = tf.keras.Sequential()
result.add(
tf.keras.layers.Conv2DTranspose(filters, size, strides=2,
padding='same',
kernel_initializer=initializer,
use_bias=False))
result.add(tf.keras.layers.BatchNormalization())
if apply_dropout:
result.add(tf.keras.layers.Dropout(0.5))
result.add(tf.keras.layers.ReLU())
return result
def Generator():
down_stack = [
downsample(64, 4, apply_batchnorm=False), # (bs, 128, 128, 64)
downsample(128, 4), # (bs, 64, 64, 128)
downsample(256, 4), # (bs, 32, 32, 256)
downsample(512, 4), # (bs, 16, 16, 512)
downsample(512, 4), # (bs, 8, 8, 512)
downsample(512, 4), # (bs, 4, 4, 512)
downsample(512, 4), # (bs, 2, 2, 512)
downsample(512, 4), # (bs, 1, 1, 512)
]
up_stack = [
upsample(512, 4, apply_dropout=True), # (bs, 2, 2, 1024)
upsample(512, 4, apply_dropout=True), # (bs, 4, 4, 1024)
upsample(512, 4, apply_dropout=True), # (bs, 8, 8, 1024)
upsample(512, 4), # (bs, 16, 16, 1024)
upsample(256, 4), # (bs, 32, 32, 512)
upsample(128, 4), # (bs, 64, 64, 256)
upsample(64, 4), # (bs, 128, 128, 128)
]
initializer = tf.random_normal_initializer(0., 0.02)
last = tf.keras.layers.Conv2DTranspose(OUTPUT_CHANNELS, 4,
strides=2,
padding='same',
kernel_initializer=initializer,
activation='tanh') # (bs, 256, 256, 3)
concat = tf.keras.layers.Concatenate()
inputs = tf.keras.layers.Input(shape=[None,None,3])
x = inputs
# Downsampling through the model
skips = []
for down in down_stack:
x = down(x)
skips.append(x)
skips = reversed(skips[:-1])
# Upsampling and establishing the skip connections
for up, skip in zip(up_stack, skips):
x = up(x)
x = concat([x, skip])
x = last(x)
return tf.keras.Model(inputs=inputs, outputs=x)
generator = Generator()
generator.summary()
generator.save('generator.h5')
generator_loaded = tf.keras.models.load_model('generator.h5')
我设法通过以下方式保存模型:
generator.save('generator.h5')
但是当我尝试加载时:
generator_loaded = tf.keras.models.load_model('generator.h5')
它永远不会结束(无错误消息)。型号是否太大?我尝试使用model.to_json()
以及完整的API tf.keras.models.save_model()
另存为JSON,但存在相同的问题,无法加载(或至少太长)。
在Windows / Linux和带有/不带有GPU的问题。
在完整的Keras和简单的模型中,保存和恢复效果很好。
答案 0 :(得分:0)
尝试将模型另存为:
model.save('model_name.model')
然后加载:
model = tf.keras.models.load_model('model_name.model')
答案 1 :(得分:0)
保存训练模型的另一种方法是在python中使用pickle
模块。
import pickle
pickle.dump(model, open(filename, 'wb'))
为了加载pickled
模型,
loaded_model = pickle.load(open(filename, 'rb'))
泡菜文件的扩展名通常为.sav
答案 2 :(得分:0)
我找到了一个临时解决方案。
似乎问题出在顺序API tf.keras.Sequential
上,通过使用功能性API,tf.keras.models.load_model
设法加载保存的模型。
我希望他们能在最终版本中解决此问题,看看我在github https://github.com/tensorflow/tensorflow/issues/28281中提出的问题。
干杯
答案 3 :(得分:0)
我通过在Keras中实现与顺序模型相似的功能来设法保存和加载自定义模型。
关键功能是CustomModel.get_config()
CustomModel.from_config()
,它也应该存在于您的任何自定义层中(类似于下面的功能,但是如果您想更好地理解,请参见keras层):
# In the CustomModel class
def get_config(self):
layer_configs = []
for layer in self.layers:
layer_configs.append({
'class_name': layer.__class__.__name__,
'config': layer.get_config()
})
config = {
'name': self.name,
'layers': copy.deepcopy(layer_configs),
"arg1": self.arg1,
...
}
if self._build_input_shape:
config['build_input_shape'] = self._build_input_shape
return config
@classmethod
def from_config(cls, config, custom_objects=None):
from tensorflow.python.keras import layers as layer_module
if custom_objects is None:
custom_objects = {'CustomLayer1Class': CustomLayer1Class, ...}
else:
custom_objects = dict(custom_objects, **{'CustomLayer1Class': CustomLayer1Class, ...})
if 'name' in config:
name = config['name']
build_input_shape = config.get('build_input_shape')
layer_configs = config['layers']
else:
name = None
build_input_shape = None
layer_configs = config
model = cls(name=name,
arg1=config['arg1'],
should_build_graph=False,
...)
for layer_config in tqdm(layer_configs, 'Loading Layers'):
layer = layer_module.deserialize(layer_config,
custom_objects=custom_objects)
model.add(layer) # This function looks at the name of the layers to place them in the right order
if not model.inputs and build_input_shape:
model.build(build_input_shape)
if not model._is_graph_network:
# Still needs to be built when passed input data.
model.built = False
return model
我还添加了一个CustomModel.add()
函数,该函数从其配置中一层一层地添加。还有一个参数should_build_graph=False
,可确保您在调用__init__()
时不在cls()
中构建图形。
然后CustomModel.save()
函数如下所示:
def save(self, filepath, overwrite=True, include_optimizer=True, **kwargs):
from tensorflow.python.keras.models import save_model
save_model(self, filepath, overwrite, include_optimizer)
之后,您可以使用以下方法保存:
model.save("model.h5")
new_model = keras.models.load_model('model.h5',
custom_objects={
'CustomModel': CustomModel,
'CustomLayer1Class': CustomLayer1Class,
...
})
但是以某种方式,这种方法似乎很慢...另一方面,这种方法快了近30倍。不知道为什么:
model.save_weights("weights.h5")
config = model.get_config()
reinitialized_model = CustomModel.from_config(config)
reinitialized_model.load_weights("weights.h5")
我工作,但是似乎很不客气。也许将来的TF2版本会使过程更清晰。
答案 4 :(得分:0)
从tensorflow 2.0.0版本开始,现在有一种使用tf.saved_model保存模型的keras / tf不可知方式
....
model.fit(images, labels , epochs=30, validation_data=(images_val, labels_val), verbose=1)
tf.saved_model.save( model, "path/to/model_dir" )
然后您可以加载
loaded_model = tf.saved_model.load("path/to/model_dir")