对抗性自动编码器无法正常工作且无法正确学习

Posted

技术标签:

【中文标题】对抗性自动编码器无法正常工作且无法正确学习【英文标题】:Adversarial Autoencoder is not working and not learning properly 【发布时间】:2021-12-17 00:34:43 【问题描述】:

我正在尝试在 keras.model 类上使用 keras Fit 方法让 Adversarial AutoEncoder 运行 但由于某种原因,它不起作用。

请记住,我尝试同时更新编码器和解码器。 我尝试在有和没有重建损失的情况下将光盘损失分配给编码器

重建损失保持不变,而编码器盘损失不断增加,而判别器自身的损失不断下降。

discriminator = keras.Sequential(
    [
        keras.Input(shape=(4, 4, 128)),
        layers.Flatten(),
        layers.Dense(128, activation="relu"),
        layers.Dense(128, activation="relu"),
        layers.Dense(128, activation="relu"),
        layers.Dense(1, activation="sigmoid"),
    ],
    name="discriminator",
)
discriminator.summary()
encoder  = keras.Sequential(
    [
        keras.Input(shape=(28, 28, 1)),
        layers.Conv2D(24, 3, activation="relu", strides=2, padding="same"),
        layers.Conv2D(48, 3, activation="relu", strides=2, padding="same"),
        layers.Conv2D(96, 3, activation="relu", strides=2, padding="same"),
        layers.Flatten(),
        layers.Dense(4 * 4 * 128, activation="linear"),
        layers.Reshape((4, 4, 128)),
    ],
    name="encoder",
)
encoder.summary()

decoder  = keras.Sequential(
    [
        keras.Input(shape=(4, 4, 128)),
        layers.Flatten(),
        layers.Dense(7 * 7 * 64, activation="relu"),
        layers.Reshape((7, 7, 64)),
        layers.Conv2DTranspose(64, 3, activation="relu", strides=2, padding="same"),
        layers.Conv2DTranspose(32, 3, activation="relu", strides=2, padding="same"),
        layers.Conv2DTranspose(1, 3, activation="sigmoid", strides=1, padding="same"),

    ],
    name="decoder",
)

我不确定是不是在模型本身。我正在为此使用 MNIST 数据集

class AAE(keras.Model):
    def __init__(self, encoder, decoder, discriminator):
        super(AAE, self).__init__()
        self.encoder = encoder
        self.decoder = decoder
        self.discriminator = discriminator

        self.total_loss_tracker = keras.metrics.Mean(name="total_loss")
        self.reconstruction_loss_tracker = keras.metrics.Mean(name="reconstruction_loss")
        self.disc_tracker = keras.metrics.Mean(name="disc_loss")
        self.discEnc_tracker = keras.metrics.Mean(name="discEnc_loss")
        
    @property
    def metrics(self):
        return [
            self.total_loss_tracker,
            self.reconstruction_loss_tracker,
            self.disc_tracker,
            self.discEnc_tracker,
        ]


    def compile(self, di_optimizer, e_optimizer,de_optimizer, loss_fn):
        super(AAE, self).compile()
        self.dis_optimizer = di_optimizer
        self.e_optimizer = e_optimizer
        self.de_optimizer = de_optimizer
        
        self.lossBCE = loss_fn[0]
        self.lossMAE = loss_fn[1]
    

    def train_step(self, data):
        latent = self.encoder(data)
        batch_size = 200
        dists = tf.random.normal((batch_size,4,4,128))

        y_real = tf.ones((batch_size, 1))
        y_fake = tf.zeros((batch_size, 1))
        real_dist_mix = tf.concat((dists, latent),axis=0)
        y_real_fake_mix = tf.concat((y_real, y_fake),axis=0)

        with tf.GradientTape() as tape:
            predictions = self.discriminator(real_dist_mix)
            
            d_loss = self.lossBCE(y_real_fake_mix, predictions)
            
        grads = tape.gradient(d_loss, self.discriminator.trainable_weights)
        self.dis_optimizer.apply_gradients(zip(grads, self.discriminator.trainable_weights))

        with tf.GradientTape() as Etape, tf.GradientTape() as Dtape:
            latent = self.encoder(data)
            reconstruction = self.decoder(latent)
            reconstruction_loss = self.lossMAE(data, reconstruction) 
            

            total_loss = reconstruction_loss
        Egrads = Etape.gradient(total_loss, self.encoder.trainable_weights)
        self.e_optimizer.apply_gradients(zip(Egrads, self.encoder.trainable_weights))

        Dgrads = Dtape.gradient(total_loss, self.decoder.trainable_weights)
        self.de_optimizer.apply_gradients(zip(Dgrads, self.decoder.trainable_weights))


        with tf.GradientTape() as tape:
            latent = self.encoder(data)
            predictions = self.discriminator(latent)
            e_loss = self.lossBCE(y_fake, predictions)

        grads = tape.gradient(e_loss, self.encoder.trainable_weights)
        self.e_optimizer.apply_gradients(zip(grads, self.encoder.trainable_weights))

        self.total_loss_tracker.update_state(total_loss)
        self.reconstruction_loss_tracker.update_state(reconstruction_loss)
        self.disc_tracker.update_state(d_loss)
        self.discEnc_tracker.update_state(e_loss)
        return 
            "loss": self.total_loss_tracker.result(),
            "reconstruction_loss": self.reconstruction_loss_tracker.result(),
            "disc_loss": self.disc_tracker.result(),
            "discEnc_loss": self.discEnc_tracker.result(),
        
(x_train, _), (x_test, _) = keras.datasets.mnist.load_data()
mnist_digits = np.concatenate([x_train, x_test], axis=0)
mnist_digits = np.expand_dims(mnist_digits, -1).astype("float32") / 255

Aae = AAE(encoder, decoder, discriminator)
#vae.compile(optimizer=keras.optimizers.Adam())
Aae.compile(
    di_optimizer=keras.optimizers.Adam(learning_rate=0.00001),
    e_optimizer=keras.optimizers.Adam(learning_rate=0.0001),
    de_optimizer=keras.optimizers.Adam(learning_rate=0.0001),
    loss_fn=[tf.keras.losses.BinaryCrossentropy(),tf.keras.losses.MeanAbsoluteError()]
)
h=Aae.fit(mnist_digits, epochs=15, batch_size=200)

【问题讨论】:

【参考方案1】:

我认为错误就在这里:

    with tf.GradientTape() as tape:
        latent = self.encoder(data)
        predictions = self.discriminator(latent)
        e_loss = self.lossBCE(y_fake, predictions)

    grads = tape.gradient(e_loss, self.encoder.trainable_weights)
    self.e_optimizer.apply_gradients(zip(grads, self.encoder.trainable_weights))

我会输入e_loss = self.lossBCE(y_real, predictions),因为编码器试图欺骗鉴别器。

【讨论】:

以上是关于对抗性自动编码器无法正常工作且无法正确学习的主要内容,如果未能解决你的问题,请参考以下文章

对抗性自动编码器系列--对抗自动编码器AAE的原理及实现-从任意随机数重建手写数字

对抗性自动编码器系列--有监督对抗自动编码器SAAE的原理及实现-随机数生成想要的数字

Pentaho 不在 UTF-8 编码中生成 PDF

无法以正确的格式、gmail api 和 ae.net.mail 对特殊字符电子邮件进行编码

UTF 8 编码在 PHP 中无法正常工作

GBK与UTF-8编码错误转换后,无法再正确恢复