【问题标题】:Unable to save model with tensorflow 2.0.0 beta1无法使用 tensorflow 2.0.0 beta1 保存模型
【发布时间】:2020-01-03 06:35:38
【问题描述】:

我已经尝试了文档中描述的所有选项,但没有一个允许我将模型保存在 tensorflow 2.0.0 beta1 中。我也尝试升级到(同样不稳定的)TF2-RC,但这甚至破坏了我在测试版中工作的代码,所以我现在迅速回滚到测试版。

请参阅下面的最小复制代码。

我尝试过的:

  1. model.save("mymodel.h5") 
    

NotImplementedError:将模型保存为 HDF5 格式需要 模型是功能模型或顺序模型。这是行不通的 对于子类模型,因为此类模型是通过 Python 方法,不能安全地序列化。考虑保存到 Tensorflow SavedModel 格式(通过设置 save_format="tf")或 使用save_weights

  1. model.save("mymodel", format='tf')
    

ValueError: Model ma​​in.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


【解决方案1】:

我在 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 中也变得更快了。

【讨论】:

  • 感谢分享。对于其他任何卡住并具有预定义调用方法的人,只需为训练提供一个默认值,例如 training=None。另请参阅stackoverflow.com/a/59870119/6043669
【解决方案2】:

你应该改变两件事:

  1. 如您所指,将decode 方法更改为call
  2. 由于您的模型是Sequential 类型,并且不是在类中构建的,因此您希望在modelself.network 属性上调用save 方法,即,
model.network.save('mymodel.h5')

或者,为了让事情更标准,您可以在AE 类中实现此方法,如下所示:

def save(self, save_dir):
    self.network.save(save_dir)

祝你好运

【讨论】:

    猜你喜欢
    • 2019-12-30
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-23
    相关资源
    最近更新 更多