无法使用Tensorflow 2.0.0 beta1

时间:2019-08-30 01:23:49

标签: tensorflow keras model neural-network

我已经尝试了文档中描述的所有选项,但是没有一个选项允许我将我的模型保存在tensorflow 2.0.0 beta1中。我也曾尝试升级到(也是不稳定的)TF2-RC,但这甚至破坏了我在beta中工作的代码,因此我很快就回滚到了beta。

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

我尝试过的:

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

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

  1. 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')

1 个答案:

答案 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的训练(或节省)也快得多。