├── assets ├── ddpm.png ├── unet.png ├── mnist_4or9.png ├── mnist_images.png ├── sde_ddpmpp.png ├── sde_process.png ├── ddpm_optimize.png ├── time_condition.png ├── class_condition.png ├── classifier_model.png ├── ddpm_architecture.png ├── ddpm_beta_in_sde.png ├── latent_diffusion.png ├── refinenet_block.png ├── vae_architecture.png ├── langevin_experiments.png ├── refinenet_architecture.png ├── sde_predictor_corrector.png └── conditioned_normalization.png ├── Readme.md └── 01-vae.ipynb /assets/ddpm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/ddpm.png -------------------------------------------------------------------------------- /assets/unet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/unet.png -------------------------------------------------------------------------------- /assets/mnist_4or9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/mnist_4or9.png -------------------------------------------------------------------------------- /assets/mnist_images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/mnist_images.png -------------------------------------------------------------------------------- /assets/sde_ddpmpp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/sde_ddpmpp.png -------------------------------------------------------------------------------- /assets/sde_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/sde_process.png -------------------------------------------------------------------------------- /assets/ddpm_optimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/ddpm_optimize.png -------------------------------------------------------------------------------- /assets/time_condition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/time_condition.png -------------------------------------------------------------------------------- /assets/class_condition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/class_condition.png -------------------------------------------------------------------------------- /assets/classifier_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/classifier_model.png -------------------------------------------------------------------------------- /assets/ddpm_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/ddpm_architecture.png -------------------------------------------------------------------------------- /assets/ddpm_beta_in_sde.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/ddpm_beta_in_sde.png -------------------------------------------------------------------------------- /assets/latent_diffusion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/latent_diffusion.png -------------------------------------------------------------------------------- /assets/refinenet_block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/refinenet_block.png -------------------------------------------------------------------------------- /assets/vae_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/vae_architecture.png -------------------------------------------------------------------------------- /assets/langevin_experiments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/langevin_experiments.png -------------------------------------------------------------------------------- /assets/refinenet_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/refinenet_architecture.png -------------------------------------------------------------------------------- /assets/sde_predictor_corrector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/sde_predictor_corrector.png -------------------------------------------------------------------------------- /assets/conditioned_normalization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsmatz/diffusion-tutorials/HEAD/assets/conditioned_normalization.png -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Diffusion Models Tutorial (Python) 2 | 3 | This repository shows you the implementation of representative diffusion model algorithms and its guidance techniques from scratch in Python (PyTorch), with theoretical aspects behind code. 4 | 5 | ## Table of Contents 6 | 7 | - [Variational Auto-Encoder (VAE)](01-vae.ipynb) 8 | - [Denoising Diffusion Probabilistic Models (DDPM)](02-ddpm.ipynb) 9 | - [Score Matching with Langevin Dynamics (SMLD)](03-smld.ipynb) 10 | - [Score-based generative modeling with Stochastic Differential Equation (SDE)](04-sde.ipynb) 11 | - [Conditional Diffusion Models](05-class-conditional.ipynb) 12 | - [Classifier Diffusion Guidance](06-classifier-guidance.ipynb) 13 | - [Classifier-free Diffusion Guidance](07-classifier-free-guidance.ipynb) 14 | 15 | In the former part in this repository (tutorial 1 - 4), I'll focus on diffusion model's algorithms.
16 | In the latter part (tutorial 5 - 7), we proceed to steer diffusion models with external knowledge (such as, a class or a generic text prompt) and learn the fundamental of diffusion guidance. 17 | 18 | Historically image generation (including text-to-image models) has been developed and improved by adopting GAN-based methods and autoregressive methods in 2014 - 2021.
19 | In recent works, diffusion models have achieved great success, outperforming these previous approaches in the quality of image generation. (GAN-based approach, however, still has its own beneficial aspects. See below note.) 20 | 21 | > Note : The drawback of diffusion models (compared to GAN) is the computational efficiency. As you will see in the examples in this repository, diffusion models requires hundreds or thousands of iterations to generate an image - i.e., slow speed for image generation.
22 | > There exist works and challenges to improve the sampling speed in diffusion models. (See note for DDIM in [this notebook](./02-ddpm.ipynb).) 23 | 24 | *Tsuyoshi Matsuzaki @ Microsoft* 25 | -------------------------------------------------------------------------------- /01-vae.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "70657d36-7f9d-41b7-985f-51b171952c70", 6 | "metadata": {}, 7 | "source": [ 8 | "# Background : Variational Auto-Encoder (VAE) and Evidence Lower Bound (ELBO)\n", 9 | "\n", 10 | "Before jumping into diffusion models, I'll first introduce VAE (Variational Auto-encoder) for your beginning. By seeing variational auto-encoder, you will learn fundamentals of modeling with forward process / reverse process.\n", 11 | "\n", 12 | "Auto-encoder is a primitive model (neural network) to copy data (e.g, images) by encoder-decoder patterns, in which the encoder compresses data to the latent space and the decoder reconstructs it from the encoded objects.
\n", 13 | "In VAE, the optimal probability distributions to describe variables is used instead of using variables directly. VAE is considered as a part of probabilistic graph or variational Bayesian.
\n", 14 | "In this manner, VAE approximates the true distribution to draw samples.\n", 15 | "\n", 16 | "> Note : The chapter 10 in \"[Pattern Recognition and Machine Learning](https://www.microsoft.com/en-us/research/uploads/prod/2006/01/Bishop-Pattern-Recognition-and-Machine-Learning-2006.pdf)\" (Christopher M. Bishop, Microsoft) is a good reading for understanding variational Bayesian.
\n", 17 | "> See [here](https://github.com/tsmatz/gmm/) for Python example of variational Bayesian in probabilistic graph.\n", 18 | "\n", 19 | "*(back to [index](https://github.com/tsmatz/diffusion-tutorials/))*" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "id": "4634b50e-3d5e-4625-8733-c9eb779a8d1d", 25 | "metadata": {}, 26 | "source": [ 27 | "## Architecture\n", 28 | "\n", 29 | "In VAE, we suppose, the distribution of generated images $p(X)$ (where $X=\\{\\mathbf{x}^{(i)}\\}_{i=1}^N$ is a set of observed $N$ data points) is derived from the continuous latent variables $p(Z)$ (where $Z=\\{\\mathbf{z}^{(i)}\\}_{i=1}^N$ is a set of corresponding latent variables).
\n", 30 | "In this problem, however, the real distribution $p(X)$ and the hidden data points $Z=\\{\\mathbf{z}^{(i)}\\}_{i=1}^N$ are never known. And it's then intractable to solve this problem by EM algorithm (likelihood approach).
\n", 31 | "Therefore, in VAE, we apply variational Bayesian to get the optimal encoder/decoder between generated images and the latent variables, by assuming some prior distribution $p(Z)$. (See [here](https://github.com/tsmatz/gmm/) for the comparison between EM algorithm and variational Bayesian in GMM example.)\n", 32 | "\n", 33 | "For clarification, here I'll show you with handwriting digit's images (MNIST) example.\n", 34 | "\n", 35 | "![MNIST images](./assets/mnist_images.png)\n", 36 | "\n", 37 | "Firstly, we suppose that the image $\\mathbf{x}$ (vector) is generated by some latent variable $\\mathbf{z}$ (vector).
\n", 38 | "For example, each digit's image $\\mathbf{x}$ (which has 28 x 28 = 786 dimension) may have been generated by supposing some digit number. In this case, the latent variable $\\mathbf{z}$ can be the discrete digit number 0, 1, 2, ... , 9.\n", 39 | "\n", 40 | "The real latent space for generating image, however, may mostly be continuous and we then consider in stochastic space.
\n", 41 | "For example, the latent value of the following image may be the middle of digit 4 and 9.\n", 42 | "\n", 43 | "![image either 4 or 9](./assets/mnist_4or9.png)\n", 44 | "\n", 45 | "In our example, we assume the latent prior distribution $p(\\mathbf{z}) = \\mathcal{N}(\\mathbf{0},\\mathbf{I})$. (I note that here the prior distribution $p(\\mathbf{z})$ doesn't have any parameters.)\n", 46 | "\n", 47 | "> Note : In practice, the dimension of latent space should be large enough to represent the latent space.\n", 48 | "\n", 49 | "We suppose that a value $\\mathbf{x}$ is generated from some conditional distribution $p_{\\theta^{\\ast}}(\\mathbf{x}|\\mathbf{z})$, where $p_{\\theta}(\\mathbf{x}|\\mathbf{z})$ is determined by a neural network (or a function) with parameter $\\theta$, and $\\theta^{\\ast}$ is the optimal parameter.
\n", 50 | "In our example, we suppose that $p_{\\theta}(\\mathbf{x}|\\mathbf{z})$ is also a Gaussian distribution $p_{\\theta}(\\mathbf{x}|\\mathbf{z}) = \\mathcal{N}(\\mu_{\\theta}^{\\verb|dec|}(\\mathbf{z}),(\\sigma^{\\verb|dec|})^2)$ where $\\sigma^{\\verb|dec|}$ is some fixed value.
\n", 51 | "For example, when the latetnt variable $\\mathbf{z}$ represents the digit number 7, then $\\mu_{\\theta}^{\\verb|dec|}(\\mathbf{z})$ will be the vector image which represents the digit number 7.\n", 52 | "\n", 53 | "We also consider a conditional distribution $q_{\\phi}(\\mathbf{z}|\\mathbf{x})$, which distribution is also determined by a neural network (or a function) with parameter $\\phi$.
\n", 54 | "In our example, we also suppose that $q_{\\phi}(\\mathbf{z}|\\mathbf{x})$ is a Gaussian distribution $q_{\\phi}(\\mathbf{z}|\\mathbf{x}) = \\mathcal{N}(\\mu_{\\phi}^{\\verb|enc|}(\\mathbf{x}),\\verb|diag|((\\sigma_{\\phi}^{\\verb|enc|}(\\mathbf{x}))^2))$.
\n", 55 | "For example, when the image vector $\\mathbf{x}$ is above (the digit's image of the middle of digit 4 and 9), then $q_{\\phi}(\\mathbf{z}|\\mathbf{x})$ represents the latent distribution of the middle of digit 4 and 9.\n", 56 | "\n", 57 | "$q_{\\phi}(\\mathbf{z}|\\mathbf{x})$ is called a encoder, and $p_{\\theta}(\\mathbf{x}|\\mathbf{z})$ is called a decoder.\n", 58 | "\n", 59 | "![VAE architecture](./assets/vae_architecture.png)\n", 60 | "\n", 61 | "Our goal is to optimize both parameters $\\phi$ and $\\theta$ to maximize the log likelihood $\\log p(\\mathbf{x})$." 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "id": "06b0b4ba-565a-40a4-ba5e-6593f2f9962b", 67 | "metadata": {}, 68 | "source": [ 69 | "## Method\n", 70 | "\n", 71 | "Let's briefly follow the methods to solve optimal $\\phi$ and $\\theta$ along with the original paper [[Diederik P. Kingma and Max Welling, 2013](https://arxiv.org/pdf/1312.6114)].\n", 72 | "\n", 73 | "Firstly, the log likelihood of observation $p(\\mathbf{x})$ is decomposed as : \n", 74 | "\n", 75 | "$\\displaystyle \\log p(\\mathbf{x})$\n", 76 | "\n", 77 | "$\\displaystyle = \\int \\log p(\\mathbf{x}) q_{\\phi}(\\mathbf{z}|\\mathbf{x}) d\\mathbf{z} $       (because $\\int q_{\\phi}(\\mathbf{z}|\\mathbf{x}) d\\mathbf{z} = 1$)\n", 78 | "\n", 79 | "$\\displaystyle = \\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}[\\log p(\\mathbf{x})] $\n", 80 | "\n", 81 | "$\\displaystyle = \\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\left[\\log \\frac{p(\\mathbf{x}, \\mathbf{z})}{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\right] + \\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\left[\\log\\frac{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}{p(\\mathbf{z}|\\mathbf{x})}\\right] $\n", 82 | "\n", 83 | "$\\displaystyle = \\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\left[\\log \\frac{p(\\mathbf{x}, \\mathbf{z})}{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\right] + D_{KL}\\left(q_{\\phi}(\\mathbf{z}|\\mathbf{x})\\|p(\\mathbf{z}|\\mathbf{x})\\right)$\n", 84 | "\n", 85 | "where $p(\\mathbf{z}|\\mathbf{x})$ is true distribution and $D_{KL}(q\\|p)$ is KL-divergence between $q$ and $p$.\n", 86 | "\n", 87 | "When $q_{\\phi}(\\mathbf{z}|\\mathbf{x})$ goes to true distribution, $D_{KL}\\left(q_{\\phi}(\\mathbf{z}|\\mathbf{x})\\|p(\\mathbf{z}|\\mathbf{x})\\right)$ goes to zero and then $\\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\left[\\log \\frac{p(\\mathbf{x}, \\mathbf{z})}{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\right]$ is a lower-bound for $\\log p(\\mathbf{x})$.\n", 88 | "\n", 89 | "$\\displaystyle \\log p(\\mathbf{x}) \\geq \\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\left[\\log \\frac{p(\\mathbf{x}, \\mathbf{z})}{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\right]$\n", 90 | "\n", 91 | "This right-hand side expectation (lower-bound) is called Evidence Lower Bound (ELBO) (see [here](https://github.com/tsmatz/gmm/blob/master/02-gmm-variational-inference.ipynb)), and our goal is to maximize this lower-bound in order to maximize $\\log p(\\mathbf{x})$ on the observed data points $\\{\\mathbf{x}^{(i)}\\}_{i=1}^N$.\n", 92 | "\n", 93 | "Because $p(\\mathbf{x}, \\mathbf{z}) = p(\\mathbf{x}|\\mathbf{z}) p(\\mathbf{z})$, Evidence Lower Bound (ELBO) is then decomposed as follows. :\n", 94 | "\n", 95 | "$\\displaystyle \\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\left[\\log \\frac{p(\\mathbf{x}, \\mathbf{z})}{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}\\right] = \\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}[\\log p_{\\theta}(\\mathbf{x}|\\mathbf{z})] - D_{KL} \\left( q_{\\phi}(\\mathbf{z}|\\mathbf{x}) \\| p(\\mathbf{z}) \\right)$\n", 96 | "\n", 97 | "The second term (KL-divergence term) $D_{KL} \\left( q_{\\phi}(\\mathbf{z}|\\mathbf{x}) \\| p(\\mathbf{z}) \\right)$ represents how the distribution $q_{\\phi}(\\mathbf{z}|\\mathbf{x})$ is similar to the marginal distribution $p(\\mathbf{z})$, and this can be easily integrated analytically, because the forms of both $q_{\\phi}(\\mathbf{z}|\\mathbf{x})$ and $p(\\mathbf{z})$ are known Gaussian distributions in this example. (See below description in the implementation.)\n", 98 | "\n", 99 | "For the first term $\\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}[\\log p_{\\theta}(\\mathbf{x}|\\mathbf{z})]$, we should maximize the possibility $p_{\\theta}(\\mathbf{x}|\\mathbf{z})$ for the given input $\\mathbf{x}$, and we can then optimize by minimizing the difference between the reconstructed image $\\hat{\\mathbf{x}}$ (= $\\mu_{\\theta}^{\\verb|dec|}(\\mathbf{z})$) and the input image $\\mathbf{x}$.
\n", 100 | "In practice, this expectation computation requires estimation by sampling from $q_{\\phi}(\\mathbf{z}|\\mathbf{x})$. :\n", 101 | "\n", 102 | "$\\displaystyle \\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}[\\log p_{\\theta}(\\mathbf{x}|\\mathbf{z})] \\simeq \\frac{1}{M} \\sum_{i=1}^M \\left( \\frac{1}{L} \\sum_{l=1}^L \\left( \\log p_{\\theta}(\\mathbf{x}^{(i)} | \\mathbf{z}^{(i,l)}) \\right) \\right)$\n", 103 | "\n", 104 | "where $M$ is the number of minibatch $\\{\\mathbf{x}^{(i)}\\}_{i=1}^M$ and $L$ is the number of samples $\\mathbf{z}^{(i,l)} \\sim q_{\\phi}(\\mathbf{z}|\\mathbf{x^{(i)}})$ in each $\\mathbf{x}^{(i)}$.\n", 105 | "\n", 106 | "But optimizing this term is problematic, because $q_{\\phi}(\\mathbf{z}|\\mathbf{x})$ depends on parameter $\\phi$ which should be optimized, and the gradient $\\nabla_{\\phi}\\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}[\\cdot]$ by sampling is then intractable.\n", 107 | "\n", 108 | "In order to solve this problem, we now apply **reparameterization** (change of parameters) trick as follows.\n", 109 | "\n", 110 | "Let $\\mathbf{z}$ be a continuous random variable with $\\mathbf{z} \\sim q_{\\phi}(\\mathbf{z}|\\mathbf{x})$, and we assume that $\\mathbf{z}$ can be expressed as $\\mathbf{z} = g_{\\phi}(\\epsilon, \\mathbf{x})$, where $\\epsilon \\sim p(\\epsilon)$ is the distribution independent of parameter $\\phi$, and $g_{\\phi}(\\cdot)$ is some vector-valued function parameterized by $\\phi$.
\n", 111 | "Under this assumption, we also assume that the interval satisfies $q_{\\phi}(\\mathbf{z}|\\mathbf{x}) dz_0 dz_1 \\ldots dz_{n-1} = p(\\epsilon) d\\epsilon_0 d\\epsilon_1 \\ldots d\\epsilon_{n-1}$, where $\\mathbf{z} = (z_0, z_1, \\ldots, z_{n-1})$ and $\\epsilon = (\\epsilon_0, \\epsilon_1, \\ldots, \\epsilon_{n-1})$.\n", 112 | "\n", 113 | "> Note : In this case, it also satisfies $q_{\\phi}(\\mathbf{x}|\\mathbf{z}) \\cdot \\left| \\det \\left( \\frac{\\partial \\mathbf{z}}{\\partial \\mathbf{\\epsilon}} \\right) \\right| = p(\\mathbf{\\epsilon})$, where $\\frac{\\partial \\mathbf{z}}{\\partial \\mathbf{\\epsilon}}$ is the Jacobian. (This is a dual condition.)
\n", 114 | "> See [here](https://tutorial.math.lamar.edu/classes/calciii/changeofvariables.aspx) for the change of variables and the Jacobian.\n", 115 | "\n", 116 | "In our example, the distribution $q_{\\phi}(\\mathbf{z}|\\mathbf{x})$ is $\\mathcal{N}(\\mu_{\\phi}^{\\verb|enc|}(\\mathbf{x}),\\verb|diag|((\\sigma_{\\phi}^{\\verb|enc|}(\\mathbf{x}))^2))$ (see above), and then we can define $p(\\epsilon)$ and $g_{\\phi}(\\epsilon, \\mathbf{x})$ to satisfy above conditions as follows. :\n", 117 | "\n", 118 | "---\n", 119 | "\n", 120 | "reparameterization\n", 121 | "\n", 122 | "$\\displaystyle \\mathbf{z} = g_{\\phi}(\\epsilon, \\mathbf{x}) \\stackrel{\\mathrm{def}}{=} \\mu_{\\phi}^{\\verb|enc|}(\\mathbf{x}) + \\verb|diag|(\\sigma_{\\phi}^{\\verb|enc|}(\\mathbf{x})) \\odot \\epsilon$\n", 123 | "\n", 124 | "where $\\epsilon \\sim \\mathcal{N}(\\mathbf{0},\\mathbf{I})$, and the second term $\\verb|diag|(\\sigma_{\\phi}^{\\verb|enc|}(\\mathbf{x})) \\odot \\epsilon$ means element-wise multiplication between diagonal elements of $\\sigma_{\\phi}^{\\verb|enc|}(\\mathbf{x})$ and the vector $\\epsilon$.\n", 125 | "\n", 126 | "---\n", 127 | "\n", 128 | "In this assumption, we can construct the differentiable estimator by sampling, because the following equation holds. :\n", 129 | "\n", 130 | "$\\displaystyle \\mathbb{E}_{q_{\\phi}(\\mathbf{z}|\\mathbf{x})}[f(\\mathbf{z})]$\n", 131 | "\n", 132 | "$\\displaystyle =\\int q_{\\phi}(\\mathbf{z}|\\mathbf{x}) f(\\mathbf{z}) d \\mathbf{z}$\n", 133 | "\n", 134 | "$\\displaystyle =\\int p(\\epsilon) f(\\mathbf{z}) d \\epsilon$\n", 135 | "\n", 136 | "$\\displaystyle =\\int p(\\epsilon) f(g_{\\phi}(\\epsilon, \\mathbf{x})) d \\epsilon$\n", 137 | "\n", 138 | "$\\displaystyle =\\mathbb{E}_{p(\\epsilon)}[f(g_{\\phi}(\\epsilon, \\mathbf{x}))]$\n", 139 | "\n", 140 | "Now we can minimize the difference between the reconstructed image $\\hat{\\mathbf{x}}$ (i.e, $\\mu_{\\theta}^{\\verb|dec|}(\\mathbf{z})$) and the input image $\\mathbf{x}$ by the gradient method, and we can then finally maximize above ELBO (Evidence Lower Bound) by optimizing $\\phi$ and $\\theta$." 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "id": "6f31e8e3-32e1-4dfe-b66d-d1e388de1104", 146 | "metadata": {}, 147 | "source": [ 148 | "## Implementation" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "id": "1a11d841-bae2-41e6-8d06-30f9997f8234", 154 | "metadata": {}, 155 | "source": [ 156 | "### Build and train VAE" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "id": "e3b70852-6571-4ba0-84c7-08d0ea86ca48", 162 | "metadata": {}, 163 | "source": [ 164 | "Before we start, we need to install the required packages." 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": null, 170 | "id": "4aadf8c8-af1d-4df8-8690-219fa984b93d", 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "!pip install torch torchvision matplotlib" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "id": "7b773d1e-30a2-4cf6-b844-2d417bb52d31", 180 | "metadata": {}, 181 | "source": [ 182 | "We load handwriting digit's images (MNIST) dataset and dataloader.
\n", 183 | "Each batch has shape ```[batch_size, 1, 28, 28]```." 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 1, 189 | "id": "66dd3529-1ddc-4580-9086-6614429284b5", 190 | "metadata": {}, 191 | "outputs": [ 192 | { 193 | "data": { 194 | "image/png": "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lJWVpXHjxqmyslJnzpyxGO+y+t3NSL/o448/1oULF5STkxPxeE5Ojv74xz8aTWWjuLhYGzdu1JgxY9Ta2qqVK1fq3nvv1aFDh5Senm49nom2tjZJ6vX18dlz14oZM2bowQcfVGFhoY4cOaJnn31W5eXlqqur04ABA6zHi7menh4tXbpUd999t8aNGyfp4ushLS1NQ4YMidg3mV8PvZ0HSXrkkUc0cuRI5efn6+DBg3rmmWfU2Niot956y3DaSP0+QPir8vLy8K8nTJig4uJijRw5Um+++aYef/xxw8nQH8ydOzf86/Hjx2vChAkaPXq0ampqNG3aNMPJ4qOiokKHDh26Jj4HvZLLnYeFCxeGfz1+/Hjl5eVp2rRpOnLkiEaPHt3XY/aq338LLisrSwMGDLjkKpb29nbl5uYaTdU/DBkyRLfccouampqsRzHz2WuA18elRo0apaysrKR8fSxevFg7duzQe++9F/HjW3Jzc3Xu3DmdOnUqYv9kfT1c7jz0pri4WJL61euh3wcoLS1NEydOVHV1dfixnp4eVVdXq6SkxHAye6dPn9aRI0eUl5dnPYqZwsJC5ebmRrw+QqGQ9u7de82/Po4dO6aTJ08m1evDOafFixdr69at2r17twoLCyOenzhxolJTUyNeD42NjTp69GhSvR6udh56c+DAAUnqX68H66sg/havv/668/v9buPGje73v/+9W7hwoRsyZIhra2uzHq1Pff/733c1NTWuubnZ/fa3v3WlpaUuKyvLnThxwnq0uOro6HD79+93+/fvd5LcSy+95Pbv3+/+/Oc/O+ec+/GPf+yGDBnitm/f7g4ePOhmzpzpCgsL3aeffmo8eWxd6Tx0dHS4J5980tXV1bnm5mb37rvvujvvvNPdfPPN7uzZs9ajx8yiRYtcIBBwNTU1rrW1NbydOXMmvM8TTzzhRowY4Xbv3u327dvnSkpKXElJieHUsXe189DU1OR+8IMfuH379rnm5ma3fft2N2rUKDdlyhTjySMlRICcc+6VV15xI0aMcGlpaW7y5Mmuvr7eeqQ+99BDD7m8vDyXlpbmvvKVr7iHHnrINTU1WY8Vd++9956TdMk2b94859zFS7Gff/55l5OT4/x+v5s2bZprbGy0HToOrnQezpw546ZPn+6GDRvmUlNT3ciRI92CBQuS7g9pvf3zS3IbNmwI7/Ppp5+67373u+7GG290gwcPdrNnz3atra12Q8fB1c7D0aNH3ZQpU1xmZqbz+/3upptuck899ZQLBoO2g38BP44BAGCi338GBABITgQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACAif8H9/7IQL7kVpcAAAAASUVORK5CYII=", 195 | "text/plain": [ 196 | "
" 197 | ] 198 | }, 199 | "metadata": {}, 200 | "output_type": "display_data" 201 | }, 202 | { 203 | "data": { 204 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaAAAAGdCAYAAABU0qcqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAbtElEQVR4nO3df1DV973n8ddB4UQTOBQRDlS0YBJto9LGKGVMLKmMSmcdTdw75sfOaNbV1WKmStNk6SQabefSmrkmm6zVmW0rydwYU3ei3qT32jEk4E0DthqtddowwpCqK2DjrhzEgCif/cPNaY+C5ns8hzfg8zHznZFzvh++73w9k6dfOHzxOeecAADoZwnWAwAAbk0ECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmBhuPcDVenp6dPr0aSUnJ8vn81mPAwDwyDmn9vZ2ZWdnKyGh7+ucAReg06dPKycnx3oMAMBNOnnypMaMGdPn8wMuQMnJyZKk+/UdDVei8TQAAK8uqVsf6F/D/z/vS9wCtHnzZr3wwgtqaWlRfn6+XnnlFU2fPv2G6z7/sttwJWq4jwABwKDz/+8weqNvo8TlTQhvvvmmysrKtG7dOn300UfKz8/XnDlzdObMmXgcDgAwCMUlQJs2bdKyZcv0xBNP6Gtf+5q2bt2qkSNH6pe//GU8DgcAGIRiHqCLFy/q0KFDKi4u/ttBEhJUXFys2traa/bv6upSKBSK2AAAQ1/MA/Tpp5/q8uXLyszMjHg8MzNTLS0t1+xfUVGhQCAQ3ngHHADcGsx/ELW8vFxtbW3h7eTJk9YjAQD6QczfBZeenq5hw4aptbU14vHW1lYFg8Fr9vf7/fL7/bEeAwAwwMX8CigpKUlTp05VVVVV+LGenh5VVVWpsLAw1ocDAAxScfk5oLKyMi1evFj33Xefpk+frpdeekkdHR164okn4nE4AMAgFJcALVq0SH/961+1du1atbS06Otf/7r27t17zRsTAAC3Lp9zzlkP8fdCoZACgYCKNJ87IQDAIHTJdatae9TW1qaUlJQ+9zN/FxwA4NZEgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACYIEADABAECAJggQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACYIEADABAECAJggQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMxDxAzz//vHw+X8Q2ceLEWB8GADDIDY/HJ73nnnv07rvv/u0gw+NyGADAIBaXMgwfPlzBYDAenxoAMETE5XtAx48fV3Z2tvLy8vT444/rxIkTfe7b1dWlUCgUsQEAhr6YB6igoECVlZXau3evtmzZoqamJj3wwANqb2/vdf+KigoFAoHwlpOTE+uRAAADkM855+J5gHPnzmncuHHatGmTli5des3zXV1d6urqCn8cCoWUk5OjIs3XcF9iPEcDAMTBJdetau1RW1ubUlJS+twv7u8OSE1N1d13362GhoZen/f7/fL7/fEeAwAwwMT954DOnz+vxsZGZWVlxftQAIBBJOYBeuqpp1RTU6NPPvlEH374oR566CENGzZMjz76aKwPBQAYxGL+JbhTp07p0Ucf1dmzZzV69Gjdf//9qqur0+jRo2N9KADAIBbzAO3YsSPWnxIAMARxLzgAgAkCBAAwQYAAACYIEADABAECAJggQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwETcfyEdcLN67v+65zUJHxyJ+Rx9GXad3/jYl1P/ZZLnNd9b9pbnNUtSTnteE61v/P5xz2s6/5zqeU1uea3nNRiYuAICAJggQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACACe6GjQHv9AMjPa8Z8+GwqI6VkJToeU39hq95XvPxP7ziec3hiz2e1/y+q//+jVl336ue1yRO8/73VNi4yvOaUT/nDtoDEVdAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACYIEADABAECAJggQAAAEwQIAGCCAAEATBAgAIAJbkaKAe8rr33iec3Hm6ZFdSyX4Dyv2Tv/nzyvuWf/dz2vyX30D57X9KeT/2uS5zV/KPR+A9PL8/6v5zX6ufcliD+ugAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACYIEADABAECAJggQAAAE9yMFANe58Qsz2v+ZcGLUR0r0dfjec2SZ77veU3ersOe13i/TWr0ho1K87xmx33R3PEz0fOK6qnbPK/55jrvf0eSNHb9h1GtwxfDFRAAwAQBAgCY8Byg/fv3a968ecrOzpbP59Pu3bsjnnfOae3atcrKytKIESNUXFys48ePx2peAMAQ4TlAHR0dys/P1+bNm3t9fuPGjXr55Ze1detWHThwQLfffrvmzJmjzs7Omx4WADB0eH4TQklJiUpKSnp9zjmnl156Sc8++6zmz58vSXrttdeUmZmp3bt365FHHrm5aQEAQ0ZMvwfU1NSklpYWFRcXhx8LBAIqKChQbW1tr2u6uroUCoUiNgDA0BfTALW0tEiSMjMzIx7PzMwMP3e1iooKBQKB8JaTkxPLkQAAA5T5u+DKy8vV1tYW3k6ePGk9EgCgH8Q0QMFgUJLU2toa8Xhra2v4uav5/X6lpKREbACAoS+mAcrNzVUwGFRVVVX4sVAopAMHDqiwsDCWhwIADHKe3wV3/vx5NTQ0hD9uamrSkSNHlJaWprFjx2r16tX68Y9/rLvuuku5ubl67rnnlJ2drQULFsRybgDAIOc5QAcPHtSDDz4Y/risrEyStHjxYlVWVurpp59WR0eHli9frnPnzun+++/X3r17ddttt8VuagDAoOc5QEVFRXKu79si+nw+bdiwQRs2bLipwYDP5f3jx57X3J2YFNWx7n57pfc1O+o8r+nPG4tGo/U/TvC8ZnTCv0RxJO83I/3DxRGe1+S99r89r5GkS1Gtwhdl/i44AMCtiQABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACY83w0b6G/7PxnveU3CmH+P6lgN87Z6XzQvqkN5Vtflfc3Ko49HdazD0zZHsWqk5xW/7fL+b+Dl/+z9juXjmmo9r0H8cQUEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACYIEADABAECAJjgZqQY8O78b22e12zYPTmqYz2bfjSqdf3hm36f5zWHpv1zVMfqiWLN4YveVy3dWep5Td5abiw6VHAFBAAwQYAAACYIEADABAECAJggQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCY4GakGPAuNf3F85rfFSRHdawZi1ZFta4/fDqry/Oa+ln/Mw6T9O7x2mWe1+Q9w41Fb2VcAQEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJrgZKYakns7OqNZ96dX+uTnm+X8o8Lzmv37j3+MwSe/+7YL3m7netea05zWXPa/AUMIVEADABAECAJjwHKD9+/dr3rx5ys7Ols/n0+7duyOeX7JkiXw+X8Q2d+7cWM0LABgiPAeoo6ND+fn52rx5c5/7zJ07V83NzeHtjTfeuKkhAQBDj+c3IZSUlKikpOS6+/j9fgWDwaiHAgAMfXH5HlB1dbUyMjI0YcIErVy5UmfPnu1z366uLoVCoYgNADD0xTxAc+fO1Wuvvaaqqir99Kc/VU1NjUpKSnT5cu9vuKyoqFAgEAhvOTk5sR4JADAAxfzngB555JHwnydPnqwpU6Zo/Pjxqq6u1qxZs67Zv7y8XGVlZeGPQ6EQEQKAW0Dc34adl5en9PR0NTQ09Pq83+9XSkpKxAYAGPriHqBTp07p7NmzysrKivehAACDiOcvwZ0/fz7iaqapqUlHjhxRWlqa0tLStH79ei1cuFDBYFCNjY16+umndeedd2rOnDkxHRwAMLh5DtDBgwf14IMPhj/+/Ps3ixcv1pYtW3T06FG9+uqrOnfunLKzszV79mz96Ec/kt/vj93UAIBBz3OAioqK5Jzr8/nf/OY3NzUQMNhEc2PRn7/wouc1dyfe5nnN0y3TPK+RpI//Q4bnNZdbW6I6Fm5d3AsOAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJmL+K7mBW803nj7ieU00d7Ye5vP+78Vf/9r7nbolaVxzbVTrAC+4AgIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACYIEADABAECAJggQAAAEwQIAGCCAAEATHAzUgxNCcOiWvZ/Fk/3vOYnWS96XnPm8iXPax6s/IHnNbn/eNjzGknqiWoV4A1XQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACACW5GiiFpeHYwqnUf/vh/RLEq0fOKez9c7nlN7tpaz2u4qSgGMq6AAAAmCBAAwAQBAgCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAAT3IwUA96wlBTPa6b/uikOk/SurafT85ovV/rjMAkwuHAFBAAwQYAAACY8BaiiokLTpk1TcnKyMjIytGDBAtXX10fs09nZqdLSUo0aNUp33HGHFi5cqNbW1pgODQAY/DwFqKamRqWlpaqrq9O+ffvU3d2t2bNnq6OjI7zPmjVr9Pbbb2vnzp2qqanR6dOn9fDDD8d8cADA4ObpTQh79+6N+LiyslIZGRk6dOiQZs6cqba2Nv3iF7/Q9u3b9e1vf1uStG3bNn31q19VXV2dvvnNb8ZucgDAoHZT3wNqa2uTJKWlpUmSDh06pO7ubhUXF4f3mThxosaOHava2t5/nXBXV5dCoVDEBgAY+qIOUE9Pj1avXq0ZM2Zo0qRJkqSWlhYlJSUpNTU1Yt/MzEy1tLT0+nkqKioUCATCW05OTrQjAQAGkagDVFpaqmPHjmnHjh03NUB5ebna2trC28mTJ2/q8wEABoeofhB11apVeuedd7R//36NGTMm/HgwGNTFixd17ty5iKug1tZWBYPBXj+X3++X388P5QHArcbTFZBzTqtWrdKuXbv03nvvKTc3N+L5qVOnKjExUVVVVeHH6uvrdeLECRUWFsZmYgDAkODpCqi0tFTbt2/Xnj17lJycHP6+TiAQ0IgRIxQIBLR06VKVlZUpLS1NKSkpevLJJ1VYWMg74AAAETwFaMuWLZKkoqKiiMe3bdumJUuWSJJefPFFJSQkaOHCherq6tKcOXP0s5/9LCbDAgCGDp9zzlkP8fdCoZACgYCKNF/DfYnW42AA+PYfO26801XK0j6OwyS9u/e/P+l5TfbGD+MwCTAwXHLdqtYetbW1KeU6NxPmXnAAABMECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwEdVvRAWi5Zt6j+c1z4x63fOay87neY0kTaj5z57XjOfO1kBUuAICAJggQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABMECABgggABAExwM1L0q+P/Kdnzmsuux/OaP17s9rxGksa/7P1YAKLDFRAAwAQBAgCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIKbkSJqw0aleV6zeva/xWGSa62qfzSqdbfXHY3xJAD6whUQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACYIEADABAECAJggQAAAEwQIAGCCm5Eiaqcfm+h5zYrUfZ7XNF/+zPOaO5673fMaSXJRrQIQDa6AAAAmCBAAwISnAFVUVGjatGlKTk5WRkaGFixYoPr6+oh9ioqK5PP5IrYVK1bEdGgAwODnKUA1NTUqLS1VXV2d9u3bp+7ubs2ePVsdHR0R+y1btkzNzc3hbePGjTEdGgAw+Hl6E8LevXsjPq6srFRGRoYOHTqkmTNnhh8fOXKkgsFgbCYEAAxJN/U9oLa2NklSWlrkr2Z+/fXXlZ6erkmTJqm8vFwXLlzo83N0dXUpFApFbACAoS/qt2H39PRo9erVmjFjhiZNmhR+/LHHHtO4ceOUnZ2to0eP6plnnlF9fb3eeuutXj9PRUWF1q9fH+0YAIBBKuoAlZaW6tixY/rggw8iHl++fHn4z5MnT1ZWVpZmzZqlxsZGjR8//prPU15errKysvDHoVBIOTk50Y4FABgkogrQqlWr9M4772j//v0aM2bMdfctKCiQJDU0NPQaIL/fL7/fH80YAIBBzFOAnHN68skntWvXLlVXVys3N/eGa44cOSJJysrKimpAAMDQ5ClApaWl2r59u/bs2aPk5GS1tLRIkgKBgEaMGKHGxkZt375d3/nOdzRq1CgdPXpUa9as0cyZMzVlypS4/AcAAAYnTwHasmWLpCs/bPr3tm3bpiVLligpKUnvvvuuXnrpJXV0dCgnJ0cLFy7Us88+G7OBAQBDg+cvwV1PTk6OampqbmogAMCtgbthI2qXb+uf4xTXrfS8Ztzv/xiHSQDEEjcjBQCYIEAAABMECABgggABAEwQIACACQIEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBM+NyNbnHdz0KhkAKBgIo0X8N9idbjAAA8uuS6Va09amtrU0pKSp/7cQUEADBBgAAAJggQAMAEAQIAmCBAAAATBAgAYIIAAQBMECAAgAkCBAAwQYAAACYIEADAxHDrAa72+a3pLqlbGlB3qQMAfBGX1C3pb/8/78uAC1B7e7sk6QP9q/EkAICb0d7erkAg0OfzA+5u2D09PTp9+rSSk5Pl8/kinguFQsrJydHJkyeve4fVoY7zcAXn4QrOwxWchysGwnlwzqm9vV3Z2dlKSOj7Oz0D7gooISFBY8aMue4+KSkpt/QL7HOchys4D1dwHq7gPFxhfR6ud+XzOd6EAAAwQYAAACYGVYD8fr/WrVsnv99vPYopzsMVnIcrOA9XcB6uGEznYcC9CQEAcGsYVFdAAIChgwABAEwQIACACQIEADAxaAK0efNmfeUrX9Ftt92mgoIC/e53v7Meqd89//zz8vl8EdvEiROtx4q7/fv3a968ecrOzpbP59Pu3bsjnnfOae3atcrKytKIESNUXFys48eP2wwbRzc6D0uWLLnm9TF37lybYeOkoqJC06ZNU3JysjIyMrRgwQLV19dH7NPZ2anS0lKNGjVKd9xxhxYuXKjW1lajiePji5yHoqKia14PK1asMJq4d4MiQG+++abKysq0bt06ffTRR8rPz9ecOXN05swZ69H63T333KPm5ubw9sEHH1iPFHcdHR3Kz8/X5s2be31+48aNevnll7V161YdOHBAt99+u+bMmaPOzs5+njS+bnQeJGnu3LkRr4833nijHyeMv5qaGpWWlqqurk779u1Td3e3Zs+erY6OjvA+a9as0dtvv62dO3eqpqZGp0+f1sMPP2w4dex9kfMgScuWLYt4PWzcuNFo4j64QWD69OmutLQ0/PHly5dddna2q6ioMJyq/61bt87l5+dbj2FKktu1a1f4456eHhcMBt0LL7wQfuzcuXPO7/e7N954w2DC/nH1eXDOucWLF7v58+ebzGPlzJkzTpKrqalxzl35u09MTHQ7d+4M7/PnP//ZSXK1tbVWY8bd1efBOee+9a1vue9973t2Q30BA/4K6OLFizp06JCKi4vDjyUkJKi4uFi1tbWGk9k4fvy4srOzlZeXp8cff1wnTpywHslUU1OTWlpaIl4fgUBABQUFt+Tro7q6WhkZGZowYYJWrlyps2fPWo8UV21tbZKktLQ0SdKhQ4fU3d0d8XqYOHGixo4dO6RfD1efh8+9/vrrSk9P16RJk1ReXq4LFy5YjNenAXcz0qt9+umnunz5sjIzMyMez8zM1Mcff2w0lY2CggJVVlZqwoQJam5u1vr16/XAAw/o2LFjSk5Oth7PREtLiyT1+vr4/Llbxdy5c/Xwww8rNzdXjY2N+uEPf6iSkhLV1tZq2LBh1uPFXE9Pj1avXq0ZM2Zo0qRJkq68HpKSkpSamhqx71B+PfR2HiTpscce07hx45Sdna2jR4/qmWeeUX19vd566y3DaSMN+ADhb0pKSsJ/njJligoKCjRu3Dj96le/0tKlSw0nw0DwyCOPhP88efJkTZkyRePHj1d1dbVmzZplOFl8lJaW6tixY7fE90Gvp6/zsHz58vCfJ0+erKysLM2aNUuNjY0aP358f4/ZqwH/Jbj09HQNGzbsmnextLa2KhgMGk01MKSmpuruu+9WQ0OD9ShmPn8N8Pq4Vl5entLT04fk62PVqlV655139P7770f8+pZgMKiLFy/q3LlzEfsP1ddDX+ehNwUFBZI0oF4PAz5ASUlJmjp1qqqqqsKP9fT0qKqqSoWFhYaT2Tt//rwaGxuVlZVlPYqZ3NxcBYPBiNdHKBTSgQMHbvnXx6lTp3T27Nkh9fpwzmnVqlXatWuX3nvvPeXm5kY8P3XqVCUmJka8Hurr63XixIkh9Xq40XnozZEjRyRpYL0erN8F8UXs2LHD+f1+V1lZ6f70pz+55cuXu9TUVNfS0mI9Wr/6/ve/76qrq11TU5P77W9/64qLi116ero7c+aM9Whx1d7e7g4fPuwOHz7sJLlNmza5w4cPu7/85S/OOed+8pOfuNTUVLdnzx539OhRN3/+fJebm+s+++wz48lj63rnob293T311FOutrbWNTU1uXfffdfde++97q677nKdnZ3Wo8fMypUrXSAQcNXV1a65uTm8XbhwIbzPihUr3NixY917773nDh486AoLC11hYaHh1LF3o/PQ0NDgNmzY4A4ePOiamprcnj17XF5enps5c6bx5JEGRYCcc+6VV15xY8eOdUlJSW769Omurq7OeqR+t2jRIpeVleWSkpLcl7/8Zbdo0SLX0NBgPVbcvf/++07SNdvixYudc1feiv3cc8+5zMxM5/f73axZs1x9fb3t0HFwvfNw4cIFN3v2bDd69GiXmJjoxo0b55YtWzbk/pHW23+/JLdt27bwPp999pn77ne/6770pS+5kSNHuoceesg1NzfbDR0HNzoPJ06ccDNnznRpaWnO7/e7O++80/3gBz9wbW1ttoNfhV/HAAAwMeC/BwQAGJoIEADABAECAJggQAAAEwQIAGCCAAEATBAgAIAJAgQAMEGAAAAmCBAAwAQBAgCYIEAAABP/D34Mj5JeZ+wqAAAAAElFTkSuQmCC", 205 | "text/plain": [ 206 | "
" 207 | ] 208 | }, 209 | "metadata": {}, 210 | "output_type": "display_data" 211 | }, 212 | { 213 | "data": { 214 | "image/png": "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", 215 | "text/plain": [ 216 | "
" 217 | ] 218 | }, 219 | "metadata": {}, 220 | "output_type": "display_data" 221 | } 222 | ], 223 | "source": [ 224 | "import torch\n", 225 | "from torchvision import datasets, transforms\n", 226 | "import matplotlib.pyplot as plt\n", 227 | "\n", 228 | "batch_size = 100\n", 229 | "\n", 230 | "dataset = datasets.MNIST(\n", 231 | " \"./data\",\n", 232 | " train=True,\n", 233 | " download=True,\n", 234 | " transform=transforms.Compose([transforms.ToTensor()]))\n", 235 | "\n", 236 | "loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)\n", 237 | "\n", 238 | "# show examples\n", 239 | "for _, (data, _) in enumerate(loader):\n", 240 | " images = data[:3]\n", 241 | " break\n", 242 | "for i in images:\n", 243 | " plt.imshow(i[0].numpy())\n", 244 | " plt.show()" 245 | ] 246 | }, 247 | { 248 | "cell_type": "markdown", 249 | "id": "62e32935-5d3e-4290-9d4b-650b0fb72f76", 250 | "metadata": {}, 251 | "source": [ 252 | "Now we build an encoder network, which outputs $\\mu_{\\phi}^{\\verb|enc|}(\\mathbf{x})$ and the diagonal elements in $\\verb|diag|((\\sigma_{\\phi}^{\\verb|enc|}(\\mathbf{x}))^2)$ in the following distribution.\n", 253 | "\n", 254 | "$q_{\\phi}(\\mathbf{z}|\\mathbf{x}) = \\mathcal{N}(\\mu_{\\phi}^{\\verb|enc|}(\\mathbf{x}),\\verb|diag|((\\sigma_{\\phi}^{\\verb|enc|}(\\mathbf{x}))^2))$" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": 2, 260 | "id": "1e02b36f-c3d7-48af-81b9-71970704f603", 261 | "metadata": {}, 262 | "outputs": [], 263 | "source": [ 264 | "import torch.nn as nn\n", 265 | "from torch.nn import functional as F\n", 266 | "\n", 267 | "latent_dim = 32\n", 268 | "\n", 269 | "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", 270 | "\n", 271 | "class EncoderNet(nn.Module):\n", 272 | " def __init__(self, latent_dim):\n", 273 | " super().__init__()\n", 274 | " self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=2, padding=1)\n", 275 | " self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=2, padding=1)\n", 276 | " cur_dim = 64 * 7 * 7\n", 277 | " self.fc_mean = nn.Linear(cur_dim, latent_dim)\n", 278 | " self.fc_logvar = nn.Linear(cur_dim, latent_dim)\n", 279 | "\n", 280 | " def forward(self, x):\n", 281 | " x = self.conv1(x) # --> size [batch_size, 32, 14, 14]\n", 282 | " x = F.relu(x)\n", 283 | " x = self.conv2(x) # --> size [batch_size, 64, 7, 7]\n", 284 | " x = F.relu(x)\n", 285 | " x = torch.flatten(x, 1) # --> size [batch_size, 64*7*7]\n", 286 | "\n", 287 | " mean = self.fc_mean(x)\n", 288 | " logvar = self.fc_logvar(x)\n", 289 | " return mean, logvar\n", 290 | "\n", 291 | "#\n", 292 | "# Generate a model for encoder distribution\n", 293 | "#\n", 294 | "encoder_net = EncoderNet(latent_dim=latent_dim).to(device)" 295 | ] 296 | }, 297 | { 298 | "cell_type": "markdown", 299 | "id": "cb5d5de9-9258-4bc0-9f50-ade3063b2174", 300 | "metadata": {}, 301 | "source": [ 302 | "We also build a decoder network.
\n", 303 | "As we saw above, $p_{\\theta}(\\mathbf{x}|\\mathbf{z}) = \\mathcal{N}(\\mu_{\\theta}^{\\verb|dec|}(\\mathbf{z}),(\\sigma^{\\verb|dec|})^2)$ (where $\\sigma$ is some constant) and we need to get only mean value in this network." 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": 3, 309 | "id": "8ddf8e49-6eb8-406f-bb04-4245ab5b8ccc", 310 | "metadata": {}, 311 | "outputs": [], 312 | "source": [ 313 | "class DecoderNet(nn.Module):\n", 314 | " def __init__(self, latent_dim):\n", 315 | " super().__init__()\n", 316 | " self.projection = nn.Linear(latent_dim, 64 * 7 * 7)\n", 317 | " self.convtrans1 = nn.ConvTranspose2d(64, 64, kernel_size=3, stride=2)\n", 318 | " self.convtrans2 = nn.ConvTranspose2d(64, 32, kernel_size=3, stride=2)\n", 319 | " self.convtrans3 = nn.ConvTranspose2d(32, 1, kernel_size=3, stride=1)\n", 320 | "\n", 321 | " def forward(self, x):\n", 322 | " x = self.projection(x) # --> size [batch_size, 64*7*7]\n", 323 | " x = torch.reshape(x, (-1, 64, 7, 7)) # --> size [batch_size, 64, 7, 7]\n", 324 | " x = self.convtrans1(x) # --> size [batch_size, 64, 15, 15]\n", 325 | " x = x[:,:,:-1,:-1] # --> size [batch_size, 64, 14, 14] (cropping)\n", 326 | " x = F.relu(x)\n", 327 | " x = self.convtrans2(x) # --> size [batch_size, 32, 29, 29]\n", 328 | " x = x[:,:,:-1,:-1] # --> size [batch_size, 32, 28, 28] (cropping)\n", 329 | " x = F.relu(x)\n", 330 | " x = self.convtrans3(x) # --> size [batch_size, 1, 30, 30]\n", 331 | " x = x[:,:,:-2,:-2] # --> size [batch_size, 1, 28, 28] (cropping)\n", 332 | " return torch.sigmoid(x)\n", 333 | "\n", 334 | "#\n", 335 | "# Generate a decoder model\n", 336 | "#\n", 337 | "decoder_net = DecoderNet(latent_dim=latent_dim).to(device)" 338 | ] 339 | }, 340 | { 341 | "cell_type": "markdown", 342 | "id": "c5983fdb-e9c4-43a5-8ccb-e5c5c1fd152b", 343 | "metadata": {}, 344 | "source": [ 345 | "We compute KL-divergence (KL-loss) : $D_{KL} \\left( q_{\\phi}(\\mathbf{z}|\\mathbf{x}) \\| p(\\mathbf{z}) \\right)$.\n", 346 | "\n", 347 | "This value is analytically computed as follows. (See \"Appendix B\" in [original paper](https://arxiv.org/pdf/1312.6114).)\n", 348 | "\n", 349 | "$\\displaystyle D_{KL} \\left( q_{\\phi}(\\mathbf{z}|\\mathbf{x}) \\| p(\\mathbf{z}) \\right)$\n", 350 | "\n", 351 | "$\\displaystyle = \\int q_{\\phi}(\\mathbf{z}|\\mathbf{x}) \\log q_{\\phi}(\\mathbf{z}|\\mathbf{x}) d\\mathbf{z} - \\int q_{\\phi}(\\mathbf{z}|\\mathbf{x}) \\log p(\\mathbf{z}) d\\mathbf{z} $\n", 352 | "\n", 353 | "$\\displaystyle = \\int \\mathcal{N}(\\mu(\\phi),\\verb|diag|(\\sigma(\\phi)^2)) \\log \\mathcal{N}(\\mu(\\phi),\\verb|diag|(\\sigma(\\phi)^2)) d\\mathbf{z} - \\int \\mathcal{N}(\\mu(\\phi),\\verb|diag|(\\sigma(\\phi)^2)) \\log \\mathcal{N}(\\mathbf{0},\\mathbf{I}) d\\mathbf{z} $\n", 354 | "\n", 355 | "$\\displaystyle = \\left( -\\frac{J}{2} \\log(2\\pi) - \\frac{1}{2} \\sum_{j=1}^J (1 + \\log (\\sigma(\\phi)_j^2)) \\right) - \\left( -\\frac{J}{2} \\log(2\\pi) - \\frac{1}{2} \\sum_{j=1}^J (\\mu(\\phi)_j^2 + \\sigma(\\phi)_j^2) \\right)$\n", 356 | "\n", 357 | "$\\displaystyle = -\\frac{1}{2} \\sum_{j=1}^J \\left( 1 + \\log (\\sigma(\\phi)_j^2) - \\mu(\\phi)_j^2 - \\sigma(\\phi)_j^2 \\right)$\n", 358 | "\n", 359 | "where $J$ is the dimensionality of latent space $\\mathbf{z}$, and $\\mu(\\phi)_j$, $\\sigma(\\phi)_j$ are j-th elements of each vector." 360 | ] 361 | }, 362 | { 363 | "cell_type": "code", 364 | "execution_count": 4, 365 | "id": "564a2422-fc0b-4d10-b391-f23ba4ab0ee1", 366 | "metadata": {}, 367 | "outputs": [], 368 | "source": [ 369 | "def kl(mean, logvar):\n", 370 | " elements = logvar + 1.0 - mean**2 - torch.exp(logvar)\n", 371 | " return torch.sum(elements, dim=-1) * (-0.5)" 372 | ] 373 | }, 374 | { 375 | "cell_type": "markdown", 376 | "id": "1dd7e7ee-4b5e-42c9-8679-4bcb80c039c8", 377 | "metadata": {}, 378 | "source": [ 379 | "Get samples from $q_{\\phi}(\\mathbf{z}|\\mathbf{x})$, by applying reparameterization as follows. :\n", 380 | "\n", 381 | "$\\displaystyle \\mathbf{z} = \\mu_{\\phi} + \\sigma_{\\phi}^{\\verb|diag|} \\odot \\epsilon$\n", 382 | "\n", 383 | "where $\\epsilon \\sim \\mathcal{N}(\\mathbf{0},\\mathbf{I})$, and $\\sigma_{\\phi}^{\\verb|diag|} \\odot \\epsilon$ means element-wise multiplication between $\\sigma_{\\phi}^{\\verb|diag|}$ (diagonal elements of $\\sigma_{\\phi}$) and $\\epsilon$." 384 | ] 385 | }, 386 | { 387 | "cell_type": "code", 388 | "execution_count": 5, 389 | "id": "735e0c98-46aa-4086-ad83-a3a2c422d23b", 390 | "metadata": {}, 391 | "outputs": [], 392 | "source": [ 393 | "# expand tensor, such as : [batch_size, latent_dim] --> [batch_size * num_sampling, latent_dim]\n", 394 | "def expand_for_sampling(x, num_sampling):\n", 395 | " latent_dim = x.shape[1]\n", 396 | "\n", 397 | " x_sampling = x.unsqueeze(dim=1)\n", 398 | " x_sampling = x_sampling.expand(-1, num_sampling, -1)\n", 399 | " return torch.reshape(x_sampling, (-1, latent_dim))\n", 400 | "\n", 401 | "def reparameter_sampling(mean, logvar, num_sampling):\n", 402 | " # expand mean : [batch_size, latent_dim] --> [batch_size * num_sampling, latent_dim]\n", 403 | " mean_sampling = torch.repeat_interleave(mean, num_sampling, dim=0)\n", 404 | "\n", 405 | " # expand logvar : [batch_size, latent_dim] --> [batch_size * num_sampling, latent_dim]\n", 406 | " logvar_sampling = torch.repeat_interleave(logvar, num_sampling, dim=0)\n", 407 | "\n", 408 | " # get epsilon\n", 409 | " epsilon_sampling = torch.randn_like(mean_sampling).to(device)\n", 410 | "\n", 411 | " return torch.mul(torch.exp(logvar_sampling*0.5), epsilon_sampling) + mean_sampling" 412 | ] 413 | }, 414 | { 415 | "cell_type": "markdown", 416 | "id": "e42212ad-9a51-43c2-9e9d-9c37c2c2926c", 417 | "metadata": {}, 418 | "source": [ 419 | "Now we train models to optimize $\\phi$ and $\\theta$.\n", 420 | "\n", 421 | "As I have mentioned [here](https://tsmatz.wordpress.com/2017/08/30/regression-in-machine-learning-math-for-beginners/), log likelihood in Gaussian is equivalent to MSE (mean square error) loss. Thus, you can also use MSE loss function instead of using ```gaussian_nll_loss()```, but please take care for the scale between reconstruction loss and KL loss in such case." 422 | ] 423 | }, 424 | { 425 | "cell_type": "code", 426 | "execution_count": 6, 427 | "id": "12a5f647-e535-411e-a411-cdd737f15532", 428 | "metadata": {}, 429 | "outputs": [ 430 | { 431 | "name": "stdout", 432 | "output_type": "stream", 433 | "text": [ 434 | "epoch0 (iter599) - loss -46608.4448\n", 435 | "epoch1 (iter599) - loss -49586.5290\n", 436 | "epoch2 (iter599) - loss -49813.8067\n", 437 | "epoch3 (iter599) - loss -49931.7259\n", 438 | "epoch4 (iter599) - loss -50013.8970\n", 439 | "epoch5 (iter599) - loss -50073.4233\n", 440 | "epoch6 (iter599) - loss -50121.1562\n", 441 | "epoch7 (iter599) - loss -50160.6847\n", 442 | "epoch8 (iter599) - loss -50191.2306\n", 443 | "epoch9 (iter599) - loss -50219.7375\n", 444 | "epoch10 (iter599) - loss -50242.0084\n", 445 | "epoch11 (iter599) - loss -50263.6263\n", 446 | "epoch12 (iter599) - loss -50283.5339\n", 447 | "epoch13 (iter599) - loss -50297.9388\n", 448 | "epoch14 (iter599) - loss -50314.2273\n", 449 | "epoch15 (iter599) - loss -50326.3326\n", 450 | "epoch16 (iter599) - loss -50337.4770\n", 451 | "epoch17 (iter599) - loss -50349.7116\n", 452 | "epoch18 (iter599) - loss -50360.9656\n", 453 | "epoch19 (iter599) - loss -50370.1686\n", 454 | "Done\n" 455 | ] 456 | } 457 | ], 458 | "source": [ 459 | "num_sampling = 5 # the number of sampling\n", 460 | "num_epochs = 20\n", 461 | "\n", 462 | "opt = torch.optim.AdamW(list(encoder_net.parameters()) + list(decoder_net.parameters()), lr=0.001)\n", 463 | "\n", 464 | "loss_records = []\n", 465 | "for epoch_idx in range(num_epochs):\n", 466 | " for batch_idx, (data, _) in enumerate(loader):\n", 467 | " x = data.to(device)\n", 468 | "\n", 469 | " opt.zero_grad()\n", 470 | "\n", 471 | " # get mean and logvar\n", 472 | " z_mean, z_logvar = encoder_net(x)\n", 473 | " \n", 474 | " # get KL-div (KL loss)\n", 475 | " kl_loss_batch = kl(z_mean, z_logvar) # shape: [batch_size,]\n", 476 | " kl_loss = torch.sum(kl_loss_batch)\n", 477 | " \n", 478 | " # sampling by reparameterization\n", 479 | " z_samples = reparameter_sampling(z_mean, z_logvar, num_sampling)\n", 480 | " \n", 481 | " # reconstruct x by decoder\n", 482 | " decoded_x_samples = decoder_net(z_samples)\n", 483 | " decoded_x_samples = torch.reshape(decoded_x_samples, (-1, 28*28))\n", 484 | " \n", 485 | " # get BCE loss between the input x and the reconstructed x\n", 486 | " x_samples = torch.repeat_interleave(x, num_sampling, dim=0) # expand to shape: [batch_size * num_sampling, 1, 28, 28]\n", 487 | " x_samples = torch.reshape(x_samples, (-1, 28*28))\n", 488 | " pvar = torch.ones_like(x_samples).to(device) * 0.25 # sharp fit (p(x)_sigma=0.5)\n", 489 | " # pvar = torch.ones_like(x_samples).to(device) * 1.00 # loose fit (p(x)_sigma=1.0)\n", 490 | " reconstruction_loss = F.gaussian_nll_loss(\n", 491 | " decoded_x_samples,\n", 492 | " x_samples,\n", 493 | " var=pvar,\n", 494 | " reduction=\"sum\"\n", 495 | " )\n", 496 | " reconstruction_loss /= num_sampling\n", 497 | " ########## for debug\n", 498 | " # if batch_idx == 0:\n", 499 | " # print(reconstruction_loss)\n", 500 | " # print(kl_loss)\n", 501 | " \n", 502 | " # optimize parameters\n", 503 | " total_loss = reconstruction_loss + kl_loss\n", 504 | " total_loss.backward()\n", 505 | " opt.step()\n", 506 | " \n", 507 | " # log\n", 508 | " loss_records.append(total_loss.item())\n", 509 | " print(\"epoch{} (iter{}) - loss {:5.4f}\".format(epoch_idx, batch_idx, total_loss), end=\"\\r\")\n", 510 | "\n", 511 | " epoch_loss_all = loss_records[-(batch_idx+1):]\n", 512 | " average_loss = sum(epoch_loss_all)/len(epoch_loss_all)\n", 513 | " print(\"epoch{} (iter{}) - loss {:5.4f}\".format(epoch_idx, batch_idx, average_loss))\n", 514 | "\n", 515 | "print(\"Done\")" 516 | ] 517 | }, 518 | { 519 | "cell_type": "markdown", 520 | "id": "0acf2cff-1268-4c44-a941-67a0164cdbae", 521 | "metadata": {}, 522 | "source": [ 523 | "After the training is completed, show loss to see the training progress." 524 | ] 525 | }, 526 | { 527 | "cell_type": "code", 528 | "execution_count": 7, 529 | "id": "126114de-f98b-497b-b60d-e7549be86f7d", 530 | "metadata": {}, 531 | "outputs": [ 532 | { 533 | "data": { 534 | "text/plain": [ 535 | "[]" 536 | ] 537 | }, 538 | "execution_count": 7, 539 | "metadata": {}, 540 | "output_type": "execute_result" 541 | }, 542 | { 543 | "data": { 544 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkUAAAGdCAYAAAAc+wceAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA/+ElEQVR4nO3deXxU1f3H//dkmySEbJCFSIJhDZuCUGJQsZZ8jUprsX5dkKooBVSwInxlcQH9VQWxVsWqaL9flV+rgvxaN0Q0BZQqMUAMO0H2IJAghMwkkH3O7w/MlWEzUcK9kNfz8ZiHmXs/c+fcg2HenHPPHZcxxggAAKCZC7C7AQAAAE5AKAIAABChCAAAQBKhCAAAQBKhCAAAQBKhCAAAQBKhCAAAQBKhCAAAQJIUZHcDzhY+n0979uxRy5Yt5XK57G4OAABoAGOMysrKlJSUpICAU48FEYoaaM+ePUpOTra7GQAA4CfYtWuX2rZte8oaQlEDtWzZUtKRTo2MjLS5NQAAoCG8Xq+Sk5Otz/FTIRQ1UP2UWWRkJKEIAICzTEMufeFCawAAABGKAAAAJBGKAAAAJBGKAAAAJBGKAAAAJBGKAAAAJBGKAAAAJBGKAAAAJBGKAAAAJBGKAAAAJBGKAAAAJBGKAAAAJPGFsLbbsq9M//iqUG2iQjXq8g52NwcAgGaLkSKb7S6t1BvLduj9VXvsbgoAAM0aochmLrsbAAAAJBGKHMPY3QAAAJo5QpHNXN8PFRlDLAIAwE6EIpu5mEADAMARCEUAAAAiFNnuh+kze9sBAEBzRyiyGZNnAAA4A6HIIQzrzwAAsBWhyG5MnwEA4AiEIpux+gwAAGcgFDkEA0UAANiLUGQzbt4IAIAzEIpsxuQZAADOQChyCMaJAACwF6HIZi5r/szedgAA0Nw1WSh64okn1L9/f4WHhys6OvqENYWFhRo0aJDCw8MVHx+vBx54QLW1tX41n332mS666CK53W517NhRb7zxxnHHefHFF3X++ecrNDRU6enpWr58ud/+yspKjR49Wq1atVJERISuv/56FRcXn65T/VlczJ8BAOAITRaKqqurdcMNN+juu+8+4f66ujoNGjRI1dXVWrZsmWbPnq033nhDU6ZMsWq2b9+uQYMG6YorrtCqVas0duxY/eEPf9Ann3xi1cydO1fjxo3T1KlT9fXXX+vCCy9UVlaW9u3bZ9Xcf//9+vDDDzVv3jx9/vnn2rNnj373u9811an/JAwUAQBgM9PEXn/9dRMVFXXc9gULFpiAgABTVFRkbXv55ZdNZGSkqaqqMsYYM2HCBNO9e3e/1910000mKyvLet6vXz8zevRo63ldXZ1JSkoy06ZNM8YYU1paaoKDg828efOsmo0bNxpJJicnp8Hn4fF4jCTj8Xga/JqGWLH9gGk3cb65fMbi03pcAADQuM9v264pysnJUc+ePZWQkGBty8rKktfr1fr1662azMxMv9dlZWUpJydH0pHRqLy8PL+agIAAZWZmWjV5eXmqqanxq0lLS1NKSopVcyJVVVXyer1+j6bA9BkAAM5gWygqKiryC0SSrOdFRUWnrPF6vaqoqND+/ftVV1d3wpqjjxESEnLcdU1H15zItGnTFBUVZT2Sk5N/0nk2FNNnAADYq1GhaNKkSXK5XKd8FBQUNFVbz6jJkyfL4/FYj127djXROx0ZKuLejQAA2CuoMcXjx4/XsGHDTlnTvn37Bh0rMTHxuFVi9SvCEhMTrf8eu0qsuLhYkZGRCgsLU2BgoAIDA09Yc/QxqqurVVpa6jdadHTNibjdbrnd7gady8/xw4p8UhEAAHZq1EhRXFyc0tLSTvkICQlp0LEyMjK0du1av1Vi2dnZioyMVLdu3ayaRYsW+b0uOztbGRkZkqSQkBD16dPHr8bn82nRokVWTZ8+fRQcHOxXs2nTJhUWFlo1duKSIgAAnKFRI0WNUVhYqJKSEhUWFqqurk6rVq2SJHXs2FERERG68sor1a1bN916662aMWOGioqK9PDDD2v06NHWCM1dd92lv/71r5owYYLuvPNOLV68WO+8844++ugj633GjRun22+/XX379lW/fv303HPP6dChQ7rjjjskSVFRURo+fLjGjRun2NhYRUZG6t5771VGRoYuvvjipjr9RmP6DAAAmzXVErjbb7/d6Mj1w36PJUuWWDU7duwwV199tQkLCzOtW7c248ePNzU1NX7HWbJkienVq5cJCQkx7du3N6+//vpx7/XCCy+YlJQUExISYvr162e++uorv/0VFRXmnnvuMTExMSY8PNxcd911Zu/evY06n6Zakp9feNC0mzjf9J+26LQeFwAANO7z22UMYxQN4fV6FRUVJY/Ho8jIyNN23NW7SvXbF7/UedFh+nLSr07b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d955R2+++abeeustde/eXatWrdLYsWOVlJREX+G0q6mp0Y033ihjjF5++WW7m3NKjBTZpHXr1goMDDxupVBxcbESExNtatWZM2bMGM2fP19LlixR27Ztre2JiYmqrq5WaWmpX/3R/ZKYmHjCfqvfd6qayMhIhYWFne7TaRJ5eXnat2+fLrroIgUFBSkoKEiff/65Zs6cqaCgICUkJNBXR2nTpo26devmt61r164qLCyU9MP5nup3LjExUfv27fPbX1tbq5KSkkb1qdM98MAD1mhRz549deutt+r++++3RiTpqxM7k/1yspqzrd/qA9HOnTuVnZ1tjRJJzuwrQpFNQkJC1KdPHy1atMja5vP5tGjRImVkZNjYsqZljNGYMWP07rvvavHixUpNTfXb36dPHwUHB/v1y6ZNm1RYWGj1S0ZGhtauXev3y1T/y1b/oZiRkeF3jPqas6lvBw4cqLVr12rVqlXWo2/fvho6dKj1M331g0suueS42zt88803ateunSQpNTVViYmJfufq9XqVm5vr11+lpaXKy8uzahYvXiyfz6f09HSrZunSpaqpqbFqsrOz1aVLF8XExDTZ+Z1Ohw8fVkCA/1//gYGB8vl8kuirkzmT/XIu/F7WB6LNmzfr3//+t1q1auW335F91ehLs3HazJkzx7jdbvPGG2+YDRs2mJEjR5ro6Gi/lULnmrvvvttERUWZzz77zOzdu9d6HD582Kq56667TEpKilm8eLFZuXKlycjIMBkZGdb++mXmV155pVm1apVZuHChiYuLO+Ey8wceeMBs3LjRvPjii2flMvNjHb36zBj66mjLly83QUFB5oknnjCbN282b775pgkPDzf/+Mc/rJrp06eb6Oho8/7775s1a9aY3/72tydcTt27d2+Tm5trvvjiC9OpUye/JcKlpaUmISHB3HrrrWbdunVmzpw5Jjw83NHLzI91++23m/POO89akv+vf/3LtG7d2kyYMMGqaa59VVZWZvLz801+fr6RZP7yl7+Y/Px8a8XUmeqXL7/80gQFBZk///nPZuPGjWbq1KmOW5J/qr6qrq421157rWnbtq1ZtWqV39/3R68kc1pfEYps9sILL5iUlBQTEhJi+vXrZ7766iu7m9SkJJ3w8frrr1s1FRUV5p577jExMTEmPDzcXHfddWbv3r1+x9mxY4e5+uqrTVhYmGndurUZP368qamp8atZsmSJ6dWrlwkJCTHt27f3e4+z1bGhiL7y9+GHH5oePXoYt9tt0tLSzKuvvuq33+fzmUceecQkJCQYt9ttBg4caDZt2uRXc+DAATNkyBATERFhIiMjzR133GHKysr8alavXm0uvfRS43a7zXnnnWemT5/e5Od2Onm9XnPfffeZlJQUExoaatq3b28eeughvw+r5tpXS5YsOeHfUbfffrsx5sz2yzvvvGM6d+5sQkJCTPfu3c1HH33UZOf9U5yqr7Zv337Sv++XLFliHcNpfeUy5qhbmAIAADRTXFMEAAAgQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAkQhEAAIAk6f8HSqiTtqNsrEAAAAAASUVORK5CYII=", 545 | "text/plain": [ 546 | "
" 547 | ] 548 | }, 549 | "metadata": {}, 550 | "output_type": "display_data" 551 | } 552 | ], 553 | "source": [ 554 | "plt.plot(loss_records)" 555 | ] 556 | }, 557 | { 558 | "cell_type": "markdown", 559 | "id": "c2cf9816-fb75-4217-8023-f9eb55221e9e", 560 | "metadata": {}, 561 | "source": [ 562 | "### Generate images" 563 | ] 564 | }, 565 | { 566 | "cell_type": "markdown", 567 | "id": "e3f16541-5b4f-42ab-9086-7b07f48e2c29", 568 | "metadata": {}, 569 | "source": [ 570 | "Using the trained model, let's generate images from random latent vectors. (Here I generate 5 latent vectors.)" 571 | ] 572 | }, 573 | { 574 | "cell_type": "code", 575 | "execution_count": 8, 576 | "id": "d14719d0-507c-414c-b629-ab071bb18502", 577 | "metadata": {}, 578 | "outputs": [ 579 | { 580 | "data": { 581 | "image/png": "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", 582 | "text/plain": [ 583 | "
" 584 | ] 585 | }, 586 | "metadata": {}, 587 | "output_type": "display_data" 588 | }, 589 | { 590 | "data": { 591 | "image/png": "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kcJvMdY/Sw1leme6JxZ7ZyRp0g8OeGfuy33LO9Mdxzqz9xz/hn9IUu1LU70zef/PfzHStD+e8c6cGTHMO/PRxDTvjCRN/s+/887cW/iad+bJq7d5Z/74T/6/p4r6270zkpTxUJ53xtW963+gy3QBU+6AAAAmKCAAgAkKCABgggICAJiggAAAJiggAIAJCggAYIICAgCYoIAAACYoIACACQoIAGCCAgIAmOi7i5E6JymOVSj7qpRU78ig3BzvzKky/4VF//5//Jt3RpJuzTjonflZi/9in6/+483emazX6r0zklTYutc/FMdCkhH/oyj4G/9raOQv/RenlaSP3h7lnVm04L97Z/5x7lbvzC1Dmr0zGyds8c5I0uIZa7wzI34b9M5EOjq8MwMBd0AAABMUEADAhHcB7dq1S3PnzlVhYaECgYC2b98e875zTg8//LAKCgo0ePBglZWV6fDhw4maFwAwQHgXUHt7u6ZMmaINGzZc9P3169frqaee0jPPPKO9e/dq6NChmj17ts6e9f+hXQCAgcv7IYTy8nKVl5df9D3nnJ588kk9+OCDmjdvniTpueeeU15enrZv367bbrvti00LABgwEvo1oMbGRjU1NamsrCz6WigUUklJiXbv3n3RTGdnp8LhcMwGABj4ElpATU1NkqS8vNifo56Xlxd975OqqqoUCoWiW1FRUSJHAgD0UeZPwVVWVqq1tTW6HTt2zHokAEAvSGgB5efnS5Kam2O/Uay5uTn63icFg0FlZmbGbACAgS+hBVRcXKz8/HxVV1dHXwuHw9q7d69KS0sTeSgAQD/n/RTc6dOn1dDQEP24sbFRBw4cUHZ2tkaOHKnVq1frBz/4ga655hoVFxfroYceUmFhoebPn5/IuQEA/Zx3Ae3bt0833/yXtbnWrDm/VtKSJUu0efNm3X///Wpvb9eKFSvU0tKiG2+8UTt37tQVV1yRuKkBAP2edwHNmDFDzl16kdBAIKBHH31Ujz766BcaTIHA+e3z+pSZEs5nrj9LGexfwG54lnem47+0emduHBrfwp2PnSz77J0+4b2VY7wzmQff8c70dHd5Z/q8OBY97WlpietQg971z+QUj/fO/PvfFnhnbh36R+/M6EHd3hlJ6sqK48+VOP58uFyZPwUHALg8UUAAABMUEADABAUEADBBAQEATFBAAAATFBAAwAQFBAAw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As2cOVNHjhzRmDFjenvMi+rz/wSXk5Oj1NTUC55iaW5uVn5+vtFUfUNWVpbGjRunhoYG61HMfHwNcH1caPTo0crJyRmQ18eqVav06quv6q233or58S35+fnq6upSS0tLzP4D9Xq41Hm4mJKSEknqU9dDny+g9PR0TZ06VdXV1dHXIpGIqqurVVpaajiZvdOnT+vIkSMqKCiwHsVMcXGx8vPzY66PcDisvXv3XvbXxwcffKBTp04NqOvDOadVq1Zp27ZtevPNN1VcXBzz/tSpU5WWlhZzPdTX1+vo0aMD6nr4rPNwMQcOHJCkvnU9WD8F8Xm88MILLhgMus2bN7t3333XrVixwmVlZbmmpibr0XrVvffe62pqalxjY6P7xS9+4crKylxOTo47efKk9WhJ1dbW5vbv3+/279/vJLnHH3/c7d+/3/3hD39wzjn3wx/+0GVlZbkdO3a4gwcPunnz5rni4mJ35swZ48kT69POQ1tbm7vvvvvc7t27XWNjo3vjjTfcdddd56655hp39uxZ69ET5q677nKhUMjV1NS4EydORLeOjo7oPitXrnQjR450b775ptu3b58rLS11paWlhlMn3medh4aGBvfoo4+6ffv2ucbGRrdjxw43evRoN336dOPJY/WLAnLOuaefftqNHDnSpaenu2nTprk9e/ZYj9TrFi1a5AoKClx6err70pe+5BYtWuQaGhqsx0q6t956y0m6YFuyZIlz7vyj2A899JDLy8tzwWDQzZw509XX19sOnQSfdh46OjrcrFmz3FVXXeXS0tLcqFGj3PLlywfcX9Iu9vuX5DZt2hTd58yZM+7b3/62u/LKK92QIUPcrbfe6k6cOGE3dBJ81nk4evSomz59usvOznbBYNCNHTvWffe733Wtra22g38CP44BAGCiz38NCAAwMFFAAAATFBAAwAQFBAAwQQEBAExQQAAAExQQAMAEBQQAMEEBAQBMUEAAABMUEADABAUEADDx/wGN5Gz5ChgkRAAAAABJRU5ErkJggg==", 592 | "text/plain": [ 593 | "
" 594 | ] 595 | }, 596 | "metadata": {}, 597 | "output_type": "display_data" 598 | }, 599 | { 600 | "data": { 601 | "image/png": "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JKw/Uo+HC+2H/pSXl0vSkDoehnwBZWZmavbs2aqrq4s/F4vFVFdXp4qKCsOR2Tt16pQOHz6soqIi66GYKS0tVWFhYcLxEYlEtGfPniv++Dh27Jja29tH1PHhnNOaNWu0detW7dy5U6WlpQmvz549WxkZGQnHQ1NTk44cOTKijodL7Yf+7N+/X5KG1vFgfRfEZ/Hyyy+7YDDoNm/e7P74xz+6e++91+Xk5LjW1lbroQ2q73znO66+vt61tLS43/72t66ystLl5eW5kydPWg9tQHV2drr33nvPvffee06Se+qpp9x7773n/vKXvzjnnPvRj37kcnJy3Pbt292BAwfc0qVLXWlpqTtz5ozxyFPrYvuhs7PTPfjgg66xsdG1tLS4t956y335y1921157rTt79qz10FNm9erVLhQKufr6enfixIn4cvr06fg69913n5s0aZLbuXOn27t3r6uoqHAVFRWGo069S+2H5uZm9/3vf9/t3bvXtbS0uO3bt7spU6a4+fPnG4880bAoIOece/bZZ92kSZNcZmammzt3rtu9e7f1kAbdbbfd5oqKilxmZqb7/Oc/72677TbX3NxsPawB9/bbbztJ5y0rVqxwzp27FfvRRx91BQUFLhgMuoULF7qmpibbQQ+Ai+2H06dPu0WLFrkJEya4jIwMN3nyZLdq1aoR90Naf39/SW7Tpk3xdc6cOeO+9a1vuc997nNu7Nix7pZbbnEnTpywG/QAuNR+OHLkiJs/f77Lzc11wWDQXXPNNe673/2uC4fDtgP/FD6OAQBgYshfAwIAjEwUEADABAUEADBBAQEATFBAAAATFBAAwAQFBAAwQQEBAExQQAAAExQQAMAEBQQAMEEBAQBM/D8DjYxjz2VkpgAAAABJRU5ErkJggg==", 602 | "text/plain": [ 603 | "
" 604 | ] 605 | }, 606 | "metadata": {}, 607 | "output_type": "display_data" 608 | }, 609 | { 610 | "data": { 611 | "image/png": "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+MCoKxtFRUXavn27Jk+erHPnzumZZ57RvffeqxMnTigjI8O6PRPNzX2/36G/6+OTYzeL0tJSLVmyRAUFBWpsbNT3v/99lZWVqa6uTqmpqdbtxV1vb682bNig2bNna+rUqZL6rof09HSNHj066tyhfD30Nw+S9OCDD2rChAkKhUI6fvy4Hn/8cdXX1+uNN94w7DbaoA8g/EVZWVnk6+nTp6uoqEgTJkzQr371K61atcqwMwwGy5cvj3w9bdo0TZ8+XZMmTVJNTY3mzZtn2FlilJeX68SJEzfF56Cf51rzsGbNmsjX06ZNU15enubNm6fGxkZNmjRpoNvs16D/Flx2drZSU1OveoqlpaVFwWDQqKvBYfTo0brzzjvV0NBg3YqZT64Bro+rTZw4UdnZ2UPy+li/fr327t2rd955J+rXtwSDQV2+fFmtra1R5w/V6+Fa89CfoqIiSRpU18OgD6D09HTNmDFD1dXVkX29vb2qrq5WcXGxYWf2Ll68qMbGRuXl5Vm3YqagoEDBYDDq+giHwzp06NBNf32cOXNGFy5cGFLXh3NO69ev165du/T222+roKAg6viMGTOUlpYWdT3U19fr1KlTQ+p6uN489OfYsWOSNLiuB+unIL6InTt3Or/f77Zv3+7ef/99t2bNGjd69GjX3Nxs3dqA+u53v+tqampcU1OT+81vfuNKSkpcdna2O3/+vHVrCdXe3u6OHj3qjh496iS55557zh09etT98Y9/dM459+Mf/9iNHj3a7dmzxx0/ftwtWrTIFRQUuI8//ti48/j6vHlob293jz76qKurq3NNTU1u//797qtf/aq74447XGdnp3XrcbNu3ToXCARcTU2NO3fuXGS7dOlS5Jy1a9e68ePHu7ffftsdPnzYFRcXu+LiYsOu4+9689DQ0OB+8IMfuMOHD7umpia3Z88eN3HiRDdnzhzjzqMlRQA559yLL77oxo8f79LT092sWbPcwYMHrVsacMuWLXN5eXkuPT3dfelLX3LLli1zDQ0N1m0l3DvvvOMkXbWtWLHCOdf3KPaTTz7pcnNznd/vd/PmzXP19fW2TSfA583DpUuX3Pz5893YsWNdWlqamzBhglu9evWQ+0daf//9kty2bdsi53z88cfu29/+trv11lvdiBEj3P333+/OnTtn13QCXG8eTp065ebMmeOysrKc3+93t99+u/ve977n2trabBv/DH4dAwDAxKD/DAgAMDQRQAAAEwQQAMAEAQQAMEEAAQBMEEAAABMEEADABAEEADBBAAEATBBAAAATBBAAwAQBBAAw8f8B2kOuD6G/3VcAAAAASUVORK5CYII=", 612 | "text/plain": [ 613 | "
" 614 | ] 615 | }, 616 | "metadata": {}, 617 | "output_type": "display_data" 618 | }, 619 | { 620 | "data": { 621 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaAAAAGdCAYAAABU0qcqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAdH0lEQVR4nO3df3DU9b3v8dcmJAtosjHEZBMJNKCCCqRXlJirUpQcIJ7jgDJz/PUHOA5cbPAUU6uTjora3kmLM9bRQ3Hu3BbqvaLWGYHR06Ej0YTaBlpQyqXWlKSxgCSh0pNsCCSE7Of+wXHrSsB+lk3eSXg+Zr4z2e/3+97vOx++5JVv9rufDTjnnAAAGGQp1g0AAC5MBBAAwAQBBAAwQQABAEwQQAAAEwQQAMAEAQQAMEEAAQBMjLJu4Mui0agOHz6sjIwMBQIB63YAAJ6cc+rs7FRBQYFSUs5+nTPkAujw4cMqLCy0bgMAcJ4OHjyo8ePHn3X7kAugjIwMSdJN+meNCqT944XMKAQAQ8Ip9ep9/SL28/xsBiyA1q5dq2effVatra0qLi7Wiy++qFmzZn1l3ed/dhsVSPMLIBFAADAk/NeP4696GWVAbkJ4/fXXVVlZqdWrV+uDDz5QcXGx5s+fryNHjgzE4QAAw9CABNBzzz2nZcuW6f7779fVV1+tl156SWPHjtVPf/rTgTgcAGAYSnoAnTx5Urt371ZZWdnfD5KSorKyMtXX15+xf09PjyKRSNwCABj5kh5An332mfr6+pSXlxe3Pi8vT62trWfsX11drVAoFFu4Aw4ALgzmb0StqqpSR0dHbDl48KB1SwCAQZD0u+BycnKUmpqqtra2uPVtbW0Kh8Nn7B8MBhUMBpPdBgBgiEv6FVB6erpmzpypmpqa2LpoNKqamhqVlpYm+3AAgGFqQN4HVFlZqSVLlui6667TrFmz9Pzzz6urq0v333//QBwOADAMDUgA3XXXXfrrX/+qJ598Uq2trfr617+urVu3nnFjAgDgwhVwbmjNYROJRBQKhTRHCz1nQgAADAWnXK9qtUUdHR3KzMw8637md8EBAC5MBBAAwAQBBAAwQQABAEwQQAAAEwQQAMAEAQQAMEEAAQBMEEAAABMEEADABAEEADBBAAEATBBAAAATBBAAwAQBBAAwQQABAEwQQAAAEwQQAMAEAQQAMEEAAQBMEEAAABMEEADABAEEADBBAAEATBBAAAATBBAAwAQBBAAwQQABAEwQQAAAEwQQAMAEAQQAMEEAAQBMEEAAABMEEADABAEEADBBAAEATBBAAAATBBAAwAQBBAAwQQABAEwQQAAAEwQQAMAEAQQAMEEAAQBMEEAAABMEEADABAEEADBBAAEATBBAAAATBBAAwAQBBAAwQQABAEyMsm4Aw1hKqndJaubF/sfJu9S7pPfSBI4jKdDnvGvSWv7Tu8a1d3jXRE90+x/n5EnvmtOF/uMA+OIKCABgggACAJhIegA99dRTCgQCccvUqVOTfRgAwDA3IK8BXXPNNdq2bdvfDzKKl5oAAPEGJBlGjRqlcDg8EE8NABghBuQ1oP3796ugoECTJk3SfffdpwMHDpx1356eHkUikbgFADDyJT2ASkpKtGHDBm3dulXr1q1Tc3Ozbr75ZnV2dva7f3V1tUKhUGwpLCxMdksAgCEo4NzA3vDf3t6uiRMn6rnnntMDDzxwxvaenh719PTEHkciERUWFmqOFmpUIG0gW8P54n1AkngfEPBlp1yvarVFHR0dyszMPOt+A353QFZWlq688ko1Njb2uz0YDCoYDA50GwCAIWbA3wd07NgxNTU1KT8/f6APBQAYRpIeQI888ojq6ur0ySef6De/+Y3uuOMOpaam6p577kn2oQAAw1jS/wR36NAh3XPPPTp69KguvfRS3XTTTdqxY4cuvdT/7/gAgJEr6QH02muvJfspMdACgYTKUidN8K7504o875q5s3/vXbM4e5d3jSRlpR73rmk9FfKuaezxf5/c5k+LvWu6X03s/Xg5b/7Bu6aPt1DAE3PBAQBMEEAAABMEEADABAEEADBBAAEATBBAAAATBBAAwAQBBAAwQQABAEwQQAAAEwQQAMAEAQQAMDHgH0iHoS9l7NiE6o7M8Z/o8tF/3uJdc9tFf/KuyUjg01olKU3+ddPS2r1rysf2/xH157Ii62Pvmn2rE5to9t5r/s275sr/+ZF3TV8CnwyLkYMrIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABgggACAJgggAAAJgggAIAJAggAYIIAAgCYIIAAACYIIACACWbDhgLp6QnV9Y32n2n5QM8475p9af41fUpsFujOvjHeNV9L+8y7ZlJat3fN2ID/TN3F6YnNCv4vt/7Ou6bh/1zuf6DIMf+aaJ9/DYYkroAAACYIIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABgggACAJgggAAAJgggAIAJAggAYIIAAgCYYDJSyJ04kVBd+Ff/6V2ztecm75q3LrrZu8Yl+KtVNM2/JoH5S5UyvcO7Zt1/e8W75rr0k941kvTfM/Z71/xuykzvmsw/+Q94tJvJSEcKroAAACYIIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABgggACAJgggAAAJgggAIAJAggAYIIAAgCYYDJSKNrTk1BdavOn3jW5hz9L6FjeEvyeXJ//RJeBsWO9a47dWORd8/4VU7xrSsbt866RpCvTjnjXHLss1bsmlJ7uXaPubv8aDElcAQEATBBAAAAT3gG0fft23X777SooKFAgENDmzZvjtjvn9OSTTyo/P19jxoxRWVmZ9u/3/2wRAMDI5h1AXV1dKi4u1tq1a/vdvmbNGr3wwgt66aWXtHPnTl100UWaP3++uvm7LQDgC7xvQigvL1d5eXm/25xzev755/X4449r4cKFkqSXX35ZeXl52rx5s+6+++7z6xYAMGIk9TWg5uZmtba2qqysLLYuFAqppKRE9fX1/db09PQoEonELQCAkS+pAdTa2ipJysvLi1ufl5cX2/Zl1dXVCoVCsaWwsDCZLQEAhijzu+CqqqrU0dERWw4ePGjdEgBgECQ1gMLhsCSpra0tbn1bW1ts25cFg0FlZmbGLQCAkS+pAVRUVKRwOKyamprYukgkop07d6q0tDSZhwIADHPed8EdO3ZMjY2NscfNzc3as2ePsrOzNWHCBK1atUrf//73dcUVV6ioqEhPPPGECgoKtGjRomT2DQAY5rwDaNeuXbrllltijysrKyVJS5Ys0YYNG/Too4+qq6tLy5cvV3t7u2666SZt3bpVo0ePTl7XAIBhzzuA5syZI+fcWbcHAgE988wzeuaZZ86rMQyic/x7nkvfsS7vmsCJBN6Q7KIJlCT2PSUiJcX/L9mpJ/y/p+NR/4k7+xL8tw0G/CdlPeU/J2tCk79i5DC/Cw4AcGEigAAAJgggAIAJAggAYIIAAgCYIIAAACYIIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABgggACAJjwng0biIn6z2ScyNzMgdRU75qU0Ymd2oH0NO+a6OTx3jWtN/jPbF2e+XvvmrSA/9hJ0v7eLO+azE8SmLX8ZK93DUYOroAAACYIIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABgggACAJgggAAAJgggAIAJAggAYIIAAgCYYDJSDHkp2VneNUf+ZXJCx+q6LOBdE5gR8a65rWiHd0049bh3TY9L7L/4u5GrvWuyPvIfh2if/4S2GDm4AgIAmCCAAAAmCCAAgAkCCABgggACAJgggAAAJgggAIAJAggAYIIAAgCYIIAAACYIIACACQIIAGCCyUgxqAIp/pN99hWFvWuiC//mXSNJS4s+8K6ZMrrFuyYj5YR3TSiBset2iU32+bu/TvCuyfqsw7sm6qLeNRg5uAICAJgggAAAJgggAIAJAggAYIIAAgCYIIAAACYIIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABggslIMajcqVPeNamNn3rX9G6f4l0jSb/KvNy7Ji3Hf8LPUOpx75ri9Ih3TaK6e/1/NLgT7f4Hcs6/BiMGV0AAABMEEADAhHcAbd++XbfffrsKCgoUCAS0efPmuO1Lly5VIBCIWxYsWJCsfgEAI4R3AHV1dam4uFhr16496z4LFixQS0tLbHn11VfPq0kAwMjj/UpjeXm5ysvLz7lPMBhUOOz/KZYAgAvHgLwGVFtbq9zcXE2ZMkUPPvigjh49etZ9e3p6FIlE4hYAwMiX9ABasGCBXn75ZdXU1OiHP/yh6urqVF5err6+/m9Vra6uVigUii2FhYXJbgkAMAQl/X1Ad999d+zr6dOna8aMGZo8ebJqa2s1d+7cM/avqqpSZWVl7HEkEiGEAOACMOC3YU+aNEk5OTlqbGzsd3swGFRmZmbcAgAY+QY8gA4dOqSjR48qPz9/oA8FABhGvP8Ed+zYsbirmebmZu3Zs0fZ2dnKzs7W008/rcWLFyscDqupqUmPPvqoLr/8cs2fPz+pjQMAhjfvANq1a5duueWW2OPPX79ZsmSJ1q1bp7179+pnP/uZ2tvbVVBQoHnz5ul73/uegsFg8roGAAx73gE0Z84cuXNMIPjLX/7yvBoCvqzvs7Pfxn824//9g8SOtW2Sd81P5/vP9HH9Hf/Pu+aejAPeNR3Rk941kvS3T7O8a3K7/PvDhY254AAAJgggAIAJAggAYIIAAgCYIIAAACYIIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABgggACAJgggAAAJpL+kdzAUBDt7k6oLvCH/j+591wmHPf/CPkPSsd716QVpvrXBALeNZKUtc//R0P0ZG9Cx8KFiysgAIAJAggAYIIAAgCYIIAAACYIIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABgggACAJgggAAAJpiMFPgC19eXQJHzLrk2fMi7Ji3gPxnp36LeJZKknN+f8C9yCR4MFyyugAAAJgggAIAJAggAYIIAAgCYIIAAACYIIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABgggACAJhgMlLgC1LS07xrjt6Q511TkfML75q+BCb73NI5w7tGktL3H/auOZXApKy4sHEFBAAwQQABAEwQQAAAEwQQAMAEAQQAMEEAAQBMEEAAABMEEADABAEEADBBAAEATBBAAAATBBAAwASTkWJECoxK7NTuveFq75rMpYe8a24ZHfGuOeb6vGv+19vzvGskafLR3QnVAT64AgIAmCCAAAAmvAKourpa119/vTIyMpSbm6tFixapoaEhbp/u7m5VVFRo3Lhxuvjii7V48WK1tbUltWkAwPDnFUB1dXWqqKjQjh079M4776i3t1fz5s1TV1dXbJ+HH35Yb731lt544w3V1dXp8OHDuvPOO5PeOABgePN6pXbr1q1xjzds2KDc3Fzt3r1bs2fPVkdHh37yk59o48aNuvXWWyVJ69ev11VXXaUdO3bohhtuSF7nAIBh7bxeA+ro6JAkZWdnS5J2796t3t5elZWVxfaZOnWqJkyYoPr6+n6fo6enR5FIJG4BAIx8CQdQNBrVqlWrdOONN2ratGmSpNbWVqWnpysrKytu37y8PLW2tvb7PNXV1QqFQrGlsLAw0ZYAAMNIwgFUUVGhffv26bXXXjuvBqqqqtTR0RFbDh48eF7PBwAYHhJ6t97KlSv19ttva/v27Ro/fnxsfTgc1smTJ9Xe3h53FdTW1qZwONzvcwWDQQWDwUTaAAAMY15XQM45rVy5Ups2bdK7776roqKiuO0zZ85UWlqaampqYusaGhp04MABlZaWJqdjAMCI4HUFVFFRoY0bN2rLli3KyMiIva4TCoU0ZswYhUIhPfDAA6qsrFR2drYyMzP10EMPqbS0lDvgAABxvAJo3bp1kqQ5c+bErV+/fr2WLl0qSfrRj36klJQULV68WD09PZo/f75+/OMfJ6VZAMDIEXDOOesmvigSiSgUCmmOFmpUIM26HQwBgbR0/5prLk/oWB8/NNa75vVb13nXTEvz/2/3SMts75pP7i3wrpGkvv1/TqgOkKRTrle12qKOjg5lZmaedT/mggMAmCCAAAAmCCAAgAkCCABgggACAJgggAAAJgggAIAJAggAYIIAAgCYIIAAACYIIACACQIIAGCCAAIAmEjoE1EBSVIg4F2SMtZ/tulAfq53zR//x8XeNZL0v+f8xLtmStop75pdJ8d41/z6/17rXVNw8APvGmCwcAUEADBBAAEATBBAAAATBBAAwAQBBAAwQQABAEwQQAAAEwQQAMAEAQQAMEEAAQBMEEAAABMEEADABJORImGB9HT/oqJC75I//+sl3jU/m7/Ou0aSrks/6V3T0tfnXbNk2zLvmqv+o8W7pq+nx7sGGCxcAQEATBBAAAATBBAAwAQBBAAwQQABAEwQQAAAEwQQAMAEAQQAMEEAAQBMEEAAABMEEADABAEEADDBZKQYVKcuGeNdM+uf/uBdMzWty7tGkjqizrvmn+r+zbtm6gud3jXRv3zqXSPn//0Ag4UrIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABgggACAJgggAAAJgggAIAJAggAYIIAAgCYIIAAACaYjBQJc72nvGvS/nbcu+ZXv5/qXfP9tBPeNZL01p5i75qrfnDUu6bvzwe8axTt868BhjCugAAAJgggAIAJrwCqrq7W9ddfr4yMDOXm5mrRokVqaGiI22fOnDkKBAJxy4oVK5LaNABg+PMKoLq6OlVUVGjHjh1655131Nvbq3nz5qmrK/7Dv5YtW6aWlpbYsmbNmqQ2DQAY/rxuQti6dWvc4w0bNig3N1e7d+/W7NmzY+vHjh2rcDicnA4BACPSeb0G1NHRIUnKzs6OW//KK68oJydH06ZNU1VVlY4fP/udTz09PYpEInELAGDkS/g27Gg0qlWrVunGG2/UtGnTYuvvvfdeTZw4UQUFBdq7d68ee+wxNTQ06M033+z3eaqrq/X0008n2gYAYJhKOIAqKiq0b98+vf/++3Hrly9fHvt6+vTpys/P19y5c9XU1KTJkyef8TxVVVWqrKyMPY5EIiosLEy0LQDAMJFQAK1cuVJvv/22tm/frvHjx59z35KSEklSY2NjvwEUDAYVDAYTaQMAMIx5BZBzTg899JA2bdqk2tpaFRUVfWXNnj17JEn5+fkJNQgAGJm8AqiiokIbN27Uli1blJGRodbWVklSKBTSmDFj1NTUpI0bN+q2227TuHHjtHfvXj388MOaPXu2ZsyYMSDfAABgePIKoHXr1kk6/WbTL1q/fr2WLl2q9PR0bdu2Tc8//7y6urpUWFioxYsX6/HHH09awwCAkcH7T3DnUlhYqLq6uvNqCABwYWA2bCQugdmZ+z76k3fNlJWp3jX+Rzntyr7d3jV9X/GLGYD+MRkpAMAEAQQAMEEAAQBMEEAAABMEEADABAEEADBBAAEATBBAAAATBBAAwAQBBAAwQQABAEwQQAAAE0xGisGVwMSd7tSpAWgEgDWugAAAJgggAIAJAggAYIIAAgCYIIAAACYIIACACQIIAGCCAAIAmCCAAAAmCCAAgAkCCABgYsjNBef+a66wU+qV/KcNAwAYO6VeSX//eX42Qy6AOjs7JUnv6xfGnQAAzkdnZ6dCodBZtwfcV0XUIItGozp8+LAyMjIUCATitkUiERUWFurgwYPKzMw06tAe43Aa43Aa43Aa43DaUBgH55w6OztVUFCglJSzv9Iz5K6AUlJSNH78+HPuk5mZeUGfYJ9jHE5jHE5jHE5jHE6zHodzXfl8jpsQAAAmCCAAgIlhFUDBYFCrV69WMBi0bsUU43Aa43Aa43Aa43DacBqHIXcTAgDgwjCsroAAACMHAQQAMEEAAQBMEEAAABPDJoDWrl2rr33taxo9erRKSkr029/+1rqlQffUU08pEAjELVOnTrVua8Bt375dt99+uwoKChQIBLR58+a47c45Pfnkk8rPz9eYMWNUVlam/fv32zQ7gL5qHJYuXXrG+bFgwQKbZgdIdXW1rr/+emVkZCg3N1eLFi1SQ0ND3D7d3d2qqKjQuHHjdPHFF2vx4sVqa2sz6nhg/CPjMGfOnDPOhxUrVhh13L9hEUCvv/66KisrtXr1an3wwQcqLi7W/PnzdeTIEevWBt0111yjlpaW2PL+++9btzTgurq6VFxcrLVr1/a7fc2aNXrhhRf00ksvaefOnbrooos0f/58dXd3D3KnA+urxkGSFixYEHd+vPrqq4PY4cCrq6tTRUWFduzYoXfeeUe9vb2aN2+eurq6Yvs8/PDDeuutt/TGG2+orq5Ohw8f1p133mnYdfL9I+MgScuWLYs7H9asWWPU8Vm4YWDWrFmuoqIi9rivr88VFBS46upqw64G3+rVq11xcbF1G6YkuU2bNsUeR6NRFw6H3bPPPhtb197e7oLBoHv11VcNOhwcXx4H55xbsmSJW7hwoUk/Vo4cOeIkubq6Oufc6X/7tLQ098Ybb8T2+eMf/+gkufr6eqs2B9yXx8E5577xjW+4b33rW3ZN/QOG/BXQyZMntXv3bpWVlcXWpaSkqKysTPX19Yad2di/f78KCgo0adIk3XfffTpw4IB1S6aam5vV2toad36EQiGVlJRckOdHbW2tcnNzNWXKFD344IM6evSodUsDqqOjQ5KUnZ0tSdq9e7d6e3vjzoepU6dqwoQJI/p8+PI4fO6VV15RTk6Opk2bpqqqKh0/ftyivbMacpORftlnn32mvr4+5eXlxa3Py8vTxx9/bNSVjZKSEm3YsEFTpkxRS0uLnn76ad18883at2+fMjIyrNsz0draKkn9nh+fb7tQLFiwQHfeeaeKiorU1NSk7373uyovL1d9fb1SU1Ot20u6aDSqVatW6cYbb9S0adMknT4f0tPTlZWVFbfvSD4f+hsHSbr33ns1ceJEFRQUaO/evXrsscfU0NCgN99807DbeEM+gPB35eXlsa9nzJihkpISTZw4UT//+c/1wAMPGHaGoeDuu++OfT19+nTNmDFDkydPVm1trebOnWvY2cCoqKjQvn37LojXQc/lbOOwfPny2NfTp09Xfn6+5s6dq6amJk2ePHmw2+zXkP8TXE5OjlJTU8+4i6WtrU3hcNioq6EhKytLV155pRobG61bMfP5OcD5caZJkyYpJydnRJ4fK1eu1Ntvv6333nsv7uNbwuGwTp48qfb29rj9R+r5cLZx6E9JSYkkDanzYcgHUHp6umbOnKmamprYumg0qpqaGpWWlhp2Zu/YsWNqampSfn6+dStmioqKFA6H486PSCSinTt3XvDnx6FDh3T06NERdX4457Ry5Upt2rRJ7777roqKiuK2z5w5U2lpaXHnQ0NDgw4cODCizoevGof+7NmzR5KG1vlgfRfEP+K1115zwWDQbdiwwX300Udu+fLlLisry7W2tlq3Nqi+/e1vu9raWtfc3Ox+/etfu7KyMpeTk+OOHDli3dqA6uzsdB9++KH78MMPnST33HPPuQ8//ND95S9/cc4594Mf/MBlZWW5LVu2uL1797qFCxe6oqIid+LECePOk+tc49DZ2ekeeeQRV19f75qbm922bdvctdde66644grX3d1t3XrSPPjggy4UCrna2lrX0tISW44fPx7bZ8WKFW7ChAnu3Xffdbt27XKlpaWutLTUsOvk+6pxaGxsdM8884zbtWuXa25udlu2bHGTJk1ys2fPNu483rAIIOece/HFF92ECRNcenq6mzVrltuxY4d1S4Purrvucvn5+S49Pd1ddtll7q677nKNjY3WbQ249957z0k6Y1myZIlz7vSt2E888YTLy8tzwWDQzZ071zU0NNg2PQDONQ7Hjx938+bNc5deeqlLS0tzEydOdMuWLRtxv6T19/1LcuvXr4/tc+LECffNb37TXXLJJW7s2LHujjvucC0tLXZND4CvGocDBw642bNnu+zsbBcMBt3ll1/uvvOd77iOjg7bxr+Ej2MAAJgY8q8BAQBGJgIIAGCCAAIAmCCAAAAmCCAAgAkCCABgggACAJgggAAAJgggAIAJAggAYIIAAgCYIIAAACb+P+KXH9p5wLxQAAAAAElFTkSuQmCC", 622 | "text/plain": [ 623 | "
" 624 | ] 625 | }, 626 | "metadata": {}, 627 | "output_type": "display_data" 628 | } 629 | ], 630 | "source": [ 631 | "import matplotlib.pyplot as plt\n", 632 | "\n", 633 | "latent_samples = torch.randn(5, latent_dim).to(device)\n", 634 | "with torch.no_grad():\n", 635 | " imgs = decoder_net(latent_samples)\n", 636 | "for i in imgs:\n", 637 | " plt.imshow(i[0].cpu().numpy())\n", 638 | " plt.show()" 639 | ] 640 | }, 641 | { 642 | "cell_type": "markdown", 643 | "id": "addfccfb-ca3b-4ebe-b79b-9cd70ea5f707", 644 | "metadata": {}, 645 | "source": [ 646 | "You can also apply variational auto-encoder (VAE) for a variety of tasks - such as, denoising, anomaly detection, etc.\n", 647 | "\n", 648 | "Here I simply recover image without noise by applying encoding / decoding.\n", 649 | "\n", 650 | "> Note : To construct the model for denoising, use the denoising dataset (i.e, pairs of noisy images and clean images) and train the model for denoising with VAE architecture. (Here I simply reuse above model for recovering clean image.)" 651 | ] 652 | }, 653 | { 654 | "cell_type": "code", 655 | "execution_count": 10, 656 | "id": "d722ac15-1084-44df-b324-ea70a0b02e71", 657 | "metadata": {}, 658 | "outputs": [ 659 | { 660 | "data": { 661 | "image/png": "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zjvvOEmuvLzc1zbb3WfPg3POfeUrX3Hf+c53/G2qFTr9I6Djx49r8+bNmjp1avPHkpKSNHXqVJWXl3vcmR87d+5Ufn6+hg4dqhtvvFF79uzxvSWvKioqVFVV1eL6iEajKioqOiOvj9LSUmVnZ+vss8/WbbfdpkOHDvneUruKxWKSpMzMTEnS5s2b1dDQ0OJ6GDlypAYNGtStr4fPnodPPPHEE8rKytKoUaO0ePFiHT161Mf2TqnTDSP9rI8++khNTU3Kyclp8fGcnBy9++67nnblR1FRkVasWKGzzz5b+/fv17333qvLL79c27dvV1pamu/teVFVVSVJJ70+PvncmWLGjBm65pprVFhYqN27d+sHP/iBZs6cqfLycoXDwd77qjNLJBK6/fbbdemll2rUqFGSTlwPqampysjIaHFsd74eTnYeJOnrX/+6Bg8erPz8fG3btk3f//73tWPHDj333HMed9tSpy8g/MXMmTObfz1mzBgVFRVp8ODBeuaZZ3TzzTd73Bk6g+uvv77516NHj9aYMWM0bNgwlZaWasqUKR531j6Ki4u1ffv2M+J50C9yqvNwyy23NP969OjRysvL05QpU7R7924NGzaso7d5Up3+v+CysrIUDoc/9yqW6upq5ebmetpV55CRkaERI0Zo165dvrfizSfXANfH5w0dOlRZWVnd8vpYuHCh1qxZo1dffbXF27fk5ubq+PHjqqmpaXF8d70eTnUeTqaoqEiSOtX10OkLKDU1VePGjdO6deuaP5ZIJLRu3TpNnDjR4878O3LkiHbv3q28vDzfW/GmsLBQubm5La6PeDyujRs3nvHXx969e3Xo0KFudX0457Rw4UKtWrVKr7zyigoLC1t8fty4cUpJSWlxPezYsUN79uzpVtfD6c7DyWzdulWSOtf14PtVEK3x1FNPuUgk4lasWOHefvttd8stt7iMjAxXVVXle2sd6rvf/a4rLS11FRUV7ne/+52bOnWqy8rKcgcOHPC9tXZ1+PBht2XLFrdlyxYnyT344INuy5Yt7oMPPnDOOfeTn/zEZWRkuNWrV7tt27a52bNnu8LCQnfs2DHPO29bX3QeDh8+7L73ve+58vJyV1FR4V5++WV34YUXuuHDh7u6ujrfW28zt912m4tGo660tNTt37+/+Xb06NHmY2699VY3aNAg98orr7hNmza5iRMnuokTJ3rcdds73XnYtWuX+4d/+Ae3adMmV1FR4VavXu2GDh3qJk2a5HnnLXWJAnLOuUceecQNGjTIpaamugkTJrgNGzb43lKHu+6661xeXp5LTU11AwYMcNddd53btWuX7221u1dffdVJ+txt3rx5zrkTL8X+4Q9/6HJyclwkEnFTpkxxO3bs8LvpdvBF5+Ho0aNu2rRprn///i4lJcUNHjzYLViwoNv9I+1k378kt3z58uZjjh075r75zW+6vn37ul69ermrr77a7d+/39+m28HpzsOePXvcpEmTXGZmpotEIu6ss85yd955p4vFYn43/hm8HQMAwItO/xwQAKB7ooAAAF5QQAAALyggAIAXFBAAwAsKCADgBQUEAPCCAgIAeEEBAQC8oIAAAF5QQAAALyggAIAX/x9C+iW7nuxImwAAAABJRU5ErkJggg==", 662 | "text/plain": [ 663 | "
" 664 | ] 665 | }, 666 | "metadata": {}, 667 | "output_type": "display_data" 668 | }, 669 | { 670 | "data": { 671 | "image/png": "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r6+HL56Hz73wwgvKycnRhAkTtGrVKrW3t1ss74KSbhjpF3366afq7u5WXl5e1ON5eXn68MMPjVZlo6SkROvXr9e4ceN07NgxPfroo7rhhht04MABZWRkWC/PRGNjoySd9/r4/LnLxZw5c7RgwQIVFxfr0KFD+tnPfqby8nLV1NQoNTXVenlxF4lEtHz5ck2fPl0TJkyQdPZ6SE9PV1ZWVtS+/fl6ON95kKTbb79do0aNUmFhofbv368HHnhAtbW1eu211wxXGy3pCwh/U15e3vPrSZMmqaSkRKNGjdIrr7yiu+66y3BlSAa33nprz68nTpyoSZMmacyYMaqqqtKsWbMMV5YYFRUVOnDgwGXxOujFXOg83H333T2/njhxogoKCjRr1iwdOnRIY8aM6e1lnlfS/xdcTk6OUlNTz3kXS1NTk/Lz841WlRyysrJ01VVXqa6uznopZj6/Brg+zjV69Gjl5OT0y+tj2bJleuONN/TOO+9E/fiW/Px8nTlzRs3NzVH799fr4ULn4XxKSkokKamuh6QvoPT0dE2ZMkVbt27teSwSiWjr1q2aNm2a4crsnTx5UocOHVJBQYH1UswUFxcrPz8/6voIh8PatWvXZX99HDlyRCdOnOhX14dzTsuWLdPGjRu1bds2FRcXRz0/ZcoUpaWlRV0PtbW1Onz4cL+6Hr7sPJzPvn37JCm5rgfrd0F8FS+99JILBoNu/fr17s9//rO7++67XVZWlmtsbLReWq/6yU9+4qqqqlx9fb374x//6EpLS11OTo47fvy49dISqrW11e3du9ft3bvXSXJPPPGE27t3r/v444+dc8798pe/dFlZWW7z5s1u//79bt68ea64uNidOnXKeOXxdbHz0Nra6u677z5XU1Pj6uvr3dtvv+2+9a1vubFjx7rTp09bLz1uli5d6kKhkKuqqnLHjh3r2drb23v2ueeee9zIkSPdtm3b3O7du920adPctGnTDFcdf192Hurq6txjjz3mdu/e7err693mzZvd6NGj3YwZM4xXHq1PFJBzzj399NNu5MiRLj093U2dOtXt3LnTekm97pZbbnEFBQUuPT3dfe1rX3O33HKLq6urs15Wwr3zzjtO0jnbokWLnHNn34r90EMPuby8PBcMBt2sWbNcbW2t7aIT4GLnob293c2ePdsNHz7cpaWluVGjRrklS5b0u3+kne/rl+TWrVvXs8+pU6fcj370Izd06FA3ePBgd/PNN7tjx47ZLToBvuw8HD582M2YMcNlZ2e7YDDorrzySvfTn/7UtbS02C78C/hxDAAAE0n/GhAAoH+igAAAJiggAIAJCggAYIICAgCYoIAAACYoIACACQoIAGCCAgIAmKCAAAAmKCAAgAkKCABg4v8BJjri023/ApoAAAAASUVORK5CYII=", 672 | "text/plain": [ 673 | "
" 674 | ] 675 | }, 676 | "metadata": {}, 677 | "output_type": "display_data" 678 | } 679 | ], 680 | "source": [ 681 | "# make noisy image\n", 682 | "noise_factor = 0.2\n", 683 | "for _, (data, _) in enumerate(loader):\n", 684 | " data = data.to(device)\n", 685 | " org_image = data[0]\n", 686 | " noisy_image = org_image + noise_factor * torch.randn_like(org_image)\n", 687 | " noisy_image = torch.clamp(noisy_image, min=0.0, max=1.0)\n", 688 | " break\n", 689 | "\n", 690 | "# show noisy image\n", 691 | "plt.imshow(noisy_image[0].cpu().numpy())\n", 692 | "plt.show()\n", 693 | "\n", 694 | "# recover thru encoder/decoder\n", 695 | "with torch.no_grad():\n", 696 | " mu, sigma = encoder_net(noisy_image.unsqueeze(dim=0))\n", 697 | " decoded_image = decoder_net(mu)\n", 698 | "\n", 699 | "# show the recovered image\n", 700 | "plt.imshow(decoded_image[0][0].cpu().numpy())\n", 701 | "plt.show()" 702 | ] 703 | }, 704 | { 705 | "cell_type": "code", 706 | "execution_count": null, 707 | "id": "c876ba48-e1ac-4580-9a40-b3c56d18b1a7", 708 | "metadata": {}, 709 | "outputs": [], 710 | "source": [] 711 | } 712 | ], 713 | "metadata": { 714 | "kernelspec": { 715 | "display_name": "Python 3 (ipykernel)", 716 | "language": "python", 717 | "name": "python3" 718 | }, 719 | "language_info": { 720 | "codemirror_mode": { 721 | "name": "ipython", 722 | "version": 3 723 | }, 724 | "file_extension": ".py", 725 | "mimetype": "text/x-python", 726 | "name": "python", 727 | "nbconvert_exporter": "python", 728 | "pygments_lexer": "ipython3", 729 | "version": "3.12.3" 730 | } 731 | }, 732 | "nbformat": 4, 733 | "nbformat_minor": 5 734 | } 735 | --------------------------------------------------------------------------------