خروجی Denoising Autoencoder و ورود به Sparse Autoencoder | Sparse Autoencoder

خروجی Denoising Autoencoder و ورود به Sparse Autoencoder | Sparse Autoencoder

توسط admin | گروه هوش مصنوعی | 1405/06/01

نظرات 0

خروجی Denoising Autoencoder و ورود به Sparse Autoencoder | Sparse Autoencoder

کتاب
Hands-On Machine Learning with Scikit-Learn, Keras & TensorFlow
بخش منبع
Sparse Autoencoders; Variational Autoencoders; Generating Fashion MNIST Images; Generative Adversarial Networks; Difficulties of Training GANs; Deep Convolutional GANs
صفحات این PDF
115-130
صفحات چاپی کتاب
651-666
جایگاه در مجموعه
69 / Machine_Learning_405_06; parent: Machine_Learning_405_06_01.html

خروجی Denoising Autoencoder و ورود به Sparse Autoencoder

در Denoising Autoencoder بخشی از Pixelها یا Featureها خراب می‌شوند، اما Target همان Data تمیز است. نتیجه نشان می‌دهد Model می‌تواند ساختار گم‌شده را از Patternهای Dataset حدس بزند.

17-9 - خروجی Denoising Autoencoder و ورود به Sparse Autoencoder
شکل 17-9. خروجی Denoising Autoencoder و ورود به Sparse Autoencoder

Sparse Autoencoder

Constraint دیگری که Feature Extraction خوبی ایجاد می‌کند Sparsity است. Coding Layer می‌تواند حتی بزرگ‌تر از Input باشد، اما Loss Model را مجبور می‌کند در هر Instance فقط تعداد کمی Neuron فعال باشند. در نتیجه هر Neuron Coding تمایل پیدا می‌کند Feature معنی‌داری را نمایندگی کند.

یک روش ساده استفاده از Activation نوع Sigmoid در Coding Layer و L1 Regularization روی Activationهاست:

sparse_l1_encoder = tf.keras.Sequential([
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(100, activation="relu"),
    tf.keras.layers.Dense(300, activation="sigmoid"),
    tf.keras.layers.ActivityRegularization(l1=1e-4)
])
sparse_l1_decoder = tf.keras.Sequential([
    tf.keras.layers.Dense(100, activation="relu"),
    tf.keras.layers.Dense(28 * 28),
    tf.keras.layers.Reshape([28, 28])
])
sparse_l1_ae = tf.keras.Sequential([sparse_l1_encoder, sparse_l1_decoder])

L1 به‌جای اینکه همهٔ Activationها را کمی کوچک کند، بسیاری از آن‌ها را به صفر نزدیک می‌کند و تعداد کمی Feature مهم را نگه می‌دارد.

Sparsity Loss با KL Divergence

روش دقیق‌تر این است که Mean Activation هر Coding Neuron روی Batch اندازه‌گیری شود و با Target Sparsity، مثلاً 0.1، مقایسه شود. برای Penalize کردن اختلاف، KL Divergence Gradient قوی‌تری از MSE دارد.

17-10 - Sparsity Loss با KL Divergence
شکل 17-10. Sparsity Loss با KL Divergence
D_KL(P || Q) = Σᵢ P(i) log(P(i) / Q(i))

D_KL(p || q) = p log(p/q) + (1-p) log((1-p)/(1-q))

Sparsity Loss همهٔ Neuronها جمع می‌شود و با یک Hyperparameter وزن‌دار به Reconstruction Loss اضافه می‌شود. Weight خیلی بزرگ Reconstruction را خراب می‌کند و Weight خیلی کوچک Constraint را بی‌اثر می‌سازد.

kl_divergence = tf.keras.losses.kullback_leibler_divergence

class KLDivergenceRegularizer(tf.keras.regularizers.Regularizer):
    def __init__(self, weight, target):
        self.weight = weight
        self.target = target

    def __call__(self, inputs):
        mean_activities = tf.reduce_mean(inputs, axis=0)
        return self.weight * (
            kl_divergence(self.target, mean_activities) +
            kl_divergence(1. - self.target, 1. - mean_activities))

Variational Autoencoder یا VAE

VAE یک Autoencoder Probabilistic و Generative است. Encoder به‌جای تولید یک Coding قطعی، Parameterهای Distribution را تولید می‌کند. برای هر Input، دو Vector ساخته می‌شود: Mean با نماد μ و Standard Deviation یا شکل پایدارتر آن γ = log(σ²). سپس Coding به‌صورت Random از این Distribution Sample می‌شود.

17-11 - Variational Autoencoder یا VAE
شکل 17-11. Variational Autoencoder یا VAE

این Randomness دو اثر مهم دارد: Latent Space Smooth می‌شود و Pointهای نزدیک معمولاً Sampleهای مشابه می‌سازند؛ همچنین می‌توان پس از Training یک Vector Random از Gaussian استاندارد Sample کرد و با Decoder نمونهٔ جدید تولید کرد.

Loss در VAE

Cost از دو بخش تشکیل می‌شود: Reconstruction Loss و Latent Loss. Latent Loss Distribution Coding را به Gaussian استاندارد نزدیک می‌کند. برای هر Instance:

L_latent = -1/2 Σᵢ (1 + log(σᵢ²) - σᵢ² - μᵢ²)

# با γ = log(σ²)
L_latent = -1/2 Σᵢ (1 + γᵢ - exp(γᵢ) - μᵢ²)

استفاده از Log Variance از نظر عددی پایدارتر است.

Reparameterization Trick

Sampling معمولی مسیر Gradient را قطع می‌کند. برای اینکه Backpropagation ممکن باشد، Noise مستقل ε ~ N(0,1) Sample می‌شود و Coding به صورت زیر ساخته می‌شود:

z = μ + exp(γ / 2) * ε

به این ترتیب Randomness در ε قرار می‌گیرد، ولی مسیر از μ و γ تا Loss Differentiable باقی می‌ماند.

پیاده‌سازی Encoder و Decoder VAE

class Sampling(tf.keras.layers.Layer):
    def call(self, inputs):
        mean, log_var = inputs
        return tf.random.normal(tf.shape(log_var)) * tf.exp(log_var / 2) + mean

codings_size = 10
inputs = tf.keras.layers.Input(shape=[28, 28])
Z = tf.keras.layers.Flatten()(inputs)
Z = tf.keras.layers.Dense(150, activation="relu")(Z)
Z = tf.keras.layers.Dense(100, activation="relu")(Z)
codings_mean = tf.keras.layers.Dense(codings_size)(Z)
codings_log_var = tf.keras.layers.Dense(codings_size)(Z)
codings = Sampling()([codings_mean, codings_log_var])
variational_encoder = tf.keras.Model(
    inputs=[inputs], outputs=[codings_mean, codings_log_var, codings])

decoder_inputs = tf.keras.layers.Input(shape=[codings_size])
x = tf.keras.layers.Dense(100, activation="relu")(decoder_inputs)
x = tf.keras.layers.Dense(150, activation="relu")(x)
x = tf.keras.layers.Dense(28 * 28)(x)
outputs = tf.keras.layers.Reshape([28, 28])(x)
variational_decoder = tf.keras.Model(decoder_inputs, outputs)

_, _, codings = variational_encoder(inputs)
reconstructions = variational_decoder(codings)
variational_ae = tf.keras.Model(inputs=[inputs], outputs=[reconstructions])

تولید Image و Semantic Interpolation با VAE

پس از Training کافی است Codingهای Random از Gaussian استاندارد Sample شوند و به Decoder داده شوند. خروجی‌ها معمولاً Smooth و کمی Blurry هستند، اما بسیاری از آن‌ها شبیه نمونه‌های واقعی Fashion MNIST خواهند بود.

17-12 - تولید Image و Semantic Interpolation با VAE
شکل 17-12. تولید Image و Semantic Interpolation با VAE

Latent Space پیوسته است؛ بنابراین می‌توان بین دو Coding Interpolate کرد و Sequence از Imageهایی ساخت که به‌تدریج از یک مفهوم به مفهوم دیگر تبدیل می‌شوند.

17-13 - تولید Image و Semantic Interpolation با VAE
شکل 17-13. تولید Image و Semantic Interpolation با VAE

Generative Adversarial Network

GAN در سال ۲۰۱۴ معرفی شد و از دو شبکه تشکیل می‌شود:

  • Generator: یک Coding تصادفی را به Sample Fake تبدیل می‌کند.
  • Discriminator: یک Sample را می‌گیرد و Probability واقعی بودن آن را پیش‌بینی می‌کند.
17-14 - Generative Adversarial Network
شکل 17-14. Generative Adversarial Network

Training دو Phase دارد. در Phase اول Discriminator با Batch ترکیبی Real/Fake Train می‌شود. در Phase دوم Generator از طریق GAN Train می‌شود و Target همهٔ Fakeها عمداً «Real» قرار می‌گیرد تا Generator یاد بگیرد Discriminator را فریب دهد.

GAN ساده برای Fashion MNIST

codings_size = 30
Dense = tf.keras.layers.Dense

generator = tf.keras.Sequential([
    Dense(100, activation="selu"),
    Dense(150, activation="selu"),
    Dense(28 * 28, activation="sigmoid"),
    tf.keras.layers.Reshape([28, 28])
])

discriminator = tf.keras.Sequential([
    tf.keras.layers.Flatten(),
    Dense(150, activation="selu"),
    Dense(100, activation="selu"),
    Dense(1, activation="sigmoid")
])

gan = tf.keras.Sequential([generator, discriminator])
discriminator.compile(loss="binary_crossentropy", optimizer="rmsprop")
discriminator.trainable = False
gan.compile(loss="binary_crossentropy", optimizer="rmsprop")

ویژگی مهم این است که trainable هنگام Compile در Graph Training لحاظ می‌شود: Discriminator در Training مستقیم خودش Trainable است، ولی هنگام Train کردن GAN Freeze می‌ماند.

Custom Training Loop برای GAN

batch_size = 32
dataset = tf.data.Dataset.from_tensor_slices(X_train).shuffle(1000)
dataset = dataset.batch(batch_size, drop_remainder=True).prefetch(1)

def train_gan(gan, dataset, batch_size, codings_size, n_epochs):
    generator, discriminator = gan.layers
    for epoch in range(n_epochs):
        for X_batch in dataset:
            # phase 1: discriminator
            noise = tf.random.normal([batch_size, codings_size])
            generated_images = generator(noise)
            X_fake_and_real = tf.concat([generated_images, X_batch], axis=0)
            y1 = tf.constant([[0.]] * batch_size + [[1.]] * batch_size)
            discriminator.train_on_batch(X_fake_and_real, y1)

            # phase 2: generator
            noise = tf.random.normal([batch_size, codings_size])
            y2 = tf.constant([[1.]] * batch_size)
            gan.train_on_batch(noise, y2)
17-15 - Custom Training Loop برای GAN
شکل 17-15. Custom Training Loop برای GAN

مشکلات Training GAN

GAN یک Game پویا بین دو Model است و Loss معمول Supervised رفتار ساده‌ای ندارد. از نظر نظری Equilibrium مطلوب زمانی است که Distribution Generator با Data واقعی یکسان شود و Discriminator فقط بتواند با Probability 50% حدس بزند. اما Gradient Descent تضمین نمی‌کند این Nash Equilibrium را پیدا کند.

Mode Collapse

Generator ممکن است فقط چند Mode محدود را تولید کند؛ مثلاً مدتی فقط Shoe بسازد چون در فریب Discriminator برای آن Class موفق‌تر است. Discriminator نیز روی همین Fakeهای جدید Overfit می‌کند و Dynamics می‌تواند بین Modeهای مختلف Oscillate کند.

راهکارهای پیشنهادی شامل Experience Replay، Mini-batch Discrimination، Lossهای جایگزین و Architectureهای پایدارتر هستند. Hyperparameterها، Random Seed و Learning Rate نسبی دو Network اثر زیادی دارند.

Deep Convolutional GAN یا DCGAN

DCGAN مجموعه‌ای از Guidelineهای تجربی برای GANهای تصویری پایدارتر معرفی کرد:

  • Pooling را با Strided Convolution در Discriminator و Transposed Convolution در Generator جایگزین کنید.
  • Batch Normalization را در بیشتر Layerهای هر دو Network استفاده کنید، به‌جز Input Discriminator و Output Generator.
  • در Architecture عمیق Fully Connected Hidden Layerها را حذف کنید.
  • در Generator از ReLU استفاده کنید و Output را با tanh بسازید.
  • در Discriminator از Leaky ReLU استفاده کنید.
codings_size = 100
generator = tf.keras.Sequential([
    tf.keras.layers.Dense(7 * 7 * 128),
    tf.keras.layers.Reshape([7, 7, 128]),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Conv2DTranspose(64, 5, strides=2,
                                    padding="same", activation="relu"),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Conv2DTranspose(1, 5, strides=2,
                                    padding="same", activation="tanh")
])

discriminator = tf.keras.Sequential([
    tf.keras.layers.Conv2D(64, 5, strides=2, padding="same",
        activation=tf.keras.layers.LeakyReLU(0.2)),
    tf.keras.layers.Dropout(0.4),
    tf.keras.layers.Conv2D(128, 5, strides=2, padding="same",
        activation=tf.keras.layers.LeakyReLU(0.2)),
    tf.keras.layers.Dropout(0.4),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(1, activation="sigmoid")
])

چون Generator با tanh Output می‌دهد، Data Training باید به بازهٔ [-1,1] Rescale شود. در این مثال Dropout در Discriminator از BatchNorm پایدارتر عمل کرده است؛ GANها به جزئیات Architecture حساس‌اند.

امتیاز کاربران به این مقاله

☆☆☆☆☆

0 نفر امتیاز داده اند. میانگین: 0.0 از 5

 

0 نظر

نظر محترم شما در مورد مقاله های وب سایت برنامه نویسی و پایگاه داده

نظرات محترم شما در خدمات رسانی بهتر ما را یاری می نمایند. لطفا اگر مایل بودید یک نظر ما را مهمان فرمائید. آدرس ایمیل و وب سایت شما نمایش داده نخواهد شد.

0 / 500

اطلاعات تماس

  • آدرس:اصفهان-خیابان ام کلثوم غربی - بعد خیابان تخم چی - بیست متر بعد از پیتزا ننه شب - کوچه تعمیر گاه سمار زغالی - پلاک 354 - درب مشکی - طبقه هفتم
  • آدرس ایمیل:najafzade@gmail.com
  • وب سایت:http://www.a00b.com/
  • تلفن ثابت:(+98)9131253620
  • تلفن همراه:09131253620