基于keras 的AdversarialAutoencoder实例

本文介绍如何使用Keras构建并训练非监督式对抗自编码器,涉及构建定制的判别器、密集编码器-解码器结构,以及根据原始论文的训练流程进行编译和迭代训练。通过实例展示了从数据预处理到模型评估的全过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本次学习目标为实现非监督AdversarialAutoencoder。

以下部分为可能用得到的package

from keras.layers import Dense, Flatten, Reshape, Conv2D, UpSampling2D, Cropping2D, MaxPool2D
from keras.models import Sequential
from keras.layers import Input
from keras.models import Model
import numpy as np
import tensorflow as tf
import datetime
from tensorflow.keras.layers.experimental import preprocessing
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

discriminator 初始化:

def build_custom_discriminator(latent_dim, initializer, info=False):
    discriminator = Sequential()
    discriminator.add(Dense(100, activation='relu',
                            kernel_initializer=initializer,
                            input_dim=latent_dim, bias_initializer=initializer)
                      )
    discriminator.add(Dense(500, activation='relu',
                            kernel_initializer=initializer,
                            bias_initializer=initializer))
    discriminator.add(Dense(1, activation="sigmoid",
                            kernel_initializer=initializer,
                            bias_initializer=initializer))

    if info:
        print(discriminator.summary())

    return discriminator

encoder 与 decoder的初始化(在这部分我使用了卷积conv2d方法):

def build_denser_omata_encoder_decoder(input_shape, latent_dim, initializer, info=False, act="elu", dense_act=None):

    encoder = Sequential()
    encoder.add(Conv2D(32, (5, 5), padding="same", activation=act, input_shape=input_shape, kernel_initializer=initializer))
    encoder.add(MaxPool2D(padding="same"))
    encoder.add(Conv2D(64, (3, 3), activation=act, padding="same", kernel_initializer=initializer))
    encoder.add(MaxPool2D(padding="same"))
    encoder.add(Conv2D(128, (3, 3), activation=act, padding="same", kernel_initializer=initializer))
    encoder.add(MaxPool2D(padding="same"))
    encoder.add(Flatten())
    encoder.add(Dense(int(5376/2),
                      kernel_initializer=initializer,
                      activation=dense_act))
    encoder.add(Dense(latent_dim, activation="linear"))

    if info:
        print(encoder.summary())

    decoder = Sequential()
    decoder.add(Dense(int(5376/2),
                      kernel_initializer=initializer,
                      activation=dense_act,
                      input_shape=(latent_dim,)))
    decoder.add(Dense(5376,
                      kernel_initializer=initializer,
                      activation=dense_act,
                      input_shape=(int(5376/2),)))
    decoder.add(Reshape((encoder.layers[6].input_shape[1],
                         encoder.layers[6].input_shape[2], 128)))
    decoder.add(Conv2D(128, (3, 3), activation=act, padding="same",
                       kernel_initializer=initializer))
    decoder.add(UpSampling2D())
    decoder.add(Conv2D(64, (3, 3), activation=act, padding="same",
                       kernel_initializer=initializer))
    decoder.add(UpSampling2D())
    decoder.add(Conv2D(32, (3, 3), activation=act, padding="same",
                       kernel_initializer=initializer))
    decoder.add(UpSampling2D())
    decoder.add(Conv2D(2, (3, 3), activation="linear", padding="same",
                kernel_initializer=initializer))
    decoder.add(Cropping2D(cropping=((1, 0), (3, 3))))

    decoder.build(input_shape)

    if info:
        print(decoder.summary())

    return encoder, decoder

初始化与训练:

class AAE:

    def __init__(self, encoder, decoder, discriminator, optimizer):
        self.encoder = encoder
        self.decoder = decoder
        self.discriminator = discriminator
        self.latent_dim = self.decoder.layers[0].input_shape[1]

        self.optimizer = optimizer

    def compile(self, input_shape):
        """
        Compilation of models according to original paper on adversarial
        autoencoders
        Args:
            input_shape (tuple): Shape of input data
        """

        self.input_shape = input_shape

        grid = Input(shape=self.input_shape)
        encoded_repr = self.encoder(grid)
        gen_grid = self.decoder(encoded_repr)
        self.autoencoder = Model(grid, gen_grid)

        valid = self.discriminator(encoded_repr)
        self.encoder_discriminator = Model(grid, valid)

        self.discriminator.compile(optimizer=self.optimizer,loss='binary_crossentropy',metrics=['accuracy'])

        self.autoencoder.compile(optimizer=self.optimizer,loss='mse',metrics=['accuracy'])

        self.discriminator.trainable = False

        self.encoder_discriminator.compile(optimizer=self.optimizer,loss='binary_crossentropy',metrics=['accuracy'])

    def train(self, train_data, epochs, val_data=None, batch_size=128,
              val_batch_size=128, wandb_log=False):
        """
        Training model according to original paper on adversarial autoencoders
        Args:
            train_data (np.ndarray): Array with train data
            epochs (int): Number of epochs
            val_data (np.ndarray, optional): Array with validation data.
                Defaults to None.
            batch_size (int, optional): Batch size. Defaults to 128.
            plot_losses (bool, optional): Whether to plot losses.
                Defaults to False.
            print_losses (bool, optional): Whether to print losses.
                Defaults to False.
        """

        d_loss_val = g_loss_val = None

        train_dataset = tf.data.Dataset.from_tensor_slices(train_data)
        train_dataset = train_dataset.shuffle(buffer_size=train_data.shape[0],reshuffle_each_iteration=True).batch(batch_size, drop_remainder=True)

        if val_data is not None:
            val_dataset = tf.data.Dataset.from_tensor_slices(val_data)
            val_dataset = val_dataset.shuffle(
                buffer_size=val_data.shape[0],
                reshuffle_each_iteration=True).\
                batch(val_batch_size, drop_remainder=True)

        # Set up tensorboard logging
        current_time = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
        train_log_dir = 'logs/' + current_time + '/train'
        val_log_dir = 'logs/' + current_time + '/val'
        train_summary_writer = tf.summary.create_file_writer(train_log_dir)
        val_summary_writer = tf.summary.create_file_writer(val_log_dir)

        # Adversarial ground truths
        valid = np.ones((batch_size, 1))
        fake = np.zeros((batch_size, 1))

        for epoch in range(epochs):

            # Reconstruction phase
            loss_cum = 0
            acc_cum = 0
            for step, grids in enumerate(train_dataset):
                # Train the autoencoder reconstruction
                loss, acc = self.autoencoder.train_on_batch(grids, grids)
                loss_cum += loss
                acc_cum += acc

            # Average the loss and accuracy over the entire dataset
            loss = loss_cum/(step+1)
            acc = acc_cum/(step+1)

            # Regularization phase
            d_loss_cum = 0
            g_loss_cum = 0
            for step, grids in enumerate(train_dataset):

                # Generate real and fake latent space. Fake latent space is
                # the normal distribution
                latent_fake = self.encoder.predict(grids)
                latent_real = np.random.normal(size=(batch_size,self.latent_dim))

                # Train the discriminator
                d_loss_real = self.discriminator.train_on_batch(latent_real,valid)[0]
                d_loss_fake = self.discriminator.train_on_batch(latent_fake,fake)[0]
                d_loss_cum += 0.5 * np.add(d_loss_real, d_loss_fake)

                # Train generator
                g_loss_cum += self.encoder_discriminator.train_on_batch(grids, valid)[0]

            d_loss = d_loss_cum/(step+1)
            g_loss = g_loss_cum/(step+1)

            with train_summary_writer.as_default():
                tf.summary.scalar('loss - ae', loss, step=epoch)
                tf.summary.scalar('accuracy - ae', acc, step=epoch)
                tf.summary.scalar('loss - g', g_loss, step=epoch)
                tf.summary.scalar('loss - d', d_loss, step=epoch)

            # Calculate the accuracies on the validation set
            if val_data is not None:
                loss_val, acc_val, d_loss_val, g_loss_val = \
                    self.validate(val_dataset, val_batch_size)

                with val_summary_writer.as_default():
                    tf.summary.scalar('loss - ae', loss_val, step=epoch)
                    tf.summary.scalar('accuracy - ae', acc_val, step=epoch)
                    tf.summary.scalar('loss - g', g_loss_val, step=epoch)
                    tf.summary.scalar('loss - d', d_loss_val, step=epoch)


    def validate(self, val_dataset, val_batch_size=128):

        # Adversarial ground truths
        valid = np.ones((val_batch_size, 1))
        fake = np.zeros((val_batch_size, 1))

        loss_cum = 0
        acc_cum = 0
        d_loss_cum = 0
        g_loss_cum = 0
        for step, val_grids in enumerate(val_dataset):

            loss, acc = self.autoencoder.evaluate(val_grids, val_grids, verbose=0)
            loss_cum += loss
            acc_cum += acc

            latent_fake = self.encoder.predict(val_grids)
            latent_real = np.random.normal(size=(val_batch_size, self.latent_dim))

            d_loss_real = self.discriminator.evaluate(latent_real, valid, verbose=0)[0]
            d_loss_fake = self.discriminator.evaluate(latent_fake, fake, verbose=0)[0]
            d_loss_cum += 0.5 * np.add(d_loss_real, d_loss_fake)

            g_loss_cum += self.encoder_discriminator.evaluate(val_grids, valid,verbose=0)[0]

        # Average the loss and accuracy over the entire dataset
        loss = loss_cum/(step+1)
        acc = acc_cum/(step+1)
        d_loss = d_loss_cum/(step+1)
        g_loss = g_loss_cum/(step+1)

        return loss, acc, d_loss, g_loss

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值