【问题标题】:Contradictory results when training Keras Adversarial Network训练 Keras 对抗网络时的矛盾结果
【发布时间】:2020-11-07 16:57:16
【问题描述】:

该模型设置为以 4000 步长的 3 个特征的时间序列形式训练 1400 个样本。我正在尝试使用模型制作合成时间序列。我在 Jupyter notebook 的最新 conda 环境中使用 TensorFlow 2.2.0 和 Python 3.6。

众所周知,GAN 很难训练。让我怀疑错误是由于我的代码而不是模型不稳定性引起的一件事是 GAN 是零和增益。在上图中,我们看到鉴别器和生成器都在朝着 100% 的准确率迈进。我期待,如果模型设置正确,它们将具有反比关系,然后可以继续调整超参数。

如果判别器太强,那么如何解释生成器的行为?我是否正确设置了训练标志?我在鉴别器的输出上使用sigmoid,这是有道理的,因为它输出的是概率。在生成器上尝试其他激活会导致相同的结果,因此我选择了“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 年 7 月 19 日更新

在用几个建议更新模型后,事情看起来有点典型的不稳定。大约是经过 500 个 epoch 训练,每批 256 个样本。

我已将两个优化器更新为 Keras Adam,并为生成器提供了比判别器更高的学习率,此外还为判别器的每批训练训练两次生成器。标签平滑似乎也有显着效果,我怀疑这是造成很多不稳定性的原因,但至少它似乎足以显示合成数据中的一些收敛性,即使训练模型的历史是到处都是。

【问题讨论】:

    标签: python tensorflow keras


    【解决方案1】:
    1. 尝试使用 LeakyReLU,它们似乎在生成器和判别器中都表现得更好。

    2. 考虑为生成器和判别器使用不同的批量大小。并尝试使用 2 次方的批量大小。

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

    4. 对鉴别器使用 SGD,对生成器使用 Adam,或者两者都使用 Adam。 SGD 也很难训练,你需要有一个良好的训练计划才能让它对你有利。

    5. 此外,针对不同数量的 epoch 训练鉴别器和生成器。就像训练 1 个 epoch 的鉴别器,然后是 5 个的生成器。

    【讨论】:

    • 关于#3,我选择了统一的,因为我假设希望训练数据中的所有样本都被使用大约相等的次数。如果我正确理解您的建议,高斯(或正态)分布不会出现这种情况?
    • 改变它是有益还是有害?使用统一采样数据很好。但是,生成应该来自 Gaussian。
    猜你喜欢
    • 2020-04-16
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 2019-07-05
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    • 2017-11-27
    相关资源
    最近更新 更多