From d426586b03e634fdac80f7e99f1717b1dfa3fa38 Mon Sep 17 00:00:00 2001 From: Shubbair Date: Fri, 26 Jul 2024 16:07:40 +0300 Subject: [PATCH] Updating GAN Code... --- gan/main.py | 2 +- gan/playground.ipynb | 493 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 494 insertions(+), 1 deletion(-) create mode 100644 gan/playground.ipynb diff --git a/gan/main.py b/gan/main.py index 7192a3bc..cd1a6ff9 100644 --- a/gan/main.py +++ b/gan/main.py @@ -119,7 +119,7 @@ def main(args:dict): return gen_loss - # training + # TODO training... if __name__ == "__main__": diff --git a/gan/playground.ipynb b/gan/playground.ipynb new file mode 100644 index 00000000..2dc3d24d --- /dev/null +++ b/gan/playground.ipynb @@ -0,0 +1,493 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Import Library" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import mnist" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import mlx.core as mx\n", + "import mlx.nn as nn\n", + "import mlx.optimizers as optim\n", + "\n", + "from tqdm import tqdm\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# GAN Architecture" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generator 👨🏻‍🎨" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def GenBlock(in_dim:int,out_dim:int):\n", + " \n", + " return nn.Sequential(\n", + " nn.Linear(in_dim,out_dim),\n", + " nn.BatchNorm(out_dim),\n", + " nn.ReLU()\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "class Generator(nn.Module):\n", + "\n", + " def __init__(self, z_dim:int = 10, im_dim:int = 784, hidden_dim: int =128):\n", + " super(Generator, self).__init__()\n", + " # Build the neural network\n", + " self.gen = nn.Sequential(\n", + " GenBlock(z_dim, hidden_dim),\n", + " GenBlock(hidden_dim, hidden_dim * 2),\n", + " GenBlock(hidden_dim * 2, hidden_dim * 4),\n", + " GenBlock(hidden_dim * 4, hidden_dim * 8),\n", + "\n", + "\n", + " nn.Linear(hidden_dim * 8,im_dim),\n", + " nn.Sigmoid()\n", + " )\n", + " \n", + " def __call__(self, noise):\n", + "\n", + " return self.gen(noise)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Generator(\n", + " (gen): Sequential(\n", + " (layers.0): Sequential(\n", + " (layers.0): Linear(input_dims=100, output_dims=128, bias=True)\n", + " (layers.1): BatchNorm(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (layers.2): ReLU()\n", + " )\n", + " (layers.1): Sequential(\n", + " (layers.0): Linear(input_dims=128, output_dims=256, bias=True)\n", + " (layers.1): BatchNorm(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (layers.2): ReLU()\n", + " )\n", + " (layers.2): Sequential(\n", + " (layers.0): Linear(input_dims=256, output_dims=512, bias=True)\n", + " (layers.1): BatchNorm(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (layers.2): ReLU()\n", + " )\n", + " (layers.3): Sequential(\n", + " (layers.0): Linear(input_dims=512, output_dims=1024, bias=True)\n", + " (layers.1): BatchNorm(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (layers.2): ReLU()\n", + " )\n", + " (layers.4): Linear(input_dims=1024, output_dims=784, bias=True)\n", + " (layers.5): Sigmoid()\n", + " )\n", + ")" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gen = Generator(100)\n", + "gen" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def get_noise(n_samples, z_dim):\n", + "\n", + " return np.random.randn(n_samples,z_dim)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Discriminator 🕵🏻‍♂️" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def DisBlock(in_dim:int,out_dim:int):\n", + " \n", + " return nn.Sequential(\n", + " nn.Linear(in_dim,out_dim),\n", + " nn.LeakyReLU(negative_slope=0.2)\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "class Discriminator(nn.Module):\n", + "\n", + " def __init__(self,im_dim:int = 784, hidden_dim:int = 128):\n", + " super(Discriminator, self).__init__()\n", + "\n", + " self.disc = nn.Sequential(\n", + " DisBlock(im_dim, hidden_dim * 4),\n", + " DisBlock(hidden_dim * 4, hidden_dim * 2),\n", + " DisBlock(hidden_dim * 2, hidden_dim),\n", + "\n", + " nn.Linear(hidden_dim,1),\n", + " )\n", + " \n", + " def __call__(self, noise):\n", + "\n", + " return self.disc(noise)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Discriminator(\n", + " (disc): Sequential(\n", + " (layers.0): Sequential(\n", + " (layers.0): Linear(input_dims=784, output_dims=512, bias=True)\n", + " (layers.1): LeakyReLU()\n", + " )\n", + " (layers.1): Sequential(\n", + " (layers.0): Linear(input_dims=512, output_dims=256, bias=True)\n", + " (layers.1): LeakyReLU()\n", + " )\n", + " (layers.2): Sequential(\n", + " (layers.0): Linear(input_dims=256, output_dims=128, bias=True)\n", + " (layers.1): LeakyReLU()\n", + " )\n", + " (layers.3): Linear(input_dims=128, output_dims=1, bias=True)\n", + " )\n", + ")" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "disc = Discriminator()\n", + "disc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Model Training 🏋🏻‍♂️" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "# Set your parameters\n", + "criterion = nn.losses.binary_cross_entropy\n", + "n_epochs = 200\n", + "z_dim = 64\n", + "display_step = 500\n", + "batch_size = 128\n", + "lr = 0.00001" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "gen = Generator(z_dim)\n", + "gen_opt = optim.Adam(learning_rate=lr)\n", + "disc = Discriminator()\n", + "disc_opt = optim.Adam(learning_rate=lr)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Losses" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def disc_loss(gen, disc, criterion, real, num_images, z_dim):\n", + " noise = mx.array(get_noise(num_images, z_dim))\n", + " fake_images = gen(noise)\n", + " \n", + " fake_disc = disc(fake_images)\n", + " \n", + " fake_labels = mx.zeros((len(fake_images),1))\n", + " fake_loss = criterion(fake_disc,fake_labels)\n", + " \n", + " real_disc = disc(real)\n", + " real_labels = mx.ones((len(real),1))\n", + " real_loss = criterion(real_disc,real_labels)\n", + "\n", + " disc_loss = (fake_loss + real_loss) / 2\n", + "\n", + " return disc_loss" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def gen_loss(gen, disc, criterion, num_images, z_dim):\n", + "\n", + " noise = mx.array(get_noise(num_images, z_dim))\n", + " fake_images = gen(noise)\n", + " \n", + " fake_disc = disc(fake_images)\n", + "\n", + " fake_labels = mx.ones((fake_images.size(0),1))\n", + " \n", + " gen_loss = criterion(fake_disc,fake_labels)\n", + "\n", + " return gen_loss" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "train_images, _, test_images, _ = map(\n", + " mx.array, getattr(mnist, 'mnist')()\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "def batch_iterate(batch_size:int, ipt:list):\n", + " perm = mx.array(np.random.permutation(len(ipt)))\n", + " for s in range(0, ipt.size, batch_size):\n", + " ids = perm[s : s + batch_size]\n", + " yield ipt[ids]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### show batch of images" + ] + }, + { + "cell_type": "code", + "execution_count": 166, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for X in batch_iterate(16, train_images):\n", + " fig,axes = plt.subplots(4, 4, figsize=(4, 4))\n", + "\n", + " for i, ax in enumerate(axes.flat):\n", + " img = mx.array(X[i]).reshape(28,28)\n", + " ax.imshow(img,cmap='gray')\n", + " ax.axis('off')\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": 167, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "0it [00:00, ?it/s]\n", + "0it [00:00, ?it/s]\n" + ] + }, + { + "ename": "TypeError", + "evalue": "'array' object is not callable", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[167], line 21\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m epoch \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(n_epochs):\n\u001b[1;32m 10\u001b[0m \n\u001b[1;32m 11\u001b[0m \u001b[38;5;66;03m# Dataloader returns the batches\u001b[39;00m\n\u001b[1;32m 12\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m real \u001b[38;5;129;01min\u001b[39;00m tqdm(batch_iterate(batch_size, train_images)):\n\u001b[1;32m 13\u001b[0m \n\u001b[1;32m 14\u001b[0m \u001b[38;5;66;03m# Flatten the batch of real images from the dataset\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 19\u001b[0m \n\u001b[1;32m 20\u001b[0m \u001b[38;5;66;03m# Calculate discriminator loss\u001b[39;00m\n\u001b[0;32m---> 21\u001b[0m disc_loss \u001b[38;5;241m=\u001b[39m \u001b[43mdisc_loss\u001b[49m\u001b[43m(\u001b[49m\u001b[43mgen\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdisc\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcriterion\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mreal\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbatch_size\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mz_dim\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 23\u001b[0m \u001b[38;5;66;03m# Update gradients\u001b[39;00m\n\u001b[1;32m 24\u001b[0m \u001b[38;5;66;03m# disc_loss.backward(retain_graph=True)\u001b[39;00m\n\u001b[1;32m 25\u001b[0m \n\u001b[1;32m 26\u001b[0m \u001b[38;5;66;03m# Update optimizer\u001b[39;00m\n\u001b[1;32m 27\u001b[0m mx\u001b[38;5;241m.\u001b[39meval(disc\u001b[38;5;241m.\u001b[39mparameters())\n", + "\u001b[0;31mTypeError\u001b[0m: 'array' object is not callable" + ] + } + ], + "source": [ + "batch_size = 8\n", + "cur_step = 0\n", + "mean_generator_loss = 0\n", + "mean_discriminator_loss = 0\n", + "test_generator = True # Whether the generator should be tested\n", + "gen_loss = False\n", + "error = False\n", + "\n", + "for epoch in range(n_epochs):\n", + " \n", + " # Dataloader returns the batches\n", + " for real in tqdm(batch_iterate(batch_size, train_images)):\n", + "\n", + " # Flatten the batch of real images from the dataset\n", + "\n", + " ### Update discriminator ###\n", + " # Zero out the gradients before backpropagation\n", + " # disc_opt.zero_grad()\n", + "\n", + " # Calculate discriminator loss\n", + " disc_loss = disc_loss(gen, disc, criterion, real, batch_size, z_dim)\n", + " \n", + " # Update gradients\n", + " # disc_loss.backward(retain_graph=True)\n", + "\n", + " # Update optimizer\n", + " mx.eval(disc.parameters())\n", + " \n", + " break\n", + " # For testing purposes, to keep track of the generator weights\n", + " if test_generator:\n", + " old_generator_weights = gen.gen[0][0].weight.detach().clone()\n", + "\n", + " ### Update generator ###\n", + " # Hint: This code will look a lot like the discriminator updates!\n", + " # These are the steps you will need to complete:\n", + " # 1) Zero out the gradients.\n", + " # 2) Calculate the generator loss, assigning it to gen_loss.\n", + " # 3) Backprop through the generator: update the gradients and optimizer.\n", + " #### START CODE HERE ####\n", + " gen_opt.zero_grad()\n", + " gen_loss = get_gen_loss(gen, disc, criterion, cur_batch_size, z_dim, device)\n", + " gen_loss.backward(retain_graph=True)\n", + " gen_opt.step()\n", + " #### END CODE HERE ####\n", + "\n", + " # For testing purposes, to check that your code changes the generator weights\n", + " if test_generator:\n", + " try:\n", + " assert lr > 0.0000002 or (gen.gen[0][0].weight.grad.abs().max() < 0.0005 and epoch == 0)\n", + " assert torch.any(gen.gen[0][0].weight.detach().clone() != old_generator_weights)\n", + " except:\n", + " error = True\n", + " print(\"Runtime tests have failed\")\n", + "\n", + " # Keep track of the average discriminator loss\n", + " mean_discriminator_loss += disc_loss.item() / display_step\n", + "\n", + " # Keep track of the average generator loss\n", + " mean_generator_loss += gen_loss.item() / display_step\n", + "\n", + " ### Visualization code ###\n", + " if cur_step % display_step == 0 and cur_step > 0:\n", + " print(f\"Step {cur_step}: Generator loss: {mean_generator_loss}, discriminator loss: {mean_discriminator_loss}\")\n", + " fake_noise = get_noise(cur_batch_size, z_dim, device=device)\n", + " fake = gen(fake_noise)\n", + " show_tensor_images(fake)\n", + " show_tensor_images(real)\n", + " mean_generator_loss = 0\n", + " mean_discriminator_loss = 0\n", + " cur_step += 1\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.10" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}