{
  "source_file": "0930",
  "source_platform": "研究机构",
  "author": "PyTorch Tutorials",
  "title_listed": "DCGAN Tutorial",
  "keywords": "GAN,DCGAN,生成",
  "domain": "图像处理",
  "content_type": "教程",
  "is_paid_flag": "否",
  "url": "https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html",
  "publish_date": "持续更新",
  "corpus_stage": "图像处理",
  "notes": "DCGAN 生成人脸",
  "id": "ed4ec7b77c42",
  "collected_at": "2026-10-02T16:38:20",
  "title": "DCGAN Tutorial — PyTorch Tutorials 2.14.0+cu130 documentation",
  "body_markdown": "Note\nGo to the end\nto download the full example code.\nDCGAN Tutorial\n#\nCreated On: Jul 31, 2018 | Last Updated: Jan 19, 2024 | Last Verified: Nov 05, 2024\nAuthor\n:\nNathan Inkawhich\nIntroduction\n#\nThis tutorial will give an introduction to DCGANs through an example. We\nwill train a generative adversarial network (GAN) to generate new\ncelebrities after showing it pictures of many real celebrities. Most of\nthe code here is from the DCGAN implementation in\npytorch/examples\n, and this\ndocument will give a thorough explanation of the implementation and shed\nlight on how and why this model works. But don’t worry, no prior\nknowledge of GANs is required, but it may require a first-timer to spend\nsome time reasoning about what is actually happening under the hood.\nAlso, for the sake of time it will help to have a GPU, or two. Lets\nstart from the beginning.\nGenerative Adversarial Networks\n#\nWhat is a GAN?\n#\nGANs are a framework for teaching a deep learning model to capture the training\ndata distribution so we can generate new data from that same\ndistribution. GANs were invented by Ian Goodfellow in 2014 and first\ndescribed in the paper\nGenerative Adversarial\nNets\n.\nThey are made of two distinct models, a\ngenerator\nand a\ndiscriminator\n. The job of the generator is to spawn ‘fake’ images that\nlook like the training images. The job of the discriminator is to look\nat an image and output whether or not it is a real training image or a\nfake image from the generator. During training, the generator is\nconstantly trying to outsmart the discriminator by generating better and\nbetter fakes, while the discriminator is working to become a better\ndetective and correctly classify the real and fake images. The\nequilibrium of this game is when the generator is generating perfect\nfakes that look as if they came directly from the training data, and the\ndiscriminator is left to always guess at 50% confidence that the\ngenerator output is real or fake.\nNow, lets define some notation to be used throughout tutorial starting\nwith the discriminator. Let\n\\(x\\)\nbe data representing an image.\n\\(D(x)\\)\nis the discriminator network which outputs the (scalar)\nprobability that\n\\(x\\)\ncame from training data rather than the\ngenerator. Here, since we are dealing with images, the input to\n\\(D(x)\\)\nis an image of CHW size 3x64x64. Intuitively,\n\\(D(x)\\)\nshould be HIGH when\n\\(x\\)\ncomes from training data and LOW when\n\\(x\\)\ncomes from the generator.\n\\(D(x)\\)\ncan also be thought of\nas a traditional binary classifier.\nFor the generator’s notation, let\n\\(z\\)\nbe a latent space vector\nsampled from a standard normal distribution.\n\\(G(z)\\)\nrepresents the\ngenerator function which maps the latent vector\n\\(z\\)\nto data-space.\nThe goal of\n\\(G\\)\nis to estimate the distribution that the training\ndata comes from (\n\\(p_{data}\\)\n) so it can generate fake samples from\nthat estimated distribution (\n\\(p_g\\)\n).\nSo,\n\\(D(G(z))\\)\nis the probability (scalar) that the output of the\ngenerator\n\\(G\\)\nis a real image. As described in\nGoodfellow’s\npaper\n,\n\\(D\\)\nand\n\\(G\\)\nplay a minimax game in which\n\\(D\\)\ntries to\nmaximize the probability it correctly classifies reals and fakes\n(\n\\(logD(x)\\)\n), and\n\\(G\\)\ntries to minimize the probability that\n\\(D\\)\nwill predict its outputs are fake (\n\\(log(1-D(G(z)))\\)\n).\nFrom the paper, the GAN loss function is\n\\[\\underset{G}{\\text{min}} \\underset{D}{\\text{max}}V(D,G) = \\mathbb{E}_{x\\sim p_{data}(x)}\\big[logD(x)\\big] + \\mathbb{E}_{z\\sim p_{z}(z)}\\big[log(1-D(G(z)))\\big]\n\n\\]\nIn theory, the solution to this minimax game is where\n\\(p_g = p_{data}\\)\n, and the discriminator guesses randomly if the\ninputs are real or fake. However, the convergence theory of GANs is\nstill being actively researched and in reality models do not always\ntrain to this point.\nWhat is a DCGAN?\n#\nA DCGAN is a direct extension of the GAN described above, except that it\nexplicitly uses convolutional and convolutional-transpose layers in the\ndiscriminator and generator, respectively. It was first described by\nRadford et. al. in the paper\nUnsupervised Representation Learning With\nDeep Convolutional Generative Adversarial\nNetworks\n. The discriminator\nis made up of strided\nconvolution\nlayers,\nbatch\nnorm\nlayers, and\nLeakyReLU\nactivations. The input is a 3x64x64 input image and the output is a\nscalar probability that the input is from the real data distribution.\nThe generator is comprised of\nconvolutional-transpose\nlayers, batch norm layers, and\nReLU\nactivations. The\ninput is a latent vector,\n\\(z\\)\n, that is drawn from a standard\nnormal distribution and the output is a 3x64x64 RGB image. The strided\nconv-transpose layers allow the latent vector to be transformed into a\nvolume with the same shape as an image. In the paper, the authors also\ngive some tips about how to setup the optimizers, how to calculate the\nloss functions, and how to initialize the model weights, all of which\nwill be explained in the coming sections.\n#%matplotlib inline\nimport\nargparse\nimport\nos\nimport\nrandom\nimport\ntorch\nimport\ntorch.nn\nas\nnn\nimport\ntorch.nn.parallel\nimport\ntorch.optim\nas\noptim\nimport\ntorch.utils.data\nimport\ntorchvision.datasets\nas\ndset\nimport\ntorchvision.transforms\nas\ntransforms\nimport\ntorchvision.utils\nas\nvutils\nimport\nnumpy\nas\nnp\nimport\nmatplotlib.pyplot\nas\nplt\nimport\nmatplotlib.animation\nas\nanimation\nfrom\nIPython.display\nimport\nHTML\n# Set random seed for reproducibility\nmanualSeed\n=\n999\n#manualSeed = random.randint(1, 10000) # use if you want new results\nprint\n(\n\"Random Seed: \"\n,\nmanualSeed\n)\nrandom\n.\nseed\n(\nmanualSeed\n)\ntorch\n.\nmanual_seed\n(\nmanualSeed\n)\ntorch\n.\nuse_deterministic_algorithms\n(\nTrue\n)\n# Needed for reproducible results\nRandom Seed:  999\nInputs\n#\nLet’s define some inputs for the run:\ndataroot\n- the path to the root of the dataset folder. We will\ntalk more about the dataset in the next section.\nworkers\n- the number of worker threads for loading the data with\nthe\nDataLoader\n.\nbatch_size\n- the batch size used in training. The DCGAN paper\nuses a batch size of 128.\nimage_size\n- the spatial size of the images used for training.\nThis implementation defaults to 64x64. If another size is desired,\nthe structures of D and G must be changed. See\nhere\nfor more\ndetails.\nnc\n- number of color channels in the input images. For color\nimages this is 3.\nnz\n- length of latent vector.\nngf\n- relates to the depth of feature maps carried through the\ngenerator.\nndf\n- sets the depth of feature maps propagated through the\ndiscriminator.\nnum_epochs\n- number of training epochs to run. Training for\nlonger will probably lead to better results but will also take much\nlonger.\nlr\n- learning rate for training. As described in the DCGAN paper,\nthis number should be 0.0002.\nbeta1\n- beta1 hyperparameter for Adam optimizers. As described in\npaper, this number should be 0.5.\nngpu\n- number of GPUs available. If this is 0, code will run in\nCPU mode. If this number is greater than 0 it will run on that number\nof GPUs.\n# Root directory for dataset\ndataroot\n=\n\"data/celeba\"\n# Number of workers for dataloader\nworkers\n=\n2\n# Batch size during training\nbatch_size\n=\n128\n# Spatial size of training images. All images will be resized to this\n#   size using a transformer.\nimage_size\n=\n64\n# Number of channels in the training images. For color images this is 3\nnc\n=\n3\n# Size of z latent vector (i.e. size of generator input)\nnz\n=\n100\n# Size of feature maps in generator\nngf\n=\n64\n# Size of feature maps in discriminator\nndf\n=\n64\n# Number of training epochs\nnum_epochs\n=\n5\n# Learning rate for optimizers\nlr\n=\n0.0002\n# Beta1 hyperparameter for Adam optimizers\nbeta1\n=\n0.5\n# Number of GPUs available. Use 0 for CPU mode.\nngpu\n=\n1\nData\n#\nIn this tutorial we will use the\nCeleb-A Faces\ndataset\nwhich can\nbe downloaded at the linked site, or in\nGoogle\nDrive\n.\nThe dataset will download as a file named\nimg_align_celeba.zip\n. Once\ndownloaded, create a directory named\nceleba\nand extract the zip file\ninto that directory. Then, set the\ndataroot\ninput for this notebook to\nthe\nceleba\ndirectory you just created. The resulting directory\nstructure should be:\n/path/to/celeba\n->\nimg_align_celeba\n->\n188242\n.jpg\n->\n173822\n.jpg\n->\n284702\n.jpg\n->\n537394\n.jpg\n...\nThis is an important step because we will be using the\nImageFolder\ndataset class, which requires there to be subdirectories in the\ndataset root folder. Now, we can create the dataset, create the\ndataloader, set the device to run on, and finally visualize some of the\ntraining data.\n# We can use an image folder dataset the way we have it setup.\n# Create the dataset\ndataset\n=\ndset\n.\nImageFolder\n(\nroot\n=\ndataroot\n,\ntransform\n=\ntransforms\n.\nCompose\n([\ntransforms\n.\nResize\n(\nimage_size\n),\ntransforms\n.\nCenterCrop\n(\nimage_size\n),\ntransforms\n.\nToTensor\n(),\ntransforms\n.\nNormalize\n((\n0.5\n,\n0.5\n,\n0.5\n),\n(\n0.5\n,\n0.5\n,\n0.5\n)),\n]))\n# Create the dataloader\ndataloader\n=\ntorch\n.\nutils\n.\ndata\n.\nDataLoader\n(\ndataset\n,\nbatch_size\n=\nbatch_size\n,\nshuffle\n=\nTrue\n,\nnum_workers\n=\nworkers\n)\n# Decide which device we want to run on\ndevice\n=\ntorch\n.\ndevice\n(\n\"cuda:0\"\nif\n(\ntorch\n.\ncuda\n.\nis_available\n()\nand\nngpu\n>\n0\n)\nelse\n\"cpu\"\n)\n# Plot some training images\nreal_batch\n=\nnext\n(\niter\n(\ndataloader\n))\nplt\n.\nfigure\n(\nfigsize\n=\n(\n8\n,\n8\n))\nplt\n.\naxis\n(\n\"off\"\n)\nplt\n.\ntitle\n(\n\"Training Images\"\n)\nplt\n.\nimshow\n(\nnp\n.\ntranspose\n(\nvutils\n.\nmake_grid\n(\nreal_batch\n[\n0\n]\n.\nto\n(\ndevice\n)[:\n64\n],\npadding\n=\n2\n,\nnormalize\n=\nTrue\n)\n.\ncpu\n(),(\n1\n,\n2\n,\n0\n)))\nplt\n.\nshow\n()\nImplementation\n#\nWith our input parameters set and the dataset prepared, we can now get\ninto the implementation. We will start with the weight initialization\nstrategy, then talk about the generator, discriminator, loss functions,\nand training loop in detail.\nWeight Initialization\n#\nFrom the DCGAN paper, the authors specify that all model weights shall\nbe randomly initialized from a Normal distribution with\nmean=0\n,\nstdev=0.02\n. The\nweights_init\nfunction takes an initialized model as\ninput and reinitializes all convolutional, convolutional-transpose, and\nbatch normalization layers to meet this criteria. This function is\napplied to the models immediately after initialization.\n# custom weights initialization called on ``netG`` and ``netD``\ndef\nweights_init\n(\nm\n):\nclassname\n=\nm\n.\n__class__\n.\n__name__\nif\nclassname\n.\nfind\n(\n'Conv'\n)\n!=\n-\n1\n:\nnn\n.\ninit\n.\nnormal_\n(\nm\n.\nweight\n.\ndata\n,\n0.0\n,\n0.02\n)\nelif\nclassname\n.\nfind\n(\n'BatchNorm'\n)\n!=\n-\n1\n:\nnn\n.\ninit\n.\nnormal_\n(\nm\n.\nweight\n.\ndata\n,\n1.0\n,\n0.02\n)\nnn\n.\ninit\n.\nconstant_\n(\nm\n.\nbias\n.\ndata\n,\n0\n)\nGenerator\n#\nThe generator,\n\\(G\\)\n, is designed to map the latent space vector\n(\n\\(z\\)\n) to data-space. Since our data are images, converting\n\\(z\\)\nto data-space means ultimately creating a RGB image with the\nsame size as the training images (i.e. 3x64x64). In practice, this is\naccomplished through a series of strided two dimensional convolutional\ntranspose layers, each paired with a 2d batch norm layer and a relu\nactivation. The output of the generator is fed through a tanh function\nto return it to the input data range of\n\\([-1,1]\\)\n. It is worth\nnoting the existence of the batch norm functions after the\nconv-transpose layers, as this is a critical contribution of the DCGAN\npaper. These layers help with the flow of gradients during training. An\nimage of the generator from the DCGAN paper is shown below.\nNotice, how the inputs we set in the input section (\nnz\n,\nngf\n, and\nnc\n) influence the generator architecture in code.\nnz\nis the length\nof the z input vector,\nngf\nrelates to the size of the feature maps\nthat are propagated through the generator, and\nnc\nis the number of\nchannels in the output image (set to 3 for RGB images). Below is the\ncode for the generator.\n# Generator Code\nclass\nGenerator\n(\nnn\n.\nModule\n):\ndef\n__init__\n(\nself\n,\nngpu\n):\nsuper\n(\nGenerator\n,\nself\n)\n.\n__init__\n()\nself\n.\nngpu\n=\nngpu\nself\n.\nmain\n=\nnn\n.\nSequential\n(\n# input is Z, going into a convolution\nnn\n.\nConvTranspose2d\n(\nnz\n,\nngf\n*\n8\n,\n4\n,\n1\n,\n0\n,\nbias\n=\nFalse\n),\nnn\n.\nBatchNorm2d\n(\nngf\n*\n8\n),\nnn\n.\nReLU\n(\nTrue\n),\n# state size. ``(ngf*8) x 4 x 4``\nnn\n.\nConvTranspose2d\n(\nngf\n*\n8\n,\nngf\n*\n4\n,\n4\n,\n2\n,\n1\n,\nbias\n=\nFalse\n),\nnn\n.\nBatchNorm2d\n(\nngf\n*\n4\n),\nnn\n.\nReLU\n(\nTrue\n),\n# state size. ``(ngf*4) x 8 x 8``\nnn\n.\nConvTranspose2d\n(\nngf\n*\n4\n,\nngf\n*\n2\n,\n4\n,\n2\n,\n1\n,\nbias\n=\nFalse\n),\nnn\n.\nBatchNorm2d\n(\nngf\n*\n2\n),\nnn\n.\nReLU\n(\nTrue\n),\n# state size. ``(ngf*2) x 16 x 16``\nnn\n.\nConvTranspose2d\n(\nngf\n*\n2\n,\nngf\n,\n4\n,\n2\n,\n1\n,\nbias\n=\nFalse\n),\nnn\n.\nBatchNorm2d\n(\nngf\n),\nnn\n.\nReLU\n(\nTrue\n),\n# state size. ``(ngf) x 32 x 32``\nnn\n.\nConvTranspose2d\n(\nngf\n,\nnc\n,\n4\n,\n2\n,\n1\n,\nbias\n=\nFalse\n),\nnn\n.\nTanh\n()\n# state size. ``(nc) x 64 x 64``\n)\ndef\nforward\n(\nself\n,\ninput\n):\nreturn\nself\n.\nmain\n(\ninput\n)\nNow, we can instantiate the generator and apply the\nweights_init\nfunction. Check out the printed model to see how the generator object is\nstructured.\n# Create the generator\nnetG\n=\nGenerator\n(\nngpu\n)\n.\nto\n(\ndevice\n)\n# Handle multi-GPU if desired\nif\n(\ndevice\n.\ntype\n==\n'cuda'\n)\nand\n(\nngpu\n>\n1\n):\nnetG\n=\nnn\n.\nDataParallel\n(\nnetG\n,\nlist\n(\nrange\n(\nngpu\n)))\n# Apply the ``weights_init`` function to randomly initialize all weights\n#  to ``mean=0``, ``stdev=0.02``.\nnetG\n.\napply\n(\nweights_init\n)\n# Print the model\nprint\n(\nnetG\n)\nGenerator(\n  (main): Sequential(\n    (0): ConvTranspose2d(100, 512, kernel_size=(4, 4), stride=(1, 1), bias=False)\n    (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (2): ReLU(inplace=True)\n    (3): ConvTranspose2d(512, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (5): ReLU(inplace=True)\n    (6): ConvTranspose2d(256, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (7): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (8): ReLU(inplace=True)\n    (9): ConvTranspose2d(128, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (10): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (11): ReLU(inplace=True)\n    (12): ConvTranspose2d(64, 3, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (13): Tanh()\n  )\n)\nDiscriminator\n#\nAs mentioned, the discriminator,\n\\(D\\)\n, is a binary classification\nnetwork that takes an image as input and outputs a scalar probability\nthat the input image is real (as opposed to fake). Here,\n\\(D\\)\ntakes\na 3x64x64 input image, processes it through a series of Conv2d,\nBatchNorm2d, and LeakyReLU layers, and outputs the final probability\nthrough a Sigmoid activation function. This architecture can be extended\nwith more layers if necessary for the problem, but there is significance\nto the use of the strided convolution, BatchNorm, and LeakyReLUs. The\nDCGAN paper mentions it is a good practice to use strided convolution\nrather than pooling to downsample because it lets the network learn its\nown pooling function. Also batch norm and leaky relu functions promote\nhealthy gradient flow which is critical for the learning process of both\n\\(G\\)\nand\n\\(D\\)\n.\nDiscriminator Code\nclass\nDiscriminator\n(\nnn\n.\nModule\n):\ndef\n__init__\n(\nself\n,\nngpu\n):\nsuper\n(\nDiscriminator\n,\nself\n)\n.\n__init__\n()\nself\n.\nngpu\n=\nngpu\nself\n.\nmain\n=\nnn\n.\nSequential\n(\n# input is ``(nc) x 64 x 64``\nnn\n.\nConv2d\n(\nnc\n,\nndf\n,\n4\n,\n2\n,\n1\n,\nbias\n=\nFalse\n),\nnn\n.\nLeakyReLU\n(\n0.2\n,\ninplace\n=\nTrue\n),\n# state size. ``(ndf) x 32 x 32``\nnn\n.\nConv2d\n(\nndf\n,\nndf\n*\n2\n,\n4\n,\n2\n,\n1\n,\nbias\n=\nFalse\n),\nnn\n.\nBatchNorm2d\n(\nndf\n*\n2\n),\nnn\n.\nLeakyReLU\n(\n0.2\n,\ninplace\n=\nTrue\n),\n# state size. ``(ndf*2) x 16 x 16``\nnn\n.\nConv2d\n(\nndf\n*\n2\n,\nndf\n*\n4\n,\n4\n,\n2\n,\n1\n,\nbias\n=\nFalse\n),\nnn\n.\nBatchNorm2d\n(\nndf\n*\n4\n),\nnn\n.\nLeakyReLU\n(\n0.2\n,\ninplace\n=\nTrue\n),\n# state size. ``(ndf*4) x 8 x 8``\nnn\n.\nConv2d\n(\nndf\n*\n4\n,\nndf\n*\n8\n,\n4\n,\n2\n,\n1\n,\nbias\n=\nFalse\n),\nnn\n.\nBatchNorm2d\n(\nndf\n*\n8\n),\nnn\n.\nLeakyReLU\n(\n0.2\n,\ninplace\n=\nTrue\n),\n# state size. ``(ndf*8) x 4 x 4``\nnn\n.\nConv2d\n(\nndf\n*\n8\n,\n1\n,\n4\n,\n1\n,\n0\n,\nbias\n=\nFalse\n),\nnn\n.\nSigmoid\n()\n)\ndef\nforward\n(\nself\n,\ninput\n):\nreturn\nself\n.\nmain\n(\ninput\n)\nNow, as with the generator, we can create the discriminator, apply the\nweights_init\nfunction, and print the model’s structure.\n# Create the Discriminator\nnetD\n=\nDiscriminator\n(\nngpu\n)\n.\nto\n(\ndevice\n)\n# Handle multi-GPU if desired\nif\n(\ndevice\n.\ntype\n==\n'cuda'\n)\nand\n(\nngpu\n>\n1\n):\nnetD\n=\nnn\n.\nDataParallel\n(\nnetD\n,\nlist\n(\nrange\n(\nngpu\n)))\n# Apply the ``weights_init`` function to randomly initialize all weights\n# like this: ``to mean=0, stdev=0.2``.\nnetD\n.\napply\n(\nweights_init\n)\n# Print the model\nprint\n(\nnetD\n)\nDiscriminator(\n  (main): Sequential(\n    (0): Conv2d(3, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (1): LeakyReLU(negative_slope=0.2, inplace=True)\n    (2): Conv2d(64, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (3): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (4): LeakyReLU(negative_slope=0.2, inplace=True)\n    (5): Conv2d(128, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (6): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (7): LeakyReLU(negative_slope=0.2, inplace=True)\n    (8): Conv2d(256, 512, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (9): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (10): LeakyReLU(negative_slope=0.2, inplace=True)\n    (11): Conv2d(512, 1, kernel_size=(4, 4), stride=(1, 1), bias=False)\n    (12): Sigmoid()\n  )\n)\nLoss Functions and Optimizers\n#\nWith\n\\(D\\)\nand\n\\(G\\)\nsetup, we can specify how they learn\nthrough the loss functions and optimizers. We will use the Binary Cross\nEntropy loss\n(\nBCELoss\n)\nfunction which is defined in PyTorch as:\n\\[\\ell(x, y) = L = \\{l_1,\\dots,l_N\\}^\\top, \\quad l_n = - \\left[ y_n \\cdot \\log x_n + (1 - y_n) \\cdot \\log (1 - x_n) \\right]\n\n\\]\nNotice how this function provides the calculation of both log components\nin the objective function (i.e.\n\\(log(D(x))\\)\nand\n\\(log(1-D(G(z)))\\)\n). We can specify what part of the BCE equation to\nuse with the\n\\(y\\)\ninput. This is accomplished in the training loop\nwhich is coming up soon, but it is important to understand how we can\nchoose which component we wish to calculate just by changing\n\\(y\\)\n(i.e. GT labels).\nNext, we define our real label as 1 and the fake label as 0. These\nlabels will be used when calculating the losses of\n\\(D\\)\nand\n\\(G\\)\n, and this is also the convention used in the original GAN\npaper. Finally, we set up two separate optimizers, one for\n\\(D\\)\nand\none for\n\\(G\\)\n. As specified in the DCGAN paper, both are Adam\noptimizers with learning rate 0.0002 and Beta1 = 0.5. For keeping track\nof the generator’s learning progression, we will generate a fixed batch\nof latent vectors that are drawn from a Gaussian distribution\n(i.e. fixed_noise) . In the training loop, we will periodically input\nthis fixed_noise into\n\\(G\\)\n, and over the iterations we will see\nimages form out of the noise.\n# Initialize the ``BCELoss`` function\ncriterion\n=\nnn\n.\nBCELoss\n()\n# Create batch of latent vectors that we will use to visualize\n#  the progression of the generator\nfixed_noise\n=\ntorch\n.\nrandn\n(\n64\n,\nnz\n,\n1\n,\n1\n,\ndevice\n=\ndevice\n)\n# Establish convention for real and fake labels during training\nreal_label\n=\n1.\nfake_label\n=\n0.\n# Setup Adam optimizers for both G and D\noptimizerD\n=\noptim\n.\nAdam\n(\nnetD\n.\nparameters\n(),\nlr\n=\nlr\n,\nbetas\n=\n(\nbeta1\n,\n0.999\n))\noptimizerG\n=\noptim\n.\nAdam\n(\nnetG\n.\nparameters\n(),\nlr\n=\nlr\n,\nbetas\n=\n(\nbeta1\n,\n0.999\n))\nTraining\n#\nFinally, now that we have all of the parts of the GAN framework defined,\nwe can train it. Be mindful that training GANs is somewhat of an art\nform, as incorrect hyperparameter settings lead to mode collapse with\nlittle explanation of what went wrong. Here, we will closely follow\nAlgorithm 1 from the\nGoodfellow’s paper\n,\nwhile abiding by some of the best\npractices shown in\nganhacks\n.\nNamely, we will “construct different mini-batches for real and fake”\nimages, and also adjust G’s objective function to maximize\n\\(log(D(G(z)))\\)\n. Training is split up into two main parts. Part 1\nupdates the Discriminator and Part 2 updates the Generator.\nPart 1 - Train the Discriminator\nRecall, the goal of training the discriminator is to maximize the\nprobability of correctly classifying a given input as real or fake. In\nterms of Goodfellow, we wish to “update the discriminator by ascending\nits stochastic gradient”. Practically, we want to maximize\n\\(log(D(x)) + log(1-D(G(z)))\\)\n. Due to the separate mini-batch\nsuggestion from\nganhacks\n,\nwe will calculate this in two steps. First, we\nwill construct a batch of real samples from the training set, forward\npass through\n\\(D\\)\n, calculate the loss (\n\\(log(D(x))\\)\n), then\ncalculate the gradients in a backward pass. Secondly, we will construct\na batch of fake samples with the current generator, forward pass this\nbatch through\n\\(D\\)\n, calculate the loss (\n\\(log(1-D(G(z)))\\)\n),\nand\naccumulate\nthe gradients with a backward pass. Now, with the\ngradients accumulated from both the all-real and all-fake batches, we\ncall a step of the Discriminator’s optimizer.\nPart 2 - Train the Generator\nAs stated in the original paper, we want to train the Generator by\nminimizing\n\\(log(1-D(G(z)))\\)\nin an effort to generate better fakes.\nAs mentioned, this was shown by Goodfellow to not provide sufficient\ngradients, especially early in the learning process. As a fix, we\ninstead wish to maximize\n\\(log(D(G(z)))\\)\n. In the code we accomplish\nthis by: classifying the Generator output from Part 1 with the\nDiscriminator, computing G’s loss\nusing real labels as GT\n, computing\nG’s gradients in a backward pass, and finally updating G’s parameters\nwith an optimizer step. It may seem counter-intuitive to use the real\nlabels as GT labels for the loss function, but this allows us to use the\n\\(log(x)\\)\npart of the\nBCELoss\n(rather than the\n\\(log(1-x)\\)\npart) which is exactly what we want.\nFinally, we will do some statistic reporting and at the end of each\nepoch we will push our fixed_noise batch through the generator to\nvisually track the progress of G’s training. The training statistics\nreported are:\nLoss_D\n- discriminator loss calculated as the sum of losses for\nthe all real and all fake batches (\n\\(log(D(x)) + log(1 - D(G(z)))\\)\n).\nLoss_G\n- generator loss calculated as\n\\(log(D(G(z)))\\)\nD(x)\n- the average output (across the batch) of the discriminator\nfor the all real batch. This should start close to 1 then\ntheoretically converge to 0.5 when G gets better. Think about why\nthis is.\nD(G(z))\n- average discriminator outputs for the all fake batch.\nThe first number is before D is updated and the second number is\nafter D is updated. These numbers should start near 0 and converge to\n0.5 as G gets better. Think about why this is.\nNote:\nThis step might take a while, depending on how many epochs you\nrun and if you removed some data from the dataset.\n# Training Loop\n# Lists to keep track of progress\nimg_list\n=\n[]\nG_losses\n=\n[]\nD_losses\n=\n[]\niters\n=\n0\nprint\n(\n\"Starting Training Loop...\"\n)\n# For each epoch\nfor\nepoch\nin\nrange\n(\nnum_epochs\n):\n# For each batch in the dataloader\nfor\ni\n,\ndata\nin\nenumerate\n(\ndataloader\n,\n0\n):\n############################\n# (1) Update D network: maximize log(D(x)) + log(1 - D(G(z)))\n###########################\n## Train with all-real batch\nnetD\n.\nzero_grad\n()\n# Format batch\nreal_cpu\n=\ndata\n[\n0\n]\n.\nto\n(\ndevice\n)\nb_size\n=\nreal_cpu\n.\nsize\n(\n0\n)\nlabel\n=\ntorch\n.\nfull\n((\nb_size\n,),\nreal_label\n,\ndtype\n=\ntorch\n.\nfloat\n,\ndevice\n=\ndevice\n)\n# Forward pass real batch through D\noutput\n=\nnetD\n(\nreal_cpu\n)\n.\nview\n(\n-\n1\n)\n# Calculate loss on all-real batch\nerrD_real\n=\ncriterion\n(\noutput\n,\nlabel\n)\n# Calculate gradients for D in backward pass\nerrD_real\n.\nbackward\n()\nD_x\n=\noutput\n.\nmean\n()\n.\nitem\n()\n## Train with all-fake batch\n# Generate batch of latent vectors\nnoise\n=\ntorch\n.\nrandn\n(\nb_size\n,\nnz\n,\n1\n,\n1\n,\ndevice\n=\ndevice\n)\n# Generate fake image batch with G\nfake\n=\nnetG\n(\nnoise\n)\nlabel\n.\nfill_\n(\nfake_label\n)\n# Classify all fake batch with D\noutput\n=\nnetD\n(\nfake\n.\ndetach\n())\n.\nview\n(\n-\n1\n)\n# Calculate D's loss on the all-fake batch\nerrD_fake\n=\ncriterion\n(\noutput\n,\nlabel\n)\n# Calculate the gradients for this batch, accumulated (summed) with previous gradients\nerrD_fake\n.\nbackward\n()\nD_G_z1\n=\noutput\n.\nmean\n()\n.\nitem\n()\n# Compute error of D as sum over the fake and the real batches\nerrD\n=\nerrD_real\n+\nerrD_fake\n# Update D\noptimizerD\n.\nstep\n()\n############################\n# (2) Update G network: maximize log(D(G(z)))\n###########################\nnetG\n.\nzero_grad\n()\nlabel\n.\nfill_\n(\nreal_label\n)\n# fake labels are real for generator cost\n# Since we just updated D, perform another forward pass of all-fake batch through D\noutput\n=\nnetD\n(\nfake\n)\n.\nview\n(\n-\n1\n)\n# Calculate G's loss based on this output\nerrG\n=\ncriterion\n(\noutput\n,\nlabel\n)\n# Calculate gradients for G\nerrG\n.\nbackward\n()\nD_G_z2\n=\noutput\n.\nmean\n()\n.\nitem\n()\n# Update G\noptimizerG\n.\nstep\n()\n# Output training stats\nif\ni\n%\n50\n==\n0\n:\nprint\n(\n'[\n%d\n/\n%d\n][\n%d\n/\n%d\n]\n\\t\nLoss_D:\n%.4f\n\\t\nLoss_G:\n%.4f\n\\t\nD(x):\n%.4f\n\\t\nD(G(z)):\n%.4f\n/\n%.4f\n'\n%\n(\nepoch\n,\nnum_epochs\n,\ni\n,\nlen\n(\ndataloader\n),\nerrD\n.\nitem\n(),\nerrG\n.\nitem\n(),\nD_x\n,\nD_G_z1\n,\nD_G_z2\n))\n# Save Losses for plotting later\nG_losses\n.\nappend\n(\nerrG\n.\nitem\n())\nD_losses\n.\nappend\n(\nerrD\n.\nitem\n())\n# Check how the generator is doing by saving G's output on fixed_noise\nif\n(\niters\n%\n500\n==\n0\n)\nor\n((\nepoch\n==\nnum_epochs\n-\n1\n)\nand\n(\ni\n==\nlen\n(\ndataloader\n)\n-\n1\n)):\nwith\ntorch\n.\nno_grad\n():\nfake\n=\nnetG\n(\nfixed_noise\n)\n.\ndetach\n()\n.\ncpu\n()\nimg_list\n.\nappend\n(\nvutils\n.\nmake_grid\n(\nfake\n,\npadding\n=\n2\n,\nnormalize\n=\nTrue\n))\niters\n+=\n1\nStarting Training Loop...\n[0/5][0/1583]   Loss_D: 1.4639  Loss_G: 6.9363  D(x): 0.7143    D(G(z)): 0.5877 / 0.0017\n[0/5][50/1583]  Loss_D: 0.0335  Loss_G: 16.0282 D(x): 0.9813    D(G(z)): 0.0000 / 0.0000\n[0/5][100/1583] Loss_D: 0.4136  Loss_G: 3.8454  D(x): 0.8426    D(G(z)): 0.1067 / 0.0408\n[0/5][150/1583] Loss_D: 0.5206  Loss_G: 4.0907  D(x): 0.7922    D(G(z)): 0.1732 / 0.0333\n[0/5][200/1583] Loss_D: 2.3379  Loss_G: 13.0434 D(x): 0.9244    D(G(z)): 0.8178 / 0.0000\n[0/5][250/1583] Loss_D: 0.3563  Loss_G: 5.1989  D(x): 0.8698    D(G(z)): 0.1518 / 0.0089\n[0/5][300/1583] Loss_D: 1.0709  Loss_G: 1.6531  D(x): 0.4849    D(G(z)): 0.0507 / 0.2972\n[0/5][350/1583] Loss_D: 0.4713  Loss_G: 6.0641  D(x): 0.9406    D(G(z)): 0.2967 / 0.0053\n[0/5][400/1583] Loss_D: 0.8053  Loss_G: 7.5662  D(x): 0.9341    D(G(z)): 0.4660 / 0.0016\n[0/5][450/1583] Loss_D: 0.5695  Loss_G: 4.7134  D(x): 0.8291    D(G(z)): 0.2157 / 0.0217\n[0/5][500/1583] Loss_D: 1.0662  Loss_G: 2.7778  D(x): 0.4828    D(G(z)): 0.0906 / 0.1134\n[0/5][550/1583] Loss_D: 0.3802  Loss_G: 4.1184  D(x): 0.7979    D(G(z)): 0.0655 / 0.0302\n[0/5][600/1583] Loss_D: 0.3569  Loss_G: 5.8982  D(x): 0.8807    D(G(z)): 0.1630 / 0.0052\n[0/5][650/1583] Loss_D: 0.6227  Loss_G: 5.1058  D(x): 0.6387    D(G(z)): 0.0158 / 0.0134\n[0/5][700/1583] Loss_D: 0.5803  Loss_G: 7.0945  D(x): 0.9065    D(G(z)): 0.3245 / 0.0021\n[0/5][750/1583] Loss_D: 0.2599  Loss_G: 8.5842  D(x): 0.8288    D(G(z)): 0.0063 / 0.0011\n[0/5][800/1583] Loss_D: 0.8226  Loss_G: 8.1796  D(x): 0.9771    D(G(z)): 0.4773 / 0.0007\n[0/5][850/1583] Loss_D: 0.6746  Loss_G: 4.8579  D(x): 0.8342    D(G(z)): 0.2834 / 0.0246\n[0/5][900/1583] Loss_D: 0.4721  Loss_G: 3.1009  D(x): 0.7903    D(G(z)): 0.1481 / 0.0659\n[0/5][950/1583] Loss_D: 0.8599  Loss_G: 1.6909  D(x): 0.6047    D(G(z)): 0.1094 / 0.2435\n[0/5][1000/1583]        Loss_D: 0.6415  Loss_G: 4.8156  D(x): 0.8288    D(G(z)): 0.2918 / 0.0197\n[0/5][1050/1583]        Loss_D: 0.4587  Loss_G: 3.6132  D(x): 0.8037    D(G(z)): 0.1277 / 0.0458\n[0/5][1100/1583]        Loss_D: 0.8629  Loss_G: 6.4246  D(x): 0.9380    D(G(z)): 0.4683 / 0.0045\n[0/5][1150/1583]        Loss_D: 0.4934  Loss_G: 6.4047  D(x): 0.9231    D(G(z)): 0.2861 / 0.0032\n[0/5][1200/1583]        Loss_D: 0.4716  Loss_G: 3.6436  D(x): 0.8290    D(G(z)): 0.1614 / 0.0494\n[0/5][1250/1583]        Loss_D: 0.4101  Loss_G: 3.6744  D(x): 0.7819    D(G(z)): 0.0860 / 0.0528\n[0/5][1300/1583]        Loss_D: 1.0250  Loss_G: 2.1397  D(x): 0.5451    D(G(z)): 0.1394 / 0.1862\n[0/5][1350/1583]        Loss_D: 0.7924  Loss_G: 2.7885  D(x): 0.7071    D(G(z)): 0.2612 / 0.0861\n[0/5][1400/1583]        Loss_D: 0.3543  Loss_G: 2.2940  D(x): 0.8108    D(G(z)): 0.0950 / 0.1510\n[0/5][1450/1583]        Loss_D: 1.6106  Loss_G: 1.8363  D(x): 0.2962    D(G(z)): 0.0046 / 0.2410\n[0/5][1500/1583]        Loss_D: 0.6485  Loss_G: 5.9762  D(x): 0.8651    D(G(z)): 0.3407 / 0.0047\n[0/5][1550/1583]        Loss_D: 0.4995  Loss_G: 4.7542  D(x): 0.8385    D(G(z)): 0.2170 / 0.0170\n[1/5][0/1583]   Loss_D: 0.3602  Loss_G: 3.8552  D(x): 0.7658    D(G(z)): 0.0422 / 0.0393\n[1/5][50/1583]  Loss_D: 1.0677  Loss_G: 2.4240  D(x): 0.4761    D(G(z)): 0.0200 / 0.1430\n[1/5][100/1583] Loss_D: 1.6919  Loss_G: 1.2506  D(x): 0.2777    D(G(z)): 0.0131 / 0.3854\n[1/5][150/1583] Loss_D: 0.8513  Loss_G: 6.0725  D(x): 0.9375    D(G(z)): 0.4965 / 0.0036\n[1/5][200/1583] Loss_D: 0.4481  Loss_G: 3.6840  D(x): 0.8617    D(G(z)): 0.2120 / 0.0417\n[1/5][250/1583] Loss_D: 0.4869  Loss_G: 2.3636  D(x): 0.7251    D(G(z)): 0.0814 / 0.1519\n[1/5][300/1583] Loss_D: 0.8142  Loss_G: 6.4943  D(x): 0.9433    D(G(z)): 0.4643 / 0.0037\n[1/5][350/1583] Loss_D: 0.3275  Loss_G: 4.3855  D(x): 0.9001    D(G(z)): 0.1706 / 0.0222\n[1/5][400/1583] Loss_D: 1.0553  Loss_G: 5.4383  D(x): 0.9198    D(G(z)): 0.5340 / 0.0113\n[1/5][450/1583] Loss_D: 0.5342  Loss_G: 3.4719  D(x): 0.6642    D(G(z)): 0.0172 / 0.0567\n[1/5][500/1583] Loss_D: 0.3529  Loss_G: 4.2050  D(x): 0.7726    D(G(z)): 0.0433 / 0.0253\n[1/5][550/1583] Loss_D: 0.3481  Loss_G: 4.0055  D(x): 0.8610    D(G(z)): 0.1469 / 0.0340\n[1/5][600/1583] Loss_D: 0.5269  Loss_G: 2.7998  D(x): 0.7031    D(G(z)): 0.0880 / 0.0907\n[1/5][650/1583] Loss_D: 0.4778  Loss_G: 3.2417  D(x): 0.8108    D(G(z)): 0.1782 / 0.0572\n[1/5][700/1583] Loss_D: 0.8457  Loss_G: 5.6924  D(x): 0.9377    D(G(z)): 0.4784 / 0.0070\n[1/5][750/1583] Loss_D: 1.6658  Loss_G: 5.8465  D(x): 0.9556    D(G(z)): 0.7095 / 0.0075\n[1/5][800/1583] Loss_D: 0.4271  Loss_G: 4.4940  D(x): 0.9294    D(G(z)): 0.2713 / 0.0171\n[1/5][850/1583] Loss_D: 0.5112  Loss_G: 2.2343  D(x): 0.7473    D(G(z)): 0.1261 / 0.1398\n[1/5][900/1583] Loss_D: 0.5887  Loss_G: 4.0595  D(x): 0.8503    D(G(z)): 0.3015 / 0.0312\n[1/5][950/1583] Loss_D: 0.8232  Loss_G: 1.7852  D(x): 0.5429    D(G(z)): 0.0224 / 0.2250\n[1/5][1000/1583]        Loss_D: 0.5225  Loss_G: 2.9947  D(x): 0.7243    D(G(z)): 0.1102 / 0.0916\n[1/5][1050/1583]        Loss_D: 0.4546  Loss_G: 2.7369  D(x): 0.7663    D(G(z)): 0.1208 / 0.0863\n[1/5][1100/1583]        Loss_D: 0.5109  Loss_G: 2.0627  D(x): 0.7003    D(G(z)): 0.0734 / 0.1667\n[1/5][1150/1583]        Loss_D: 0.5148  Loss_G: 1.9273  D(x): 0.7022    D(G(z)): 0.0851 / 0.1940\n[1/5][1200/1583]        Loss_D: 0.4869  Loss_G: 3.4446  D(x): 0.9155    D(G(z)): 0.2814 / 0.0543\n[1/5][1250/1583]        Loss_D: 2.1255  Loss_G: 8.5872  D(x): 0.9635    D(G(z)): 0.8007 / 0.0004\n[1/5][1300/1583]        Loss_D: 0.5144  Loss_G: 3.7323  D(x): 0.9250    D(G(z)): 0.3080 / 0.0413\n[1/5][1350/1583]        Loss_D: 0.4774  Loss_G: 2.0437  D(x): 0.7005    D(G(z)): 0.0573 / 0.1662\n[1/5][1400/1583]        Loss_D: 0.6017  Loss_G: 3.7591  D(x): 0.8787    D(G(z)): 0.3448 / 0.0338\n[1/5][1450/1583]        Loss_D: 0.3361  Loss_G: 2.5965  D(x): 0.8415    D(G(z)): 0.1248 / 0.1041\n[1/5][1500/1583]        Loss_D: 0.6442  Loss_G: 3.5299  D(x): 0.8733    D(G(z)): 0.3358 / 0.0457\n[1/5][1550/1583]        Loss_D: 0.5264  Loss_G: 3.3173  D(x): 0.8866    D(G(z)): 0.2955 / 0.0530\n[2/5][0/1583]   Loss_D: 0.4355  Loss_G: 2.9453  D(x): 0.8170    D(G(z)): 0.1740 / 0.0790\n[2/5][50/1583]  Loss_D: 0.5613  Loss_G: 2.2878  D(x): 0.7624    D(G(z)): 0.1989 / 0.1445\n[2/5][100/1583] Loss_D: 0.4071  Loss_G: 2.8658  D(x): 0.8440    D(G(z)): 0.1788 / 0.0787\n[2/5][150/1583] Loss_D: 0.7194  Loss_G: 2.3804  D(x): 0.6915    D(G(z)): 0.2386 / 0.1237\n[2/5][200/1583] Loss_D: 0.7337  Loss_G: 3.2976  D(x): 0.8361    D(G(z)): 0.3657 / 0.0505\n[2/5][250/1583] Loss_D: 0.6978  Loss_G: 1.1942  D(x): 0.5845    D(G(z)): 0.0600 / 0.3464\n[2/5][300/1583] Loss_D: 1.8758  Loss_G: 0.1049  D(x): 0.2247    D(G(z)): 0.0231 / 0.9067\n[2/5][350/1583] Loss_D: 0.7192  Loss_G: 1.6271  D(x): 0.7092    D(G(z)): 0.2432 / 0.2475\n[2/5][400/1583] Loss_D: 0.9044  Loss_G: 4.5618  D(x): 0.9135    D(G(z)): 0.5016 / 0.0175\n[2/5][450/1583] Loss_D: 0.4705  Loss_G: 2.6927  D(x): 0.8290    D(G(z)): 0.2166 / 0.0926\n[2/5][500/1583] Loss_D: 0.9481  Loss_G: 1.7050  D(x): 0.4741    D(G(z)): 0.0644 / 0.2479\n[2/5][550/1583] Loss_D: 0.8897  Loss_G: 1.5763  D(x): 0.5010    D(G(z)): 0.0646 / 0.2718\n[2/5][600/1583] Loss_D: 0.6414  Loss_G: 4.1424  D(x): 0.8967    D(G(z)): 0.3749 / 0.0225\n[2/5][650/1583] Loss_D: 1.1566  Loss_G: 0.6323  D(x): 0.4067    D(G(z)): 0.0403 / 0.5921\n[2/5][700/1583] Loss_D: 0.7189  Loss_G: 4.4080  D(x): 0.8873    D(G(z)): 0.4014 / 0.0205\n[2/5][750/1583] Loss_D: 0.6507  Loss_G: 3.0001  D(x): 0.8545    D(G(z)): 0.3497 / 0.0659\n[2/5][800/1583] Loss_D: 0.5050  Loss_G: 2.2567  D(x): 0.7411    D(G(z)): 0.1453 / 0.1463\n[2/5][850/1583] Loss_D: 0.6416  Loss_G: 1.8507  D(x): 0.6685    D(G(z)): 0.1546 / 0.1972\n[2/5][900/1583] Loss_D: 0.5452  Loss_G: 2.5952  D(x): 0.8675    D(G(z)): 0.2913 / 0.0956\n[2/5][950/1583] Loss_D: 0.7234  Loss_G: 2.6786  D(x): 0.7113    D(G(z)): 0.2608 / 0.0905\n[2/5][1000/1583]        Loss_D: 0.5062  Loss_G: 2.4790  D(x): 0.7909    D(G(z)): 0.2073 / 0.1052\n[2/5][1050/1583]        Loss_D: 0.7153  Loss_G: 2.3895  D(x): 0.8569    D(G(z)): 0.3822 / 0.1211\n[2/5][1100/1583]        Loss_D: 0.8595  Loss_G: 3.8420  D(x): 0.9298    D(G(z)): 0.5028 / 0.0325\n[2/5][1150/1583]        Loss_D: 0.6264  Loss_G: 2.0854  D(x): 0.7232    D(G(z)): 0.2128 / 0.1611\n[2/5][1200/1583]        Loss_D: 0.7019  Loss_G: 3.6000  D(x): 0.8918    D(G(z)): 0.3990 / 0.0429\n[2/5][1250/1583]        Loss_D: 0.5670  Loss_G: 2.2590  D(x): 0.7721    D(G(z)): 0.2216 / 0.1288\n[2/5][1300/1583]        Loss_D: 0.5370  Loss_G: 2.5245  D(x): 0.7748    D(G(z)): 0.2041 / 0.1076\n[2/5][1350/1583]        Loss_D: 1.2343  Loss_G: 5.6195  D(x): 0.9171    D(G(z)): 0.6329 / 0.0070\n[2/5][1400/1583]        Loss_D: 0.7298  Loss_G: 3.7086  D(x): 0.8529    D(G(z)): 0.3842 / 0.0335\n[2/5][1450/1583]        Loss_D: 0.5449  Loss_G: 3.5281  D(x): 0.8691    D(G(z)): 0.3028 / 0.0389\n[2/5][1500/1583]        Loss_D: 0.6057  Loss_G: 1.9677  D(x): 0.6187    D(G(z)): 0.0668 / 0.1777\n[2/5][1550/1583]        Loss_D: 0.4917  Loss_G: 3.4132  D(x): 0.8972    D(G(z)): 0.2894 / 0.0423\n[3/5][0/1583]   Loss_D: 0.5575  Loss_G: 1.8105  D(x): 0.7082    D(G(z)): 0.1537 / 0.2037\n[3/5][50/1583]  Loss_D: 1.7413  Loss_G: 5.1448  D(x): 0.9646    D(G(z)): 0.7700 / 0.0103\n[3/5][100/1583] Loss_D: 1.1206  Loss_G: 1.3007  D(x): 0.4276    D(G(z)): 0.0554 / 0.3365\n[3/5][150/1583] Loss_D: 0.5955  Loss_G: 1.7999  D(x): 0.7076    D(G(z)): 0.1747 / 0.2029\n[3/5][200/1583] Loss_D: 0.6961  Loss_G: 3.7222  D(x): 0.8321    D(G(z)): 0.3667 / 0.0321\n[3/5][250/1583] Loss_D: 0.4007  Loss_G: 2.8452  D(x): 0.7988    D(G(z)): 0.1379 / 0.0781\n[3/5][300/1583] Loss_D: 0.6564  Loss_G: 2.0469  D(x): 0.7051    D(G(z)): 0.2095 / 0.1643\n[3/5][350/1583] Loss_D: 0.6704  Loss_G: 1.3749  D(x): 0.6466    D(G(z)): 0.1634 / 0.2931\n[3/5][400/1583] Loss_D: 0.6857  Loss_G: 2.0913  D(x): 0.5764    D(G(z)): 0.0540 / 0.1542\n[3/5][450/1583] Loss_D: 0.6722  Loss_G: 3.6257  D(x): 0.8451    D(G(z)): 0.3591 / 0.0353\n[3/5][500/1583] Loss_D: 1.2377  Loss_G: 0.6136  D(x): 0.3546    D(G(z)): 0.0484 / 0.5801\n[3/5][550/1583] Loss_D: 0.4995  Loss_G: 2.5051  D(x): 0.8135    D(G(z)): 0.2210 / 0.1020\n[3/5][600/1583] Loss_D: 0.7371  Loss_G: 1.3311  D(x): 0.5612    D(G(z)): 0.0663 / 0.3027\n[3/5][650/1583] Loss_D: 0.5689  Loss_G: 1.7670  D(x): 0.6286    D(G(z)): 0.0547 / 0.2199\n[3/5][700/1583] Loss_D: 0.5304  Loss_G: 2.7843  D(x): 0.8501    D(G(z)): 0.2718 / 0.0785\n[3/5][750/1583] Loss_D: 0.4839  Loss_G: 2.3616  D(x): 0.8008    D(G(z)): 0.2041 / 0.1190\n[3/5][800/1583] Loss_D: 0.5746  Loss_G: 2.0189  D(x): 0.6863    D(G(z)): 0.1333 / 0.1655\n[3/5][850/1583] Loss_D: 0.8328  Loss_G: 3.7750  D(x): 0.8823    D(G(z)): 0.4617 / 0.0326\n[3/5][900/1583] Loss_D: 0.5305  Loss_G: 2.9058  D(x): 0.8745    D(G(z)): 0.2987 / 0.0696\n[3/5][950/1583] Loss_D: 0.5446  Loss_G: 2.5951  D(x): 0.8808    D(G(z)): 0.2981 / 0.1071\n[3/5][1000/1583]        Loss_D: 0.5476  Loss_G: 2.1378  D(x): 0.6528    D(G(z)): 0.0669 / 0.1621\n[3/5][1050/1583]        Loss_D: 0.9009  Loss_G: 1.1014  D(x): 0.5071    D(G(z)): 0.0916 / 0.3846\n[3/5][1100/1583]        Loss_D: 0.5750  Loss_G: 2.9691  D(x): 0.8845    D(G(z)): 0.3302 / 0.0663\n[3/5][1150/1583]        Loss_D: 0.8456  Loss_G: 1.7220  D(x): 0.6015    D(G(z)): 0.2135 / 0.2143\n[3/5][1200/1583]        Loss_D: 0.5376  Loss_G: 1.9356  D(x): 0.7530    D(G(z)): 0.1877 / 0.1840\n[3/5][1250/1583]        Loss_D: 0.9893  Loss_G: 3.8034  D(x): 0.9370    D(G(z)): 0.5492 / 0.0315\n[3/5][1300/1583]        Loss_D: 0.8103  Loss_G: 1.5027  D(x): 0.5088    D(G(z)): 0.0404 / 0.2727\n[3/5][1350/1583]        Loss_D: 0.5382  Loss_G: 1.4694  D(x): 0.7231    D(G(z)): 0.1599 / 0.2731\n[3/5][1400/1583]        Loss_D: 1.0334  Loss_G: 1.0126  D(x): 0.4632    D(G(z)): 0.1031 / 0.4122\n[3/5][1450/1583]        Loss_D: 0.4757  Loss_G: 1.9061  D(x): 0.7601    D(G(z)): 0.1547 / 0.1823\n[3/5][1500/1583]        Loss_D: 0.6546  Loss_G: 3.2963  D(x): 0.8076    D(G(z)): 0.3076 / 0.0504\n[3/5][1550/1583]        Loss_D: 0.7705  Loss_G: 3.2457  D(x): 0.8294    D(G(z)): 0.3949 / 0.0516\n[4/5][0/1583]   Loss_D: 0.6028  Loss_G: 2.3475  D(x): 0.7754    D(G(z)): 0.2488 / 0.1262\n[4/5][50/1583]  Loss_D: 0.7614  Loss_G: 3.9099  D(x): 0.9312    D(G(z)): 0.4557 / 0.0279\n[4/5][100/1583] Loss_D: 1.3392  Loss_G: 0.6799  D(x): 0.3213    D(G(z)): 0.0230 / 0.5560\n[4/5][150/1583] Loss_D: 0.5082  Loss_G: 3.0762  D(x): 0.8566    D(G(z)): 0.2760 / 0.0600\n[4/5][200/1583] Loss_D: 0.8252  Loss_G: 4.0072  D(x): 0.9221    D(G(z)): 0.4694 / 0.0296\n[4/5][250/1583] Loss_D: 0.4909  Loss_G: 2.6500  D(x): 0.7729    D(G(z)): 0.1818 / 0.0935\n[4/5][300/1583] Loss_D: 0.6793  Loss_G: 3.8483  D(x): 0.8954    D(G(z)): 0.3954 / 0.0293\n[4/5][350/1583] Loss_D: 0.5959  Loss_G: 3.2546  D(x): 0.8589    D(G(z)): 0.3267 / 0.0502\n[4/5][400/1583] Loss_D: 0.7204  Loss_G: 1.8128  D(x): 0.5761    D(G(z)): 0.0747 / 0.2132\n[4/5][450/1583] Loss_D: 0.6253  Loss_G: 3.8699  D(x): 0.9221    D(G(z)): 0.3843 / 0.0295\n[4/5][500/1583] Loss_D: 0.5200  Loss_G: 2.4470  D(x): 0.7570    D(G(z)): 0.1796 / 0.1181\n[4/5][550/1583] Loss_D: 0.9892  Loss_G: 4.7044  D(x): 0.8942    D(G(z)): 0.5066 / 0.0135\n[4/5][600/1583] Loss_D: 0.4343  Loss_G: 2.9781  D(x): 0.8453    D(G(z)): 0.2101 / 0.0642\n[4/5][650/1583] Loss_D: 1.5967  Loss_G: 4.2490  D(x): 0.9419    D(G(z)): 0.7255 / 0.0231\n[4/5][700/1583] Loss_D: 0.5672  Loss_G: 3.5243  D(x): 0.8898    D(G(z)): 0.3383 / 0.0360\n[4/5][750/1583] Loss_D: 0.5089  Loss_G: 3.1110  D(x): 0.8679    D(G(z)): 0.2821 / 0.0553\n[4/5][800/1583] Loss_D: 0.6581  Loss_G: 3.1131  D(x): 0.7878    D(G(z)): 0.2940 / 0.0682\n[4/5][850/1583] Loss_D: 1.3859  Loss_G: 0.6585  D(x): 0.3220    D(G(z)): 0.0369 / 0.6021\n[4/5][900/1583] Loss_D: 0.5722  Loss_G: 3.0522  D(x): 0.8335    D(G(z)): 0.2775 / 0.0693\n[4/5][950/1583] Loss_D: 0.4414  Loss_G: 2.5937  D(x): 0.8578    D(G(z)): 0.2228 / 0.1017\n[4/5][1000/1583]        Loss_D: 0.5011  Loss_G: 2.4809  D(x): 0.8281    D(G(z)): 0.2443 / 0.0999\n[4/5][1050/1583]        Loss_D: 0.7283  Loss_G: 1.9399  D(x): 0.6368    D(G(z)): 0.1740 / 0.1767\n[4/5][1100/1583]        Loss_D: 0.4500  Loss_G: 3.4137  D(x): 0.9333    D(G(z)): 0.2733 / 0.0502\n[4/5][1150/1583]        Loss_D: 0.7120  Loss_G: 3.4910  D(x): 0.8907    D(G(z)): 0.3977 / 0.0437\n[4/5][1200/1583]        Loss_D: 0.5525  Loss_G: 2.6768  D(x): 0.8155    D(G(z)): 0.2422 / 0.0931\n[4/5][1250/1583]        Loss_D: 0.6997  Loss_G: 1.5459  D(x): 0.5832    D(G(z)): 0.0603 / 0.2608\n[4/5][1300/1583]        Loss_D: 0.4300  Loss_G: 2.2103  D(x): 0.7592    D(G(z)): 0.1148 / 0.1421\n[4/5][1350/1583]        Loss_D: 2.4836  Loss_G: 5.5115  D(x): 0.9568    D(G(z)): 0.8612 / 0.0065\n[4/5][1400/1583]        Loss_D: 0.9552  Loss_G: 3.1371  D(x): 0.8761    D(G(z)): 0.5150 / 0.0606\n[4/5][1450/1583]        Loss_D: 0.5326  Loss_G: 1.7700  D(x): 0.7328    D(G(z)): 0.1584 / 0.2052\n[4/5][1500/1583]        Loss_D: 0.7565  Loss_G: 3.8208  D(x): 0.8543    D(G(z)): 0.4054 / 0.0292\n[4/5][1550/1583]        Loss_D: 0.5943  Loss_G: 2.3004  D(x): 0.7305    D(G(z)): 0.2107 / 0.1229\nResults\n#\nFinally, lets check out how we did. Here, we will look at three\ndifferent results. First, we will see how D and G’s losses changed\nduring training. Second, we will visualize G’s output on the fixed_noise\nbatch for every epoch. And third, we will look at a batch of real data\nnext to a batch of fake data from G.\nLoss versus training iteration\nBelow is a plot of D & G’s losses versus training iterations.\nplt\n.\nfigure\n(\nfigsize\n=\n(\n10\n,\n5\n))\nplt\n.\ntitle\n(\n\"Generator and Discriminator Loss During Training\"\n)\nplt\n.\nplot\n(\nG_losses\n,\nlabel\n=\n\"G\"\n)\nplt\n.\nplot\n(\nD_losses\n,\nlabel\n=\n\"D\"\n)\nplt\n.\nxlabel\n(\n\"iterations\"\n)\nplt\n.\nylabel\n(\n\"Loss\"\n)\nplt\n.\nlegend\n()\nplt\n.\nshow\n()\nVisualization of G’s progression\nRemember how we saved the generator’s output on the fixed_noise batch\nafter every epoch of training. Now, we can visualize the training\nprogression of G with an animation. Press the play button to start the\nanimation.\nfig\n=\nplt\n.\nfigure\n(\nfigsize\n=\n(\n8\n,\n8\n))\nplt\n.\naxis\n(\n\"off\"\n)\nims\n=\n[[\nplt\n.\nimshow\n(\nnp\n.\ntranspose\n(\ni\n,(\n1\n,\n2\n,\n0\n)),\nanimated\n=\nTrue\n)]\nfor\ni\nin\nimg_list\n]\nani\n=\nanimation\n.\nArtistAnimation\n(\nfig\n,\nims\n,\ninterval\n=\n1000\n,\nrepeat_delay\n=\n1000\n,\nblit\n=\nTrue\n)\nHTML\n(\nani\n.\nto_jshtml\n())\nOnce\nLoop\nReflect\nReal Images vs. Fake Images\nFinally, lets take a look at some real images and fake images side by\nside.\n# Grab a batch of real images from the dataloader\nreal_batch\n=\nnext\n(\niter\n(\ndataloader\n))\n# Plot the real images\nplt\n.\nfigure\n(\nfigsize\n=\n(\n15\n,\n15\n))\nplt\n.\nsubplot\n(\n1\n,\n2\n,\n1\n)\nplt\n.\naxis\n(\n\"off\"\n)\nplt\n.\ntitle\n(\n\"Real Images\"\n)\nplt\n.\nimshow\n(\nnp\n.\ntranspose\n(\nvutils\n.\nmake_grid\n(\nreal_batch\n[\n0\n]\n.\nto\n(\ndevice\n)[:\n64\n],\npadding\n=\n5\n,\nnormalize\n=\nTrue\n)\n.\ncpu\n(),(\n1\n,\n2\n,\n0\n)))\n# Plot the fake images from the last epoch\nplt\n.\nsubplot\n(\n1\n,\n2\n,\n2\n)\nplt\n.\naxis\n(\n\"off\"\n)\nplt\n.\ntitle\n(\n\"Fake Images\"\n)\nplt\n.\nimshow\n(\nnp\n.\ntranspose\n(\nimg_list\n[\n-\n1\n],(\n1\n,\n2\n,\n0\n)))\nplt\n.\nshow\n()\nWhere to Go Next\n#\nWe have reached the end of our journey, but there are several places you\ncould go from here. You could:\nTrain for longer to see how good the results get\nModify this model to take a different dataset and possibly change the\nsize of the images and the model architecture\nCheck out some other cool GAN projects\nhere\nCreate GANs that generate\nmusic\nTotal running time of the script:\n(6 minutes 25.847 seconds)\nDownload\nJupyter\nnotebook:\ndcgan_faces_tutorial.ipynb\nDownload\nPython\nsource\ncode:\ndcgan_faces_tutorial.py\nDownload\nzipped:\ndcgan_faces_tutorial.zip",
  "metadata": {
    "title": "DCGAN Tutorial — PyTorch Tutorials 2.14.0+cu130 documentation",
    "description": null,
    "keywords": null,
    "author": null,
    "og:image": "https://docs.pytorch.org/docs/stable/_static/img/pytorch_seo.png",
    "article:modified_time": "2022-07-20T23:02:43+00:00"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/ed4ec7b77c42/code/body-000.txt",
      "chars": 701,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-001.txt",
      "chars": 18,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-002.txt",
      "chars": 711,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-003.txt",
      "chars": 143,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-004.txt",
      "chars": 1047,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-005.txt",
      "chars": 345,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-006.txt",
      "chars": 1148,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-007.txt",
      "chars": 347,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-008.txt",
      "chars": 1044,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-009.txt",
      "chars": 1076,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-010.txt",
      "chars": 360,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-011.txt",
      "chars": 1003,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-012.txt",
      "chars": 501,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-013.txt",
      "chars": 3036,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-014.txt",
      "chars": 14746,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-015.txt",
      "chars": 215,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-016.txt",
      "chars": 237,
      "language": "text"
    },
    {
      "file": "attachments/ed4ec7b77c42/code/body-017.txt",
      "chars": 475,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_001.png",
      "bytes": 700163,
      "reused": true,
      "local_path": "attachments/ed4ec7b77c42/images/body-8b33e1a329e5e2567e3f.png",
      "src": "https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_001.png",
      "alt": "Training Images",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://docs.pytorch.org/tutorials/_images/dcgan_generator.png",
      "bytes": 85361,
      "reused": true,
      "local_path": "attachments/ed4ec7b77c42/images/body-5ee9f4797137fdc5a5e6.png",
      "src": "https://docs.pytorch.org/tutorials/_images/dcgan_generator.png",
      "alt": "dcgan_generator",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_002.png",
      "bytes": 47025,
      "reused": true,
      "local_path": "attachments/ed4ec7b77c42/images/body-b9388f8e452d33cce997.png",
      "src": "https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_002.png",
      "alt": "Generator and Discriminator Loss During Training",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_003.png",
      "bytes": 733323,
      "reused": true,
      "local_path": "attachments/ed4ec7b77c42/images/body-c7266476e6dd85c876db.png",
      "src": "https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_003.png",
      "alt": "dcgan faces tutorial",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_004.png",
      "bytes": 1083902,
      "reused": false,
      "content_type": "image/png",
      "local_path": "attachments/ed4ec7b77c42/images/body-6b0d9926a77a8ad20211.png",
      "src": "https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_004.png",
      "alt": "Real Images, Fake Images",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://github.com/inkawhich",
      "label": "Nathan Inkawhich",
      "type": "a"
    },
    {
      "href": "https://github.com/pytorch/examples",
      "label": "pytorch/examples",
      "type": "a"
    },
    {
      "href": "https://papers.nips.cc/paper/5423-generative-adversarial-nets.pdf",
      "label": "Generative Adversarial\nNets",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/pdf/1511.06434.pdf",
      "label": "Unsupervised Representation Learning With\nDeep Convolutional Generative Adversarial\nNetworks",
      "type": "a"
    },
    {
      "href": "https://pytorch.org/docs/stable/nn.html",
      "label": "convolution",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.manual_seed.html",
      "label": "torch . manual_seed",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.use_deterministic_algorithms.html",
      "label": "torch . use_deterministic_algorithms",
      "type": "a"
    },
    {
      "href": "https://github.com/pytorch/examples/issues/70",
      "label": "here",
      "type": "a"
    },
    {
      "href": "http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html",
      "label": "Celeb-A Faces\ndataset",
      "type": "a"
    },
    {
      "href": "https://drive.google.com/drive/folders/0B7EVK8r0v71pTUZsaXdaSnZBZzg",
      "label": "Google\nDrive",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.datasets.ImageFolder.html",
      "label": "dataset",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.Compose.html",
      "label": "transforms . Compose",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.Resize.html",
      "label": "transforms . Resize",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.CenterCrop.html",
      "label": "transforms . CenterCrop",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.ToTensor.html",
      "label": "transforms . ToTensor",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.Normalize.html",
      "label": "transforms . Normalize",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/data.html",
      "label": "dataloader",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/tensor_attributes.html",
      "label": "device",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.cuda.is_available.html",
      "label": "torch . cuda . is_available",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/vision/stable/generated/torchvision.utils.make_grid.html",
      "label": "vutils . make_grid",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/nn.init.html",
      "label": "nn . init . normal_",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html",
      "label": "nn . Module",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.Sequential.html",
      "label": "nn . Sequential",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.ConvTranspose2d.html",
      "label": "nn . ConvTranspose2d",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html",
      "label": "nn . BatchNorm2d",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.ReLU.html",
      "label": "nn . ReLU",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.Tanh.html",
      "label": "nn . Tanh",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.DataParallel.html",
      "label": "nn . DataParallel",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.Conv2d.html",
      "label": "nn . Conv2d",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.LeakyReLU.html",
      "label": "nn . LeakyReLU",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.Sigmoid.html",
      "label": "nn . Sigmoid",
      "type": "a"
    },
    {
      "href": "https://pytorch.org/docs/stable/generated/torch.nn.BCELoss.html",
      "label": "BCELoss",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.nn.BCELoss.html",
      "label": "criterion",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/tensors.html",
      "label": "fixed_noise",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.randn.html",
      "label": "torch . randn",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.optim.Adam.html",
      "label": "optimizerD",
      "type": "a"
    },
    {
      "href": "https://github.com/soumith/ganhacks",
      "label": "ganhacks",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.full.html",
      "label": "torch . full",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.Tensor.backward.html",
      "label": "errD_real . backward",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/docs/stable/generated/torch.no_grad.html",
      "label": "torch . no_grad",
      "type": "a"
    },
    {
      "href": "https://github.com/nashory/gans-awesome-applications",
      "label": "here",
      "type": "a"
    },
    {
      "href": "https://www.deepmind.com/blog/wavenet-a-generative-model-for-raw-audio/",
      "label": "music",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/tutorials/_downloads/5f81194dd43910d586578638f83205a3/dcgan_faces_tutorial.ipynb",
      "label": "Download Jupyter notebook: dcgan_faces_tutorial.ipynb",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/tutorials/_downloads/176a0eb17083f2a53b7e388098a15704/dcgan_faces_tutorial.py",
      "label": "Download Python source code: dcgan_faces_tutorial.py",
      "type": "a"
    },
    {
      "href": "https://docs.pytorch.org/tutorials/_downloads/1171400bfac7e45d5ecb874319f1a261/dcgan_faces_tutorial.zip",
      "label": "Download zipped: dcgan_faces_tutorial.zip",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-20T17:30:14Z",
  "source_url": "https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html",
  "delivery_status": "ok",
  "discovery_status": "ok",
  "missing_reason": "",
  "repair_error": "",
  "actual_video_files": [],
  "expected_saved_body_images": 1,
  "image_discovery": "saved_markdown",
  "source_body_markdown": "Opens in a new window Opens an external website Opens an external website in a new window\n<!---->Close this dialog<!---->\nThis website utilizes technologies such as cookies to enable essential site functionality, as well as for analytics, personalization, and targeted advertising. To learn more, view the following link:  [Privacy Policy](https://lfprojects.org/policies/privacy-policy/)\nManage Preferences \n<!---->Close Cookie Preferences<!---->\n[Skip to main content](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#main-content)\nBack to top\n`Ctrl`+`K`\n[ ![PyTorch Tutorials - Home](https://docs.pytorch.org/tutorials/_static/img/logo-dark.svg) ![PyTorch Tutorials - Home](https://docs.pytorch.org/tutorials/_static/img/logo-white.svg) ](https://docs.pytorch.org/tutorials/index.html)\n[ ![PyTorch Tutorials - Home](https://docs.pytorch.org/tutorials/_static/img/logo-dark.svg) ![PyTorch Tutorials - Home](https://docs.pytorch.org/tutorials/_static/img/logo-white.svg) ](https://docs.pytorch.org/tutorials/index.html)\n[v2.14.0+cu130](https://docs.pytorch.org/tutorials/index.html)\n  * [ Intro ](https://docs.pytorch.org/tutorials/intro.html)\n    * [ Learn the Basics ](https://docs.pytorch.org/tutorials/beginner/basics/intro.html)\n    * [ Introduction to PyTorch - YouTube Series ](https://docs.pytorch.org/tutorials/beginner/introyt/introyt_index.html)\n    * [ Deep Learning with PyTorch: A 60 Minute Blitz ](https://docs.pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html)\n    * [ Learning PyTorch with Examples ](https://docs.pytorch.org/tutorials/beginner/pytorch_with_examples.html)\n    * [ What is torch.nn really? ](https://docs.pytorch.org/tutorials/beginner/nn_tutorial.html)\n    * [ Understanding requires_grad, retain_grad, Leaf, and Non-leaf Tensors ](https://docs.pytorch.org/tutorials/beginner/understanding_leaf_vs_nonleaf_tutorial.html)\n    * [ NLP from Scratch ](https://docs.pytorch.org/tutorials/intermediate/nlp_from_scratch_index.html)\n    * [ Visualizing Models, Data, and Training with TensorBoard ](https://docs.pytorch.org/tutorials/intermediate/tensorboard_tutorial.html)\n    * [ A guide on good usage of non_blocking and pin_memory() in PyTorch ](https://docs.pytorch.org/tutorials/intermediate/pinmem_nonblock.html)\n    * [ Data Loading Optimization in PyTorch ](https://docs.pytorch.org/tutorials/intermediate/intermediate_data_loading_tutorial.html)\n    * [ Visualizing Gradients ](https://docs.pytorch.org/tutorials/intermediate/visualizing_gradients_tutorial.html)\n  * [ Compilers ](https://docs.pytorch.org/tutorials/compilers_index.html)\n    * [ Introduction to torch.compile ](https://docs.pytorch.org/tutorials/intermediate/torch_compile_tutorial.html)\n    * [ torch.compile End-to-End Tutorial ](https://docs.pytorch.org/tutorials/intermediate/torch_compile_full_example.html)\n    * [ Compiled Autograd: Capturing a larger backward graph for torch.compile ](https://docs.pytorch.org/tutorials/intermediate/compiled_autograd_tutorial.html)\n    * [ Inductor CPU backend debugging and profiling ](https://docs.pytorch.org/tutorials/intermediate/inductor_debug_cpu.html)\n    * [ Dynamic Compilation Control with torch.compiler.set_stance ](https://docs.pytorch.org/tutorials/recipes/torch_compiler_set_stance_tutorial.html)\n    * [ Demonstration of torch.export flow, common challenges and the solutions to address them ](https://docs.pytorch.org/tutorials/recipes/torch_export_challenges_solutions.html)\n    * [ (beta) Compiling the optimizer with torch.compile ](https://docs.pytorch.org/tutorials/recipes/compiling_optimizer.html)\n    * [ (beta) Running the compiled optimizer with an LR Scheduler ](https://docs.pytorch.org/tutorials/recipes/compiling_optimizer_lr_scheduler.html)\n    * [ Using Variable Length Attention in PyTorch ](https://docs.pytorch.org/tutorials/intermediate/variable_length_attention_tutorial.html)\n    * [ Using User-Defined Triton Kernels with torch.compile ](https://docs.pytorch.org/tutorials/recipes/torch_compile_user_defined_triton_kernel_tutorial.html)\n    * [ Compile Time Caching in torch.compile ](https://docs.pytorch.org/tutorials/recipes/torch_compile_caching_tutorial.html)\n    * [ Reducing torch.compile cold start compilation time with regional compilation ](https://docs.pytorch.org/tutorials/recipes/regional_compilation.html)\n    * [ torch.export Tutorial ](https://docs.pytorch.org/tutorials/intermediate/torch_export_tutorial.html)\n    * [ torch.export AOTInductor Tutorial for Python runtime (Beta) ](https://docs.pytorch.org/tutorials/recipes/torch_export_aoti_python.html)\n    * [ Demonstration of torch.export flow, common challenges and the solutions to address them ](https://docs.pytorch.org/tutorials/recipes/torch_export_challenges_solutions.html)\n    * [ Introduction to ONNX ](https://docs.pytorch.org/tutorials/beginner/onnx/intro_onnx.html)\n    * [ Export a PyTorch model to ONNX ](https://docs.pytorch.org/tutorials/beginner/onnx/export_simple_model_to_onnx_tutorial.html)\n    * [ Extending the ONNX Exporter Operator Support ](https://docs.pytorch.org/tutorials/beginner/onnx/onnx_registry_tutorial.html)\n    * [ Export a model with control flow to ONNX ](https://docs.pytorch.org/tutorials/beginner/onnx/export_control_flow_model_to_onnx_tutorial.html)\n    * [ Building a Convolution/Batch Norm fuser with torch.compile ](https://docs.pytorch.org/tutorials/intermediate/torch_compile_conv_bn_fuser.html)\n    * [ (beta) Building a Simple CPU Performance Profiler with FX ](https://docs.pytorch.org/tutorials/intermediate/fx_profiling_tutorial.html)\n  * [ Domains ](https://docs.pytorch.org/tutorials/domains.html)\n    * [ TorchVision Object Detection Finetuning Tutorial ](https://docs.pytorch.org/tutorials/intermediate/torchvision_tutorial.html)\n    * [ Transfer Learning for Computer Vision Tutorial ](https://docs.pytorch.org/tutorials/beginner/transfer_learning_tutorial.html)\n    * [ Adversarial Example Generation ](https://docs.pytorch.org/tutorials/beginner/fgsm_tutorial.html)\n    * [ DCGAN Tutorial ](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html)\n    * [ Spatial Transformer Networks Tutorial ](https://docs.pytorch.org/tutorials/intermediate/spatial_transformer_tutorial.html)\n    * [ Reinforcement Learning (DQN) Tutorial ](https://docs.pytorch.org/tutorials/intermediate/reinforcement_q_learning.html)\n    * [ Reinforcement Learning (PPO) with TorchRL Tutorial ](https://docs.pytorch.org/tutorials/intermediate/reinforcement_ppo.html)\n    * [ Train a Mario-playing RL Agent ](https://docs.pytorch.org/tutorials/intermediate/mario_rl_tutorial.html)\n    * [ Pendulum: Writing your environment and transforms with TorchRL ](https://docs.pytorch.org/tutorials/advanced/pendulum.html)\n    * [ Introduction to TorchRec ](https://docs.pytorch.org/tutorials/intermediate/torchrec_intro_tutorial.html)\n    * [ Exploring TorchRec sharding ](https://docs.pytorch.org/tutorials/advanced/sharding.html)\n  * [ Distributed ](https://docs.pytorch.org/tutorials/distributed.html)\n    * [ PyTorch Distributed Overview ](https://docs.pytorch.org/tutorials/beginner/dist_overview.html)\n    * [ Distributed Data Parallel in PyTorch - Video Tutorials ](https://docs.pytorch.org/tutorials/beginner/ddp_series_intro.html)\n    * [ Getting Started with Distributed Data Parallel ](https://docs.pytorch.org/tutorials/intermediate/ddp_tutorial.html)\n    * [ Writing Distributed Applications with PyTorch ](https://docs.pytorch.org/tutorials/intermediate/dist_tuto.html)\n    * [ Getting Started with Fully Sharded Data Parallel (FSDP2) ](https://docs.pytorch.org/tutorials/intermediate/FSDP_tutorial.html)\n    * [ Introduction to Libuv TCPStore Backend ](https://docs.pytorch.org/tutorials/intermediate/TCPStore_libuv_backend.html)\n    * [ Large Scale Transformer model training with Tensor Parallel (TP) ](https://docs.pytorch.org/tutorials/intermediate/TP_tutorial.html)\n    * [ Introduction to Distributed Pipeline Parallelism ](https://docs.pytorch.org/tutorials/intermediate/pipelining_tutorial.html)\n    * [ Customize Process Group Backends Using Cpp Extensions ](https://docs.pytorch.org/tutorials/intermediate/process_group_cpp_extension_tutorial.html)\n    * [ Getting Started with Distributed RPC Framework ](https://docs.pytorch.org/tutorials/intermediate/rpc_tutorial.html)\n    * [ Implementing a Parameter Server Using Distributed RPC Framework ](https://docs.pytorch.org/tutorials/intermediate/rpc_param_server_tutorial.html)\n    * [ Implementing Batch RPC Processing Using Asynchronous Executions ](https://docs.pytorch.org/tutorials/intermediate/rpc_async_execution.html)\n    * [ Interactive Distributed Applications with Monarch ](https://docs.pytorch.org/tutorials/intermediate/monarch_distributed_tutorial.html)\n    * [ Debugging Hangs with Flight Recorder Using TorchComms and Debug Server ](https://docs.pytorch.org/tutorials/intermediate/debug_hangs_with_flight_recorder.html)\n    * [ Combining Distributed DataParallel with Distributed RPC Framework ](https://docs.pytorch.org/tutorials/advanced/rpc_ddp_tutorial.html)\n    * [ Distributed Training with Uneven Inputs Using the Join Context Manager ](https://docs.pytorch.org/tutorials/advanced/generic_join.html)\n    * [ Distributed training at scale with PyTorch and Ray Train ](https://docs.pytorch.org/tutorials/beginner/distributed_training_with_ray_tutorial.html)\n  * [ Deep Dive ](https://docs.pytorch.org/tutorials/deep-dive.html)\n    * [ Profiling your PyTorch Module ](https://docs.pytorch.org/tutorials/beginner/profiler.html)\n    * [ CUDA Graph Kernel Annotations and Profiling ](https://docs.pytorch.org/tutorials/advanced/cuda_graph_annotations_tutorial.html)\n    * [ Parametrizations Tutorial ](https://docs.pytorch.org/tutorials/intermediate/parametrizations.html)\n    * [ Pruning Tutorial ](https://docs.pytorch.org/tutorials/intermediate/pruning_tutorial.html)\n    * [ Inductor CPU backend debugging and profiling ](https://docs.pytorch.org/tutorials/intermediate/inductor_debug_cpu.html)\n    * [ (Beta) Implementing High-Performance Transformers with Scaled Dot Product Attention (SDPA) ](https://docs.pytorch.org/tutorials/intermediate/scaled_dot_product_attention_tutorial.html)\n    * [ Knowledge Distillation Tutorial ](https://docs.pytorch.org/tutorials/beginner/knowledge_distillation_tutorial.html)\n    * [ Channels Last Memory Format in PyTorch ](https://docs.pytorch.org/tutorials/intermediate/memory_format_tutorial.html)\n    * [ Forward-mode Automatic Differentiation (Beta) ](https://docs.pytorch.org/tutorials/intermediate/forward_ad_usage.html)\n    * [ Jacobians, Hessians, hvp, vhp, and more: composing function transforms ](https://docs.pytorch.org/tutorials/intermediate/jacobians_hessians.html)\n    * [ Model ensembling ](https://docs.pytorch.org/tutorials/intermediate/ensembling.html)\n    * [ Per-sample-gradients ](https://docs.pytorch.org/tutorials/intermediate/per_sample_grads.html)\n    * [ Using the PyTorch C++ Frontend ](https://docs.pytorch.org/tutorials/advanced/cpp_frontend.html)\n    * [ Autograd in C++ Frontend ](https://docs.pytorch.org/tutorials/advanced/cpp_autograd.html)\n  * [ Extension ](https://docs.pytorch.org/tutorials/extension.html)\n    * [ PyTorch Custom Operators ](https://docs.pytorch.org/tutorials/advanced/custom_ops_landing_page.html)\n    * [ Double Backward with Custom Functions ](https://docs.pytorch.org/tutorials/intermediate/custom_function_double_backward_tutorial.html)\n    * [ Fusing Convolution and Batch Norm using Custom Function ](https://docs.pytorch.org/tutorials/intermediate/custom_function_conv_bn_tutorial.html)\n    * [ Registering a Dispatched Operator in C++ ](https://docs.pytorch.org/tutorials/advanced/dispatcher.html)\n    * [ Extending dispatcher for a new backend in C++ ](https://docs.pytorch.org/tutorials/advanced/extend_dispatcher.html)\n    * [ Facilitating New Backend Integration by PrivateUse1 ](https://docs.pytorch.org/tutorials/advanced/privateuseone.html)\n  * [ Ecosystem ](https://docs.pytorch.org/tutorials/ecosystem.html)\n    * [ Hyperparameter tuning using Ray Tune ](https://docs.pytorch.org/tutorials/beginner/hyperparameter_tuning_tutorial.html)\n    * [ Serve PyTorch models at scale with Ray Serve ](https://docs.pytorch.org/tutorials/beginner/serving_tutorial.html)\n    * [ Multi-Objective NAS with Ax ](https://docs.pytorch.org/tutorials/intermediate/ax_multiobjective_nas_tutorial.html)\n    * [ Real Time Inference on Raspberry Pi 4 and 5 (40 fps!) ](https://docs.pytorch.org/tutorials/intermediate/realtime_rpi.html)\n    * [ Mosaic: Memory Profiling for PyTorch ](https://docs.pytorch.org/tutorials/beginner/mosaic_memory_profiling_tutorial.html)\n    * [ Distributed training at scale with PyTorch and Ray Train ](https://docs.pytorch.org/tutorials/beginner/distributed_training_with_ray_tutorial.html)\n  * More \n    * [ Recipes ](https://docs.pytorch.org/tutorials/recipes_index.html)\n    * [ Unstable ](https://docs.pytorch.org/tutorials/unstable_index.html)\n\n\n[ Go to pytorch.org  ](https://pytorch.org)\n`Ctrl`+`K`  \n|   \n |   | [×](javascript:void\\(0\\) \"Clear search box\")  |  \n| --- | --- |  \n| search  |   |  \nCustom Search  \n|   |  Sort by Relevance Date  |  \n| --- | --- |  \n  * [ X](https://x.com/PyTorch)\n  * [ GitHub](https://github.com/pytorch/tutorials)\n  * [ Discourse](https://dev-discuss.pytorch.org/)\n  * [ PyPi](https://pypi.org/project/torch/)\n\n\n[v2.14.0+cu130](https://docs.pytorch.org/tutorials/index.html)\n  * [ Intro ](https://docs.pytorch.org/tutorials/intro.html)\n    * [ Learn the Basics ](https://docs.pytorch.org/tutorials/beginner/basics/intro.html)\n    * [ Introduction to PyTorch - YouTube Series ](https://docs.pytorch.org/tutorials/beginner/introyt/introyt_index.html)\n    * [ Deep Learning with PyTorch: A 60 Minute Blitz ](https://docs.pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html)\n    * [ Learning PyTorch with Examples ](https://docs.pytorch.org/tutorials/beginner/pytorch_with_examples.html)\n    * [ What is torch.nn really? ](https://docs.pytorch.org/tutorials/beginner/nn_tutorial.html)\n    * [ Understanding requires_grad, retain_grad, Leaf, and Non-leaf Tensors ](https://docs.pytorch.org/tutorials/beginner/understanding_leaf_vs_nonleaf_tutorial.html)\n    * [ NLP from Scratch ](https://docs.pytorch.org/tutorials/intermediate/nlp_from_scratch_index.html)\n    * [ Visualizing Models, Data, and Training with TensorBoard ](https://docs.pytorch.org/tutorials/intermediate/tensorboard_tutorial.html)\n    * [ A guide on good usage of non_blocking and pin_memory() in PyTorch ](https://docs.pytorch.org/tutorials/intermediate/pinmem_nonblock.html)\n    * [ Data Loading Optimization in PyTorch ](https://docs.pytorch.org/tutorials/intermediate/intermediate_data_loading_tutorial.html)\n    * [ Visualizing Gradients ](https://docs.pytorch.org/tutorials/intermediate/visualizing_gradients_tutorial.html)\n  * [ Compilers ](https://docs.pytorch.org/tutorials/compilers_index.html)\n    * [ Introduction to torch.compile ](https://docs.pytorch.org/tutorials/intermediate/torch_compile_tutorial.html)\n    * [ torch.compile End-to-End Tutorial ](https://docs.pytorch.org/tutorials/intermediate/torch_compile_full_example.html)\n    * [ Compiled Autograd: Capturing a larger backward graph for torch.compile ](https://docs.pytorch.org/tutorials/intermediate/compiled_autograd_tutorial.html)\n    * [ Inductor CPU backend debugging and profiling ](https://docs.pytorch.org/tutorials/intermediate/inductor_debug_cpu.html)\n    * [ Dynamic Compilation Control with torch.compiler.set_stance ](https://docs.pytorch.org/tutorials/recipes/torch_compiler_set_stance_tutorial.html)\n    * [ Demonstration of torch.export flow, common challenges and the solutions to address them ](https://docs.pytorch.org/tutorials/recipes/torch_export_challenges_solutions.html)\n    * [ (beta) Compiling the optimizer with torch.compile ](https://docs.pytorch.org/tutorials/recipes/compiling_optimizer.html)\n    * [ (beta) Running the compiled optimizer with an LR Scheduler ](https://docs.pytorch.org/tutorials/recipes/compiling_optimizer_lr_scheduler.html)\n    * [ Using Variable Length Attention in PyTorch ](https://docs.pytorch.org/tutorials/intermediate/variable_length_attention_tutorial.html)\n    * [ Using User-Defined Triton Kernels with torch.compile ](https://docs.pytorch.org/tutorials/recipes/torch_compile_user_defined_triton_kernel_tutorial.html)\n    * [ Compile Time Caching in torch.compile ](https://docs.pytorch.org/tutorials/recipes/torch_compile_caching_tutorial.html)\n    * [ Reducing torch.compile cold start compilation time with regional compilation ](https://docs.pytorch.org/tutorials/recipes/regional_compilation.html)\n    * [ torch.export Tutorial ](https://docs.pytorch.org/tutorials/intermediate/torch_export_tutorial.html)\n    * [ torch.export AOTInductor Tutorial for Python runtime (Beta) ](https://docs.pytorch.org/tutorials/recipes/torch_export_aoti_python.html)\n    * [ Demonstration of torch.export flow, common challenges and the solutions to address them ](https://docs.pytorch.org/tutorials/recipes/torch_export_challenges_solutions.html)\n    * [ Introduction to ONNX ](https://docs.pytorch.org/tutorials/beginner/onnx/intro_onnx.html)\n    * [ Export a PyTorch model to ONNX ](https://docs.pytorch.org/tutorials/beginner/onnx/export_simple_model_to_onnx_tutorial.html)\n    * [ Extending the ONNX Exporter Operator Support ](https://docs.pytorch.org/tutorials/beginner/onnx/onnx_registry_tutorial.html)\n    * [ Export a model with control flow to ONNX ](https://docs.pytorch.org/tutorials/beginner/onnx/export_control_flow_model_to_onnx_tutorial.html)\n    * [ Building a Convolution/Batch Norm fuser with torch.compile ](https://docs.pytorch.org/tutorials/intermediate/torch_compile_conv_bn_fuser.html)\n    * [ (beta) Building a Simple CPU Performance Profiler with FX ](https://docs.pytorch.org/tutorials/intermediate/fx_profiling_tutorial.html)\n  * [ Domains ](https://docs.pytorch.org/tutorials/domains.html)\n    * [ TorchVision Object Detection Finetuning Tutorial ](https://docs.pytorch.org/tutorials/intermediate/torchvision_tutorial.html)\n    * [ Transfer Learning for Computer Vision Tutorial ](https://docs.pytorch.org/tutorials/beginner/transfer_learning_tutorial.html)\n    * [ Adversarial Example Generation ](https://docs.pytorch.org/tutorials/beginner/fgsm_tutorial.html)\n    * [ DCGAN Tutorial ](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html)\n    * [ Spatial Transformer Networks Tutorial ](https://docs.pytorch.org/tutorials/intermediate/spatial_transformer_tutorial.html)\n    * [ Reinforcement Learning (DQN) Tutorial ](https://docs.pytorch.org/tutorials/intermediate/reinforcement_q_learning.html)\n    * [ Reinforcement Learning (PPO) with TorchRL Tutorial ](https://docs.pytorch.org/tutorials/intermediate/reinforcement_ppo.html)\n    * [ Train a Mario-playing RL Agent ](https://docs.pytorch.org/tutorials/intermediate/mario_rl_tutorial.html)\n    * [ Pendulum: Writing your environment and transforms with TorchRL ](https://docs.pytorch.org/tutorials/advanced/pendulum.html)\n    * [ Introduction to TorchRec ](https://docs.pytorch.org/tutorials/intermediate/torchrec_intro_tutorial.html)\n    * [ Exploring TorchRec sharding ](https://docs.pytorch.org/tutorials/advanced/sharding.html)\n  * [ Distributed ](https://docs.pytorch.org/tutorials/distributed.html)\n    * [ PyTorch Distributed Overview ](https://docs.pytorch.org/tutorials/beginner/dist_overview.html)\n    * [ Distributed Data Parallel in PyTorch - Video Tutorials ](https://docs.pytorch.org/tutorials/beginner/ddp_series_intro.html)\n    * [ Getting Started with Distributed Data Parallel ](https://docs.pytorch.org/tutorials/intermediate/ddp_tutorial.html)\n    * [ Writing Distributed Applications with PyTorch ](https://docs.pytorch.org/tutorials/intermediate/dist_tuto.html)\n    * [ Getting Started with Fully Sharded Data Parallel (FSDP2) ](https://docs.pytorch.org/tutorials/intermediate/FSDP_tutorial.html)\n    * [ Introduction to Libuv TCPStore Backend ](https://docs.pytorch.org/tutorials/intermediate/TCPStore_libuv_backend.html)\n    * [ Large Scale Transformer model training with Tensor Parallel (TP) ](https://docs.pytorch.org/tutorials/intermediate/TP_tutorial.html)\n    * [ Introduction to Distributed Pipeline Parallelism ](https://docs.pytorch.org/tutorials/intermediate/pipelining_tutorial.html)\n    * [ Customize Process Group Backends Using Cpp Extensions ](https://docs.pytorch.org/tutorials/intermediate/process_group_cpp_extension_tutorial.html)\n    * [ Getting Started with Distributed RPC Framework ](https://docs.pytorch.org/tutorials/intermediate/rpc_tutorial.html)\n    * [ Implementing a Parameter Server Using Distributed RPC Framework ](https://docs.pytorch.org/tutorials/intermediate/rpc_param_server_tutorial.html)\n    * [ Implementing Batch RPC Processing Using Asynchronous Executions ](https://docs.pytorch.org/tutorials/intermediate/rpc_async_execution.html)\n    * [ Interactive Distributed Applications with Monarch ](https://docs.pytorch.org/tutorials/intermediate/monarch_distributed_tutorial.html)\n    * [ Debugging Hangs with Flight Recorder Using TorchComms and Debug Server ](https://docs.pytorch.org/tutorials/intermediate/debug_hangs_with_flight_recorder.html)\n    * [ Combining Distributed DataParallel with Distributed RPC Framework ](https://docs.pytorch.org/tutorials/advanced/rpc_ddp_tutorial.html)\n    * [ Distributed Training with Uneven Inputs Using the Join Context Manager ](https://docs.pytorch.org/tutorials/advanced/generic_join.html)\n    * [ Distributed training at scale with PyTorch and Ray Train ](https://docs.pytorch.org/tutorials/beginner/distributed_training_with_ray_tutorial.html)\n  * [ Deep Dive ](https://docs.pytorch.org/tutorials/deep-dive.html)\n    * [ Profiling your PyTorch Module ](https://docs.pytorch.org/tutorials/beginner/profiler.html)\n    * [ CUDA Graph Kernel Annotations and Profiling ](https://docs.pytorch.org/tutorials/advanced/cuda_graph_annotations_tutorial.html)\n    * [ Parametrizations Tutorial ](https://docs.pytorch.org/tutorials/intermediate/parametrizations.html)\n    * [ Pruning Tutorial ](https://docs.pytorch.org/tutorials/intermediate/pruning_tutorial.html)\n    * [ Inductor CPU backend debugging and profiling ](https://docs.pytorch.org/tutorials/intermediate/inductor_debug_cpu.html)\n    * [ (Beta) Implementing High-Performance Transformers with Scaled Dot Product Attention (SDPA) ](https://docs.pytorch.org/tutorials/intermediate/scaled_dot_product_attention_tutorial.html)\n    * [ Knowledge Distillation Tutorial ](https://docs.pytorch.org/tutorials/beginner/knowledge_distillation_tutorial.html)\n    * [ Channels Last Memory Format in PyTorch ](https://docs.pytorch.org/tutorials/intermediate/memory_format_tutorial.html)\n    * [ Forward-mode Automatic Differentiation (Beta) ](https://docs.pytorch.org/tutorials/intermediate/forward_ad_usage.html)\n    * [ Jacobians, Hessians, hvp, vhp, and more: composing function transforms ](https://docs.pytorch.org/tutorials/intermediate/jacobians_hessians.html)\n    * [ Model ensembling ](https://docs.pytorch.org/tutorials/intermediate/ensembling.html)\n    * [ Per-sample-gradients ](https://docs.pytorch.org/tutorials/intermediate/per_sample_grads.html)\n    * [ Using the PyTorch C++ Frontend ](https://docs.pytorch.org/tutorials/advanced/cpp_frontend.html)\n    * [ Autograd in C++ Frontend ](https://docs.pytorch.org/tutorials/advanced/cpp_autograd.html)\n  * [ Extension ](https://docs.pytorch.org/tutorials/extension.html)\n    * [ PyTorch Custom Operators ](https://docs.pytorch.org/tutorials/advanced/custom_ops_landing_page.html)\n    * [ Double Backward with Custom Functions ](https://docs.pytorch.org/tutorials/intermediate/custom_function_double_backward_tutorial.html)\n    * [ Fusing Convolution and Batch Norm using Custom Function ](https://docs.pytorch.org/tutorials/intermediate/custom_function_conv_bn_tutorial.html)\n    * [ Registering a Dispatched Operator in C++ ](https://docs.pytorch.org/tutorials/advanced/dispatcher.html)\n    * [ Extending dispatcher for a new backend in C++ ](https://docs.pytorch.org/tutorials/advanced/extend_dispatcher.html)\n    * [ Facilitating New Backend Integration by PrivateUse1 ](https://docs.pytorch.org/tutorials/advanced/privateuseone.html)\n  * [ Ecosystem ](https://docs.pytorch.org/tutorials/ecosystem.html)\n    * [ Hyperparameter tuning using Ray Tune ](https://docs.pytorch.org/tutorials/beginner/hyperparameter_tuning_tutorial.html)\n    * [ Serve PyTorch models at scale with Ray Serve ](https://docs.pytorch.org/tutorials/beginner/serving_tutorial.html)\n    * [ Multi-Objective NAS with Ax ](https://docs.pytorch.org/tutorials/intermediate/ax_multiobjective_nas_tutorial.html)\n    * [ Real Time Inference on Raspberry Pi 4 and 5 (40 fps!) ](https://docs.pytorch.org/tutorials/intermediate/realtime_rpi.html)\n    * [ Mosaic: Memory Profiling for PyTorch ](https://docs.pytorch.org/tutorials/beginner/mosaic_memory_profiling_tutorial.html)\n    * [ Distributed training at scale with PyTorch and Ray Train ](https://docs.pytorch.org/tutorials/beginner/distributed_training_with_ray_tutorial.html)\n  * [ Recipes ](https://docs.pytorch.org/tutorials/recipes_index.html)\n    * [ Defining a Neural Network in PyTorch ](https://docs.pytorch.org/tutorials/recipes/recipes/defining_a_neural_network.html)\n    * [ (beta) Using TORCH_LOGS python API with torch.compile ](https://docs.pytorch.org/tutorials/recipes/torch_logs.html)\n    * [ What is a state_dict in PyTorch ](https://docs.pytorch.org/tutorials/recipes/recipes/what_is_state_dict.html)\n    * [ Warmstarting model using parameters from a different model in PyTorch ](https://docs.pytorch.org/tutorials/recipes/recipes/warmstarting_model_using_parameters_from_a_different_model.html)\n    * [ Zeroing out gradients in PyTorch ](https://docs.pytorch.org/tutorials/recipes/recipes/zeroing_out_gradients.html)\n    * [ PyTorch Profiler ](https://docs.pytorch.org/tutorials/recipes/recipes/profiler_recipe.html)\n    * [ Model Interpretability using Captum ](https://docs.pytorch.org/tutorials/recipes/recipes/Captum_Recipe.html)\n    * [ How to use TensorBoard with PyTorch ](https://docs.pytorch.org/tutorials/recipes/recipes/tensorboard_with_pytorch.html)\n    * [ Automatic Mixed Precision ](https://docs.pytorch.org/tutorials/recipes/recipes/amp_recipe.html)\n    * [ Performance Tuning Guide ](https://docs.pytorch.org/tutorials/recipes/recipes/tuning_guide.html)\n    * [ (beta) Compiling the optimizer with torch.compile ](https://docs.pytorch.org/tutorials/recipes/compiling_optimizer.html)\n    * [ Timer quick start ](https://docs.pytorch.org/tutorials/recipes/recipes/timer_quick_start.html)\n    * [ Shard Optimizer States with ZeroRedundancyOptimizer ](https://docs.pytorch.org/tutorials/recipes/zero_redundancy_optimizer.html)\n    * [ Getting Started with CommDebugMode ](https://docs.pytorch.org/tutorials/recipes/distributed_comm_debug_mode.html)\n    * [ Demonstration of torch.export flow, common challenges and the solutions to address them ](https://docs.pytorch.org/tutorials/recipes/torch_export_challenges_solutions.html)\n    * [ SyntaxError ](https://docs.pytorch.org/tutorials/recipes/recipes/benchmark.html)\n    * [ Tips for Loading an nn.Module from a Checkpoint ](https://docs.pytorch.org/tutorials/recipes/recipes/module_load_state_dict_tips.html)\n    * [ Reasoning about Shapes in PyTorch ](https://docs.pytorch.org/tutorials/recipes/recipes/reasoning_about_shapes.html)\n    * [ Extension points in nn.Module for load_state_dict and tensor subclasses ](https://docs.pytorch.org/tutorials/recipes/recipes/swap_tensors.html)\n    * [ torch.export AOTInductor Tutorial for Python runtime (Beta) ](https://docs.pytorch.org/tutorials/recipes/torch_export_aoti_python.html)\n    * [ How to use TensorBoard with PyTorch ](https://docs.pytorch.org/tutorials/recipes/recipes/tensorboard_with_pytorch.html)\n    * [ (beta) Utilizing Torch Function modes with torch.compile ](https://docs.pytorch.org/tutorials/recipes/torch_compile_torch_function_modes.html)\n    * [ (beta) Running the compiled optimizer with an LR Scheduler ](https://docs.pytorch.org/tutorials/recipes/compiling_optimizer_lr_scheduler.html)\n    * [ Explicit horizontal fusion with foreach_map and torch.compile ](https://docs.pytorch.org/tutorials/recipes/foreach_map.html)\n    * [ Using User-Defined Triton Kernels with torch.compile ](https://docs.pytorch.org/tutorials/recipes/torch_compile_user_defined_triton_kernel_tutorial.html)\n    * [ Compile Time Caching in torch.compile ](https://docs.pytorch.org/tutorials/recipes/torch_compile_caching_tutorial.html)\n    * [ Compile Time Caching Configuration ](https://docs.pytorch.org/tutorials/recipes/torch_compile_caching_configuration_tutorial.html)\n    * [ Reducing torch.compile cold start compilation time with regional compilation ](https://docs.pytorch.org/tutorials/recipes/regional_compilation.html)\n    * [ Reducing AoT cold start compilation time with regional compilation ](https://docs.pytorch.org/tutorials/recipes/regional_aot.html)\n    * [ Ease-of-use quantization for PyTorch with Intel® Neural Compressor ](https://docs.pytorch.org/tutorials/recipes/intel_neural_compressor_for_pytorch.html)\n    * [ Getting Started with DeviceMesh ](https://docs.pytorch.org/tutorials/recipes/distributed_device_mesh.html)\n    * [ Getting Started with Distributed Checkpoint (DCP) ](https://docs.pytorch.org/tutorials/recipes/distributed_checkpoint_recipe.html)\n    * [ Asynchronous Saving with Distributed Checkpoint (DCP) ](https://docs.pytorch.org/tutorials/recipes/distributed_async_checkpoint_recipe.html)\n    * [ DebugMode: Recording Dispatched Operations and Numerical Debugging ](https://docs.pytorch.org/tutorials/recipes/debug_mode_tutorial.html)\n  * [ Unstable ](https://docs.pytorch.org/tutorials/unstable_index.html)\n    * [ Introduction to Context Parallel ](https://docs.pytorch.org/tutorials/unstable/context_parallel.html)\n    * [ Flight Recorder for Debugging Stuck Jobs ](https://docs.pytorch.org/tutorials/unstable/flight_recorder_tutorial.html)\n    * [ TorchInductor C++ Wrapper Tutorial ](https://docs.pytorch.org/tutorials/unstable/inductor_cpp_wrapper_tutorial.html)\n    * [ How to use torch.compile on Windows CPU/XPU ](https://docs.pytorch.org/tutorials/unstable/inductor_windows.html)\n    * [ torch.vmap ](https://docs.pytorch.org/tutorials/unstable/vmap_recipe.html)\n    * [ Getting Started with Nested Tensors ](https://docs.pytorch.org/tutorials/unstable/nestedtensor.html)\n    * [ MaskedTensor Overview ](https://docs.pytorch.org/tutorials/unstable/maskedtensor_overview.html)\n    * [ MaskedTensor Sparsity ](https://docs.pytorch.org/tutorials/unstable/maskedtensor_sparsity.html)\n    * [ MaskedTensor Advanced Semantics ](https://docs.pytorch.org/tutorials/unstable/maskedtensor_advanced_semantics.html)\n    * [ Efficiently writing “sparse” semantics for Adagrad with MaskedTensor ](https://docs.pytorch.org/tutorials/unstable/maskedtensor_adagrad.html)\n    * [ Autoloading Out-of-Tree Extension ](https://docs.pytorch.org/tutorials/unstable/python_extension_autoload.html)\n    * [ Using Max-Autotune Compilation on CPU for Better Performance ](https://docs.pytorch.org/tutorials/unstable/max_autotune_on_CPU_tutorial.html)\n\n\n[ Go to pytorch.org  ](https://pytorch.org)\n`Ctrl`+`K`  \n|   \n |   | [×](javascript:void\\(0\\) \"Clear search box\")  |  \n| --- | --- |  \n| search  |   |  \nCustom Search  \n|   |  Sort by Relevance Date  |  \n| --- | --- |  \n  * [ X](https://x.com/PyTorch)\n  * [ GitHub](https://github.com/pytorch/tutorials)\n  * [ Discourse](https://dev-discuss.pytorch.org/)\n  * [ PyPi](https://pypi.org/project/torch/)\n\n\nSection Navigation\nImage and Video\n  * [TorchVision Object Detection Finetuning Tutorial](https://docs.pytorch.org/tutorials/intermediate/torchvision_tutorial.html)\n  * [Transfer Learning for Computer Vision Tutorial](https://docs.pytorch.org/tutorials/beginner/transfer_learning_tutorial.html)\n  * [Adversarial Example Generation](https://docs.pytorch.org/tutorials/beginner/fgsm_tutorial.html)\n  * [DCGAN Tutorial](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html)\n  * [Spatial Transformer Networks Tutorial](https://docs.pytorch.org/tutorials/intermediate/spatial_transformer_tutorial.html)\n\n\nReinforcement Learning\n  * [Reinforcement Learning (DQN) Tutorial](https://docs.pytorch.org/tutorials/intermediate/reinforcement_q_learning.html)\n  * [Reinforcement Learning (PPO) with TorchRL Tutorial](https://docs.pytorch.org/tutorials/intermediate/reinforcement_ppo.html)\n  * [Train a Mario-playing RL Agent](https://docs.pytorch.org/tutorials/intermediate/mario_rl_tutorial.html)\n  * [Pendulum: Writing your environment and transforms with TorchRL](https://docs.pytorch.org/tutorials/advanced/pendulum.html)\n\n\nRecommendation Systems\n  * [Introduction to TorchRec](https://docs.pytorch.org/tutorials/intermediate/torchrec_intro_tutorial.html)\n  * [Exploring TorchRec sharding](https://docs.pytorch.org/tutorials/advanced/sharding.html)\n\n\nOther Domains\n  * [See Audio tutorials on the audio website](https://pytorch.org/audio/stable/index.html)\n  * [See ExecuTorch tutorials on the ExecuTorch website](https://pytorch.org/executorch/stable/index.html)\n\n\n  * [ ](https://docs.pytorch.org/tutorials/index.html)\n  * [Domains](https://docs.pytorch.org/tutorials/domains.html)\n  * DCGAN Tutorial\n\n\nRate this Page \n★ ★ ★ ★ ★\nbeginner/dcgan_faces_tutorial\n[ ![](https://docs.pytorch.org/tutorials/_static/img/pytorch-colab.svg) Run in Google Colab Colab ](https://colab.research.google.com/github/pytorch/tutorials/blob/gh-pages/_downloads/5f81194dd43910d586578638f83205a3/dcgan_faces_tutorial.ipynb) [ ![](https://docs.pytorch.org/tutorials/_static/img/pytorch-download.svg) Download Notebook Notebook ](https://docs.pytorch.org/tutorials/_downloads/5f81194dd43910d586578638f83205a3/dcgan_faces_tutorial.ipynb) [ ![](https://docs.pytorch.org/tutorials/_static/img/pytorch-github.svg) View on GitHub GitHub ](https://github.com/pytorch/tutorials/blob/main/beginner_source/dcgan_faces_tutorial.py)\nNote\n[Go to the end](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#sphx-glr-download-beginner-dcgan-faces-tutorial-py) to download the full example code.\n# DCGAN Tutorial[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#dcgan-tutorial \"Link to this heading\")\nCreated On: Jul 31, 2018 | Last Updated: Jan 19, 2024 | Last Verified: Nov 05, 2024\n**Author** : [Nathan Inkawhich](https://github.com/inkawhich)\n## Introduction[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#introduction \"Link to this heading\")\nThis tutorial will give an introduction to DCGANs through an example. We will train a generative adversarial network (GAN) to generate new celebrities after showing it pictures of many real celebrities. Most of the code here is from the DCGAN implementation in [pytorch/examples](https://github.com/pytorch/examples), and this document will give a thorough explanation of the implementation and shed light on how and why this model works. But don’t worry, no prior knowledge of GANs is required, but it may require a first-timer to spend some time reasoning about what is actually happening under the hood. Also, for the sake of time it will help to have a GPU, or two. Lets start from the beginning.\n## Generative Adversarial Networks[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#generative-adversarial-networks \"Link to this heading\")\n### What is a GAN?[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#what-is-a-gan \"Link to this heading\")\nGANs are a framework for teaching a deep learning model to capture the training data distribution so we can generate new data from that same distribution. GANs were invented by Ian Goodfellow in 2014 and first described in the paper [Generative Adversarial Nets](https://papers.nips.cc/paper/5423-generative-adversarial-nets.pdf). They are made of two distinct models, a _generator_ and a _discriminator_. The job of the generator is to spawn ‘fake’ images that look like the training images. The job of the discriminator is to look at an image and output whether or not it is a real training image or a fake image from the generator. During training, the generator is constantly trying to outsmart the discriminator by generating better and better fakes, while the discriminator is working to become a better detective and correctly classify the real and fake images. The equilibrium of this game is when the generator is generating perfect fakes that look as if they came directly from the training data, and the discriminator is left to always guess at 50% confidence that the generator output is real or fake.\nNow, lets define some notation to be used throughout tutorial starting with the discriminator. Let xxx be data representing an image. D(x)D(x)D(x) is the discriminator network which outputs the (scalar) probability that xxx came from training data rather than the generator. Here, since we are dealing with images, the input to D(x)D(x)D(x) is an image of CHW size 3x64x64. Intuitively, D(x)D(x)D(x) should be HIGH when xxx comes from training data and LOW when xxx comes from the generator. D(x)D(x)D(x) can also be thought of as a traditional binary classifier.\nFor the generator’s notation, let zzz be a latent space vector sampled from a standard normal distribution. G(z)G(z)G(z) represents the generator function which maps the latent vector zzz to data-space. The goal of GGG is to estimate the distribution that the training data comes from (pdatap_{data}pdata​) so it can generate fake samples from that estimated distribution (pgp_gpg​).\nSo, D(G(z))D(G(z))D(G(z)) is the probability (scalar) that the output of the generator GGG is a real image. As described in [Goodfellow’s paper](https://papers.nips.cc/paper/5423-generative-adversarial-nets.pdf), DDD and GGG play a minimax game in which DDD tries to maximize the probability it correctly classifies reals and fakes (logD(x)logD(x)logD(x)), and GGG tries to minimize the probability that DDD will predict its outputs are fake (log(1−D(G(z)))log(1-D(G(z)))log(1−D(G(z)))). From the paper, the GAN loss function is\nminGmaxDV(D,G)=Ex∼pdata(x)[logD(x)]+Ez∼pz(z)[log(1−D(G(z)))]\\underset{G}{\\text{min}} \\underset{D}{\\text{max}}V(D,G) = \\mathbb{E}_{x\\sim p_{data}(x)}\\big[logD(x)\\big] + \\mathbb{E}_{z\\sim p_{z}(z)}\\big[log(1-D(G(z)))\\big] Gmin​Dmax​V(D,G)=Ex∼pdata​(x)​[logD(x)]+Ez∼pz​(z)​[log(1−D(G(z)))]\nIn theory, the solution to this minimax game is where pg=pdatap_g = p_{data}pg​=pdata​, and the discriminator guesses randomly if the inputs are real or fake. However, the convergence theory of GANs is still being actively researched and in reality models do not always train to this point.\n### What is a DCGAN?[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#what-is-a-dcgan \"Link to this heading\")\nA DCGAN is a direct extension of the GAN described above, except that it explicitly uses convolutional and convolutional-transpose layers in the discriminator and generator, respectively. It was first described by Radford et. al. in the paper [Unsupervised Representation Learning With Deep Convolutional Generative Adversarial Networks](https://arxiv.org/pdf/1511.06434.pdf). The discriminator is made up of strided [convolution](https://pytorch.org/docs/stable/nn.html#torch.nn.Conv2d) layers, [batch norm](https://pytorch.org/docs/stable/nn.html#torch.nn.BatchNorm2d) layers, and [LeakyReLU](https://pytorch.org/docs/stable/nn.html#torch.nn.LeakyReLU) activations. The input is a 3x64x64 input image and the output is a scalar probability that the input is from the real data distribution. The generator is comprised of [convolutional-transpose](https://pytorch.org/docs/stable/nn.html#torch.nn.ConvTranspose2d) layers, batch norm layers, and [ReLU](https://pytorch.org/docs/stable/nn.html#relu) activations. The input is a latent vector, zzz, that is drawn from a standard normal distribution and the output is a 3x64x64 RGB image. The strided conv-transpose layers allow the latent vector to be transformed into a volume with the same shape as an image. In the paper, the authors also give some tips about how to setup the optimizers, how to calculate the loss functions, and how to initialize the model weights, all of which will be explained in the coming sections.\n\n```\n#%matplotlib inline\nimport argparse\nimport os\nimport random\nimport torch\nimport torch.nn as nn\nimport torch.nn.parallel\nimport torch.optim as optim\nimport torch.utils.data\nimport torchvision.datasets as dset\nimport torchvision.transforms as transforms\nimport torchvision.utils as vutils\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib.animation as animation\nfrom IPython.display import HTML\n\n# Set random seed for reproducibility\nmanualSeed = 999\n#manualSeed = random.randint(1, 10000) # use if you want new results\nprint(\"Random Seed: \", manualSeed)\nrandom.seed(manualSeed)\n[torch.manual_seed](https://docs.pytorch.org/docs/stable/generated/torch.manual_seed.html#torch.manual_seed \"torch.manual_seed\")(manualSeed)\n[torch.use_deterministic_algorithms](https://docs.pytorch.org/docs/stable/generated/torch.use_deterministic_algorithms.html#torch.use_deterministic_algorithms \"torch.use_deterministic_algorithms\")(True) # Needed for reproducible results\n\n```\nCopy to clipboard\n\n```\nRandom Seed:  999\n\n```\nCopy to clipboard\n## Inputs[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#inputs \"Link to this heading\")\nLet’s define some inputs for the run:\n  * `dataroot` - the path to the root of the dataset folder. We will talk more about the dataset in the next section.\n  * `workers` - the number of worker threads for loading the data with the `DataLoader`.\n  * `batch_size` - the batch size used in training. The DCGAN paper uses a batch size of 128.\n  * `image_size` - the spatial size of the images used for training. This implementation defaults to 64x64. If another size is desired, the structures of D and G must be changed. See [here](https://github.com/pytorch/examples/issues/70) for more details.\n  * `nc` - number of color channels in the input images. For color images this is 3.\n  * `nz` - length of latent vector.\n  * `ngf` - relates to the depth of feature maps carried through the generator.\n  * `ndf` - sets the depth of feature maps propagated through the discriminator.\n  * `num_epochs` - number of training epochs to run. Training for longer will probably lead to better results but will also take much longer.\n  * `lr` - learning rate for training. As described in the DCGAN paper, this number should be 0.0002.\n  * `beta1` - beta1 hyperparameter for Adam optimizers. As described in paper, this number should be 0.5.\n  * `ngpu` - number of GPUs available. If this is 0, code will run in CPU mode. If this number is greater than 0 it will run on that number of GPUs.\n\n\n\n```\n# Root directory for dataset\ndataroot = \"data/celeba\"\n\n# Number of workers for dataloader\nworkers = 2\n\n# Batch size during training\nbatch_size = 128\n\n# Spatial size of training images. All images will be resized to this\n#   size using a transformer.\nimage_size = 64\n\n# Number of channels in the training images. For color images this is 3\nnc = 3\n\n# Size of z latent vector (i.e. size of generator input)\nnz = 100\n\n# Size of feature maps in generator\nngf = 64\n\n# Size of feature maps in discriminator\nndf = 64\n\n# Number of training epochs\nnum_epochs = 5\n\n# Learning rate for optimizers\nlr = 0.0002\n\n# Beta1 hyperparameter for Adam optimizers\nbeta1 = 0.5\n\n# Number of GPUs available. Use 0 for CPU mode.\nngpu = 1\n\n```\nCopy to clipboard\n## Data[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#data \"Link to this heading\")\nIn this tutorial we will use the [Celeb-A Faces dataset](http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html) which can be downloaded at the linked site, or in [Google Drive](https://drive.google.com/drive/folders/0B7EVK8r0v71pTUZsaXdaSnZBZzg). The dataset will download as a file named `img_align_celeba.zip`. Once downloaded, create a directory named `celeba` and extract the zip file into that directory. Then, set the `dataroot` input for this notebook to the `celeba` directory you just created. The resulting directory structure should be:\n\n```\n/path/to/celeba\n    -> img_align_celeba\n        -> 188242.jpg\n        -> 173822.jpg\n        -> 284702.jpg\n        -> 537394.jpg\n           ...\n\n```\nCopy to clipboard\nThis is an important step because we will be using the `ImageFolder` dataset class, which requires there to be subdirectories in the dataset root folder. Now, we can create the dataset, create the dataloader, set the device to run on, and finally visualize some of the training data.\n\n```\n# We can use an image folder dataset the way we have it setup.\n# Create the dataset\n[dataset](https://docs.pytorch.org/vision/stable/generated/torchvision.datasets.ImageFolder.html#torchvision.datasets.ImageFolder \"torchvision.datasets.ImageFolder\") = [dset.ImageFolder](https://docs.pytorch.org/vision/stable/generated/torchvision.datasets.ImageFolder.html#torchvision.datasets.ImageFolder \"torchvision.datasets.ImageFolder\")(root=dataroot,\n                           transform=[transforms.Compose](https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.Compose.html#torchvision.transforms.Compose \"torchvision.transforms.Compose\")([\n                               [transforms.Resize](https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.Resize.html#torchvision.transforms.Resize \"torchvision.transforms.Resize\")(image_size),\n                               [transforms.CenterCrop](https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.CenterCrop.html#torchvision.transforms.CenterCrop \"torchvision.transforms.CenterCrop\")(image_size),\n                               [transforms.ToTensor](https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.ToTensor.html#torchvision.transforms.ToTensor \"torchvision.transforms.ToTensor\")(),\n                               [transforms.Normalize](https://docs.pytorch.org/vision/stable/generated/torchvision.transforms.Normalize.html#torchvision.transforms.Normalize \"torchvision.transforms.Normalize\")((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),\n                           ]))\n# Create the dataloader\n[dataloader](https://docs.pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader \"torch.utils.data.DataLoader\") = [torch.utils.data.DataLoader](https://docs.pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader \"torch.utils.data.DataLoader\")([dataset](https://docs.pytorch.org/vision/stable/generated/torchvision.datasets.ImageFolder.html#torchvision.datasets.ImageFolder \"torchvision.datasets.ImageFolder\"), batch_size=batch_size,\n                                         shuffle=True, num_workers=workers)\n\n# Decide which device we want to run on\n[device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\") = [torch.device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\")(\"cuda:0\" if ([torch.cuda.is_available](https://docs.pytorch.org/docs/stable/generated/torch.cuda.is_available.html#torch.cuda.is_available \"torch.cuda.is_available\")() and ngpu > 0) else \"cpu\")\n\n# Plot some training images\nreal_batch = next(iter([dataloader](https://docs.pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader \"torch.utils.data.DataLoader\")))\nplt.figure(figsize=(8,8))\nplt.axis(\"off\")\nplt.title(\"Training Images\")\nplt.imshow(np.transpose([vutils.make_grid](https://docs.pytorch.org/vision/stable/generated/torchvision.utils.make_grid.html#torchvision.utils.make_grid \"torchvision.utils.make_grid\")(real_batch[0].to([device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\"))[:64], padding=2, normalize=True).cpu(),(1,2,0)))\nplt.show()\n\n```\nCopy to clipboard\n![Training Images](https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_001.png)\n## Implementation[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#implementation \"Link to this heading\")\nWith our input parameters set and the dataset prepared, we can now get into the implementation. We will start with the weight initialization strategy, then talk about the generator, discriminator, loss functions, and training loop in detail.\n### Weight Initialization[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#weight-initialization \"Link to this heading\")\nFrom the DCGAN paper, the authors specify that all model weights shall be randomly initialized from a Normal distribution with `mean=0`, `stdev=0.02`. The `weights_init` function takes an initialized model as input and reinitializes all convolutional, convolutional-transpose, and batch normalization layers to meet this criteria. This function is applied to the models immediately after initialization.\n\n```\n# custom weights initialization called on ``netG`` and ``netD``\ndef weights_init(m):\n    classname = m.__class__.__name__\n    if classname.find('Conv') != -1:\n        [nn.init.normal_](https://docs.pytorch.org/docs/stable/nn.init.html#torch.nn.init.normal_ \"torch.nn.init.normal_\")(m.weight.data, 0.0, 0.02)\n    elif classname.find('BatchNorm') != -1:\n        [nn.init.normal_](https://docs.pytorch.org/docs/stable/nn.init.html#torch.nn.init.normal_ \"torch.nn.init.normal_\")(m.weight.data, 1.0, 0.02)\n        [nn.init.constant_](https://docs.pytorch.org/docs/stable/nn.init.html#torch.nn.init.constant_ \"torch.nn.init.constant_\")(m.bias.data, 0)\n\n```\nCopy to clipboard\n### Generator[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#generator \"Link to this heading\")\nThe generator, GGG, is designed to map the latent space vector (zzz) to data-space. Since our data are images, converting zzz to data-space means ultimately creating a RGB image with the same size as the training images (i.e. 3x64x64). In practice, this is accomplished through a series of strided two dimensional convolutional transpose layers, each paired with a 2d batch norm layer and a relu activation. The output of the generator is fed through a tanh function to return it to the input data range of [−1,1][-1,1][−1,1]. It is worth noting the existence of the batch norm functions after the conv-transpose layers, as this is a critical contribution of the DCGAN paper. These layers help with the flow of gradients during training. An image of the generator from the DCGAN paper is shown below.\n![dcgan_generator](https://docs.pytorch.org/tutorials/_images/dcgan_generator.png)\nNotice, how the inputs we set in the input section (`nz`, `ngf`, and `nc`) influence the generator architecture in code. `nz` is the length of the z input vector, `ngf` relates to the size of the feature maps that are propagated through the generator, and `nc` is the number of channels in the output image (set to 3 for RGB images). Below is the code for the generator.\n\n```\n# Generator Code\n\nclass Generator([nn.Module](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module \"torch.nn.Module\")):\n    def __init__(self, ngpu):\n        super([Generator](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module \"torch.nn.Module\"), self).__init__()\n        self.ngpu = ngpu\n        self.main = [nn.Sequential](https://docs.pytorch.org/docs/stable/generated/torch.nn.Sequential.html#torch.nn.Sequential \"torch.nn.Sequential\")(\n            # input is Z, going into a convolution\n            [nn.ConvTranspose2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.ConvTranspose2d.html#torch.nn.ConvTranspose2d \"torch.nn.ConvTranspose2d\")( nz, ngf * 8, 4, 1, 0, bias=False),\n            [nn.BatchNorm2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html#torch.nn.BatchNorm2d \"torch.nn.BatchNorm2d\")(ngf * 8),\n            [nn.ReLU](https://docs.pytorch.org/docs/stable/generated/torch.nn.ReLU.html#torch.nn.ReLU \"torch.nn.ReLU\")(True),\n            # state size. ``(ngf*8) x 4 x 4``\n            [nn.ConvTranspose2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.ConvTranspose2d.html#torch.nn.ConvTranspose2d \"torch.nn.ConvTranspose2d\")(ngf * 8, ngf * 4, 4, 2, 1, bias=False),\n            [nn.BatchNorm2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html#torch.nn.BatchNorm2d \"torch.nn.BatchNorm2d\")(ngf * 4),\n            [nn.ReLU](https://docs.pytorch.org/docs/stable/generated/torch.nn.ReLU.html#torch.nn.ReLU \"torch.nn.ReLU\")(True),\n            # state size. ``(ngf*4) x 8 x 8``\n            [nn.ConvTranspose2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.ConvTranspose2d.html#torch.nn.ConvTranspose2d \"torch.nn.ConvTranspose2d\")( ngf * 4, ngf * 2, 4, 2, 1, bias=False),\n            [nn.BatchNorm2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html#torch.nn.BatchNorm2d \"torch.nn.BatchNorm2d\")(ngf * 2),\n            [nn.ReLU](https://docs.pytorch.org/docs/stable/generated/torch.nn.ReLU.html#torch.nn.ReLU \"torch.nn.ReLU\")(True),\n            # state size. ``(ngf*2) x 16 x 16``\n            [nn.ConvTranspose2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.ConvTranspose2d.html#torch.nn.ConvTranspose2d \"torch.nn.ConvTranspose2d\")( ngf * 2, ngf, 4, 2, 1, bias=False),\n            [nn.BatchNorm2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html#torch.nn.BatchNorm2d \"torch.nn.BatchNorm2d\")(ngf),\n            [nn.ReLU](https://docs.pytorch.org/docs/stable/generated/torch.nn.ReLU.html#torch.nn.ReLU \"torch.nn.ReLU\")(True),\n            # state size. ``(ngf) x 32 x 32``\n            [nn.ConvTranspose2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.ConvTranspose2d.html#torch.nn.ConvTranspose2d \"torch.nn.ConvTranspose2d\")( ngf, nc, 4, 2, 1, bias=False),\n            [nn.Tanh](https://docs.pytorch.org/docs/stable/generated/torch.nn.Tanh.html#torch.nn.Tanh \"torch.nn.Tanh\")()\n            # state size. ``(nc) x 64 x 64``\n        )\n\n    def forward(self, input):\n        return self.main(input)\n\n```\nCopy to clipboard\nNow, we can instantiate the generator and apply the `weights_init` function. Check out the printed model to see how the generator object is structured.\n\n```\n# Create the generator\nnetG = [Generator](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module \"torch.nn.Module\")(ngpu).to([device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\"))\n\n# Handle multi-GPU if desired\nif ([device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\").type == 'cuda') and (ngpu > 1):\n    netG = [nn.DataParallel](https://docs.pytorch.org/docs/stable/generated/torch.nn.DataParallel.html#torch.nn.DataParallel \"torch.nn.DataParallel\")(netG, list(range(ngpu)))\n\n# Apply the ``weights_init`` function to randomly initialize all weights\n#  to ``mean=0``, ``stdev=0.02``.\n[netG.apply](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module.apply \"torch.nn.Module.apply\")(weights_init)\n\n# Print the model\nprint(netG)\n\n```\nCopy to clipboard\n\n```\nGenerator(\n  (main): Sequential(\n    (0): ConvTranspose2d(100, 512, kernel_size=(4, 4), stride=(1, 1), bias=False)\n    (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (2): ReLU(inplace=True)\n    (3): ConvTranspose2d(512, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (5): ReLU(inplace=True)\n    (6): ConvTranspose2d(256, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (7): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (8): ReLU(inplace=True)\n    (9): ConvTranspose2d(128, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (10): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (11): ReLU(inplace=True)\n    (12): ConvTranspose2d(64, 3, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (13): Tanh()\n  )\n)\n\n```\nCopy to clipboard\n### Discriminator[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#discriminator \"Link to this heading\")\nAs mentioned, the discriminator, DDD, is a binary classification network that takes an image as input and outputs a scalar probability that the input image is real (as opposed to fake). Here, DDD takes a 3x64x64 input image, processes it through a series of Conv2d, BatchNorm2d, and LeakyReLU layers, and outputs the final probability through a Sigmoid activation function. This architecture can be extended with more layers if necessary for the problem, but there is significance to the use of the strided convolution, BatchNorm, and LeakyReLUs. The DCGAN paper mentions it is a good practice to use strided convolution rather than pooling to downsample because it lets the network learn its own pooling function. Also batch norm and leaky relu functions promote healthy gradient flow which is critical for the learning process of both GGG and DDD.\nDiscriminator Code\n\n```\nclass Discriminator([nn.Module](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module \"torch.nn.Module\")):\n    def __init__(self, ngpu):\n        super([Discriminator](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module \"torch.nn.Module\"), self).__init__()\n        self.ngpu = ngpu\n        self.main = [nn.Sequential](https://docs.pytorch.org/docs/stable/generated/torch.nn.Sequential.html#torch.nn.Sequential \"torch.nn.Sequential\")(\n            # input is ``(nc) x 64 x 64``\n            [nn.Conv2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.Conv2d.html#torch.nn.Conv2d \"torch.nn.Conv2d\")(nc, ndf, 4, 2, 1, bias=False),\n            [nn.LeakyReLU](https://docs.pytorch.org/docs/stable/generated/torch.nn.LeakyReLU.html#torch.nn.LeakyReLU \"torch.nn.LeakyReLU\")(0.2, inplace=True),\n            # state size. ``(ndf) x 32 x 32``\n            [nn.Conv2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.Conv2d.html#torch.nn.Conv2d \"torch.nn.Conv2d\")(ndf, ndf * 2, 4, 2, 1, bias=False),\n            [nn.BatchNorm2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html#torch.nn.BatchNorm2d \"torch.nn.BatchNorm2d\")(ndf * 2),\n            [nn.LeakyReLU](https://docs.pytorch.org/docs/stable/generated/torch.nn.LeakyReLU.html#torch.nn.LeakyReLU \"torch.nn.LeakyReLU\")(0.2, inplace=True),\n            # state size. ``(ndf*2) x 16 x 16``\n            [nn.Conv2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.Conv2d.html#torch.nn.Conv2d \"torch.nn.Conv2d\")(ndf * 2, ndf * 4, 4, 2, 1, bias=False),\n            [nn.BatchNorm2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html#torch.nn.BatchNorm2d \"torch.nn.BatchNorm2d\")(ndf * 4),\n            [nn.LeakyReLU](https://docs.pytorch.org/docs/stable/generated/torch.nn.LeakyReLU.html#torch.nn.LeakyReLU \"torch.nn.LeakyReLU\")(0.2, inplace=True),\n            # state size. ``(ndf*4) x 8 x 8``\n            [nn.Conv2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.Conv2d.html#torch.nn.Conv2d \"torch.nn.Conv2d\")(ndf * 4, ndf * 8, 4, 2, 1, bias=False),\n            [nn.BatchNorm2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html#torch.nn.BatchNorm2d \"torch.nn.BatchNorm2d\")(ndf * 8),\n            [nn.LeakyReLU](https://docs.pytorch.org/docs/stable/generated/torch.nn.LeakyReLU.html#torch.nn.LeakyReLU \"torch.nn.LeakyReLU\")(0.2, inplace=True),\n            # state size. ``(ndf*8) x 4 x 4``\n            [nn.Conv2d](https://docs.pytorch.org/docs/stable/generated/torch.nn.Conv2d.html#torch.nn.Conv2d \"torch.nn.Conv2d\")(ndf * 8, 1, 4, 1, 0, bias=False),\n            [nn.Sigmoid](https://docs.pytorch.org/docs/stable/generated/torch.nn.Sigmoid.html#torch.nn.Sigmoid \"torch.nn.Sigmoid\")()\n        )\n\n    def forward(self, input):\n        return self.main(input)\n\n```\nCopy to clipboard\nNow, as with the generator, we can create the discriminator, apply the `weights_init` function, and print the model’s structure.\n\n```\n# Create the Discriminator\nnetD = [Discriminator](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module \"torch.nn.Module\")(ngpu).to([device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\"))\n\n# Handle multi-GPU if desired\nif ([device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\").type == 'cuda') and (ngpu > 1):\n    netD = [nn.DataParallel](https://docs.pytorch.org/docs/stable/generated/torch.nn.DataParallel.html#torch.nn.DataParallel \"torch.nn.DataParallel\")(netD, list(range(ngpu)))\n\n# Apply the ``weights_init`` function to randomly initialize all weights\n# like this: ``to mean=0, stdev=0.2``.\n[netD.apply](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module.apply \"torch.nn.Module.apply\")(weights_init)\n\n# Print the model\nprint(netD)\n\n```\nCopy to clipboard\n\n```\nDiscriminator(\n  (main): Sequential(\n    (0): Conv2d(3, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (1): LeakyReLU(negative_slope=0.2, inplace=True)\n    (2): Conv2d(64, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (3): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (4): LeakyReLU(negative_slope=0.2, inplace=True)\n    (5): Conv2d(128, 256, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (6): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (7): LeakyReLU(negative_slope=0.2, inplace=True)\n    (8): Conv2d(256, 512, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1), bias=False)\n    (9): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, bias=True, track_running_stats=True)\n    (10): LeakyReLU(negative_slope=0.2, inplace=True)\n    (11): Conv2d(512, 1, kernel_size=(4, 4), stride=(1, 1), bias=False)\n    (12): Sigmoid()\n  )\n)\n\n```\nCopy to clipboard\n### Loss Functions and Optimizers[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#loss-functions-and-optimizers \"Link to this heading\")\nWith DDD and GGG setup, we can specify how they learn through the loss functions and optimizers. We will use the Binary Cross Entropy loss ([BCELoss](https://pytorch.org/docs/stable/generated/torch.nn.BCELoss.html#torch.nn.BCELoss)) function which is defined in PyTorch as:\nℓ(x,y)=L={l1,…,lN}⊤,ln=−[yn⋅log⁡xn+(1−yn)⋅log⁡(1−xn)]\\ell(x, y) = L = \\\\{l_1,\\dots,l_N\\\\}^\\top, \\quad l_n = - \\left[ y_n \\cdot \\log x_n + (1 - y_n) \\cdot \\log (1 - x_n) \\right] ℓ(x,y)=L={l1​,…,lN​}⊤,ln​=−[yn​⋅logxn​+(1−yn​)⋅log(1−xn​)]\nNotice how this function provides the calculation of both log components in the objective function (i.e. log(D(x))log(D(x))log(D(x)) and log(1−D(G(z)))log(1-D(G(z)))log(1−D(G(z)))). We can specify what part of the BCE equation to use with the yyy input. This is accomplished in the training loop which is coming up soon, but it is important to understand how we can choose which component we wish to calculate just by changing yyy (i.e. GT labels).\nNext, we define our real label as 1 and the fake label as 0. These labels will be used when calculating the losses of DDD and GGG, and this is also the convention used in the original GAN paper. Finally, we set up two separate optimizers, one for DDD and one for GGG. As specified in the DCGAN paper, both are Adam optimizers with learning rate 0.0002 and Beta1 = 0.5. For keeping track of the generator’s learning progression, we will generate a fixed batch of latent vectors that are drawn from a Gaussian distribution (i.e. fixed_noise) . In the training loop, we will periodically input this fixed_noise into GGG, and over the iterations we will see images form out of the noise.\n\n```\n# Initialize the ``BCELoss`` function\n[criterion](https://docs.pytorch.org/docs/stable/generated/torch.nn.BCELoss.html#torch.nn.BCELoss \"torch.nn.BCELoss\") = [nn.BCELoss](https://docs.pytorch.org/docs/stable/generated/torch.nn.BCELoss.html#torch.nn.BCELoss \"torch.nn.BCELoss\")()\n\n# Create batch of latent vectors that we will use to visualize\n#  the progression of the generator\n[fixed_noise](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = [torch.randn](https://docs.pytorch.org/docs/stable/generated/torch.randn.html#torch.randn \"torch.randn\")(64, nz, 1, 1, [device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\")=[device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\"))\n\n# Establish convention for real and fake labels during training\nreal_label = 1.\nfake_label = 0.\n\n# Setup Adam optimizers for both G and D\n[optimizerD](https://docs.pytorch.org/docs/stable/generated/torch.optim.Adam.html#torch.optim.Adam \"torch.optim.Adam\") = [optim.Adam](https://docs.pytorch.org/docs/stable/generated/torch.optim.Adam.html#torch.optim.Adam \"torch.optim.Adam\")([netD.parameters](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module.parameters \"torch.nn.Module.parameters\")(), lr=lr, betas=(beta1, 0.999))\n[optimizerG](https://docs.pytorch.org/docs/stable/generated/torch.optim.Adam.html#torch.optim.Adam \"torch.optim.Adam\") = [optim.Adam](https://docs.pytorch.org/docs/stable/generated/torch.optim.Adam.html#torch.optim.Adam \"torch.optim.Adam\")([netG.parameters](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module.parameters \"torch.nn.Module.parameters\")(), lr=lr, betas=(beta1, 0.999))\n\n```\nCopy to clipboard\n### Training[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#training \"Link to this heading\")\nFinally, now that we have all of the parts of the GAN framework defined, we can train it. Be mindful that training GANs is somewhat of an art form, as incorrect hyperparameter settings lead to mode collapse with little explanation of what went wrong. Here, we will closely follow Algorithm 1 from the [Goodfellow’s paper](https://papers.nips.cc/paper/5423-generative-adversarial-nets.pdf), while abiding by some of the best practices shown in [ganhacks](https://github.com/soumith/ganhacks). Namely, we will “construct different mini-batches for real and fake” images, and also adjust G’s objective function to maximize log(D(G(z)))log(D(G(z)))log(D(G(z))). Training is split up into two main parts. Part 1 updates the Discriminator and Part 2 updates the Generator.\n**Part 1 - Train the Discriminator**\nRecall, the goal of training the discriminator is to maximize the probability of correctly classifying a given input as real or fake. In terms of Goodfellow, we wish to “update the discriminator by ascending its stochastic gradient”. Practically, we want to maximize log(D(x))+log(1−D(G(z)))log(D(x)) + log(1-D(G(z)))log(D(x))+log(1−D(G(z))). Due to the separate mini-batch suggestion from [ganhacks](https://github.com/soumith/ganhacks), we will calculate this in two steps. First, we will construct a batch of real samples from the training set, forward pass through DDD, calculate the loss (log(D(x))log(D(x))log(D(x))), then calculate the gradients in a backward pass. Secondly, we will construct a batch of fake samples with the current generator, forward pass this batch through DDD, calculate the loss (log(1−D(G(z)))log(1-D(G(z)))log(1−D(G(z)))), and _accumulate_ the gradients with a backward pass. Now, with the gradients accumulated from both the all-real and all-fake batches, we call a step of the Discriminator’s optimizer.\n**Part 2 - Train the Generator**\nAs stated in the original paper, we want to train the Generator by minimizing log(1−D(G(z)))log(1-D(G(z)))log(1−D(G(z))) in an effort to generate better fakes. As mentioned, this was shown by Goodfellow to not provide sufficient gradients, especially early in the learning process. As a fix, we instead wish to maximize log(D(G(z)))log(D(G(z)))log(D(G(z))). In the code we accomplish this by: classifying the Generator output from Part 1 with the Discriminator, computing G’s loss _using real labels as GT_ , computing G’s gradients in a backward pass, and finally updating G’s parameters with an optimizer step. It may seem counter-intuitive to use the real labels as GT labels for the loss function, but this allows us to use the log(x)log(x)log(x) part of the `BCELoss` (rather than the log(1−x)log(1-x)log(1−x) part) which is exactly what we want.\nFinally, we will do some statistic reporting and at the end of each epoch we will push our fixed_noise batch through the generator to visually track the progress of G’s training. The training statistics reported are:\n  * **Loss_D** - discriminator loss calculated as the sum of losses for the all real and all fake batches (log(D(x))+log(1−D(G(z)))log(D(x)) + log(1 - D(G(z)))log(D(x))+log(1−D(G(z)))).\n  * **Loss_G** - generator loss calculated as log(D(G(z)))log(D(G(z)))log(D(G(z)))\n  * **D(x)** - the average output (across the batch) of the discriminator for the all real batch. This should start close to 1 then theoretically converge to 0.5 when G gets better. Think about why this is.\n  * **D(G(z))** - average discriminator outputs for the all fake batch. The first number is before D is updated and the second number is after D is updated. These numbers should start near 0 and converge to 0.5 as G gets better. Think about why this is.\n\n\n**Note:** This step might take a while, depending on how many epochs you run and if you removed some data from the dataset.\n\n```\n# Training Loop\n\n# Lists to keep track of progress\nimg_list = []\nG_losses = []\nD_losses = []\niters = 0\n\nprint(\"Starting Training Loop...\")\n# For each epoch\nfor epoch in range(num_epochs):\n    # For each batch in the dataloader\n    for i, data in enumerate([dataloader](https://docs.pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader \"torch.utils.data.DataLoader\"), 0):\n\n        ############################\n        # (1) Update D network: maximize log(D(x)) + log(1 - D(G(z)))\n        ###########################\n        ## Train with all-real batch\n        [netD.zero_grad](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module.zero_grad \"torch.nn.Module.zero_grad\")()\n        # Format batch\n        [real_cpu](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = data[0].to([device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\"))\n        b_size = [real_cpu](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").size(0)\n        [label](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = [torch.full](https://docs.pytorch.org/docs/stable/generated/torch.full.html#torch.full \"torch.full\")((b_size,), real_label, dtype=[torch.float](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.dtype \"torch.dtype\"), [device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\")=[device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\"))\n        # Forward pass real batch through D\n        [output](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = netD([real_cpu](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\")).view(-1)\n        # Calculate loss on all-real batch\n        [errD_real](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = [criterion](https://docs.pytorch.org/docs/stable/generated/torch.nn.BCELoss.html#torch.nn.BCELoss \"torch.nn.BCELoss\")([output](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\"), [label](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\"))\n        # Calculate gradients for D in backward pass\n        [errD_real.backward](https://docs.pytorch.org/docs/stable/generated/torch.Tensor.backward.html#torch.Tensor.backward \"torch.Tensor.backward\")()\n        D_x = [output](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").mean().item()\n\n        ## Train with all-fake batch\n        # Generate batch of latent vectors\n        [noise](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = [torch.randn](https://docs.pytorch.org/docs/stable/generated/torch.randn.html#torch.randn \"torch.randn\")(b_size, nz, 1, 1, [device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\")=[device](https://docs.pytorch.org/docs/stable/tensor_attributes.html#torch.device \"torch.device\"))\n        # Generate fake image batch with G\n        [fake](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = netG([noise](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\"))\n        [label](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").fill_(fake_label)\n        # Classify all fake batch with D\n        [output](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = netD([fake](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").detach()).view(-1)\n        # Calculate D's loss on the all-fake batch\n        [errD_fake](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = [criterion](https://docs.pytorch.org/docs/stable/generated/torch.nn.BCELoss.html#torch.nn.BCELoss \"torch.nn.BCELoss\")([output](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\"), [label](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\"))\n        # Calculate the gradients for this batch, accumulated (summed) with previous gradients\n        [errD_fake.backward](https://docs.pytorch.org/docs/stable/generated/torch.Tensor.backward.html#torch.Tensor.backward \"torch.Tensor.backward\")()\n        D_G_z1 = [output](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").mean().item()\n        # Compute error of D as sum over the fake and the real batches\n        [errD](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = [errD_real](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") + [errD_fake](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\")\n        # Update D\n        [optimizerD.step](https://docs.pytorch.org/docs/stable/generated/torch.optim.Adam.html#torch.optim.Adam.step \"torch.optim.Adam.step\")()\n\n        ############################\n        # (2) Update G network: maximize log(D(G(z)))\n        ###########################\n        [netG.zero_grad](https://docs.pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module.zero_grad \"torch.nn.Module.zero_grad\")()\n        [label](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").fill_(real_label)  # fake labels are real for generator cost\n        # Since we just updated D, perform another forward pass of all-fake batch through D\n        [output](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = netD([fake](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\")).view(-1)\n        # Calculate G's loss based on this output\n        [errG](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = [criterion](https://docs.pytorch.org/docs/stable/generated/torch.nn.BCELoss.html#torch.nn.BCELoss \"torch.nn.BCELoss\")([output](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\"), [label](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\"))\n        # Calculate gradients for G\n        [errG.backward](https://docs.pytorch.org/docs/stable/generated/torch.Tensor.backward.html#torch.Tensor.backward \"torch.Tensor.backward\")()\n        D_G_z2 = [output](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").mean().item()\n        # Update G\n        [optimizerG.step](https://docs.pytorch.org/docs/stable/generated/torch.optim.Adam.html#torch.optim.Adam.step \"torch.optim.Adam.step\")()\n\n        # Output training stats\n        if i % 50 == 0:\n            print('[%d/%d][%d/%d]\\tLoss_D: %.4f\\tLoss_G: %.4f\\tD(x): %.4f\\tD(G(z)): %.4f / %.4f'\n                  % (epoch, num_epochs, i, len([dataloader](https://docs.pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader \"torch.utils.data.DataLoader\")),\n                     [errD](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").item(), [errG](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").item(), D_x, D_G_z1, D_G_z2))\n\n        # Save Losses for plotting later\n        G_losses.append([errG](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").item())\n        D_losses.append([errD](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\").item())\n\n        # Check how the generator is doing by saving G's output on fixed_noise\n        if (iters % 500 == 0) or ((epoch == num_epochs-1) and (i == len([dataloader](https://docs.pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader \"torch.utils.data.DataLoader\"))-1)):\n            with [torch.no_grad](https://docs.pytorch.org/docs/stable/generated/torch.no_grad.html#torch.no_grad \"torch.no_grad\")():\n                [fake](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\") = netG([fixed_noise](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\")).detach().cpu()\n            img_list.append([vutils.make_grid](https://docs.pytorch.org/vision/stable/generated/torchvision.utils.make_grid.html#torchvision.utils.make_grid \"torchvision.utils.make_grid\")([fake](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\"), padding=2, normalize=True))\n\n        iters += 1\n\n```\nCopy to clipboard\n\n```\nStarting Training Loop...\n[0/5][0/1583]   Loss_D: 1.4639  Loss_G: 6.9363  D(x): 0.7143    D(G(z)): 0.5877 / 0.0017\n[0/5][50/1583]  Loss_D: 0.0335  Loss_G: 16.0282 D(x): 0.9813    D(G(z)): 0.0000 / 0.0000\n[0/5][100/1583] Loss_D: 0.4136  Loss_G: 3.8454  D(x): 0.8426    D(G(z)): 0.1067 / 0.0408\n[0/5][150/1583] Loss_D: 0.5206  Loss_G: 4.0907  D(x): 0.7922    D(G(z)): 0.1732 / 0.0333\n[0/5][200/1583] Loss_D: 2.3379  Loss_G: 13.0434 D(x): 0.9244    D(G(z)): 0.8178 / 0.0000\n[0/5][250/1583] Loss_D: 0.3563  Loss_G: 5.1989  D(x): 0.8698    D(G(z)): 0.1518 / 0.0089\n[0/5][300/1583] Loss_D: 1.0709  Loss_G: 1.6531  D(x): 0.4849    D(G(z)): 0.0507 / 0.2972\n[0/5][350/1583] Loss_D: 0.4713  Loss_G: 6.0641  D(x): 0.9406    D(G(z)): 0.2967 / 0.0053\n[0/5][400/1583] Loss_D: 0.8053  Loss_G: 7.5662  D(x): 0.9341    D(G(z)): 0.4660 / 0.0016\n[0/5][450/1583] Loss_D: 0.5695  Loss_G: 4.7134  D(x): 0.8291    D(G(z)): 0.2157 / 0.0217\n[0/5][500/1583] Loss_D: 1.0662  Loss_G: 2.7778  D(x): 0.4828    D(G(z)): 0.0906 / 0.1134\n[0/5][550/1583] Loss_D: 0.3802  Loss_G: 4.1184  D(x): 0.7979    D(G(z)): 0.0655 / 0.0302\n[0/5][600/1583] Loss_D: 0.3569  Loss_G: 5.8982  D(x): 0.8807    D(G(z)): 0.1630 / 0.0052\n[0/5][650/1583] Loss_D: 0.6227  Loss_G: 5.1058  D(x): 0.6387    D(G(z)): 0.0158 / 0.0134\n[0/5][700/1583] Loss_D: 0.5803  Loss_G: 7.0945  D(x): 0.9065    D(G(z)): 0.3245 / 0.0021\n[0/5][750/1583] Loss_D: 0.2599  Loss_G: 8.5842  D(x): 0.8288    D(G(z)): 0.0063 / 0.0011\n[0/5][800/1583] Loss_D: 0.8226  Loss_G: 8.1796  D(x): 0.9771    D(G(z)): 0.4773 / 0.0007\n[0/5][850/1583] Loss_D: 0.6746  Loss_G: 4.8579  D(x): 0.8342    D(G(z)): 0.2834 / 0.0246\n[0/5][900/1583] Loss_D: 0.4721  Loss_G: 3.1009  D(x): 0.7903    D(G(z)): 0.1481 / 0.0659\n[0/5][950/1583] Loss_D: 0.8599  Loss_G: 1.6909  D(x): 0.6047    D(G(z)): 0.1094 / 0.2435\n[0/5][1000/1583]        Loss_D: 0.6415  Loss_G: 4.8156  D(x): 0.8288    D(G(z)): 0.2918 / 0.0197\n[0/5][1050/1583]        Loss_D: 0.4587  Loss_G: 3.6132  D(x): 0.8037    D(G(z)): 0.1277 / 0.0458\n[0/5][1100/1583]        Loss_D: 0.8629  Loss_G: 6.4246  D(x): 0.9380    D(G(z)): 0.4683 / 0.0045\n[0/5][1150/1583]        Loss_D: 0.4934  Loss_G: 6.4047  D(x): 0.9231    D(G(z)): 0.2861 / 0.0032\n[0/5][1200/1583]        Loss_D: 0.4716  Loss_G: 3.6436  D(x): 0.8290    D(G(z)): 0.1614 / 0.0494\n[0/5][1250/1583]        Loss_D: 0.4101  Loss_G: 3.6744  D(x): 0.7819    D(G(z)): 0.0860 / 0.0528\n[0/5][1300/1583]        Loss_D: 1.0250  Loss_G: 2.1397  D(x): 0.5451    D(G(z)): 0.1394 / 0.1862\n[0/5][1350/1583]        Loss_D: 0.7924  Loss_G: 2.7885  D(x): 0.7071    D(G(z)): 0.2612 / 0.0861\n[0/5][1400/1583]        Loss_D: 0.3543  Loss_G: 2.2940  D(x): 0.8108    D(G(z)): 0.0950 / 0.1510\n[0/5][1450/1583]        Loss_D: 1.6106  Loss_G: 1.8363  D(x): 0.2962    D(G(z)): 0.0046 / 0.2410\n[0/5][1500/1583]        Loss_D: 0.6485  Loss_G: 5.9762  D(x): 0.8651    D(G(z)): 0.3407 / 0.0047\n[0/5][1550/1583]        Loss_D: 0.4995  Loss_G: 4.7542  D(x): 0.8385    D(G(z)): 0.2170 / 0.0170\n[1/5][0/1583]   Loss_D: 0.3602  Loss_G: 3.8552  D(x): 0.7658    D(G(z)): 0.0422 / 0.0393\n[1/5][50/1583]  Loss_D: 1.0677  Loss_G: 2.4240  D(x): 0.4761    D(G(z)): 0.0200 / 0.1430\n[1/5][100/1583] Loss_D: 1.6919  Loss_G: 1.2506  D(x): 0.2777    D(G(z)): 0.0131 / 0.3854\n[1/5][150/1583] Loss_D: 0.8513  Loss_G: 6.0725  D(x): 0.9375    D(G(z)): 0.4965 / 0.0036\n[1/5][200/1583] Loss_D: 0.4481  Loss_G: 3.6840  D(x): 0.8617    D(G(z)): 0.2120 / 0.0417\n[1/5][250/1583] Loss_D: 0.4869  Loss_G: 2.3636  D(x): 0.7251    D(G(z)): 0.0814 / 0.1519\n[1/5][300/1583] Loss_D: 0.8142  Loss_G: 6.4943  D(x): 0.9433    D(G(z)): 0.4643 / 0.0037\n[1/5][350/1583] Loss_D: 0.3275  Loss_G: 4.3855  D(x): 0.9001    D(G(z)): 0.1706 / 0.0222\n[1/5][400/1583] Loss_D: 1.0553  Loss_G: 5.4383  D(x): 0.9198    D(G(z)): 0.5340 / 0.0113\n[1/5][450/1583] Loss_D: 0.5342  Loss_G: 3.4719  D(x): 0.6642    D(G(z)): 0.0172 / 0.0567\n[1/5][500/1583] Loss_D: 0.3529  Loss_G: 4.2050  D(x): 0.7726    D(G(z)): 0.0433 / 0.0253\n[1/5][550/1583] Loss_D: 0.3481  Loss_G: 4.0055  D(x): 0.8610    D(G(z)): 0.1469 / 0.0340\n[1/5][600/1583] Loss_D: 0.5269  Loss_G: 2.7998  D(x): 0.7031    D(G(z)): 0.0880 / 0.0907\n[1/5][650/1583] Loss_D: 0.4778  Loss_G: 3.2417  D(x): 0.8108    D(G(z)): 0.1782 / 0.0572\n[1/5][700/1583] Loss_D: 0.8457  Loss_G: 5.6924  D(x): 0.9377    D(G(z)): 0.4784 / 0.0070\n[1/5][750/1583] Loss_D: 1.6658  Loss_G: 5.8465  D(x): 0.9556    D(G(z)): 0.7095 / 0.0075\n[1/5][800/1583] Loss_D: 0.4271  Loss_G: 4.4940  D(x): 0.9294    D(G(z)): 0.2713 / 0.0171\n[1/5][850/1583] Loss_D: 0.5112  Loss_G: 2.2343  D(x): 0.7473    D(G(z)): 0.1261 / 0.1398\n[1/5][900/1583] Loss_D: 0.5887  Loss_G: 4.0595  D(x): 0.8503    D(G(z)): 0.3015 / 0.0312\n[1/5][950/1583] Loss_D: 0.8232  Loss_G: 1.7852  D(x): 0.5429    D(G(z)): 0.0224 / 0.2250\n[1/5][1000/1583]        Loss_D: 0.5225  Loss_G: 2.9947  D(x): 0.7243    D(G(z)): 0.1102 / 0.0916\n[1/5][1050/1583]        Loss_D: 0.4546  Loss_G: 2.7369  D(x): 0.7663    D(G(z)): 0.1208 / 0.0863\n[1/5][1100/1583]        Loss_D: 0.5109  Loss_G: 2.0627  D(x): 0.7003    D(G(z)): 0.0734 / 0.1667\n[1/5][1150/1583]        Loss_D: 0.5148  Loss_G: 1.9273  D(x): 0.7022    D(G(z)): 0.0851 / 0.1940\n[1/5][1200/1583]        Loss_D: 0.4869  Loss_G: 3.4446  D(x): 0.9155    D(G(z)): 0.2814 / 0.0543\n[1/5][1250/1583]        Loss_D: 2.1255  Loss_G: 8.5872  D(x): 0.9635    D(G(z)): 0.8007 / 0.0004\n[1/5][1300/1583]        Loss_D: 0.5144  Loss_G: 3.7323  D(x): 0.9250    D(G(z)): 0.3080 / 0.0413\n[1/5][1350/1583]        Loss_D: 0.4774  Loss_G: 2.0437  D(x): 0.7005    D(G(z)): 0.0573 / 0.1662\n[1/5][1400/1583]        Loss_D: 0.6017  Loss_G: 3.7591  D(x): 0.8787    D(G(z)): 0.3448 / 0.0338\n[1/5][1450/1583]        Loss_D: 0.3361  Loss_G: 2.5965  D(x): 0.8415    D(G(z)): 0.1248 / 0.1041\n[1/5][1500/1583]        Loss_D: 0.6442  Loss_G: 3.5299  D(x): 0.8733    D(G(z)): 0.3358 / 0.0457\n[1/5][1550/1583]        Loss_D: 0.5264  Loss_G: 3.3173  D(x): 0.8866    D(G(z)): 0.2955 / 0.0530\n[2/5][0/1583]   Loss_D: 0.4355  Loss_G: 2.9453  D(x): 0.8170    D(G(z)): 0.1740 / 0.0790\n[2/5][50/1583]  Loss_D: 0.5613  Loss_G: 2.2878  D(x): 0.7624    D(G(z)): 0.1989 / 0.1445\n[2/5][100/1583] Loss_D: 0.4071  Loss_G: 2.8658  D(x): 0.8440    D(G(z)): 0.1788 / 0.0787\n[2/5][150/1583] Loss_D: 0.7194  Loss_G: 2.3804  D(x): 0.6915    D(G(z)): 0.2386 / 0.1237\n[2/5][200/1583] Loss_D: 0.7337  Loss_G: 3.2976  D(x): 0.8361    D(G(z)): 0.3657 / 0.0505\n[2/5][250/1583] Loss_D: 0.6978  Loss_G: 1.1942  D(x): 0.5845    D(G(z)): 0.0600 / 0.3464\n[2/5][300/1583] Loss_D: 1.8758  Loss_G: 0.1049  D(x): 0.2247    D(G(z)): 0.0231 / 0.9067\n[2/5][350/1583] Loss_D: 0.7192  Loss_G: 1.6271  D(x): 0.7092    D(G(z)): 0.2432 / 0.2475\n[2/5][400/1583] Loss_D: 0.9044  Loss_G: 4.5618  D(x): 0.9135    D(G(z)): 0.5016 / 0.0175\n[2/5][450/1583] Loss_D: 0.4705  Loss_G: 2.6927  D(x): 0.8290    D(G(z)): 0.2166 / 0.0926\n[2/5][500/1583] Loss_D: 0.9481  Loss_G: 1.7050  D(x): 0.4741    D(G(z)): 0.0644 / 0.2479\n[2/5][550/1583] Loss_D: 0.8897  Loss_G: 1.5763  D(x): 0.5010    D(G(z)): 0.0646 / 0.2718\n[2/5][600/1583] Loss_D: 0.6414  Loss_G: 4.1424  D(x): 0.8967    D(G(z)): 0.3749 / 0.0225\n[2/5][650/1583] Loss_D: 1.1566  Loss_G: 0.6323  D(x): 0.4067    D(G(z)): 0.0403 / 0.5921\n[2/5][700/1583] Loss_D: 0.7189  Loss_G: 4.4080  D(x): 0.8873    D(G(z)): 0.4014 / 0.0205\n[2/5][750/1583] Loss_D: 0.6507  Loss_G: 3.0001  D(x): 0.8545    D(G(z)): 0.3497 / 0.0659\n[2/5][800/1583] Loss_D: 0.5050  Loss_G: 2.2567  D(x): 0.7411    D(G(z)): 0.1453 / 0.1463\n[2/5][850/1583] Loss_D: 0.6416  Loss_G: 1.8507  D(x): 0.6685    D(G(z)): 0.1546 / 0.1972\n[2/5][900/1583] Loss_D: 0.5452  Loss_G: 2.5952  D(x): 0.8675    D(G(z)): 0.2913 / 0.0956\n[2/5][950/1583] Loss_D: 0.7234  Loss_G: 2.6786  D(x): 0.7113    D(G(z)): 0.2608 / 0.0905\n[2/5][1000/1583]        Loss_D: 0.5062  Loss_G: 2.4790  D(x): 0.7909    D(G(z)): 0.2073 / 0.1052\n[2/5][1050/1583]        Loss_D: 0.7153  Loss_G: 2.3895  D(x): 0.8569    D(G(z)): 0.3822 / 0.1211\n[2/5][1100/1583]        Loss_D: 0.8595  Loss_G: 3.8420  D(x): 0.9298    D(G(z)): 0.5028 / 0.0325\n[2/5][1150/1583]        Loss_D: 0.6264  Loss_G: 2.0854  D(x): 0.7232    D(G(z)): 0.2128 / 0.1611\n[2/5][1200/1583]        Loss_D: 0.7019  Loss_G: 3.6000  D(x): 0.8918    D(G(z)): 0.3990 / 0.0429\n[2/5][1250/1583]        Loss_D: 0.5670  Loss_G: 2.2590  D(x): 0.7721    D(G(z)): 0.2216 / 0.1288\n[2/5][1300/1583]        Loss_D: 0.5370  Loss_G: 2.5245  D(x): 0.7748    D(G(z)): 0.2041 / 0.1076\n[2/5][1350/1583]        Loss_D: 1.2343  Loss_G: 5.6195  D(x): 0.9171    D(G(z)): 0.6329 / 0.0070\n[2/5][1400/1583]        Loss_D: 0.7298  Loss_G: 3.7086  D(x): 0.8529    D(G(z)): 0.3842 / 0.0335\n[2/5][1450/1583]        Loss_D: 0.5449  Loss_G: 3.5281  D(x): 0.8691    D(G(z)): 0.3028 / 0.0389\n[2/5][1500/1583]        Loss_D: 0.6057  Loss_G: 1.9677  D(x): 0.6187    D(G(z)): 0.0668 / 0.1777\n[2/5][1550/1583]        Loss_D: 0.4917  Loss_G: 3.4132  D(x): 0.8972    D(G(z)): 0.2894 / 0.0423\n[3/5][0/1583]   Loss_D: 0.5575  Loss_G: 1.8105  D(x): 0.7082    D(G(z)): 0.1537 / 0.2037\n[3/5][50/1583]  Loss_D: 1.7413  Loss_G: 5.1448  D(x): 0.9646    D(G(z)): 0.7700 / 0.0103\n[3/5][100/1583] Loss_D: 1.1206  Loss_G: 1.3007  D(x): 0.4276    D(G(z)): 0.0554 / 0.3365\n[3/5][150/1583] Loss_D: 0.5955  Loss_G: 1.7999  D(x): 0.7076    D(G(z)): 0.1747 / 0.2029\n[3/5][200/1583] Loss_D: 0.6961  Loss_G: 3.7222  D(x): 0.8321    D(G(z)): 0.3667 / 0.0321\n[3/5][250/1583] Loss_D: 0.4007  Loss_G: 2.8452  D(x): 0.7988    D(G(z)): 0.1379 / 0.0781\n[3/5][300/1583] Loss_D: 0.6564  Loss_G: 2.0469  D(x): 0.7051    D(G(z)): 0.2095 / 0.1643\n[3/5][350/1583] Loss_D: 0.6704  Loss_G: 1.3749  D(x): 0.6466    D(G(z)): 0.1634 / 0.2931\n[3/5][400/1583] Loss_D: 0.6857  Loss_G: 2.0913  D(x): 0.5764    D(G(z)): 0.0540 / 0.1542\n[3/5][450/1583] Loss_D: 0.6722  Loss_G: 3.6257  D(x): 0.8451    D(G(z)): 0.3591 / 0.0353\n[3/5][500/1583] Loss_D: 1.2377  Loss_G: 0.6136  D(x): 0.3546    D(G(z)): 0.0484 / 0.5801\n[3/5][550/1583] Loss_D: 0.4995  Loss_G: 2.5051  D(x): 0.8135    D(G(z)): 0.2210 / 0.1020\n[3/5][600/1583] Loss_D: 0.7371  Loss_G: 1.3311  D(x): 0.5612    D(G(z)): 0.0663 / 0.3027\n[3/5][650/1583] Loss_D: 0.5689  Loss_G: 1.7670  D(x): 0.6286    D(G(z)): 0.0547 / 0.2199\n[3/5][700/1583] Loss_D: 0.5304  Loss_G: 2.7843  D(x): 0.8501    D(G(z)): 0.2718 / 0.0785\n[3/5][750/1583] Loss_D: 0.4839  Loss_G: 2.3616  D(x): 0.8008    D(G(z)): 0.2041 / 0.1190\n[3/5][800/1583] Loss_D: 0.5746  Loss_G: 2.0189  D(x): 0.6863    D(G(z)): 0.1333 / 0.1655\n[3/5][850/1583] Loss_D: 0.8328  Loss_G: 3.7750  D(x): 0.8823    D(G(z)): 0.4617 / 0.0326\n[3/5][900/1583] Loss_D: 0.5305  Loss_G: 2.9058  D(x): 0.8745    D(G(z)): 0.2987 / 0.0696\n[3/5][950/1583] Loss_D: 0.5446  Loss_G: 2.5951  D(x): 0.8808    D(G(z)): 0.2981 / 0.1071\n[3/5][1000/1583]        Loss_D: 0.5476  Loss_G: 2.1378  D(x): 0.6528    D(G(z)): 0.0669 / 0.1621\n[3/5][1050/1583]        Loss_D: 0.9009  Loss_G: 1.1014  D(x): 0.5071    D(G(z)): 0.0916 / 0.3846\n[3/5][1100/1583]        Loss_D: 0.5750  Loss_G: 2.9691  D(x): 0.8845    D(G(z)): 0.3302 / 0.0663\n[3/5][1150/1583]        Loss_D: 0.8456  Loss_G: 1.7220  D(x): 0.6015    D(G(z)): 0.2135 / 0.2143\n[3/5][1200/1583]        Loss_D: 0.5376  Loss_G: 1.9356  D(x): 0.7530    D(G(z)): 0.1877 / 0.1840\n[3/5][1250/1583]        Loss_D: 0.9893  Loss_G: 3.8034  D(x): 0.9370    D(G(z)): 0.5492 / 0.0315\n[3/5][1300/1583]        Loss_D: 0.8103  Loss_G: 1.5027  D(x): 0.5088    D(G(z)): 0.0404 / 0.2727\n[3/5][1350/1583]        Loss_D: 0.5382  Loss_G: 1.4694  D(x): 0.7231    D(G(z)): 0.1599 / 0.2731\n[3/5][1400/1583]        Loss_D: 1.0334  Loss_G: 1.0126  D(x): 0.4632    D(G(z)): 0.1031 / 0.4122\n[3/5][1450/1583]        Loss_D: 0.4757  Loss_G: 1.9061  D(x): 0.7601    D(G(z)): 0.1547 / 0.1823\n[3/5][1500/1583]        Loss_D: 0.6546  Loss_G: 3.2963  D(x): 0.8076    D(G(z)): 0.3076 / 0.0504\n[3/5][1550/1583]        Loss_D: 0.7705  Loss_G: 3.2457  D(x): 0.8294    D(G(z)): 0.3949 / 0.0516\n[4/5][0/1583]   Loss_D: 0.6028  Loss_G: 2.3475  D(x): 0.7754    D(G(z)): 0.2488 / 0.1262\n[4/5][50/1583]  Loss_D: 0.7614  Loss_G: 3.9099  D(x): 0.9312    D(G(z)): 0.4557 / 0.0279\n[4/5][100/1583] Loss_D: 1.3392  Loss_G: 0.6799  D(x): 0.3213    D(G(z)): 0.0230 / 0.5560\n[4/5][150/1583] Loss_D: 0.5082  Loss_G: 3.0762  D(x): 0.8566    D(G(z)): 0.2760 / 0.0600\n[4/5][200/1583] Loss_D: 0.8252  Loss_G: 4.0072  D(x): 0.9221    D(G(z)): 0.4694 / 0.0296\n[4/5][250/1583] Loss_D: 0.4909  Loss_G: 2.6500  D(x): 0.7729    D(G(z)): 0.1818 / 0.0935\n[4/5][300/1583] Loss_D: 0.6793  Loss_G: 3.8483  D(x): 0.8954    D(G(z)): 0.3954 / 0.0293\n[4/5][350/1583] Loss_D: 0.5959  Loss_G: 3.2546  D(x): 0.8589    D(G(z)): 0.3267 / 0.0502\n[4/5][400/1583] Loss_D: 0.7204  Loss_G: 1.8128  D(x): 0.5761    D(G(z)): 0.0747 / 0.2132\n[4/5][450/1583] Loss_D: 0.6253  Loss_G: 3.8699  D(x): 0.9221    D(G(z)): 0.3843 / 0.0295\n[4/5][500/1583] Loss_D: 0.5200  Loss_G: 2.4470  D(x): 0.7570    D(G(z)): 0.1796 / 0.1181\n[4/5][550/1583] Loss_D: 0.9892  Loss_G: 4.7044  D(x): 0.8942    D(G(z)): 0.5066 / 0.0135\n[4/5][600/1583] Loss_D: 0.4343  Loss_G: 2.9781  D(x): 0.8453    D(G(z)): 0.2101 / 0.0642\n[4/5][650/1583] Loss_D: 1.5967  Loss_G: 4.2490  D(x): 0.9419    D(G(z)): 0.7255 / 0.0231\n[4/5][700/1583] Loss_D: 0.5672  Loss_G: 3.5243  D(x): 0.8898    D(G(z)): 0.3383 / 0.0360\n[4/5][750/1583] Loss_D: 0.5089  Loss_G: 3.1110  D(x): 0.8679    D(G(z)): 0.2821 / 0.0553\n[4/5][800/1583] Loss_D: 0.6581  Loss_G: 3.1131  D(x): 0.7878    D(G(z)): 0.2940 / 0.0682\n[4/5][850/1583] Loss_D: 1.3859  Loss_G: 0.6585  D(x): 0.3220    D(G(z)): 0.0369 / 0.6021\n[4/5][900/1583] Loss_D: 0.5722  Loss_G: 3.0522  D(x): 0.8335    D(G(z)): 0.2775 / 0.0693\n[4/5][950/1583] Loss_D: 0.4414  Loss_G: 2.5937  D(x): 0.8578    D(G(z)): 0.2228 / 0.1017\n[4/5][1000/1583]        Loss_D: 0.5011  Loss_G: 2.4809  D(x): 0.8281    D(G(z)): 0.2443 / 0.0999\n[4/5][1050/1583]        Loss_D: 0.7283  Loss_G: 1.9399  D(x): 0.6368    D(G(z)): 0.1740 / 0.1767\n[4/5][1100/1583]        Loss_D: 0.4500  Loss_G: 3.4137  D(x): 0.9333    D(G(z)): 0.2733 / 0.0502\n[4/5][1150/1583]        Loss_D: 0.7120  Loss_G: 3.4910  D(x): 0.8907    D(G(z)): 0.3977 / 0.0437\n[4/5][1200/1583]        Loss_D: 0.5525  Loss_G: 2.6768  D(x): 0.8155    D(G(z)): 0.2422 / 0.0931\n[4/5][1250/1583]        Loss_D: 0.6997  Loss_G: 1.5459  D(x): 0.5832    D(G(z)): 0.0603 / 0.2608\n[4/5][1300/1583]        Loss_D: 0.4300  Loss_G: 2.2103  D(x): 0.7592    D(G(z)): 0.1148 / 0.1421\n[4/5][1350/1583]        Loss_D: 2.4836  Loss_G: 5.5115  D(x): 0.9568    D(G(z)): 0.8612 / 0.0065\n[4/5][1400/1583]        Loss_D: 0.9552  Loss_G: 3.1371  D(x): 0.8761    D(G(z)): 0.5150 / 0.0606\n[4/5][1450/1583]        Loss_D: 0.5326  Loss_G: 1.7700  D(x): 0.7328    D(G(z)): 0.1584 / 0.2052\n[4/5][1500/1583]        Loss_D: 0.7565  Loss_G: 3.8208  D(x): 0.8543    D(G(z)): 0.4054 / 0.0292\n[4/5][1550/1583]        Loss_D: 0.5943  Loss_G: 2.3004  D(x): 0.7305    D(G(z)): 0.2107 / 0.1229\n\n```\nCopy to clipboard\n## Results[#](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#results \"Link to this heading\")\nFinally, lets check out how we did. Here, we will look at three different results. First, we will see how D and G’s losses changed during training. Second, we will visualize G’s output on the fixed_noise batch for every epoch. And third, we will look at a batch of real data next to a batch of fake data from G.\n**Loss versus training iteration**\nBelow is a plot of D & G’s losses versus training iterations.\n\n```\nplt.figure(figsize=(10,5))\nplt.title(\"Generator and Discriminator Loss During Training\")\nplt.plot(G_losses,[label](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\")=\"G\")\nplt.plot(D_losses,[label](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor \"torch.Tensor\")=\"D\")\nplt.xlabel(\"iterations\")\nplt.ylabel(\"Loss\")\nplt.legend()\nplt.show()\n\n```\nCopy to clipboard\n![Generator and Discriminator Loss During Training](https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_002.png)\n**Visualization of G’s progression**\nRemember how we saved the generator’s output on the fixed_noise batch after every epoch of training. Now, we can visualize the training progression of G with an animation. Press the play button to start the animation.\n\n```\nfig = plt.figure(figsize=(8,8))\nplt.axis(\"off\")\nims = [[plt.imshow(np.transpose(i,(1,2,0)), animated=True)] for i in img_list]\nani = animation.ArtistAnimation(fig, ims, interval=1000, repeat_delay=1000, blit=True)\n\nHTML(ani.to_jshtml())\n\n```\nCopy to clipboard\n![dcgan faces tutorial](https://docs.pytorch.org/tutorials/_images/sphx_glr_dcgan_faces_tutorial_003.png)\n![](https://docs.pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html)\nOnce Loop Reflect\n",
  "body_base_path": "attachments/ed4ec7b77c42/pages/",
  "body_markdown_path": "attachments/ed4ec7b77c42/pages/article.md",
  "local_html": "attachments/ed4ec7b77c42/pages/article.html",
  "body_source": "prior_capture",
  "papers": [
    {
      "status": "ok",
      "url": "https://papers.nips.cc/paper/5423-generative-adversarial-nets.pdf",
      "bytes": 539761,
      "reused": false,
      "content_type": "application/pdf",
      "local_path": "papers/repair/4fe9bfb466ba8e7131d8.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1511.06434.pdf",
      "bytes": 7457198,
      "reused": true,
      "local_path": "papers/repair/acba31430a1d10daf99d.pdf"
    }
  ],
  "body_chars": 42905,
  "expected_body_images": 5,
  "raw_html": "attachments/ed4ec7b77c42/pages/source.html"
}