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
的动态形状。
我目前正尝试按照此处的设置在 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
的动态形状。