训练Keras对抗网络时产生矛盾的结果

时间:2020-07-17 20:43:21

标签: python tensorflow keras

training history

该模型设置为以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

enter image description here

在对模型进行了一些建议更新之后,事情看起来更加不稳定。大约是经过500个时期的训练后,每批256个样本。

我已经将两个优化器都更新为Keras Adam,并为鉴别器提供了比鉴别器更高的学习率,此外,对于鉴别器的每一批训练,都要对生成器进行两次训练。标签平滑处理似乎也起了很大作用,我怀疑是造成大量不稳定性的原因,但即使训练模型的历史很长,至少看起来足以显示出综合数据中的某些收敛性。到处都是。

1 个答案:

答案 0 :(得分:1)

  1. 尝试使用LeakyReLU,它们似乎在生成器和鉴别器上均能更好地工作。

  2. 考虑将不同的批处理大小用于生成器和鉴别器。并尝试使用2的幂的批量大小。

  3. 使用标签平滑。您可以在二进制交叉熵函数中找到它。

  4. 使用SGD作为鉴别器,使用Adam作为生成器,或者仅使用Adam作为两者。 SGD也很难训练,您需要有一个良好的训练时间表以使其对您有利。

  5. 此外,针对不同时期的火车鉴别器和发生器。就像火车鉴别器1个纪元,然后是发电机5个。