该模型设置为以3个特征的4000步长的时间序列的形式训练1400个样本。我正在尝试使用该模型制作一个综合时间序列。我正在Jupyter笔记本电脑的最新conda环境中使用带有Python 3.6的Tensorflow 2.2.0。
众所周知,GAN很难训练。使我怀疑该错误是由于我的代码而不是模型不稳定性引起的,是GAN的总和为零。在上图中,我们看到鉴别器和生成器都朝着100%的精度方向发展。我期望,如果模型建立正确,它们将具有反比关系,然后人们可以继续调整超参数。
如果判别器太强,该如何解释生成器的行为?我的训练标志设置正确吗?我在鉴别器的输出上使用了sigmoid
,因为它输出的是概率。在Generator上尝试其他激活会产生相同的结果,因此我选择了“ Sigmoid”,但也许有人有更好的建议?
BATCH_SIZE = 24
# Compile the model
g = build_generator()
d = build_discriminator()
d.compile(optimizer=SGD(learning_rate=0.0005), loss="binary_crossentropy", metrics=['accuracy'])
model_input = Input(shape=(750,), batch_size=BATCH_SIZE, name='model_input')
model_output = d(g(model_input))
GAN = Model(model_input, model_output)
GAN.compile(optimizer=SGD(learning_rate=0.0004), loss="binary_crossentropy", metrics=['accuracy'])
def train_discriminator():
valid = np.ones((BATCH_SIZE,1))
fake = np.zeros((BATCH_SIZE,1))
# Samples for the batch of training
idx = tf.random.uniform((1,BATCH_SIZE), minval=0, maxval=training_data.shape[0], dtype=tf.dtypes.int32,)
samples = training_data[idx]
# Genorate Synthetic Data to Test
noise = tf.random.normal((BATCH_SIZE,750,), 0, 1, dtype=tf.dtypes.float32)
new_traces = g.predict(noise)
d.trainable = True
d_loss_real, d_acc_real = d.train_on_batch(samples, valid)
d_loss_fake, d_acc_fake = d.train_on_batch(new_traces, fake)
d_loss = 0.5 * (d_loss_real + d_loss_fake)
d_acc = 0.5 * (d_acc_real + d_acc_fake)
return [d_loss, d_loss_real, d_loss_fake, d_acc, d_acc_real, d_acc_fake]
def train_generator():
d.trainable = False
noise = tf.random.normal((BATCH_SIZE,750,), 0, 1, dtype=tf.dtypes.float32)
valid = np.ones((BATCH_SIZE,1))
g_loss, g_acc = GAN.train_on_batch(noise, valid)
return [g_loss, g_acc]
def train(epochs):
# Main Training Loop
start = time.time()
epoch = 1
d_losses = []
g_losses = []
for year in range(epochs):
d_training = train_discriminator()
g_training = train_generator()
print ("%d [D loss: (%.3f)(R %.3f, F %.3f)] [D acc: (%.3f)(%.3f, %.3f)] [G loss: %.3f] [G acc: %.3f]" % (epoch, d_training[0], d_training[1], d_training[2], d_training[3], d_training[4], d_training[5], g_training[0], g_training[1]))
d_losses.append(d_training)
g_losses.append(g_training)
epoch += 1
adjusted = round( (time.time()-start)/60, 2 )
print(f"\nCompleted {epoch} epochs in {adjusted} min")
return [d_losses, g_losses]
更新2020-07-19
在对模型进行了一些建议更新之后,事情看起来更加不稳定。大约是经过500个时期的训练后,每批256个样本。
我已经将两个优化器都更新为Keras Adam
,并为鉴别器提供了比鉴别器更高的学习率,此外,对于鉴别器的每一批训练,都要对生成器进行两次训练。标签平滑处理似乎也起了很大作用,我怀疑是造成大量不稳定性的原因,但即使训练模型的历史很长,至少看起来足以显示出综合数据中的某些收敛性。到处都是。
答案 0 :(得分:1)
尝试使用LeakyReLU,它们似乎在生成器和鉴别器上均能更好地工作。
考虑将不同的批处理大小用于生成器和鉴别器。并尝试使用2的幂的批量大小。
使用标签平滑。您可以在二进制交叉熵函数中找到它。
使用SGD作为鉴别器,使用Adam作为生成器,或者仅使用Adam作为两者。 SGD也很难训练,您需要有一个良好的训练时间表以使其对您有利。
此外,针对不同时期的火车鉴别器和发生器。就像火车鉴别器1个纪元,然后是发电机5个。