From 4f11140cdcf3f2be607b16ad15297f4e05863068 Mon Sep 17 00:00:00 2001 From: sineeli <113718461+sineeli@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:31:18 -0800 Subject: [PATCH 1/8] Migrate to Keras 3 --- .../generative/dcgan_overriding_train_step.py | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/examples/generative/dcgan_overriding_train_step.py b/examples/generative/dcgan_overriding_train_step.py index 14455251c6..e6117c69c1 100644 --- a/examples/generative/dcgan_overriding_train_step.py +++ b/examples/generative/dcgan_overriding_train_step.py @@ -2,7 +2,7 @@ Title: DCGAN to generate face images Author: [fchollet](https://twitter.com/fchollet) Date created: 2019/04/29 -Last modified: 2021/01/01 +Last modified: 2023/12/21 Description: A simple DCGAN trained using `fit()` by overriding `train_step` on CelebA images. Accelerator: GPU """ @@ -10,9 +10,11 @@ ## Setup """ +import keras import tensorflow as tf -from tensorflow import keras -from tensorflow.keras import layers + +from keras import layers +from keras import ops import matplotlib.pyplot as plt import os import gdown @@ -64,11 +66,11 @@ [ keras.Input(shape=(64, 64, 3)), layers.Conv2D(64, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2D(128, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2D(128, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Flatten(), layers.Dropout(0.2), layers.Dense(1, activation="sigmoid"), @@ -91,11 +93,11 @@ layers.Dense(8 * 8 * 128), layers.Reshape((8, 8, 128)), layers.Conv2DTranspose(128, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2DTranspose(256, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2DTranspose(512, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2D(3, kernel_size=5, padding="same", activation="sigmoid"), ], name="generator", @@ -107,6 +109,7 @@ """ + class GAN(keras.Model): def __init__(self, discriminator, generator, latent_dim): super().__init__() @@ -128,18 +131,18 @@ def metrics(self): def train_step(self, real_images): # Sample random points in the latent space - batch_size = tf.shape(real_images)[0] - random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim)) + batch_size = ops.shape(real_images)[0] + random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim)) # Decode them to fake images generated_images = self.generator(random_latent_vectors) # Combine them with real images - combined_images = tf.concat([generated_images, real_images], axis=0) + combined_images = ops.concatenate([generated_images, real_images], axis=0) # Assemble labels discriminating real from fake images - labels = tf.concat( - [tf.ones((batch_size, 1)), tf.zeros((batch_size, 1))], axis=0 + labels = ops.concatenate( + [ops.ones((batch_size, 1)), ops.zeros((batch_size, 1))], axis=0 ) # Add random noise to the labels - important trick! labels += 0.05 * tf.random.uniform(tf.shape(labels)) @@ -154,10 +157,10 @@ def train_step(self, real_images): ) # Sample random points in the latent space - random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim)) + random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim)) # Assemble labels that say "all real images" - misleading_labels = tf.zeros((batch_size, 1)) + misleading_labels = ops.zeros((batch_size, 1)) # Train the generator (note that we should *not* update the weights # of the discriminator)! @@ -176,6 +179,7 @@ def train_step(self, real_images): } + """ ## Create a callback that periodically saves generated images """ @@ -187,7 +191,7 @@ def __init__(self, num_img=3, latent_dim=128): self.latent_dim = latent_dim def on_epoch_end(self, epoch, logs=None): - random_latent_vectors = tf.random.normal(shape=(self.num_img, self.latent_dim)) + random_latent_vectors = keras.random.normal(shape=(self.num_img, self.latent_dim)) generated_images = self.model.generator(random_latent_vectors) generated_images *= 255 generated_images.numpy() From 75050b840ccc24aa1d423cb89a60039d5bc70f4d Mon Sep 17 00:00:00 2001 From: Sravana Neeli Date: Thu, 21 Dec 2023 22:32:35 +0000 Subject: [PATCH 2/8] Keras 3 Migration --- .../generative/dcgan_overriding_train_step.py | 6 +- .../dcgan_overriding_train_step_8_0.png | Bin 10737 -> 17155 bytes .../ipynb/dcgan_overriding_train_step.ipynb | 40 ++-- .../md/dcgan_overriding_train_step.md | 212 +++++++++++------- 4 files changed, 157 insertions(+), 101 deletions(-) diff --git a/examples/generative/dcgan_overriding_train_step.py b/examples/generative/dcgan_overriding_train_step.py index e6117c69c1..e7f698f409 100644 --- a/examples/generative/dcgan_overriding_train_step.py +++ b/examples/generative/dcgan_overriding_train_step.py @@ -109,7 +109,6 @@ """ - class GAN(keras.Model): def __init__(self, discriminator, generator, latent_dim): super().__init__() @@ -179,7 +178,6 @@ def train_step(self, real_images): } - """ ## Create a callback that periodically saves generated images """ @@ -191,7 +189,9 @@ def __init__(self, num_img=3, latent_dim=128): self.latent_dim = latent_dim def on_epoch_end(self, epoch, logs=None): - random_latent_vectors = keras.random.normal(shape=(self.num_img, self.latent_dim)) + random_latent_vectors = keras.random.normal( + shape=(self.num_img, self.latent_dim) + ) generated_images = self.model.generator(random_latent_vectors) generated_images *= 255 generated_images.numpy() diff --git a/examples/generative/img/dcgan_overriding_train_step/dcgan_overriding_train_step_8_0.png b/examples/generative/img/dcgan_overriding_train_step/dcgan_overriding_train_step_8_0.png index 37a0f5d18b363daaa922fd82b807d23b818203a4..4dcd88352add502ec32571fce6b30d2bed272951 100644 GIT binary patch literal 17155 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 B?QQ@7 literal 10737 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 Hybk_\n", "**Date created:** 2019/04/29
\n", - "**Last modified:** 2021/01/01
\n", + "**Last modified:** 2023/12/21
\n", "**Description:** A simple DCGAN trained using `fit()` by overriding `train_step` on CelebA images." ] }, @@ -31,9 +31,11 @@ }, "outputs": [], "source": [ + "import keras\n", "import tensorflow as tf\n", - "from tensorflow import keras\n", - "from tensorflow.keras import layers\n", + "\n", + "from keras import layers\n", + "from keras import ops\n", "import matplotlib.pyplot as plt\n", "import os\n", "import gdown\n", @@ -141,11 +143,11 @@ " [\n", " keras.Input(shape=(64, 64, 3)),\n", " layers.Conv2D(64, kernel_size=4, strides=2, padding=\"same\"),\n", - " layers.LeakyReLU(alpha=0.2),\n", + " layers.LeakyReLU(negative_slope=0.2),\n", " layers.Conv2D(128, kernel_size=4, strides=2, padding=\"same\"),\n", - " layers.LeakyReLU(alpha=0.2),\n", + " layers.LeakyReLU(negative_slope=0.2),\n", " layers.Conv2D(128, kernel_size=4, strides=2, padding=\"same\"),\n", - " layers.LeakyReLU(alpha=0.2),\n", + " layers.LeakyReLU(negative_slope=0.2),\n", " layers.Flatten(),\n", " layers.Dropout(0.2),\n", " layers.Dense(1, activation=\"sigmoid\"),\n", @@ -182,11 +184,11 @@ " layers.Dense(8 * 8 * 128),\n", " layers.Reshape((8, 8, 128)),\n", " layers.Conv2DTranspose(128, kernel_size=4, strides=2, padding=\"same\"),\n", - " layers.LeakyReLU(alpha=0.2),\n", + " layers.LeakyReLU(negative_slope=0.2),\n", " layers.Conv2DTranspose(256, kernel_size=4, strides=2, padding=\"same\"),\n", - " layers.LeakyReLU(alpha=0.2),\n", + " layers.LeakyReLU(negative_slope=0.2),\n", " layers.Conv2DTranspose(512, kernel_size=4, strides=2, padding=\"same\"),\n", - " layers.LeakyReLU(alpha=0.2),\n", + " layers.LeakyReLU(negative_slope=0.2),\n", " layers.Conv2D(3, kernel_size=5, padding=\"same\", activation=\"sigmoid\"),\n", " ],\n", " name=\"generator\",\n", @@ -233,18 +235,18 @@ "\n", " def train_step(self, real_images):\n", " # Sample random points in the latent space\n", - " batch_size = tf.shape(real_images)[0]\n", - " random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim))\n", + " batch_size = ops.shape(real_images)[0]\n", + " random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim))\n", "\n", " # Decode them to fake images\n", " generated_images = self.generator(random_latent_vectors)\n", "\n", " # Combine them with real images\n", - " combined_images = tf.concat([generated_images, real_images], axis=0)\n", + " combined_images = ops.concatenate([generated_images, real_images], axis=0)\n", "\n", " # Assemble labels discriminating real from fake images\n", - " labels = tf.concat(\n", - " [tf.ones((batch_size, 1)), tf.zeros((batch_size, 1))], axis=0\n", + " labels = ops.concatenate(\n", + " [ops.ones((batch_size, 1)), ops.zeros((batch_size, 1))], axis=0\n", " )\n", " # Add random noise to the labels - important trick!\n", " labels += 0.05 * tf.random.uniform(tf.shape(labels))\n", @@ -259,10 +261,10 @@ " )\n", "\n", " # Sample random points in the latent space\n", - " random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim))\n", + " random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim))\n", "\n", " # Assemble labels that say \"all real images\"\n", - " misleading_labels = tf.zeros((batch_size, 1))\n", + " misleading_labels = ops.zeros((batch_size, 1))\n", "\n", " # Train the generator (note that we should *not* update the weights\n", " # of the discriminator)!\n", @@ -306,7 +308,9 @@ " self.latent_dim = latent_dim\n", "\n", " def on_epoch_end(self, epoch, logs=None):\n", - " random_latent_vectors = tf.random.normal(shape=(self.num_img, self.latent_dim))\n", + " random_latent_vectors = keras.random.normal(\n", + " shape=(self.num_img, self.latent_dim)\n", + " )\n", " generated_images = self.model.generator(random_latent_vectors)\n", " generated_images *= 255\n", " generated_images.numpy()\n", @@ -389,4 +393,4 @@ }, "nbformat": 4, "nbformat_minor": 0 -} +} \ No newline at end of file diff --git a/examples/generative/md/dcgan_overriding_train_step.md b/examples/generative/md/dcgan_overriding_train_step.md index 2b76f4f9ee..7a121698d2 100644 --- a/examples/generative/md/dcgan_overriding_train_step.md +++ b/examples/generative/md/dcgan_overriding_train_step.md @@ -2,7 +2,7 @@ **Author:** [fchollet](https://twitter.com/fchollet)
**Date created:** 2019/04/29
-**Last modified:** 2021/01/01
+**Last modified:** 2023/12/21
**Description:** A simple DCGAN trained using `fit()` by overriding `train_step` on CelebA images. @@ -15,9 +15,11 @@ ```python +import keras import tensorflow as tf -from tensorflow import keras -from tensorflow.keras import layers + +from keras import layers +from keras import ops import matplotlib.pyplot as plt import os import gdown @@ -54,7 +56,7 @@ dataset = dataset.map(lambda x: x / 255.0)
``` -Found 202599 files belonging to 1 classes. +Found 202599 files. ```
@@ -71,7 +73,9 @@ for x in dataset: ``` + ![png](/img/examples/generative/dcgan_overriding_train_step/dcgan_overriding_train_step_8_0.png) + --- @@ -85,11 +89,11 @@ discriminator = keras.Sequential( [ keras.Input(shape=(64, 64, 3)), layers.Conv2D(64, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2D(128, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2D(128, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Flatten(), layers.Dropout(0.2), layers.Dense(1, activation="sigmoid"), @@ -99,37 +103,56 @@ discriminator = keras.Sequential( discriminator.summary() ``` -
-``` -Model: "discriminator" -_________________________________________________________________ -Layer (type) Output Shape Param # -================================================================= -conv2d (Conv2D) (None, 32, 32, 64) 3136 -_________________________________________________________________ -leaky_re_lu (LeakyReLU) (None, 32, 32, 64) 0 -_________________________________________________________________ -conv2d_1 (Conv2D) (None, 16, 16, 128) 131200 -_________________________________________________________________ -leaky_re_lu_1 (LeakyReLU) (None, 16, 16, 128) 0 -_________________________________________________________________ -conv2d_2 (Conv2D) (None, 8, 8, 128) 262272 -_________________________________________________________________ -leaky_re_lu_2 (LeakyReLU) (None, 8, 8, 128) 0 -_________________________________________________________________ -flatten (Flatten) (None, 8192) 0 -_________________________________________________________________ -dropout (Dropout) (None, 8192) 0 -_________________________________________________________________ -dense (Dense) (None, 1) 8193 -================================================================= -Total params: 404,801 -Trainable params: 404,801 -Non-trainable params: 0 -_________________________________________________________________ -``` -
+
Model: "discriminator"
+
+ + + + +
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
+┃ Layer (type)                     Output Shape                  Param # ┃
+┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
+│ conv2d (Conv2D)                 │ (None, 32, 32, 64)        │      3,136 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ leaky_re_lu (LeakyReLU)         │ (None, 32, 32, 64)        │          0 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ conv2d_1 (Conv2D)               │ (None, 16, 16, 128)       │    131,200 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ leaky_re_lu_1 (LeakyReLU)       │ (None, 16, 16, 128)       │          0 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ conv2d_2 (Conv2D)               │ (None, 8, 8, 128)         │    262,272 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ leaky_re_lu_2 (LeakyReLU)       │ (None, 8, 8, 128)         │          0 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ flatten (Flatten)               │ (None, 8192)              │          0 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ dropout (Dropout)               │ (None, 8192)              │          0 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ dense (Dense)                   │ (None, 1)                 │      8,193 │
+└─────────────────────────────────┴───────────────────────────┴────────────┘
+
+ + + + +
 Total params: 404,801 (1.54 MB)
+
+ + + + +
 Trainable params: 404,801 (1.54 MB)
+
+ + + + +
 Non-trainable params: 0 (0.00 B)
+
+ + + --- ## Create the generator @@ -145,11 +168,11 @@ generator = keras.Sequential( layers.Dense(8 * 8 * 128), layers.Reshape((8, 8, 128)), layers.Conv2DTranspose(128, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2DTranspose(256, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2DTranspose(512, kernel_size=4, strides=2, padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2D(3, kernel_size=5, padding="same", activation="sigmoid"), ], name="generator", @@ -157,37 +180,59 @@ generator = keras.Sequential( generator.summary() ``` -
-``` -Model: "generator" -_________________________________________________________________ -Layer (type) Output Shape Param # -================================================================= -dense_1 (Dense) (None, 8192) 1056768 -_________________________________________________________________ -reshape (Reshape) (None, 8, 8, 128) 0 -_________________________________________________________________ -conv2d_transpose (Conv2DTran (None, 16, 16, 128) 262272 -_________________________________________________________________ -leaky_re_lu_3 (LeakyReLU) (None, 16, 16, 128) 0 -_________________________________________________________________ -conv2d_transpose_1 (Conv2DTr (None, 32, 32, 256) 524544 -_________________________________________________________________ -leaky_re_lu_4 (LeakyReLU) (None, 32, 32, 256) 0 -_________________________________________________________________ -conv2d_transpose_2 (Conv2DTr (None, 64, 64, 512) 2097664 -_________________________________________________________________ -leaky_re_lu_5 (LeakyReLU) (None, 64, 64, 512) 0 -_________________________________________________________________ -conv2d_3 (Conv2D) (None, 64, 64, 3) 38403 -================================================================= -Total params: 3,979,651 -Trainable params: 3,979,651 -Non-trainable params: 0 -_________________________________________________________________ -``` -
+
Model: "generator"
+
+ + + + +
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
+┃ Layer (type)                     Output Shape                  Param # ┃
+┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
+│ dense_1 (Dense)                 │ (None, 8192)              │  1,056,768 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ reshape (Reshape)               │ (None, 8, 8, 128)         │          0 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ conv2d_transpose                │ (None, 16, 16, 128)       │    262,272 │
+│ (Conv2DTranspose)               │                           │            │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ leaky_re_lu_3 (LeakyReLU)       │ (None, 16, 16, 128)       │          0 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ conv2d_transpose_1              │ (None, 32, 32, 256)       │    524,544 │
+│ (Conv2DTranspose)               │                           │            │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ leaky_re_lu_4 (LeakyReLU)       │ (None, 32, 32, 256)       │          0 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ conv2d_transpose_2              │ (None, 64, 64, 512)       │  2,097,664 │
+│ (Conv2DTranspose)               │                           │            │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ leaky_re_lu_5 (LeakyReLU)       │ (None, 64, 64, 512)       │          0 │
+├─────────────────────────────────┼───────────────────────────┼────────────┤
+│ conv2d_3 (Conv2D)               │ (None, 64, 64, 3)         │     38,403 │
+└─────────────────────────────────┴───────────────────────────┴────────────┘
+
+ + + + +
 Total params: 3,979,651 (15.18 MB)
+
+ + + + +
 Trainable params: 3,979,651 (15.18 MB)
+
+ + + + +
 Non-trainable params: 0 (0.00 B)
+
+ + + --- ## Override `train_step` @@ -215,18 +260,18 @@ class GAN(keras.Model): def train_step(self, real_images): # Sample random points in the latent space - batch_size = tf.shape(real_images)[0] - random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim)) + batch_size = ops.shape(real_images)[0] + random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim)) # Decode them to fake images generated_images = self.generator(random_latent_vectors) # Combine them with real images - combined_images = tf.concat([generated_images, real_images], axis=0) + combined_images = ops.concatenate([generated_images, real_images], axis=0) # Assemble labels discriminating real from fake images - labels = tf.concat( - [tf.ones((batch_size, 1)), tf.zeros((batch_size, 1))], axis=0 + labels = ops.concatenate( + [ops.ones((batch_size, 1)), ops.zeros((batch_size, 1))], axis=0 ) # Add random noise to the labels - important trick! labels += 0.05 * tf.random.uniform(tf.shape(labels)) @@ -241,10 +286,10 @@ class GAN(keras.Model): ) # Sample random points in the latent space - random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim)) + random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim)) # Assemble labels that say "all real images" - misleading_labels = tf.zeros((batch_size, 1)) + misleading_labels = ops.zeros((batch_size, 1)) # Train the generator (note that we should *not* update the weights # of the discriminator)! @@ -276,7 +321,9 @@ class GANMonitor(keras.callbacks.Callback): self.latent_dim = latent_dim def on_epoch_end(self, epoch, logs=None): - random_latent_vectors = tf.random.normal(shape=(self.num_img, self.latent_dim)) + random_latent_vectors = keras.random.normal( + shape=(self.num_img, self.latent_dim) + ) generated_images = self.model.generator(random_latent_vectors) generated_images *= 255 generated_images.numpy() @@ -307,9 +354,14 @@ gan.fit(
``` -6332/6332 [==============================] - 605s 96ms/step - d_loss: 0.6113 - g_loss: 1.1976 + 2/6332 ━━━━━━━━━━━━━━━━━━━━ 9:37 91ms/step - d_loss: 0.6853 - g_loss: 0.7761 + +WARNING: All log messages before absl::InitializeLog() is called are written to STDERR +I0000 00:00:1703188912.818851 3649 device_compiler.h:186] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process. + + 6332/6332 ━━━━━━━━━━━━━━━━━━━━ 558s 84ms/step - d_loss: 0.5599 - g_loss: 1.4323 - + ```
From 4daca88c0dc6a68847226020e27d5960173a7293 Mon Sep 17 00:00:00 2001 From: sineeli <113718461+sineeli@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:00:31 -0800 Subject: [PATCH 3/8] Add seed generator to keras.random --- .../generative/dcgan_overriding_train_step.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/examples/generative/dcgan_overriding_train_step.py b/examples/generative/dcgan_overriding_train_step.py index e7f698f409..c236458627 100644 --- a/examples/generative/dcgan_overriding_train_step.py +++ b/examples/generative/dcgan_overriding_train_step.py @@ -20,6 +20,8 @@ import gdown from zipfile import ZipFile +seed_generator = keras.random.SeedGenerator(42) + """ ## Prepare CelebA data @@ -131,7 +133,10 @@ def metrics(self): def train_step(self, real_images): # Sample random points in the latent space batch_size = ops.shape(real_images)[0] - random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim)) + random_latent_vectors = keras.random.normal( + shape=(batch_size, self.latent_dim), + seed=seed_generator + ) # Decode them to fake images generated_images = self.generator(random_latent_vectors) @@ -156,7 +161,10 @@ def train_step(self, real_images): ) # Sample random points in the latent space - random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim)) + random_latent_vectors = keras.random.normal( + shape=(batch_size, self.latent_dim), + seed=seed_generator + ) # Assemble labels that say "all real images" misleading_labels = ops.zeros((batch_size, 1)) @@ -190,7 +198,8 @@ def __init__(self, num_img=3, latent_dim=128): def on_epoch_end(self, epoch, logs=None): random_latent_vectors = keras.random.normal( - shape=(self.num_img, self.latent_dim) + shape=(self.num_img, self.latent_dim), + seed=seed_generator ) generated_images = self.model.generator(random_latent_vectors) generated_images *= 255 From 876653641c4ba2f7fb87088490656f15223c950d Mon Sep 17 00:00:00 2001 From: Siva Sravana Kumar Neeli Date: Wed, 27 Dec 2023 22:30:23 +0000 Subject: [PATCH 4/8] Train using seed generator --- .../generative/dcgan_overriding_train_step.py | 9 +++----- .../dcgan_overriding_train_step_8_0.png | Bin 17155 -> 16279 bytes .../ipynb/dcgan_overriding_train_step.ipynb | 14 ++++++++---- .../md/dcgan_overriding_train_step.md | 20 ++++++++++++------ 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/examples/generative/dcgan_overriding_train_step.py b/examples/generative/dcgan_overriding_train_step.py index c236458627..b54139812c 100644 --- a/examples/generative/dcgan_overriding_train_step.py +++ b/examples/generative/dcgan_overriding_train_step.py @@ -134,8 +134,7 @@ def train_step(self, real_images): # Sample random points in the latent space batch_size = ops.shape(real_images)[0] random_latent_vectors = keras.random.normal( - shape=(batch_size, self.latent_dim), - seed=seed_generator + shape=(batch_size, self.latent_dim), seed=seed_generator ) # Decode them to fake images @@ -162,8 +161,7 @@ def train_step(self, real_images): # Sample random points in the latent space random_latent_vectors = keras.random.normal( - shape=(batch_size, self.latent_dim), - seed=seed_generator + shape=(batch_size, self.latent_dim), seed=seed_generator ) # Assemble labels that say "all real images" @@ -198,8 +196,7 @@ def __init__(self, num_img=3, latent_dim=128): def on_epoch_end(self, epoch, logs=None): random_latent_vectors = keras.random.normal( - shape=(self.num_img, self.latent_dim), - seed=seed_generator + shape=(self.num_img, self.latent_dim), seed=seed_generator ) generated_images = self.model.generator(random_latent_vectors) generated_images *= 255 diff --git a/examples/generative/img/dcgan_overriding_train_step/dcgan_overriding_train_step_8_0.png b/examples/generative/img/dcgan_overriding_train_step/dcgan_overriding_train_step_8_0.png index 4dcd88352add502ec32571fce6b30d2bed272951..bb14a72a81f93e558881e38901d74f3e90eca7ea 100644 GIT binary patch literal 16279 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 Qv?sZzWvE%BZXff107gZ;$N&HU literal 17155 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 B?QQ@7 diff --git a/examples/generative/ipynb/dcgan_overriding_train_step.ipynb b/examples/generative/ipynb/dcgan_overriding_train_step.ipynb index 828fff6b8c..5b7052321e 100644 --- a/examples/generative/ipynb/dcgan_overriding_train_step.ipynb +++ b/examples/generative/ipynb/dcgan_overriding_train_step.ipynb @@ -39,7 +39,9 @@ "import matplotlib.pyplot as plt\n", "import os\n", "import gdown\n", - "from zipfile import ZipFile" + "from zipfile import ZipFile\n", + "\n", + "seed_generator = keras.random.SeedGenerator(42)" ] }, { @@ -236,7 +238,9 @@ " def train_step(self, real_images):\n", " # Sample random points in the latent space\n", " batch_size = ops.shape(real_images)[0]\n", - " random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim))\n", + " random_latent_vectors = keras.random.normal(\n", + " shape=(batch_size, self.latent_dim), seed=seed_generator\n", + " )\n", "\n", " # Decode them to fake images\n", " generated_images = self.generator(random_latent_vectors)\n", @@ -261,7 +265,9 @@ " )\n", "\n", " # Sample random points in the latent space\n", - " random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim))\n", + " random_latent_vectors = keras.random.normal(\n", + " shape=(batch_size, self.latent_dim), seed=seed_generator\n", + " )\n", "\n", " # Assemble labels that say \"all real images\"\n", " misleading_labels = ops.zeros((batch_size, 1))\n", @@ -309,7 +315,7 @@ "\n", " def on_epoch_end(self, epoch, logs=None):\n", " random_latent_vectors = keras.random.normal(\n", - " shape=(self.num_img, self.latent_dim)\n", + " shape=(self.num_img, self.latent_dim), seed=seed_generator\n", " )\n", " generated_images = self.model.generator(random_latent_vectors)\n", " generated_images *= 255\n", diff --git a/examples/generative/md/dcgan_overriding_train_step.md b/examples/generative/md/dcgan_overriding_train_step.md index 7a121698d2..8592f9acf6 100644 --- a/examples/generative/md/dcgan_overriding_train_step.md +++ b/examples/generative/md/dcgan_overriding_train_step.md @@ -24,6 +24,8 @@ import matplotlib.pyplot as plt import os import gdown from zipfile import ZipFile + +seed_generator = keras.random.SeedGenerator(42) ``` --- @@ -261,7 +263,9 @@ class GAN(keras.Model): def train_step(self, real_images): # Sample random points in the latent space batch_size = ops.shape(real_images)[0] - random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim)) + random_latent_vectors = keras.random.normal( + shape=(batch_size, self.latent_dim), seed=seed_generator + ) # Decode them to fake images generated_images = self.generator(random_latent_vectors) @@ -286,7 +290,9 @@ class GAN(keras.Model): ) # Sample random points in the latent space - random_latent_vectors = keras.random.normal(shape=(batch_size, self.latent_dim)) + random_latent_vectors = keras.random.normal( + shape=(batch_size, self.latent_dim), seed=seed_generator + ) # Assemble labels that say "all real images" misleading_labels = ops.zeros((batch_size, 1)) @@ -322,7 +328,7 @@ class GANMonitor(keras.callbacks.Callback): def on_epoch_end(self, epoch, logs=None): random_latent_vectors = keras.random.normal( - shape=(self.num_img, self.latent_dim) + shape=(self.num_img, self.latent_dim), seed=seed_generator ) generated_images = self.model.generator(random_latent_vectors) generated_images *= 255 @@ -354,14 +360,14 @@ gan.fit(
``` - 2/6332 ━━━━━━━━━━━━━━━━━━━━ 9:37 91ms/step - d_loss: 0.6853 - g_loss: 0.7761 + 2/6332 ━━━━━━━━━━━━━━━━━━━━ 10:07 96ms/step - d_loss: 0.6940 - g_loss: 0.7699 WARNING: All log messages before absl::InitializeLog() is called are written to STDERR -I0000 00:00:1703188912.818851 3649 device_compiler.h:186] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process. +I0000 00:00:1703715357.169335 1399 device_compiler.h:186] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process. - 6332/6332 ━━━━━━━━━━━━━━━━━━━━ 558s 84ms/step - d_loss: 0.5599 - g_loss: 1.4323 + 6332/6332 ━━━━━━━━━━━━━━━━━━━━ 562s 85ms/step - d_loss: 0.6062 - g_loss: 1.2240 - + ```
From b3f8e5de93b729821adeee961d1bbb664f60ee5d Mon Sep 17 00:00:00 2001 From: sineeli <113718461+sineeli@users.noreply.github.com> Date: Sat, 30 Dec 2023 12:15:21 -0800 Subject: [PATCH 5/8] Update dcgan_overriding_train_step.py --- examples/generative/dcgan_overriding_train_step.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/generative/dcgan_overriding_train_step.py b/examples/generative/dcgan_overriding_train_step.py index b54139812c..fef6405cf9 100644 --- a/examples/generative/dcgan_overriding_train_step.py +++ b/examples/generative/dcgan_overriding_train_step.py @@ -20,7 +20,6 @@ import gdown from zipfile import ZipFile -seed_generator = keras.random.SeedGenerator(42) """ ## Prepare CelebA data @@ -117,6 +116,7 @@ def __init__(self, discriminator, generator, latent_dim): self.discriminator = discriminator self.generator = generator self.latent_dim = latent_dim + self.seed_generator = keras.random.SeedGenerator(1337) def compile(self, d_optimizer, g_optimizer, loss_fn): super().compile() @@ -134,7 +134,7 @@ def train_step(self, real_images): # Sample random points in the latent space batch_size = ops.shape(real_images)[0] random_latent_vectors = keras.random.normal( - shape=(batch_size, self.latent_dim), seed=seed_generator + shape=(batch_size, self.latent_dim), seed=self.seed_generator ) # Decode them to fake images @@ -161,7 +161,7 @@ def train_step(self, real_images): # Sample random points in the latent space random_latent_vectors = keras.random.normal( - shape=(batch_size, self.latent_dim), seed=seed_generator + shape=(batch_size, self.latent_dim), seed=self.seed_generator ) # Assemble labels that say "all real images" @@ -193,10 +193,12 @@ class GANMonitor(keras.callbacks.Callback): def __init__(self, num_img=3, latent_dim=128): self.num_img = num_img self.latent_dim = latent_dim + self.seed_generator = keras.random.SeedGenerator(42) + def on_epoch_end(self, epoch, logs=None): random_latent_vectors = keras.random.normal( - shape=(self.num_img, self.latent_dim), seed=seed_generator + shape=(self.num_img, self.latent_dim), seed=self.seed_generator ) generated_images = self.model.generator(random_latent_vectors) generated_images *= 255 From 2a9b52d76965978fcddb212e4574b13a1e3e7f96 Mon Sep 17 00:00:00 2001 From: Siva Sravana Kumar Neeli Date: Tue, 2 Jan 2024 17:07:43 +0000 Subject: [PATCH 6/8] Rgenerate files --- .../generative/dcgan_overriding_train_step.py | 1 - .../dcgan_overriding_train_step_8_0.png | Bin 16279 -> 16398 bytes .../ipynb/dcgan_overriding_train_step.ipynb | 11 ++++++----- .../md/dcgan_overriding_train_step.md | 17 +++++++++-------- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/examples/generative/dcgan_overriding_train_step.py b/examples/generative/dcgan_overriding_train_step.py index fef6405cf9..62bb5a1717 100644 --- a/examples/generative/dcgan_overriding_train_step.py +++ b/examples/generative/dcgan_overriding_train_step.py @@ -194,7 +194,6 @@ def __init__(self, num_img=3, latent_dim=128): self.num_img = num_img self.latent_dim = latent_dim self.seed_generator = keras.random.SeedGenerator(42) - def on_epoch_end(self, epoch, logs=None): random_latent_vectors = keras.random.normal( diff --git a/examples/generative/img/dcgan_overriding_train_step/dcgan_overriding_train_step_8_0.png b/examples/generative/img/dcgan_overriding_train_step/dcgan_overriding_train_step_8_0.png index bb14a72a81f93e558881e38901d74f3e90eca7ea..c2a6b93b6b19e04baebb99a5f284d1ab3d6eef36 100644 GIT binary patch literal 16398 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 Qv?sZzWvE%BZXff107gZ;$N&HU diff --git a/examples/generative/ipynb/dcgan_overriding_train_step.ipynb b/examples/generative/ipynb/dcgan_overriding_train_step.ipynb index 5b7052321e..8c6185a8cd 100644 --- a/examples/generative/ipynb/dcgan_overriding_train_step.ipynb +++ b/examples/generative/ipynb/dcgan_overriding_train_step.ipynb @@ -40,8 +40,7 @@ "import os\n", "import gdown\n", "from zipfile import ZipFile\n", - "\n", - "seed_generator = keras.random.SeedGenerator(42)" + "" ] }, { @@ -222,6 +221,7 @@ " self.discriminator = discriminator\n", " self.generator = generator\n", " self.latent_dim = latent_dim\n", + " self.seed_generator = keras.random.SeedGenerator(1337)\n", "\n", " def compile(self, d_optimizer, g_optimizer, loss_fn):\n", " super().compile()\n", @@ -239,7 +239,7 @@ " # Sample random points in the latent space\n", " batch_size = ops.shape(real_images)[0]\n", " random_latent_vectors = keras.random.normal(\n", - " shape=(batch_size, self.latent_dim), seed=seed_generator\n", + " shape=(batch_size, self.latent_dim), seed=self.seed_generator\n", " )\n", "\n", " # Decode them to fake images\n", @@ -266,7 +266,7 @@ "\n", " # Sample random points in the latent space\n", " random_latent_vectors = keras.random.normal(\n", - " shape=(batch_size, self.latent_dim), seed=seed_generator\n", + " shape=(batch_size, self.latent_dim), seed=self.seed_generator\n", " )\n", "\n", " # Assemble labels that say \"all real images\"\n", @@ -312,10 +312,11 @@ " def __init__(self, num_img=3, latent_dim=128):\n", " self.num_img = num_img\n", " self.latent_dim = latent_dim\n", + " self.seed_generator = keras.random.SeedGenerator(42)\n", "\n", " def on_epoch_end(self, epoch, logs=None):\n", " random_latent_vectors = keras.random.normal(\n", - " shape=(self.num_img, self.latent_dim), seed=seed_generator\n", + " shape=(self.num_img, self.latent_dim), seed=self.seed_generator\n", " )\n", " generated_images = self.model.generator(random_latent_vectors)\n", " generated_images *= 255\n", diff --git a/examples/generative/md/dcgan_overriding_train_step.md b/examples/generative/md/dcgan_overriding_train_step.md index 8592f9acf6..53e1e9f843 100644 --- a/examples/generative/md/dcgan_overriding_train_step.md +++ b/examples/generative/md/dcgan_overriding_train_step.md @@ -25,7 +25,6 @@ import os import gdown from zipfile import ZipFile -seed_generator = keras.random.SeedGenerator(42) ``` --- @@ -247,6 +246,7 @@ class GAN(keras.Model): self.discriminator = discriminator self.generator = generator self.latent_dim = latent_dim + self.seed_generator = keras.random.SeedGenerator(1337) def compile(self, d_optimizer, g_optimizer, loss_fn): super().compile() @@ -264,7 +264,7 @@ class GAN(keras.Model): # Sample random points in the latent space batch_size = ops.shape(real_images)[0] random_latent_vectors = keras.random.normal( - shape=(batch_size, self.latent_dim), seed=seed_generator + shape=(batch_size, self.latent_dim), seed=self.seed_generator ) # Decode them to fake images @@ -291,7 +291,7 @@ class GAN(keras.Model): # Sample random points in the latent space random_latent_vectors = keras.random.normal( - shape=(batch_size, self.latent_dim), seed=seed_generator + shape=(batch_size, self.latent_dim), seed=self.seed_generator ) # Assemble labels that say "all real images" @@ -325,10 +325,11 @@ class GANMonitor(keras.callbacks.Callback): def __init__(self, num_img=3, latent_dim=128): self.num_img = num_img self.latent_dim = latent_dim + self.seed_generator = keras.random.SeedGenerator(42) def on_epoch_end(self, epoch, logs=None): random_latent_vectors = keras.random.normal( - shape=(self.num_img, self.latent_dim), seed=seed_generator + shape=(self.num_img, self.latent_dim), seed=self.seed_generator ) generated_images = self.model.generator(random_latent_vectors) generated_images *= 255 @@ -360,14 +361,14 @@ gan.fit(
``` - 2/6332 ━━━━━━━━━━━━━━━━━━━━ 10:07 96ms/step - d_loss: 0.6940 - g_loss: 0.7699 + 2/6332 ━━━━━━━━━━━━━━━━━━━━ 9:54 94ms/step - d_loss: 0.6792 - g_loss: 0.7880 WARNING: All log messages before absl::InitializeLog() is called are written to STDERR -I0000 00:00:1703715357.169335 1399 device_compiler.h:186] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process. +I0000 00:00:1704214667.959762 1319 device_compiler.h:186] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process. - 6332/6332 ━━━━━━━━━━━━━━━━━━━━ 562s 85ms/step - d_loss: 0.6062 - g_loss: 1.2240 + 6332/6332 ━━━━━━━━━━━━━━━━━━━━ 557s 84ms/step - d_loss: 0.5616 - g_loss: 1.4099 - + ```
From 7b003f5ea8202ef8526899983d685b59ea786bc1 Mon Sep 17 00:00:00 2001 From: sineeli <113718461+sineeli@users.noreply.github.com> Date: Tue, 2 Jan 2024 13:37:51 -0800 Subject: [PATCH 7/8] Migration to Keras 3 --- examples/generative/conditional_gan.py | 73 ++++++++++++++------------ 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/examples/generative/conditional_gan.py b/examples/generative/conditional_gan.py index 0e48f06bfe..f9ae4690fb 100644 --- a/examples/generative/conditional_gan.py +++ b/examples/generative/conditional_gan.py @@ -51,9 +51,10 @@ ## Imports """ -from tensorflow import keras -from tensorflow.keras import layers +import keras +from keras import layers +from keras import ops from tensorflow_docs.vis import embed import tensorflow as tf import numpy as np @@ -118,9 +119,9 @@ [ keras.layers.InputLayer((28, 28, discriminator_in_channels)), layers.Conv2D(64, (3, 3), strides=(2, 2), padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2D(128, (3, 3), strides=(2, 2), padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.GlobalMaxPooling2D(), layers.Dense(1), ], @@ -134,12 +135,12 @@ # We want to generate 128 + num_classes coefficients to reshape into a # 7x7x(128 + num_classes) map. layers.Dense(7 * 7 * generator_in_channels), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Reshape((7, 7, generator_in_channels)), layers.Conv2DTranspose(128, (4, 4), strides=(2, 2), padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2DTranspose(128, (4, 4), strides=(2, 2), padding="same"), - layers.LeakyReLU(alpha=0.2), + layers.LeakyReLU(negative_slope=0.2), layers.Conv2D(1, (7, 7), padding="same", activation="sigmoid"), ], name="generator", @@ -156,6 +157,7 @@ def __init__(self, discriminator, generator, latent_dim): self.discriminator = discriminator self.generator = generator self.latent_dim = latent_dim + self.seed_generator = keras.random.SeedGenerator(1337) self.gen_loss_tracker = keras.metrics.Mean(name="generator_loss") self.disc_loss_tracker = keras.metrics.Mean(name="discriminator_loss") @@ -176,18 +178,20 @@ def train_step(self, data): # Add dummy dimensions to the labels so that they can be concatenated with # the images. This is for the discriminator. image_one_hot_labels = one_hot_labels[:, :, None, None] - image_one_hot_labels = tf.repeat( + image_one_hot_labels = ops.repeat( image_one_hot_labels, repeats=[image_size * image_size] ) - image_one_hot_labels = tf.reshape( + image_one_hot_labels = ops.reshape( image_one_hot_labels, (-1, image_size, image_size, num_classes) ) # Sample random points in the latent space and concatenate the labels. # This is for the generator. - batch_size = tf.shape(real_images)[0] - random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim)) - random_vector_labels = tf.concat( + batch_size = ops.shape(real_images)[0] + random_latent_vectors = keras.random.normal( + shape=(batch_size, self.latent_dim), + seed=self.seed_generator) + random_vector_labels = ops.concatenate( [random_latent_vectors, one_hot_labels], axis=1 ) @@ -196,15 +200,15 @@ def train_step(self, data): # Combine them with real images. Note that we are concatenating the labels # with these images here. - fake_image_and_labels = tf.concat([generated_images, image_one_hot_labels], -1) - real_image_and_labels = tf.concat([real_images, image_one_hot_labels], -1) - combined_images = tf.concat( + fake_image_and_labels = ops.concatenate([generated_images, image_one_hot_labels], -1) + real_image_and_labels = ops.concatenate([real_images, image_one_hot_labels], -1) + combined_images = ops.concatenate( [fake_image_and_labels, real_image_and_labels], axis=0 ) # Assemble labels discriminating real from fake images. - labels = tf.concat( - [tf.ones((batch_size, 1)), tf.zeros((batch_size, 1))], axis=0 + labels = ops.concatenate( + [ops.ones((batch_size, 1)), ops.zeros((batch_size, 1))], axis=0 ) # Train the discriminator. @@ -217,19 +221,22 @@ def train_step(self, data): ) # Sample random points in the latent space. - random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim)) - random_vector_labels = tf.concat( + random_latent_vectors = keras.random.normal( + shape=(batch_size, self.latent_dim), + seed=self.seed_generator + ) + random_vector_labels = ops.concatenate( [random_latent_vectors, one_hot_labels], axis=1 ) # Assemble labels that say "all real images". - misleading_labels = tf.zeros((batch_size, 1)) + misleading_labels = ops.zeros((batch_size, 1)) # Train the generator (note that we should *not* update the weights # of the discriminator)! with tf.GradientTape() as tape: fake_images = self.generator(random_vector_labels) - fake_image_and_labels = tf.concat([fake_images, image_one_hot_labels], -1) + fake_image_and_labels = ops.concatenate([fake_images, image_one_hot_labels], -1) predictions = self.discriminator(fake_image_and_labels) g_loss = self.loss_fn(misleading_labels, predictions) grads = tape.gradient(g_loss, self.generator.trainable_weights) @@ -271,33 +278,33 @@ def train_step(self, data): num_interpolation = 9 # @param {type:"integer"} # Sample noise for the interpolation. -interpolation_noise = tf.random.normal(shape=(1, latent_dim)) -interpolation_noise = tf.repeat(interpolation_noise, repeats=num_interpolation) -interpolation_noise = tf.reshape(interpolation_noise, (num_interpolation, latent_dim)) +interpolation_noise = keras.random.normal(shape=(1, latent_dim)) +interpolation_noise = ops.repeat(interpolation_noise, repeats=num_interpolation) +interpolation_noise = ops.reshape(interpolation_noise, (num_interpolation, latent_dim)) def interpolate_class(first_number, second_number): # Convert the start and end labels to one-hot encoded vectors. first_label = keras.utils.to_categorical([first_number], num_classes) second_label = keras.utils.to_categorical([second_number], num_classes) - first_label = tf.cast(first_label, tf.float32) - second_label = tf.cast(second_label, tf.float32) + first_label = ops.cast(first_label, "float32") + second_label = ops.cast(second_label, "float32") # Calculate the interpolation vector between the two labels. - percent_second_label = tf.linspace(0, 1, num_interpolation)[:, None] - percent_second_label = tf.cast(percent_second_label, tf.float32) + percent_second_label = ops.linspace(0, 1, num_interpolation)[:, None] + percent_second_label = ops.cast(percent_second_label, "float32") interpolation_labels = ( first_label * (1 - percent_second_label) + second_label * percent_second_label ) # Combine the noise and the labels and run inference with the generator. - noise_and_labels = tf.concat([interpolation_noise, interpolation_labels], 1) + noise_and_labels = ops.concatenate([interpolation_noise, interpolation_labels], 1) fake = trained_gen.predict(noise_and_labels) return fake -start_class = 1 # @param {type:"slider", min:0, max:9, step:1} -end_class = 5 # @param {type:"slider", min:0, max:9, step:1} +start_class = 2 # @param {type:"slider", min:0, max:9, step:1} +end_class = 6 # @param {type:"slider", min:0, max:9, step:1} fake_images = interpolate_class(start_class, end_class) @@ -310,8 +317,8 @@ def interpolate_class(first_number, second_number): fake_images *= 255.0 converted_images = fake_images.astype(np.uint8) -converted_images = tf.image.resize(converted_images, (96, 96)).numpy().astype(np.uint8) -imageio.mimsave("animation.gif", converted_images, fps=1) +converted_images = ops.image.resize(converted_images, (96, 96)).numpy().astype(np.uint8) +imageio.mimsave("animation.gif", converted_images[:, :, :, 0], fps=1) embed.embed_file("animation.gif") """ From 42e42628eb2d1eff0a3c484ec69a216aed586482 Mon Sep 17 00:00:00 2001 From: Siva Sravana Kumar Neeli Date: Tue, 2 Jan 2024 21:48:15 +0000 Subject: [PATCH 8/8] Revert "Migration to Keras 3" This reverts commit 7b003f5ea8202ef8526899983d685b59ea786bc1. --- examples/generative/conditional_gan.py | 73 ++++++++++++-------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/examples/generative/conditional_gan.py b/examples/generative/conditional_gan.py index f9ae4690fb..0e48f06bfe 100644 --- a/examples/generative/conditional_gan.py +++ b/examples/generative/conditional_gan.py @@ -51,10 +51,9 @@ ## Imports """ -import keras +from tensorflow import keras +from tensorflow.keras import layers -from keras import layers -from keras import ops from tensorflow_docs.vis import embed import tensorflow as tf import numpy as np @@ -119,9 +118,9 @@ [ keras.layers.InputLayer((28, 28, discriminator_in_channels)), layers.Conv2D(64, (3, 3), strides=(2, 2), padding="same"), - layers.LeakyReLU(negative_slope=0.2), + layers.LeakyReLU(alpha=0.2), layers.Conv2D(128, (3, 3), strides=(2, 2), padding="same"), - layers.LeakyReLU(negative_slope=0.2), + layers.LeakyReLU(alpha=0.2), layers.GlobalMaxPooling2D(), layers.Dense(1), ], @@ -135,12 +134,12 @@ # We want to generate 128 + num_classes coefficients to reshape into a # 7x7x(128 + num_classes) map. layers.Dense(7 * 7 * generator_in_channels), - layers.LeakyReLU(negative_slope=0.2), + layers.LeakyReLU(alpha=0.2), layers.Reshape((7, 7, generator_in_channels)), layers.Conv2DTranspose(128, (4, 4), strides=(2, 2), padding="same"), - layers.LeakyReLU(negative_slope=0.2), + layers.LeakyReLU(alpha=0.2), layers.Conv2DTranspose(128, (4, 4), strides=(2, 2), padding="same"), - layers.LeakyReLU(negative_slope=0.2), + layers.LeakyReLU(alpha=0.2), layers.Conv2D(1, (7, 7), padding="same", activation="sigmoid"), ], name="generator", @@ -157,7 +156,6 @@ def __init__(self, discriminator, generator, latent_dim): self.discriminator = discriminator self.generator = generator self.latent_dim = latent_dim - self.seed_generator = keras.random.SeedGenerator(1337) self.gen_loss_tracker = keras.metrics.Mean(name="generator_loss") self.disc_loss_tracker = keras.metrics.Mean(name="discriminator_loss") @@ -178,20 +176,18 @@ def train_step(self, data): # Add dummy dimensions to the labels so that they can be concatenated with # the images. This is for the discriminator. image_one_hot_labels = one_hot_labels[:, :, None, None] - image_one_hot_labels = ops.repeat( + image_one_hot_labels = tf.repeat( image_one_hot_labels, repeats=[image_size * image_size] ) - image_one_hot_labels = ops.reshape( + image_one_hot_labels = tf.reshape( image_one_hot_labels, (-1, image_size, image_size, num_classes) ) # Sample random points in the latent space and concatenate the labels. # This is for the generator. - batch_size = ops.shape(real_images)[0] - random_latent_vectors = keras.random.normal( - shape=(batch_size, self.latent_dim), - seed=self.seed_generator) - random_vector_labels = ops.concatenate( + batch_size = tf.shape(real_images)[0] + random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim)) + random_vector_labels = tf.concat( [random_latent_vectors, one_hot_labels], axis=1 ) @@ -200,15 +196,15 @@ def train_step(self, data): # Combine them with real images. Note that we are concatenating the labels # with these images here. - fake_image_and_labels = ops.concatenate([generated_images, image_one_hot_labels], -1) - real_image_and_labels = ops.concatenate([real_images, image_one_hot_labels], -1) - combined_images = ops.concatenate( + fake_image_and_labels = tf.concat([generated_images, image_one_hot_labels], -1) + real_image_and_labels = tf.concat([real_images, image_one_hot_labels], -1) + combined_images = tf.concat( [fake_image_and_labels, real_image_and_labels], axis=0 ) # Assemble labels discriminating real from fake images. - labels = ops.concatenate( - [ops.ones((batch_size, 1)), ops.zeros((batch_size, 1))], axis=0 + labels = tf.concat( + [tf.ones((batch_size, 1)), tf.zeros((batch_size, 1))], axis=0 ) # Train the discriminator. @@ -221,22 +217,19 @@ def train_step(self, data): ) # Sample random points in the latent space. - random_latent_vectors = keras.random.normal( - shape=(batch_size, self.latent_dim), - seed=self.seed_generator - ) - random_vector_labels = ops.concatenate( + random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim)) + random_vector_labels = tf.concat( [random_latent_vectors, one_hot_labels], axis=1 ) # Assemble labels that say "all real images". - misleading_labels = ops.zeros((batch_size, 1)) + misleading_labels = tf.zeros((batch_size, 1)) # Train the generator (note that we should *not* update the weights # of the discriminator)! with tf.GradientTape() as tape: fake_images = self.generator(random_vector_labels) - fake_image_and_labels = ops.concatenate([fake_images, image_one_hot_labels], -1) + fake_image_and_labels = tf.concat([fake_images, image_one_hot_labels], -1) predictions = self.discriminator(fake_image_and_labels) g_loss = self.loss_fn(misleading_labels, predictions) grads = tape.gradient(g_loss, self.generator.trainable_weights) @@ -278,33 +271,33 @@ def train_step(self, data): num_interpolation = 9 # @param {type:"integer"} # Sample noise for the interpolation. -interpolation_noise = keras.random.normal(shape=(1, latent_dim)) -interpolation_noise = ops.repeat(interpolation_noise, repeats=num_interpolation) -interpolation_noise = ops.reshape(interpolation_noise, (num_interpolation, latent_dim)) +interpolation_noise = tf.random.normal(shape=(1, latent_dim)) +interpolation_noise = tf.repeat(interpolation_noise, repeats=num_interpolation) +interpolation_noise = tf.reshape(interpolation_noise, (num_interpolation, latent_dim)) def interpolate_class(first_number, second_number): # Convert the start and end labels to one-hot encoded vectors. first_label = keras.utils.to_categorical([first_number], num_classes) second_label = keras.utils.to_categorical([second_number], num_classes) - first_label = ops.cast(first_label, "float32") - second_label = ops.cast(second_label, "float32") + first_label = tf.cast(first_label, tf.float32) + second_label = tf.cast(second_label, tf.float32) # Calculate the interpolation vector between the two labels. - percent_second_label = ops.linspace(0, 1, num_interpolation)[:, None] - percent_second_label = ops.cast(percent_second_label, "float32") + percent_second_label = tf.linspace(0, 1, num_interpolation)[:, None] + percent_second_label = tf.cast(percent_second_label, tf.float32) interpolation_labels = ( first_label * (1 - percent_second_label) + second_label * percent_second_label ) # Combine the noise and the labels and run inference with the generator. - noise_and_labels = ops.concatenate([interpolation_noise, interpolation_labels], 1) + noise_and_labels = tf.concat([interpolation_noise, interpolation_labels], 1) fake = trained_gen.predict(noise_and_labels) return fake -start_class = 2 # @param {type:"slider", min:0, max:9, step:1} -end_class = 6 # @param {type:"slider", min:0, max:9, step:1} +start_class = 1 # @param {type:"slider", min:0, max:9, step:1} +end_class = 5 # @param {type:"slider", min:0, max:9, step:1} fake_images = interpolate_class(start_class, end_class) @@ -317,8 +310,8 @@ def interpolate_class(first_number, second_number): fake_images *= 255.0 converted_images = fake_images.astype(np.uint8) -converted_images = ops.image.resize(converted_images, (96, 96)).numpy().astype(np.uint8) -imageio.mimsave("animation.gif", converted_images[:, :, :, 0], fps=1) +converted_images = tf.image.resize(converted_images, (96, 96)).numpy().astype(np.uint8) +imageio.mimsave("animation.gif", converted_images, fps=1) embed.embed_file("animation.gif") """