YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
- BEHOLD! A WHISPER OF THE GODS (aka, a massively simplified GAN skeleton in Keras)
- === GENERATOR === (The Artist, the Dream Weaver)
- === DISCRIMINATOR === (The Art Critic, the Gatekeeper of Reality)
- --- HYPERPARAMETERS - TWEAK THESE UNTIL YOUR BRAIN MELTS (or magic happens) ---
- --- BUILD THE COMBATANTS! ---
- --- LOSS FUNCTIONS & OPTIMIZERS - THE SECRET SAUCE ---
- --- TRAINING STEP - WHERE THE MAGIC HAPPENS (and your GPUs sweat) ---
- --- TRAINING LOOP - THE ENDLESS GRIND (prepare for weeks, maybe months) ---
- YOU NEED TO LOAD YOUR OWN DATASET OF IMAGES HERE!
train_images = load_your_damn_dataset() - train_dataset = tf.data.Dataset.from_tensor_slices(train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
- BUFFER_SIZE = 60000 # or however large your dataset is
- for epoch in range(EPOCHS):
- for image_batch in train_dataset:
- train_step(image_batch)
- print ('Epoch {} complete'.format(epoch + 1))
- # YOU'LL WANT TO SAVE GENERATOR MODELS PERIODICALLY AND SAMPLE GENERATED IMAGES TO TRACK PROGRESS
- --- AFTER TRAINING (IF YOU SURVIVE) ---
- noise = tf.random.normal([1, LATENT_DIM]) # Generate a SINGLE enhanced image
- enhanced_image = generator(noise, training=False)
- # Post-process 'enhanced_image' (scale from [-1, 1] to [0, 255], convert to PIL image, etc.)
- # SAVE OR DISPLAY YOUR CREATION!
BEHOLD! A WHISPER OF THE GODS (aka, a massively simplified GAN skeleton in Keras)
import tensorflow as tf from tensorflow.keras import layers, models
=== GENERATOR === (The Artist, the Dream Weaver)
def build_generator(latent_dim, output_channels=3): model = models.Sequential([ layers.Dense(77256, use_bias=False, input_shape=(latent_dim,)), layers.BatchNormalization(), layers.LeakyReLU(),
layers.Reshape((7, 7, 256)),
# Upsample to 14x14
layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same', use_bias=False),
layers.BatchNormalization(),
layers.LeakyReLU(),
# Upsample to 28x28
layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=False),
layers.BatchNormalization(),
layers.LeakyReLU(),
# Upsample to desired resolution (let's say...64x64 for now - YOU'LL WANT MORE)
layers.Conv2DTranspose(output_channels, (5, 5), strides=(2, 2), padding='same', use_bias=False, activation='tanh') # tanh output for pixel values -1 to 1
])
return model
=== DISCRIMINATOR === (The Art Critic, the Gatekeeper of Reality)
def build_discriminator(input_shape=(64, 64, 3)): # Adjust input shape to match Generator output model = models.Sequential([ layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=input_shape), layers.LeakyReLU(), layers.Dropout(0.3),
layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'),
layers.LeakyReLU(),
layers.Dropout(0.3),
layers.Flatten(),
layers.Dense(1) # Output: Real or Fake (Binary Classification)
])
return model
--- HYPERPARAMETERS - TWEAK THESE UNTIL YOUR BRAIN MELTS (or magic happens) ---
LATENT_DIM = 100 # Noise dimension for Generator input IMG_WIDTH = 64 # Target image width (start small, go BIG later) IMG_HEIGHT = 64 # Target image height CHANNELS = 3 # Color channels (RGB)
--- BUILD THE COMBATANTS! ---
generator = build_generator(LATENT_DIM, CHANNELS) discriminator = build_discriminator((IMG_WIDTH, IMG_HEIGHT, CHANNELS))
--- LOSS FUNCTIONS & OPTIMIZERS - THE SECRET SAUCE ---
cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True) # For Real vs Fake battles
def discriminator_loss(real_output, fake_output): real_loss = cross_entropy(tf.ones_like(real_output), real_output) # Discriminator wants to classify REAL images as REAL (ones) fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output) # Discriminator wants to classify FAKE images as FAKE (zeros) total_loss = real_loss + fake_loss return total_loss
def generator_loss(fake_output): return cross_entropy(tf.ones_like(fake_output), fake_output) # Generator wants Discriminator to think FAKE images are REAL (ones)
generator_optimizer = tf.keras.optimizers.Adam(1e-4) # Adam - the workhorse optimizer discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)
--- TRAINING STEP - WHERE THE MAGIC HAPPENS (and your GPUs sweat) ---
@tf.function # Compile into a callable TensorFlow graph for speed def train_step(images): noise = tf.random.normal([BATCH_SIZE, LATENT_DIM]) # Generator input: random noise
with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
generated_images = generator(noise, training=True) # Generator creates FAKE images
real_output = discriminator(images, training=True) # Discriminator judges REAL images
fake_output = discriminator(generated_images, training=True) # Discriminator judges FAKE images
gen_loss = generator_loss(fake_output) # Generator loss based on Discriminator's judgment
disc_loss = discriminator_loss(real_output, fake_output) # Discriminator loss
gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables) # Backpropagate Generator loss
gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables) # Backpropagate Discriminator loss
generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables)) # Update Generator weights
discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables)) # Update Discriminator weights
--- TRAINING LOOP - THE ENDLESS GRIND (prepare for weeks, maybe months) ---
BATCH_SIZE = 256 # Tune this - higher might be faster but need more GPU RAM EPOCHS = 50 # Start with this, you'll need WAY more in reality