【发布时间】:2020-01-03 06:35:38
【问题描述】:
我已经尝试了文档中描述的所有选项,但没有一个允许我将模型保存在 tensorflow 2.0.0 beta1 中。我也尝试升级到(同样不稳定的)TF2-RC,但这甚至破坏了我在测试版中工作的代码,所以我现在迅速回滚到测试版。
请参阅下面的最小复制代码。
我尝试过的:
model.save("mymodel.h5")
NotImplementedError:将模型保存为 HDF5 格式需要 模型是功能模型或顺序模型。这是行不通的 对于子类模型,因为此类模型是通过 Python 方法,不能安全地序列化。考虑保存到 Tensorflow SavedModel 格式(通过设置 save_format="tf")或 使用
save_weights。
model.save("mymodel", format='tf')
ValueError: Model main.CVAE object at 0x7f1cac2e7c50> 不能 保存,因为尚未设置输入形状。通常,输入 形状是通过调用 .fit() 或 .predict() 自动确定的。 要手动设置形状,请调用 model._set_inputs(inputs)。
3.
model._set_input(input_sample)
model.save("mymodel", format='tf')
AssertionError: tf.saved_model.save 在跟踪的内部不受支持 @tf.function。将调用移至外部急切执行的上下文。
这就是我现在卡住的地方,因为它没有给我任何合理的提示。那是因为我没有从@tf.function 调用 save() 函数,我已经从可能的最外层调用它。事实上,我在下面这个最小的复制脚本中根本没有 @tf.function 并且仍然得到同样的错误。
所以我真的不知道如何保存我的模型,我已经尝试了所有选项,但它们都抛出错误并且没有提供任何提示。
如果您设置 save_model=False,下面的最小重现示例可以正常工作,并且它会在 save_model=True 时重现错误。
在这个简化的自动编码器代码示例中,使用子类模型似乎没有必要,但我在原始 VAE 代码中添加了许多自定义函数,我需要它。
代码:
import tensorflow as tf
save_model = True
learning_rate = 1e-4
BATCH_SIZE = 100
TEST_BATCH_SIZE = 10
color_channels = 1
imsize = 28
(train_images, _), (test_images, _) = tf.keras.datasets.mnist.load_data()
train_images = train_images[:5000, ::]
test_images = train_images[:1000, ::]
train_images = train_images.reshape(-1, imsize, imsize, 1).astype('float32')
test_images = test_images.reshape(-1, imsize, imsize, 1).astype('float32')
train_images /= 255.
test_images /= 255.
train_dataset = tf.data.Dataset.from_tensor_slices(train_images).batch(BATCH_SIZE)
test_dataset = tf.data.Dataset.from_tensor_slices(test_images).batch(TEST_BATCH_SIZE)
class AE(tf.keras.Model):
def __init__(self):
super(AE, self).__init__()
self.network = tf.keras.Sequential([
tf.keras.layers.InputLayer(input_shape=(imsize, imsize, color_channels)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(50),
tf.keras.layers.Dense(imsize**2 * color_channels),
tf.keras.layers.Reshape(target_shape=(imsize, imsize, color_channels)),
])
def decode(self, input):
logits = self.network(input)
return logits
optimizer = tf.keras.optimizers.Adam(learning_rate)
model = AE()
def compute_loss(data):
logits = model.decode(data)
loss = tf.reduce_mean(tf.losses.mean_squared_error(logits, data))
return loss
def train_step(data):
with tf.GradientTape() as tape:
loss = compute_loss(data)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
return loss, 0
def test_step(data):
loss = compute_loss(data)
return loss
input_shape_set = False
epoch = 0
epochs = 20
for epoch in range(epochs):
for train_x in train_dataset:
train_step(train_x)
if epoch % 1 == 0:
loss = 0.0
num_batches = 0
for test_x in test_dataset:
loss += test_step(test_x)
num_batches += 1
loss /= num_batches
print("Epoch: {}, Loss: {}".format(epoch, loss))
if save_model:
print("Saving model...")
if not input_shape_set:
# Note: Why set input shape manually and why here:
# 1. If I do not set input shape manually: ValueError: Model <main.CVAE object at 0x7f1cac2e7c50> cannot be saved because the input shapes have not been set. Usually, input shapes are automatically determined from calling .fit() or .predict(). To manually set the shapes, call model._set_inputs(inputs).
# 2. If I set input shape manually BEFORE the first actual train step, I get: RuntimeError: Attempting to capture an EagerTensor without building a function.
model._set_inputs(train_dataset.__iter__().next())
input_shape_set = True
# Note: Why choose tf format: model.save('MNIST/Models/model.h5') will return NotImplementedError: Saving the model to HDF5 format requires the model to be a Functional model or a Sequential model. It does not work for subclassed models, because such models are defined via the body of a Python method, which isn't safely serializable. Consider saving to the Tensorflow SavedModel format (by setting save_format="tf") or using save_weights.
model.save('MNIST/Models/model', save_format='tf')
【问题讨论】:
-
您能分享用于构建模型的代码吗?
标签: tensorflow keras model neural-network