我已经尝试了文档中描述的所有选项,但是没有一个选项允许我将我的模型保存在tensorflow 2.0.0 beta1中。我也曾尝试升级到(也是不稳定的)TF2-RC,但这甚至破坏了我在beta中工作的代码,因此我很快就回滚到了beta。
请参阅下面的最小复制代码。
我尝试过的:
model.save("mymodel.h5")
NotImplementedError:将模型保存为HDF5格式需要 模型是功能模型还是顺序模型。这是行不通的 对于子类模型,因为此类模型是通过 Python方法,该方法无法安全地序列化。考虑保存到 Tensorflow SavedModel格式(通过设置save_format =“ tf”)或 使用
save_weights
。
model.save("mymodel", format='tf')
ValueError:模型<< strong> main 。位于0x7f1cac2e7c50>的CVAE对象不能为 由于未设置输入形状而保存。通常,输入 形状是通过调用.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')
答案 0 :(得分:0)
我在tensorflow-gpu 2.0.0-rc0中尝试了相同的最小复制示例,该错误比beta版本给我的显示的更多。 RC中的错误说:
NotImplementedError:子类化Model类时,您应该 实现调用方法。
这使我通读了https://www.tensorflow.org/beta/guide/keras/custom_layers_and_models,在其中找到了有关如何以允许保存的方式在TF2中进行子类化的示例。在上面的示例中,通过将我的“解码”方法替换为“调用”,我能够解决该错误并保存了模型(尽管对于我为类定义了各种方法的实际代码,这将更加复杂)。这解决了beta和rc中的错误。奇怪的是,rc的训练(或节省)也快得多。