tf.get_shape() 错误地返回 None

tf.get_shape() returning None incorrectly

我目前正尝试按照此处的设置在 keras 中创建具有梯度惩罚的 WGAN 实现:https://keras.io/examples/generative/wgan_gp/。但是,我修改了它以使用 RNN 生成时间序列。

训练集中的时间序列长度可变,因此我使用 train_on_batch 一次训练一个时间序列的模型。我已经修改了上面链接的代码中的 train_step 函数来处理这个问题,新函数由

    def train_step(self, X):
        if isinstance(X, tuple):
            X = X[0]
        batch_size = X.get_shape()[0]
        timesteps = X.get_shape()[1]

        for i in range(self.d_steps):
            # Get the latent vector
            noise = tf.random.normal((batch_size, self.latent_dims))
            noise = tf.reshape(noise, (batch_size, 1, self.latent_dims))
            noise = tf.repeat(noise, timesteps, 1)
            with tf.GradientTape() as tape:
                fake_images = self.generator(noise, training=True)
                fake_logits = self.discriminator(fake_images, training=True)
                real_logits = self.discriminator(X, training=True)

                d_cost = self.d_loss_fn(real_img=real_logits, fake_img=fake_logits)
                gp = self.gradient_penalty(batch_size, X, fake_images)
                d_loss = d_cost + gp * self.gp_weight

            d_gradient = tape.gradient(d_loss, self.discriminator.trainable_variables)
            self.d_optimizer.apply_gradients(
                zip(d_gradient, self.discriminator.trainable_variables)
            )

        noise = tf.random.normal((batch_size, self.latent_dims))
        noise = tf.reshape(noise, (batch_size, 1, self.latent_dims))
        noise = tf.repeat(noise, timesteps, 1)
        with tf.GradientTape() as tape:
            generated_data = self.generator(noise, training=True)
            gen_img_logits = self.discriminator(generated_data, training=True)
            g_loss = self.g_loss_fn(gen_img_logits)

        gen_gradient = tape.gradient(g_loss, self.generator.trainable_variables)
        self.g_optimizer.apply_gradients(
            zip(gen_gradient, self.generator.trainable_variables)
        )
        return {"d_loss": d_loss, "g_loss": g_loss}

和运行这使用

for epoch in epochs:
    names = train_df.names.unique()
    for batch in nbatches:
        name = names[batch]
        X = train_df[train_df.name == name].values
        X = X[:, 1:] # removes name column
        X = X.reshape((1, *X.shape))
        wgan.train_on_batch(X)

此处,train_df 只是一个 pandas 数据框,其中包含 12 列,其中包含 0 到 1 之间的值(这些列包含时间序列中的观察值),第 13 列仅包含名称每个时间序列的数据分离出来(这是第一列)。

这个想法是,对于每个时间序列,train_step 的第一部分将生成时间步数与时间序列相同的噪声,以确保生成的数据与时间序列的形状相同真实数据。

时间步数应该由 X.get_shape()[1] 给出。对于第一次迭代,X 是一个形状为 (1, 18, 12) 的 numpy 数组,当传递给 train_step 时,张量 X 的大小也是 (1, 18, 12),这意味着变量 timesteps 按预期由 timesteps = X.get_shape()[1] 设置为 18。对于第二次迭代,X 是一个形状为 (1, 15, 12) 的 numpy 数组,这也按预期工作。然而,在第三次迭代中,X 是一个形状为 (1, 13, 12) 的 numpy 数组,当传递给 train_step 时,形状现在为 (1, None, 12),这意味着设置了时间步长到 None 然后代码不起作用。

我很困惑为什么 X.get_shape() 在开始时可以正常工作,但在第三次迭代后就不能正常工作,而且找不到修复方法。基本上我只需要将时间步设置为正确的值,我也在考虑将值作为单独的变量传递以确保该值正确而不是依赖 get_shape 但想不出办法去做。谁能建议为什么 get_shape 在 2 次迭代后开始返回 None 以及如何避免它?如果您已经读到这里,非常感谢您的阅读,对于篇幅,我们深表歉意!

尝试更改:

timesteps = X.get_shape()[1]

收件人:

timesteps = tf.shape(X)[1]

在训练过程中获得X的动态形状。