{"id":4842,"date":"2020-05-15T15:00:00","date_gmt":"2020-05-15T13:00:00","guid":{"rendered":"https:\/\/www.codemotion.com\/magazine\/?p=4842"},"modified":"2022-08-03T12:01:48","modified_gmt":"2022-08-03T10:01:48","slug":"how-to-build-a-gan-in-python","status":"publish","type":"post","link":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/","title":{"rendered":"How to build a GAN in Python"},"content":{"rendered":"\t\t\t\t<div class=\"wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-e38102f2      \"\n\t\t\t\t\tdata-scroll= \"1\"\n\t\t\t\t\tdata-offset= \"30\"\n\t\t\t\t\tstyle=\"\"\n\t\t\t\t>\n\t\t\t\t<div class=\"uagb-toc__wrap\">\n\t\t\t\t\t\t<div class=\"uagb-toc__title\">\n\t\t\t\t\t\t\tTable Of Contents\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"uagb-toc__list-wrap \">\n\t\t\t\t\t\t<ol class=\"uagb-toc__list\"><li class=\"uagb-toc__list\"><a href=\"#introduction\" class=\"uagb-toc-link__trigger\">Introduction<\/a><li class=\"uagb-toc__list\"><a href=\"#what-is-a-generative-adversarial-network\" class=\"uagb-toc-link__trigger\">What is a Generative Adversarial Network?<\/a><li class=\"uagb-toc__list\"><a href=\"#a-homemade-gan\" class=\"uagb-toc-link__trigger\">A homemade GAN<\/a><li class=\"uagb-toc__list\"><a href=\"#an-artificial-dataset\" class=\"uagb-toc-link__trigger\">An artificial dataset<\/a><li class=\"uagb-toc__list\"><a href=\"#our-gan-in-small-pieces\" class=\"uagb-toc-link__trigger\">Our GAN in small pieces<\/a><li class=\"uagb-toc__list\"><a href=\"#how-is-a-gan-trained\" class=\"uagb-toc-link__trigger\">How is a GAN trained?<\/a><li class=\"uagb-toc__list\"><a href=\"#conclusions\" class=\"uagb-toc-link__trigger\">Conclusions<\/a><\/ol>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\n\n\n<h2 class=\"wp-block-heading\" id=\"h-introduction\">Introduction<\/h2>\n\n\n\n<p><strong><span id=\"urn:local-annotation-964160\" class=\"textannotation disambiguated\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/generative_adversarial_nets\">Generative Adversarial Networks<\/span><\/strong> (<strong>GANs<\/strong>) are a hot topic in <span id=\"urn:enhancement-394924e1\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/machine_learning\">machine learning<\/span> for several good reasons. Here are three of the best:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>GANs can provide astonishing results, creating new things (images, texts, sounds, etc.) by imitating samples they have previously been exposed to.<\/li><li>A GAN offers a new paradigm in machine learning &#8211; a <em>generative<\/em> one &#8211;  that combines pre-existing techniques to provide both current and brand new ideas and results.<\/li><li>GANs are a recent (2014) creation of Ian Goodfellow, the former Google, now Apple,  researcher (also the co-author of a standard reference in deep learning with Joshua Bengio and Aaron Courville).<\/li><\/ol>\n\n\n\n<p>It is likely that readers will already have encountered some of the impressive results GANs are capable of, especially in the realm of <span id=\"urn:enhancement-5f3199f5\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/image_processing\">image processing<\/span>. Such networks are able, upon request, to draw a <span id=\"urn:enhancement-f0e422fc\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/image\">picture<\/span> of a red flower, a black bird or even a violet cat. Furthermore, that flower, bird, or cat does not exist at all in reality, but is entirely the product of the network&#8217;s &#8216;imagination&#8217;.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/00-1024x576.jpg\" alt=\"\" class=\"wp-image-4850\" srcset=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/00-1024x576.jpg 1024w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/00-300x169.jpg 300w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/00-768x432.jpg 768w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/00-896x504.jpg 896w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/00-400x225.jpg 400w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/00.jpg 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>These images are not photos of real people &#8211; they have been generated by a properly trained GAN!<\/figcaption><\/figure><\/div>\n\n\n<p>How is this possible, and can we share in the fun? This article endeavours to address both questions, using functional <strong>Python<\/strong> code that can be run on your laptop. You may need to add some packages that are missing from your <span id=\"urn:enhancement-a4ac70b3\" class=\"textannotation disambiguated wl-creative-work\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/python_programming_language\">Python<\/span> installation, but that\u2019s what Pip is there for\u2026<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-what-is-a-generative-adversarial-network\">What is a Generative Adversarial Network?<\/h2>\n\n\n\n<p><span id=\"urn:enhancement-1faa5516\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/artificial_neural_network\">Neural networks<\/span> (NNs) were devised as prediction and <span id=\"urn:enhancement-5469ca62\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/statistical_classification\">classification<\/span> <span id=\"urn:enhancement-e42cc3fe\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/conceptual_model\">models<\/span>. They are powerful, non-linear optimizers which can be trained to evolve their inner <span id=\"urn:enhancement-2b1aa137\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/parameter\">parameters<\/span> (neuron <span id=\"urn:enhancement-651f8598\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/weight_function\">weights<\/span>) to fit the training <span id=\"urn:enhancement-91d67585\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span>. This will enable the NN to predict and <span id=\"urn:enhancement-d80af0f9\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/statistical_classification\">classify<\/span> unknown <span id=\"urn:enhancement-95ffe8a9\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> of the same kind.<\/p>\n\n\n\n<p>We all know how impressive the <span id=\"urn:enhancement-9209572c\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> <span id=\"urn:enhancement-22ed451\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/approximation\">approximations<\/span> of neural networks, in which &#8216;<span id=\"urn:enhancement-721afd95\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span>&#8216; can mean just about anything, can be. However, the <span id=\"urn:enhancement-4ee6938a\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/feature_machine_learning\">features<\/span> of such algorithms also suggest some of their drawbacks, such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Neural networks need labelled data to be trained properly<\/li><li>Worse, they need a lot of labelled data<\/li><li>Worse still, we generally have no idea what the contents of a neuron actually do, except in some special cases<\/li><\/ul>\n\n\n\n<p>Intrinsically, neural networks are <strong>supervised algorithms<\/strong>. Nonetheless, some of their variants work perfectly well as <strong>unsupervised algorithms<\/strong>.  These can be trained on any kind of <span id=\"urn:enhancement-f22ce49\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span>, without requiring the &#8216;<span id=\"urn:enhancement-b3fca304\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/label\">label<\/span>&#8216; usually attached to enable the network to differentiate known things from unknown things.<\/p>\n\n\n\n<p>Unsupervised networks have previously been discussed in my articles, using the example of dealing with time series. Any time series may be thought of as a labelled <span id=\"urn:enhancement-6bae5924\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/training_set\">training set<\/span> if it points to the <span id=\"urn:enhancement-fa119cd3\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/prediction\">prediction<\/span>, while any remaining series provide the input <span id=\"urn:enhancement-2d50bf03\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> (see <a href=\"https:\/\/www.codemotion.com\/magazine\/dev-hub\/machine-learning-dev\/epidemic-intelligence-part-2-data-models-and-machine-learning-in-the-age-of-coronavirus\/\" class=\"ek-link\">this article<\/a> for more details).<\/p>\n\n\n\n<p>The GAN paradigm offers another interesting unsupervised setting for neural networks to play in, and is decribed briefly below.<\/p>\n\n\n\n<p>Let us begin with the words the acronym GAN stands for: <em><span id=\"urn:enhancement-70540a30\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/generative_model\">generative<\/span><\/em>, <em>adversarial<\/em>, <em>networks<\/em>. The last is the most obvious &#8211; <em>network<\/em>s: GANs are built up using (usually deep) neural networks. A GAN starts out with an input <span id=\"urn:enhancement-4ac64417\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/abstraction_layer\">layer<\/span> with a certain amount of parallel input neurons (one for each number represented by the input <span class=\"textannotation disambiguated wl-thing\" id=\"urn:enhancement-d5d339a3\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span>), some hidden layers and an output <span id=\"urn:enhancement-a259bbcc\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/abstraction_layer\">layer<\/span>, connected in a directed graph and trained by a variant of the gradient-descent <strong>backpropagation<\/strong> algorithm.<\/p>\n\n\n\n<p>Next, we come to the word <em><span id=\"urn:enhancement-15410bfb\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/generative_model\">generative<\/span><\/em>, which denotes the aim of this class of algorithms. <strong>They produce rather than consume <span id=\"urn:enhancement-461564e9\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span><\/strong>. More specifically, the <span id=\"urn:enhancement-9633aed1\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> these algorithms produce contains new information of the same &#8216;class&#8217; as the input <span id=\"urn:enhancement-5930377a\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> used to generate it. The generation <span id=\"urn:enhancement-c238916a\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/process_computing\">process<\/span> is not spontaneous, but <span id=\"urn:enhancement-fe9ea444\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> are generated from other <span id=\"urn:enhancement-bd9d56f0\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span>, via a mechanism that will be described later.<\/p>\n\n\n\n<p>Finally, the word <em><span id=\"urn:enhancement-ce936aba\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/adversarial_system\">adversarial<\/span><\/em> &#8211; the most mysterious term in the acronym &#8211; explains how generation occurs, namely through a competition between two adversaries. In the case of a GAN, the adversaries are neural networks.<\/p>\n\n\n\n<p>Therefore, <strong>a GAN aims at generating new <span id=\"urn:enhancement-695ef97b\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> via networks deliberately set up in competition with each other in order to achieve this goal<\/strong>. A GAN is always split into two components &#8211; two neural (usually deep) networks. The first is known as the <em>discriminator,<\/em> and it is trained to distinguish a set of <span id=\"urn:enhancement-b637e9b6\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> from pure noise. For example, the input data could include a collection of photos of flowers as well as a huge number of other <span id=\"urn:enhancement-4f929530\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/digital_image\">images<\/span> which have nothing to do with flowers. Each photo may not have an explicit <span id=\"urn:enhancement-d9fe3b54\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/label\">label<\/span>, but which photos belong to the collection of flowers, and which do not, is known.<\/p>\n\n\n\n<p>The network can then be trained to differentiate flowers from non-flowers or, for that matter, to distinguish photos from <span id=\"urn:enhancement-c46895b8\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/image\">pictures<\/span> created from <span id=\"urn:enhancement-a54dc385\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/randomness\">random<\/span> <span id=\"urn:enhancement-b194a8f8\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/pixel\">pixels<\/span>. This first &#8216;discriminator&#8217; component of the GAN is a standard network trained to <span id=\"urn:enhancement-1a186c65\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/statistical_classification\">classify<\/span> things. The input is an example of the <span id=\"urn:enhancement-dae84f85\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> we want to generate (a collection of photos of flowers if we want to generate flower images), while the output is a yes\/no flag.<\/p>\n\n\n\n<p>The other network is the <em>generator<\/em>: this produces as output the kind of <span id=\"urn:enhancement-e97d5cdd\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> the discriminator is trained to identify. To achieve this output, the generator uses a <span id=\"urn:enhancement-a90d40b9\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/randomness\">random<\/span> input. Initially this will produce a <span id=\"urn:enhancement-b6b0a5a4\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/randomness\">random<\/span> output, but the generator is trained to backpropagate the information, whether or not its output is similar to the desired <span id=\"urn:enhancement-7dcfe48e\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> (e.g., photos of flowers).<\/p>\n\n\n\n<p>To that end, <strong>the generator&#8217;s <span id=\"urn:enhancement-6e31ab92\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/prediction\">predictions<\/span> are fed into the discriminator<\/strong>. The latter is trained to recognize genuine flowers (in this example), so if the generator can counterfeit a flower sufficiently well to trick the discriminator, then our GAN can produce fake photos of flowers that a well trained observer (the discriminator) will take for the genuine article.<\/p>\n\n\n\n<p>At last, our generation task is accomplished.<\/p>\n\n\n\n<p>One way to think of a GAN is as a room where a forger and an art critic meet: the former offers fake paintings, affirming their authenticity; the latter tries to confirm whether or not they actually are the real deal. If the forger is so good at counterfeiting that the critic mistakes the fakes for the original paintings, then the fakes may be offered at auction in the hope that someone will buy them&#8230;<\/p>\n\n\n\n<p>At first glance, GANs may seem to be analogous to reinforcement learning, but the apparent similarity does not stand up to scrutiny. A GAN sets up two networks in competition with each other &#8211; the goal is to augment their opposing skills in order to produce fake <span id=\"urn:enhancement-e7b14ccf\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> that seems genuine. Reinforcement learnng, on the other hand, checks a single agent against an environment and either &#8216;reinforces&#8217; or &#8216;punishes&#8217; the agent to correct its behaviour. There\u2019s no competition &#8211; just a pattern that needs to be discovered in order to survive.<\/p>\n\n\n\n<p>Instead, GANs may be thought of as a generalisation of the <strong><span id=\"urn:enhancement-d541b4d4\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/turing_test\">Turing test<\/span> principle<\/strong>: the discriminator is the tester and the generator the machine willing to pass it, the only difference is that in this case both actors are machines (<a href=\"https:\/\/www.codemotion.com\/magazine\/dev-hub\/machine-learning-dev\/artificial-intelligence-the-new-electricity\" class=\"ek-link\"> see <em>here<\/em> for more detail on why Turing&#8217;s ideas were seminal for machine learning<\/a>).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-a-homemade-gan\">A homemade GAN<\/h2>\n\n\n\n<p>GANs usually find their most spectacular <span id=\"urn:enhancement-7bb21cea\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">applications<\/span> in counterfeiting <span id=\"urn:enhancement-b735e673\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/digital_image\">images<\/span>, as already discussed. However videos, texts, and even sounds may be generated, although technical issues can complicate the <span id=\"urn:enhancement-65d0cf1\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/implementation\">implementation<\/span> of such &#8216;time series generators&#8217;.<\/p>\n\n\n\n<p>In most tutorials, classic <span id=\"urn:enhancement-a90b07db\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/image\">image<\/span> generation is demonstrated, typically by using the MNIST <span id=\"urn:enhancement-bce19dc8\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_set\">dataset<\/span> to teach the GAN how to write letters and digits. However, convolutional networks are required for this process, and the GAN element itself is often neglected in favour of details about setting up the convolutional and &#8216;deconvolutional&#8217; networks which <span id=\"urn:enhancement-946081eb\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/implementation\">implement<\/span> the discriminator and generator. In addition, training is quite a long process when appropriate equipment is lacking (a description of such GANs can be found in <a href=\"https:\/\/www.codemotion.com\/magazine\/dev-hub\/machine-learning-dev\/generative-ai-creating-objects-with-machine-learning\/\" class=\"ek-link\">another contribution to the Codemotion magazine<\/a>).<\/p>\n\n\n\n<p>Instead, what follows is an explanation of a simple GAN programmed in Python, using the <strong><span id=\"urn:local-annotation-581304\" class=\"textannotation disambiguated\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/keras\">Keras<\/span><\/strong> library (which can be run on any laptop) to teach it how to draw a specific class of curves. I\u2019ve chosen sinusoids, but any other pattern would work equally well.<\/p>\n\n\n\n<p>Below, I\u2019ll demonstrate how to:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Generate a dataset of sinusoids;<\/li><li>Set up the discriminator and generator networks;<\/li><li>Use these to build up the GAN;<\/li><li>Train the GAN, showing how to combine the training of its components, and;<\/li><li>Contemplate a somewhat skewed and distorted sinusoid drawn by the program from pure noise.<\/li><\/ol>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-an-artificial-dataset\">An artificial dataset<\/h2>\n\n\n\n<p>Instead of a collection of images, I\u2019ll produce a description of the curves I am interested in: sinusoids may be mathematically described as the graph of functions<\/p>\n\n\n\n<p class=\"has-text-align-center\"><em>a <\/em>sin(<em>bx<\/em>+<em>c<\/em>)<\/p>\n\n\n\n<p>where <em>a<\/em>, <em>b<\/em>, <em>c<\/em> are parameters which determine the height, frequency and phase of the curve. Some examples of such curves are plotted in the following picture,  produced via a Python snippet.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> matplotlib.pyplot <span class=\"hljs-keyword\">as<\/span> plt\n<span class=\"hljs-keyword\">import<\/span> numpy <span class=\"hljs-keyword\">as<\/span> np\n<span class=\"hljs-keyword\">from<\/span> numpy.random <span class=\"hljs-keyword\">import<\/span> randint, uniform\n \nX_MIN = <span class=\"hljs-number\">-5.0<\/span>\nX_MAX = <span class=\"hljs-number\">5.0<\/span>\nX_COORDS = np.linspace(X_MIN , X_MAX, SAMPLE_LEN)\nfig, axis = plt.subplots(<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>)\n<span class=\"hljs-keyword\">for<\/span> i <span class=\"hljs-keyword\">in<\/span> range(<span class=\"hljs-number\">4<\/span>):\n    axis.plot(X_COORDS, uniform(<span class=\"hljs-number\">0.1<\/span>,<span class=\"hljs-number\">2.0<\/span>)*np.sin(uniform(<span class=\"hljs-number\">0.2<\/span>,<span class=\"hljs-number\">2.0<\/span>)*X_COORDS + uniform(<span class=\"hljs-number\">2<\/span>)))<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"386\" height=\"250\" src=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/image1-3.png\" alt=\"\" class=\"wp-image-4843\" srcset=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/image1-3.png 386w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/image1-3-300x194.png 300w\" sizes=\"auto, (max-width: 386px) 100vw, 386px\" \/><\/figure><\/div>\n\n\n<p>We want our GAN to generate curves with this sort of form. To keep things simple we consider <em>a<\/em>=1 and let <em>b<\/em>\u2208[1\/2,2] and <em>c<\/em>\u2208[0,<em>\u03c0<\/em>].<\/p>\n\n\n\n<p>First, we define some constants and <strong>produce a dataset<\/strong> of such curves. To describe a curve, we do not use the symbolic form by means of the sine function, but rather choose some points in the curve, sampled over the same <em>x<\/em> values, and represent the curve <em>y <\/em>= <em>f<\/em>(<em>x<\/em>) by the vector (<em>y<\/em>1,&#8230;,<em>yN<\/em>) where <em>yi <\/em>= <em>f<\/em>(<em>xi<\/em>) for the fixed <em>x<\/em>s.<\/p>\n\n\n\n<p>The <em>y<\/em> values are generated by using the previous formula for random values of <em>b <\/em>and <em>c<\/em> within the prescribed intervals. Having definined the training set, some of these curves can be plotted.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">import numpy <span class=\"hljs-keyword\">as<\/span> np\nfrom numpy.random import uniform\n \nimport matplotlib.pyplot <span class=\"hljs-keyword\">as<\/span> plt\n \nSAMPLE_LEN = <span class=\"hljs-number\">64<\/span>       <span class=\"hljs-comment\"># number N of points where a curve is sampled<\/span>\nSAMPLE_SIZE = <span class=\"hljs-number\">32768<\/span>   <span class=\"hljs-comment\"># number of curves in the training set<\/span>\nX_MIN = <span class=\"hljs-number\">-5.0<\/span>          <span class=\"hljs-comment\"># least ordinate where to sample<\/span>\nX_MAX = <span class=\"hljs-number\">5.0<\/span>           <span class=\"hljs-comment\"># last ordinate where to sample<\/span>\n \n<span class=\"hljs-comment\"># The set of coordinates over which curves are sampled<\/span>\nX_COORDS = np.linspace(X_MIN , X_MAX, SAMPLE_LEN)\n \n<span class=\"hljs-comment\"># The training set<\/span>\nSAMPLE = np.zeros((SAMPLE_SIZE, SAMPLE_LEN))\n<span class=\"hljs-keyword\">for<\/span> i in range(<span class=\"hljs-number\">0<\/span>, SAMPLE_SIZE):\n    b = uniform(<span class=\"hljs-number\">0.5<\/span>, <span class=\"hljs-number\">2.0<\/span>)\n    c = uniform(np.math.pi)\n    SAMPLE&#91;i] = np.<span class=\"hljs-keyword\">array<\/span>(&#91;np.sin(b*x + c) <span class=\"hljs-keyword\">for<\/span> x in X_COORDS])\n \n<span class=\"hljs-comment\"># We plot the first 8 curves<\/span>\nfig, axis = plt.subplots(<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">1<\/span>)\n<span class=\"hljs-keyword\">for<\/span> i in range(<span class=\"hljs-number\">8<\/span>):\n    axis.plot(X_COORDS, SAMPLE&#91;i])<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"386\" height=\"248\" src=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/image3-3.png\" alt=\"\" class=\"wp-image-4845\" srcset=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/image3-3.png 386w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/image3-3-300x193.png 300w\" sizes=\"auto, (max-width: 386px) 100vw, 386px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-our-gan-in-small-pieces\">Our GAN in small pieces<\/h2>\n\n\n\n<p>Next we define our discriminator, namely the neural network used to distinguish a sinusoidal curve from any other set of sampled points. The discriminator consequently accepts an input vector (<em>y<\/em>1, &#8230;, <em>yN<\/em>) and returns 1 if it corresponds to a sinusoidal curve, otherwise 0.<\/p>\n\n\n\n<p>The Keras library is then used to create a <code>Sequence<\/code> object in which to stack the different layers of the network. This discriminator is arranged as a simple shallow multilayer perceptron, with three layers: the input layer with <em>N<\/em> neurons, <em>N<\/em> being the size of the input vectors, a second layer with the same number of hidden neurons, and a third with just one neuron, the output layer.<\/p>\n\n\n\n<p>The output of the input and hidden layers is filtered by a &#8216;relu&#8217; function (which cuts negative values of its argument <em>x<\/em>) and by a &#8216;dropout&#8217; (which randomly sets input units to 0 at a prescribed frequency during each step of training, to prevent <span id=\"urn:local-annotation-261309\" class=\"textannotation disambiguated\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/overfitting\">overfitting<\/span>).<\/p>\n\n\n\n<p>The output neuron is activated via a sigmoid function which smoothly extends from 0 to 1, the two possible answers.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">from keras.models import Sequential\nfrom keras.layers import Dense, Dropout, LeakyReLU\n \nDROPOUT = Dropout(<span class=\"hljs-number\">0.4<\/span>)        <span class=\"hljs-comment\"># Empirical hyperparameter<\/span>\ndiscriminator = Sequential()\ndiscriminator.add(Dense(SAMPLE_LEN, activation=<span class=\"hljs-string\">\"relu\"<\/span>))\ndiscriminator.add(DROPOUT)\ndiscriminator.add(Dense(SAMPLE_LEN, activation=<span class=\"hljs-string\">\"relu\"<\/span>))\ndiscriminator.add(DROPOUT)\ndiscriminator.add(Dense(<span class=\"hljs-number\">1<\/span>, activation = <span class=\"hljs-string\">\"sigmoid\"<\/span>))\ndiscriminator.compile(optimizer = <span class=\"hljs-string\">\"adam\"<\/span>, loss = <span class=\"hljs-string\">\"binary_crossentropy\"<\/span>, metrics = &#91;<span class=\"hljs-string\">\"accuracy\"<\/span>])<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next we come to the <strong>generator network<\/strong>. This is in a sense a mirror of the discriminator; we still have three layers, in which the input layer accepts a noisy input of the same size as the output (a vector with <em>N<\/em> elements), and applies a &#8216;leaky relu&#8217; function (which cuts negative values of its argument <em>x<\/em> to a small multiple of <em>x<\/em> itself). However, this network does not perform dropout, and outputs the result via a hyperbolic tangent function. Since classification is not our goal, we use <em>mean square error <\/em>as the loss function instead of <em>binary cross entropy<\/em> when training the network and using it to make predictions.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">LEAKY_RELU = LeakyReLU(<span class=\"hljs-number\">0.2<\/span>)   <span class=\"hljs-comment\"># Empirical hyperparameter<\/span>\ngenerator = Sequential()\ngenerator.add(Dense(SAMPLE_LEN))\ngenerator.add(LEAKY_RELU)\ngenerator.add(Dense(<span class=\"hljs-number\">512<\/span>))\ngenerator.add(LEAKY_RELU)\ngenerator.add(Dense(SAMPLE_LEN, activation = <span class=\"hljs-string\">\"tanh\"<\/span>))\ngenerator.compile(optimizer = <span class=\"hljs-string\">\"adam\"<\/span>, loss = <span class=\"hljs-string\">\"mse\"<\/span>, metrics = &#91;<span class=\"hljs-string\">\"accuracy\"<\/span>])<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, we plug the output of the generator into the discriminator as input, so that the whole GAN network is ready to be trained.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">gan = Sequential()\ngan.add(generator)\ngan.add(discriminator)\ngan.compile(optimizer = <span class=\"hljs-string\">\"adam\"<\/span>, loss = <span class=\"hljs-string\">\"binary_crossentropy\"<\/span>, metrics = &#91;<span class=\"hljs-string\">\"accuracy\"<\/span>])<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-how-is-a-gan-trained\">How is a GAN trained?<\/h2>\n\n\n\n<p>The GAN is now ready to be trained. Instead of immediately launching the <code>fit<\/code> Keras method on the <code>gan<\/code> object we just instantiated, let&#8217;s pause and reflect on the concept of GAN to understand how to train it properly.<\/p>\n\n\n\n<p>As has already been stated, the discriminator needs to learn how to distinguish between a sinusoid and another curve. This can be done by simply training it on our <code>SAMPLES<\/code> dataset and a noisy dataset, labelling elements in the former <em>sinusoids<\/em>, and in the latter <em>non-sinusoids<\/em>.<\/p>\n\n\n\n<p>However, the aim of the discriminator is not merely to learn our dataset but to intercept the fakes produced by the generator. With this in mind, the discriminator is trained as follows:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>For each epoch, a batch training is performed on both the discriminator and the generator.<\/li><li>This batch training starts by asking the generator to generate a batch of curves.<\/li><li>The output of this is coupled to a batch of sinusoids from our <code>SAMPLE<\/code> dataset, and a dataset with labels 1 (=genuine sinusoid) and 0 (=sinusoid produced by the generator) is provided to batch train the discriminator, which is thereby trained to recognise the generated sinusoid among the genuine examples.<\/li><li>The generator is batch trained on random data: this training backpropagates along the whole GAN network, but weights in the discriminator are left untouched.<\/li><\/ol>\n\n\n\n<p>The result is that the discriminator is not trained to recognize sinusoids, but to distinguish between sinusoids from our datasets and sinusoids produced by the generator. Meanwhile, the generator is trained to produce sinusoids from random data in order to deceive the discriminator.<\/p>\n\n\n\n<p>When the success rate of this deception is high (from the point of view of the discriminator), the GAN is able to generate fake sinusoids. Because we want the code to run without starving our laptops (which can be assumed in the absence of GPUs etc.) relatively small parameters are used to produce our dataset and train the GAN. Therefore we cannot expect the network to draw a smooth sinusoid; instead we expect a rather wobbly line that nonetheless displays a sinusoidal pattern.<\/p>\n\n\n\n<p>To demonstrate how the GAN starts by drawing randomly, then gradually improves its skill at drawing a sinusoid during its &#8216;apprenticeship&#8217;, I have plotted some of the GAN outputs created during its training (10 epochs are plotted, since we are using just 64 epochs in total).<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">EPOCHS = <span class=\"hljs-number\">64<\/span>\n \nNOISE = uniform(X_MIN, X_MAX, size = (SAMPLE_SIZE, SAMPLE_LEN))\nONES = np.ones((SAMPLE_SIZE))\nZEROS = np.zeros((SAMPLE_SIZE))\n<span class=\"hljs-keyword\">print<\/span>(<span class=\"hljs-string\">\"epoch | dis. loss | dis. acc | gen. loss | gen. acc\"<\/span>)\n<span class=\"hljs-keyword\">print<\/span>(<span class=\"hljs-string\">\"------+-----------+----------+-----------+----------\"<\/span>)\n \nfig = plt.figure(figsize = (<span class=\"hljs-number\">8<\/span>, <span class=\"hljs-number\">12<\/span>))\nax_index = <span class=\"hljs-number\">1<\/span>\n<span class=\"hljs-keyword\">for<\/span> e in range(EPOCHS):\n    <span class=\"hljs-keyword\">for<\/span> k in range(SAMPLE_SIZE<span class=\"hljs-comment\">\/\/BATCH):<\/span>\n        <span class=\"hljs-comment\"># Addestra il discriminatore a riconoscere le sinusoidi vere da quelle prodotte dal generatore<\/span>\n        n = randint(<span class=\"hljs-number\">0<\/span>, SAMPLE_SIZE, size = BATCH)\n        <span class=\"hljs-comment\"># Ora prepara un batch di training record per il discriminatore<\/span>\n        p = generator.predict(NOISE&#91;n])\n        x = np.concatenate((SAMPLE&#91;n], p))\n        y = np.concatenate((ONES&#91;n], ZEROS&#91;n]))\n        d_result = discriminator.train_on_batch(x, y)\n        discriminator.trainable = <span class=\"hljs-keyword\">False<\/span>\n        g_result = gan.train_on_batch(NOISE&#91;n], ONES&#91;n])\n        discriminator.trainable = <span class=\"hljs-keyword\">True<\/span>\n    <span class=\"hljs-keyword\">print<\/span>(f<span class=\"hljs-string\">\" {e:04n} |  {d_result&#91;0]:.5f}  |  {d_result&#91;1]:.5f} |  {g_result&#91;0]:.5f}  |  {d_result&#91;1]:.5f}\"<\/span>)\n    <span class=\"hljs-comment\"># At 3, 13, 23, ... plots the last generator prediction<\/span>\n    <span class=\"hljs-keyword\">if<\/span> e % <span class=\"hljs-number\">10<\/span> == <span class=\"hljs-number\">3<\/span>:\n        ax = fig.add_subplot(<span class=\"hljs-number\">8<\/span>, <span class=\"hljs-number\">1<\/span>, ax_index)\n        plt.plot(X_COORDS, p&#91;<span class=\"hljs-number\">-1<\/span>])\n        ax.xaxis.set_visible(<span class=\"hljs-keyword\">False<\/span>)\n        plt.ylabel(f<span class=\"hljs-string\">\"Epoch: {e}\"<\/span>)\n        ax_index += <span class=\"hljs-number\">1<\/span>\n \n<span class=\"hljs-comment\"># Plots a curve generated by the GAN<\/span>\ny = generator.predict(uniform(X_MIN, X_MAX, size = (<span class=\"hljs-number\">1<\/span>, SAMPLE_LEN)))&#91;<span class=\"hljs-number\">0<\/span>]\nax = fig.add_subplot(<span class=\"hljs-number\">8<\/span>, <span class=\"hljs-number\">1<\/span>, ax_index)\nplt.plot(X_COORDS, y)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The output is:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">epoch | dis. loss | dis. acc | gen. loss | gen. acc\n------+-----------+----------+-----------+----------\n 0000 |  0.10589  |  0.96484 |  7.93257  |  0.96484   \n 0001 |  0.03285  |  1.00000 |  8.62279  |  1.00000   \n 0002 |  0.01879  |  1.00000 |  9.54678  |  1.00000   \n 0003 |  0.01875  |  1.00000 |  11.18307  |  1.00000   \n 0004 |  0.00816  |  1.00000 |  13.98673  |  1.00000   \n 0005 |  0.01707  |  0.99609 |  16.46034  |  0.99609   \n 0006 |  0.00579  |  1.00000 |  13.86913  |  1.00000   \n 0007 |  0.00189  |  1.00000 |  17.36512  |  1.00000   \n 0008 |  0.00688  |  1.00000 |  17.61729  |  1.00000   \n 0009 |  0.00306  |  1.00000 |  18.18118  |  1.00000   \n 0010 |  0.00045  |  1.00000 |  24.42766  |  1.00000   \n 0011 |  0.00137  |  1.00000 |  18.18817  |  1.00000   \n 0012 |  0.06852  |  0.98438 |  7.04744  |  0.98438   \n 0013 |  0.20359  |  0.91797 |  4.13820  |  0.91797   \n 0014 |  0.17984  |  0.93750 |  3.62651  |  0.93750   \n 0015 |  0.18223  |  0.91797 |  3.20522  |  0.91797   \n 0016 |  0.20050  |  0.91797 |  2.61011  |  0.91797   \n 0017 |  0.24295  |  0.90625 |  2.62364  |  0.90625   \n 0018 |  0.34922  |  0.83203 |  1.88428  |  0.83203   \n 0019 |  0.25503  |  0.88281 |  2.24889  |  0.88281   \n 0020 |  0.28527  |  0.88281 |  1.84421  |  0.88281   \n 0021 |  0.27210  |  0.88672 |  1.92973  |  0.88672   \n 0022 |  0.30241  |  0.88672 |  2.13511  |  0.88672   \n 0023 |  0.33156  |  0.82422 |  2.02396  |  0.82422   \n 0024 |  0.26693  |  0.86328 |  2.46276  |  0.86328   \n 0025 |  0.39710  |  0.82422 |  1.64815  |  0.82422   \n 0026 |  0.34780  |  0.83984 |  2.34444  |  0.83984   \n 0027 |  0.26145  |  0.90625 |  2.20919  |  0.90625   \n 0028 |  0.28858  |  0.86328 |  2.15237  |  0.86328   \n 0029 |  0.34291  |  0.83984 |  2.15610  |  0.83984   \n 0030 |  0.31965  |  0.86719 |  2.10919  |  0.86719   \n 0031 |  0.27913  |  0.89844 |  1.92525  |  0.89844   \n 0032 |  0.31357  |  0.87500 |  2.10098  |  0.87500   \n 0033 |  0.38449  |  0.83984 |  2.03964  |  0.83984   \n 0034 |  0.34802  |  0.81641 |  1.73214  |  0.81641   \n 0035 |  0.28982  |  0.87500 |  1.74905  |  0.87500   \n 0036 |  0.33509  |  0.85156 |  1.83760  |  0.85156   \n 0037 |  0.29839  |  0.86719 |  1.90305  |  0.86719   \n 0038 |  0.34962  |  0.83594 |  1.86196  |  0.83594   \n 0039 |  0.32271  |  0.84766 |  2.21418  |  0.84766   \n 0040 |  0.31684  |  0.84766 |  2.22909  |  0.84766   \n 0041 |  0.37983  |  0.83984 |  1.79734  |  0.83984   \n 0042 |  0.31909  |  0.83984 |  2.10337  |  0.83984   \n 0043 |  0.30426  |  0.86719 |  1.98194  |  0.86719   \n 0044 |  0.30465  |  0.86328 |  2.31558  |  0.86328   \n 0045 |  0.35478  |  0.84766 |  2.40368  |  0.84766   \n 0046 |  0.30423  |  0.86328 |  1.93115  |  0.86328   \n 0047 |  0.30887  |  0.83984 |  2.17885  |  0.83984   \n 0048 |  0.35123  |  0.86719 |  2.00351  |  0.86719   \n 0049 |  0.24366  |  0.90234 |  2.21016  |  0.90234   \n 0050 |  0.33797  |  0.84375 |  1.99375  |  0.84375   \n 0051 |  0.35846  |  0.84375 |  2.17887  |  0.84375   \n 0052 |  0.35476  |  0.83203 |  2.15312  |  0.83203   \n 0053 |  0.28164  |  0.87109 |  2.60571  |  0.87109   \n 0054 |  0.25782  |  0.89844 |  1.87386  |  0.89844   \n 0055 |  0.28027  |  0.87500 |  2.30517  |  0.87500   \n 0056 |  0.31118  |  0.84375 |  2.00939  |  0.84375   \n 0057 |  0.32034  |  0.85547 |  2.22501  |  0.85547   \n 0058 |  0.34665  |  0.84375 |  2.11842  |  0.84375   \n 0059 |  0.32069  |  0.85547 |  1.79891  |  0.85547   \n 0060 |  0.32578  |  0.87500 |  1.85051  |  0.87500   \n 0061 |  0.32067  |  0.87109 |  1.70326  |  0.87109   \n 0062 |  0.31929  |  0.85938 |  1.99901  |  0.85938   \n 0063 |  0.38814  |  0.83984 |  1.55212  |  0.83984   \n&#91;<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">matplotlib.lines.Line2D<\/span> <span class=\"hljs-attr\">at<\/span> <span class=\"hljs-attr\">0x1b5c3054c48<\/span>&gt;<\/span>]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"506\" height=\"684\" src=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/image2-3.png\" alt=\"\" class=\"wp-image-4844\" srcset=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/image2-3.png 506w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/image2-3-222x300.png 222w\" sizes=\"auto, (max-width: 506px) 100vw, 506px\" \/><\/figure><\/div>\n\n\n<p>Notice that the first picture, after three epochs, is more or less random, while the subsequent images move towards a smoother curve (even if our 64 epochs are not enough for a really good curve!) and, more importantly, towards a curve that displays a sinusoidal trend.<\/p>\n\n\n\n<p>What can also be observed is the progress of loss and accuracy for both the discriminator and the whole generative network during training. On examining this log we can see that the lower the  loss value of the GAN, the better the curve approximates a sinusoid. Finally, on examining the values for the discriminator, it is clear that some adjustments in the hyper-parameters (or even in the architecture of the networks) are in order.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-conclusions\">Conclusions<\/h2>\n\n\n\n<p>The example we have played with here may not seem especially impressive, but it really should. In the course of this article, two shallow networks have been assembled which (dropout and leaky relu aside) could have been programmed in the late 1980s. However, setting these networks up against each other in competition has produced a generating network that &#8216;draws&#8217; curves resembling the one fed to it.<\/p>\n\n\n\n<p>Beyond that, the network understands which models to imitate from just a small sample description, and running the programs on your computer has probably taken a few minutes at most.<\/p>\n\n\n\n<p>By combining more sophisticated networks along the same lines, a GAN able to generate digits, letters, or more complex figures can be created. Some modifications in the training techniques and in the representation of data would allow the GAN to generate speeches, videos, and in the near future, anything of which there are plenty of examples on the Web, which is to say, almost everything!<\/p>\n\n\n\n<p><strong><em>Recommended Article: <a href=\"https:\/\/www.codemotion.com\/magazine\/backend\/languages\/top-python-frameworks\/\" target=\"_blank\" aria-label=\"Top Trending Python Frameworks (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\">Top Trending Python Frameworks<\/a><\/em><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Generative Adversarial Networks (GANs) are a hot topic in machine learning for several good reasons. Here are three of the best: GANs can provide astonishing results, creating new things (images, texts, sounds, etc.) by imitating samples they have previously been exposed to. A GAN offers a new paradigm in machine learning &#8211; a generative&#8230; <a class=\"more-link\" href=\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/\">Read more<\/a><\/p>\n","protected":false},"author":5,"featured_media":4853,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_editorskit_title_hidden":false,"_editorskit_reading_time":12,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","_uag_custom_page_level_css":"","_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","footnotes":""},"categories":[47],"tags":[5572,68],"collections":[],"class_list":{"0":"post-4842","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-deep-learning","8":"tag-neural-networks","9":"tag-python","10":"entry"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.9 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>How to build a GAN in Python - Codemotion Magazine<\/title>\n<meta name=\"description\" content=\"Learn how to build a working Generative Adversarial Network (GAN) with ease in Python, using machine learning to allow an AI to &#039;create&#039; realistic content!\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to build a GAN in Python\" \/>\n<meta property=\"og:description\" content=\"Learn how to build a working Generative Adversarial Network (GAN) with ease in Python, using machine learning to allow an AI to &#039;create&#039; realistic content!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/\" \/>\n<meta property=\"og:site_name\" content=\"Codemotion Magazine\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Codemotion.Italy\/\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-15T13:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-08-03T10:01:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"596\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Paolo Caressa\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@www_caressa_it\" \/>\n<meta name=\"twitter:site\" content=\"@CodemotionIT\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Paolo Caressa\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"17 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/\"},\"author\":{\"name\":\"Paolo Caressa\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/11b502309bc50a6923aafd79c6259f85\"},\"headline\":\"How to build a GAN in Python\",\"datePublished\":\"2020-05-15T13:00:00+00:00\",\"dateModified\":\"2022-08-03T10:01:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/\"},\"wordCount\":2586,\"publisher\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg\",\"keywords\":[\"Neural Networks\",\"Python\"],\"articleSection\":[\"Deep Learning\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/\",\"url\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/\",\"name\":\"How to build a GAN in Python - Codemotion Magazine\",\"isPartOf\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg\",\"datePublished\":\"2020-05-15T13:00:00+00:00\",\"dateModified\":\"2022-08-03T10:01:48+00:00\",\"description\":\"Learn how to build a working Generative Adversarial Network (GAN) with ease in Python, using machine learning to allow an AI to 'create' realistic content!\",\"breadcrumb\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#primaryimage\",\"url\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg\",\"contentUrl\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg\",\"width\":1200,\"height\":596},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.codemotion.com\/magazine\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"AI\/ML\",\"item\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Deep Learning\",\"item\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"How to build a GAN in Python\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#website\",\"url\":\"https:\/\/www.codemotion.com\/magazine\/\",\"name\":\"Codemotion Magazine\",\"description\":\"We code the future. Together\",\"publisher\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.codemotion.com\/magazine\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#organization\",\"name\":\"Codemotion\",\"url\":\"https:\/\/www.codemotion.com\/magazine\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2019\/11\/codemotionlogo.png\",\"contentUrl\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2019\/11\/codemotionlogo.png\",\"width\":225,\"height\":225,\"caption\":\"Codemotion\"},\"image\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/Codemotion.Italy\/\",\"https:\/\/x.com\/CodemotionIT\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/11b502309bc50a6923aafd79c6259f85\",\"name\":\"Paolo Caressa\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b55795d60b54b1cc8b605f9967dbbe68b3fcf826249490cecafd797ee4f18d4c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b55795d60b54b1cc8b605f9967dbbe68b3fcf826249490cecafd797ee4f18d4c?s=96&d=mm&r=g\",\"caption\":\"Paolo Caressa\"},\"description\":\"I spent the first part of my life enjoying studies up to a math BS+MS and PhD. Next I worked both as math researcher (differential geometry) and as IT consultant (R&amp;D, feasibility studies, business analysis). Eventually I left academia and worked some years in finance (maths &amp; implementation of derivative pricings and risk management models), then again in IT (as technical consultant and writer, project manager, program manager). In the meanwhile I write books and articles on maths and computer science and I give lectures on workshops and conferences (applied maths, AI, etc.). I also serve as adjunct professor in the Engineering Department of \\\"Sapienza\\\" University of Rome (calculus and CS classes).\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/paolocaressa\/\",\"https:\/\/x.com\/www_caressa_it\"],\"url\":\"https:\/\/www.codemotion.com\/magazine\/author\/paolo-caressa\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"How to build a GAN in Python - Codemotion Magazine","description":"Learn how to build a working Generative Adversarial Network (GAN) with ease in Python, using machine learning to allow an AI to 'create' realistic content!","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/","og_locale":"en_US","og_type":"article","og_title":"How to build a GAN in Python","og_description":"Learn how to build a working Generative Adversarial Network (GAN) with ease in Python, using machine learning to allow an AI to 'create' realistic content!","og_url":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/","og_site_name":"Codemotion Magazine","article_publisher":"https:\/\/www.facebook.com\/Codemotion.Italy\/","article_published_time":"2020-05-15T13:00:00+00:00","article_modified_time":"2022-08-03T10:01:48+00:00","og_image":[{"width":1200,"height":596,"url":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg","type":"image\/jpeg"}],"author":"Paolo Caressa","twitter_card":"summary_large_image","twitter_creator":"@www_caressa_it","twitter_site":"@CodemotionIT","twitter_misc":{"Written by":"Paolo Caressa","Est. reading time":"17 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#article","isPartOf":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/"},"author":{"name":"Paolo Caressa","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/11b502309bc50a6923aafd79c6259f85"},"headline":"How to build a GAN in Python","datePublished":"2020-05-15T13:00:00+00:00","dateModified":"2022-08-03T10:01:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/"},"wordCount":2586,"publisher":{"@id":"https:\/\/www.codemotion.com\/magazine\/#organization"},"image":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#primaryimage"},"thumbnailUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg","keywords":["Neural Networks","Python"],"articleSection":["Deep Learning"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/","url":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/","name":"How to build a GAN in Python - Codemotion Magazine","isPartOf":{"@id":"https:\/\/www.codemotion.com\/magazine\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#primaryimage"},"image":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#primaryimage"},"thumbnailUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg","datePublished":"2020-05-15T13:00:00+00:00","dateModified":"2022-08-03T10:01:48+00:00","description":"Learn how to build a working Generative Adversarial Network (GAN) with ease in Python, using machine learning to allow an AI to 'create' realistic content!","breadcrumb":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#primaryimage","url":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg","contentUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg","width":1200,"height":596},{"@type":"BreadcrumbList","@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/how-to-build-a-gan-in-python\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.codemotion.com\/magazine\/"},{"@type":"ListItem","position":2,"name":"AI\/ML","item":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/"},{"@type":"ListItem","position":3,"name":"Deep Learning","item":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/deep-learning\/"},{"@type":"ListItem","position":4,"name":"How to build a GAN in Python"}]},{"@type":"WebSite","@id":"https:\/\/www.codemotion.com\/magazine\/#website","url":"https:\/\/www.codemotion.com\/magazine\/","name":"Codemotion Magazine","description":"We code the future. Together","publisher":{"@id":"https:\/\/www.codemotion.com\/magazine\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.codemotion.com\/magazine\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.codemotion.com\/magazine\/#organization","name":"Codemotion","url":"https:\/\/www.codemotion.com\/magazine\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/logo\/image\/","url":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2019\/11\/codemotionlogo.png","contentUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2019\/11\/codemotionlogo.png","width":225,"height":225,"caption":"Codemotion"},"image":{"@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Codemotion.Italy\/","https:\/\/x.com\/CodemotionIT"]},{"@type":"Person","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/11b502309bc50a6923aafd79c6259f85","name":"Paolo Caressa","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b55795d60b54b1cc8b605f9967dbbe68b3fcf826249490cecafd797ee4f18d4c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b55795d60b54b1cc8b605f9967dbbe68b3fcf826249490cecafd797ee4f18d4c?s=96&d=mm&r=g","caption":"Paolo Caressa"},"description":"I spent the first part of my life enjoying studies up to a math BS+MS and PhD. Next I worked both as math researcher (differential geometry) and as IT consultant (R&amp;D, feasibility studies, business analysis). Eventually I left academia and worked some years in finance (maths &amp; implementation of derivative pricings and risk management models), then again in IT (as technical consultant and writer, project manager, program manager). In the meanwhile I write books and articles on maths and computer science and I give lectures on workshops and conferences (applied maths, AI, etc.). I also serve as adjunct professor in the Engineering Department of \"Sapienza\" University of Rome (calculus and CS classes).","sameAs":["https:\/\/www.linkedin.com\/in\/paolocaressa\/","https:\/\/x.com\/www_caressa_it"],"url":"https:\/\/www.codemotion.com\/magazine\/author\/paolo-caressa\/"}]}},"featured_image_src":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-600x400.jpg","featured_image_src_square":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-600x596.jpg","author_info":{"display_name":"Paolo Caressa","author_link":"https:\/\/www.codemotion.com\/magazine\/author\/paolo-caressa\/"},"uagb_featured_image_src":{"full":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg",1200,596,false],"thumbnail":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-150x150.jpg",150,150,true],"medium":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-300x149.jpg",300,149,true],"medium_large":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-768x381.jpg",768,381,true],"large":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-1024x509.jpg",1024,509,true],"1536x1536":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg",1200,596,false],"2048x2048":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg",1200,596,false],"small-home-featured":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1.jpg",100,50,false],"sidebar-featured":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-180x128.jpg",180,128,true],"genesis-singular-images":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-896x504.jpg",896,504,true],"archive-featured":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-400x225.jpg",400,225,true],"gb-block-post-grid-landscape":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-600x400.jpg",600,400,true],"gb-block-post-grid-square":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/05\/robowar1-600x596.jpg",600,596,true]},"uagb_author_info":{"display_name":"Paolo Caressa","author_link":"https:\/\/www.codemotion.com\/magazine\/author\/paolo-caressa\/"},"uagb_comment_info":0,"uagb_excerpt":"Introduction Generative Adversarial Networks (GANs) are a hot topic in machine learning for several good reasons. Here are three of the best: GANs can provide astonishing results, creating new things (images, texts, sounds, etc.) by imitating samples they have previously been exposed to. A GAN offers a new paradigm in machine learning &#8211; a generative&#8230;&hellip;","lang":"en","_links":{"self":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts\/4842","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/comments?post=4842"}],"version-history":[{"count":15,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts\/4842\/revisions"}],"predecessor-version":[{"id":18428,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts\/4842\/revisions\/18428"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/media\/4853"}],"wp:attachment":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/media?parent=4842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/categories?post=4842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/tags?post=4842"},{"taxonomy":"collections","embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/collections?post=4842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}