{
  "id": 99215,
  "title": "Memorization GAN Explained",
  "url": "/competitions/generative-dog-images/discussion/99215",
  "author_name": "Chris Deotte",
  "post_date": "2019-07-09T15:14:53.286000",
  "votes": 159,
  "comment_count": 45,
  "views": 0,
  "content": "<h1>Basic GAN</h1>\n<h2>Real Images</h2>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F3faca66b6ada321ba1833658b2913b44%2Fimg1.jpg?generation=1602507212344417&amp;alt=media\" alt=\"\"></p>\n<h2>Fake Images</h2>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8744346a500b57317b79e2b6887b43d2%2Fimg2.jpg?generation=1602507224756646&amp;alt=media\" alt=\"\"></p>\n<h2>Summary</h2>\n<p>After a GAN is trained, we can input a random vector (seed) of length 100 into a Generator and we get a dog image out. But how can we teach a Generator to output realistic dog images? We repeatedly have it output a dog image and input that into a Discriminator. The Discriminator will output the probability of that image being real, <code>Pr(Real)</code>. We would like <code>Pr(Real)=1</code> and here's where the math comes in.</p>\n<p>The Generator's image is completely determined by it weights. Weights are numbers, call them <code>x</code>. When the Generator makes an image, the Discriminator gives it a score, <code>Pr(Real)</code>. Call that <code>y</code>. We want <code>y=1</code> but we have <code>y &lt; 1</code>. From calculus, we know how to increase <code>y</code> by changing <code>x</code> (the <strong>generator weights</strong>). Move <code>x</code> in the direction of the derivative <code>dy/dx</code>, so <code>x_new = x_old + lr * dy/dx</code> (where lr = learning rate).</p>\n<p>The Discriminator wants <code>Pr(Real)=0</code> for fake and <code>Pr(Real)=1</code> for real, so the Discriminator changes it's weights (the <strong>discriminator weights</strong>) in the direction that will accomplish this.</p>\n<h1>Feature Matching</h1>\n<p>The Generator and Discriminator repeatedly update their weights and we hope that the Generator starts to draw realistic dogs. We can improve GANs by changing the architecture of the Generator and/or changing the \"score\" (the <code>y</code> from above) that the generator uses to update its weights. A <a href=\"https://arxiv.org/abs/1406.2661\" target=\"_blank\">basic GAN</a> doesn't actually use <code>y</code>, instead it minimizes <code>error = -log(y)</code> by updating its weights as <code>x_new = x_old + lr * Gradient(error)</code> which is binary cross entropy (or negative log likelihood).</p>\n<p><a href=\"https://arxiv.org/abs/1511.06434\" target=\"_blank\">DCGAN</a> improves GAN with a better architecture, namely deep convolutional net. <a href=\"https://arxiv.org/abs/1807.00734\" target=\"_blank\">RaGAN</a> improves GAN with a better error function. <a href=\"https://arxiv.org/abs/1611.04076\" target=\"_blank\">LSGAN</a> improves with a better error function. <a href=\"https://arxiv.org/abs/1606.03498\" target=\"_blank\">Feature Matching</a> also uses a better error function.</p>\n<p>Feature Matching works by defining <code>error = ||layer_K_fake - layer_K_real||^2</code>. Note that if we use <code>k=4</code> then we have a basic GAN. If we use <code>k=3</code> then we are comparing layer 3 activations of what real dogs look like versus layer 3 activations of fake dogs. See Ian Goodfellow's paper <a href=\"https://arxiv.org/abs/1606.03498\" target=\"_blank\">here</a>.<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8f10b58c8e93c3f4aa098b166ea3f411%2Fimg3.jpg?generation=1602507244576959&amp;alt=media\" alt=\"\"></p>\n<h1>Conditional GAN</h1>\n<p>A <a href=\"https://arxiv.org/abs/1411.1784\" target=\"_blank\">CGAN</a> (conditional GAN) uses image class information. For example, when we give our Generator a random vector Z, we can also give it the name of a breed, C. Then the Discriminator will evaluate how well the Generator draws a dog of breed C. And we use that error to update the Generator's weights (which includes new weights to accommodate the input C).<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F486f86b5b5feb3dadbe3e04f1bab2f09%2Fimg4.jpg?generation=1602507260984478&amp;alt=media\" alt=\"\"></p>\n<h1>CGAN with Feature Matching</h1>\n<p>We can combine these two ideas as Ian Goodfellow does in his paper <a href=\"https://arxiv.org/abs/1606.03498\" target=\"_blank\">here</a>.<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8b2360ef699290fbb27a7aed333ff95f%2Fimg5.jpg?generation=1602507277962407&amp;alt=media\" alt=\"\"></p>\n<h1>Memorization GAN</h1>\n<p>What happens when we build a CGAN with Feature Matching and increase the number of classes to equal the number of images? i.e. we have 20000 classes with every dog in its own class. And what if we match features not on layer 4 nor 3 nor 2 nor 1 but on <code>layer 0</code>, the pixel layer? Then you get a Memorization GAN! Of course memorizing images and regurgitating them isn't a valid solution but it makes you wonder at what point does a CGAN with Feature Matching turn invalid? </p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2Fd1badfa0f343f0e2cf988f20beb0029e%2Fimg6.jpg?generation=1602507292297882&amp;alt=media\" alt=\"\"></p>\n<p>A Memorization GAN is posted <a href=\"https://www.kaggle.com/cdeotte/dog-memorizer-gan\" target=\"_blank\">here</a>. The Discriminator learns the training images ahead of time but it could learn the images while the Generator learns like a typical CGAN with Feature Matching training.</p>\n<p>If a Memorization GAN is invalid, can we start with a Memorization GAN, then drop the class labels and drop feature matching, and continue training it as a usual basic GAN? If so, how many epochs of additional training make it valid?</p>",
  "messages": [
    {
      "id": 571415,
      "postDate": "2019-07-09T15:14:53.287Z",
      "content": "<h1>Basic GAN</h1>\n<h2>Real Images</h2>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F3faca66b6ada321ba1833658b2913b44%2Fimg1.jpg?generation=1602507212344417&amp;alt=media\" alt=\"\"></p>\n<h2>Fake Images</h2>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8744346a500b57317b79e2b6887b43d2%2Fimg2.jpg?generation=1602507224756646&amp;alt=media\" alt=\"\"></p>\n<h2>Summary</h2>\n<p>After a GAN is trained, we can input a random vector (seed) of length 100 into a Generator and we get a dog image out. But how can we teach a Generator to output realistic dog images? We repeatedly have it output a dog image and input that into a Discriminator. The Discriminator will output the probability of that image being real, <code>Pr(Real)</code>. We would like <code>Pr(Real)=1</code> and here's where the math comes in.</p>\n<p>The Generator's image is completely determined by it weights. Weights are numbers, call them <code>x</code>. When the Generator makes an image, the Discriminator gives it a score, <code>Pr(Real)</code>. Call that <code>y</code>. We want <code>y=1</code> but we have <code>y &lt; 1</code>. From calculus, we know how to increase <code>y</code> by changing <code>x</code> (the <strong>generator weights</strong>). Move <code>x</code> in the direction of the derivative <code>dy/dx</code>, so <code>x_new = x_old + lr * dy/dx</code> (where lr = learning rate).</p>\n<p>The Discriminator wants <code>Pr(Real)=0</code> for fake and <code>Pr(Real)=1</code> for real, so the Discriminator changes it's weights (the <strong>discriminator weights</strong>) in the direction that will accomplish this.</p>\n<h1>Feature Matching</h1>\n<p>The Generator and Discriminator repeatedly update their weights and we hope that the Generator starts to draw realistic dogs. We can improve GANs by changing the architecture of the Generator and/or changing the \"score\" (the <code>y</code> from above) that the generator uses to update its weights. A <a href=\"https://arxiv.org/abs/1406.2661\" target=\"_blank\">basic GAN</a> doesn't actually use <code>y</code>, instead it minimizes <code>error = -log(y)</code> by updating its weights as <code>x_new = x_old + lr * Gradient(error)</code> which is binary cross entropy (or negative log likelihood).</p>\n<p><a href=\"https://arxiv.org/abs/1511.06434\" target=\"_blank\">DCGAN</a> improves GAN with a better architecture, namely deep convolutional net. <a href=\"https://arxiv.org/abs/1807.00734\" target=\"_blank\">RaGAN</a> improves GAN with a better error function. <a href=\"https://arxiv.org/abs/1611.04076\" target=\"_blank\">LSGAN</a> improves with a better error function. <a href=\"https://arxiv.org/abs/1606.03498\" target=\"_blank\">Feature Matching</a> also uses a better error function.</p>\n<p>Feature Matching works by defining <code>error = ||layer_K_fake - layer_K_real||^2</code>. Note that if we use <code>k=4</code> then we have a basic GAN. If we use <code>k=3</code> then we are comparing layer 3 activations of what real dogs look like versus layer 3 activations of fake dogs. See Ian Goodfellow's paper <a href=\"https://arxiv.org/abs/1606.03498\" target=\"_blank\">here</a>.<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8f10b58c8e93c3f4aa098b166ea3f411%2Fimg3.jpg?generation=1602507244576959&amp;alt=media\" alt=\"\"></p>\n<h1>Conditional GAN</h1>\n<p>A <a href=\"https://arxiv.org/abs/1411.1784\" target=\"_blank\">CGAN</a> (conditional GAN) uses image class information. For example, when we give our Generator a random vector Z, we can also give it the name of a breed, C. Then the Discriminator will evaluate how well the Generator draws a dog of breed C. And we use that error to update the Generator's weights (which includes new weights to accommodate the input C).<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F486f86b5b5feb3dadbe3e04f1bab2f09%2Fimg4.jpg?generation=1602507260984478&amp;alt=media\" alt=\"\"></p>\n<h1>CGAN with Feature Matching</h1>\n<p>We can combine these two ideas as Ian Goodfellow does in his paper <a href=\"https://arxiv.org/abs/1606.03498\" target=\"_blank\">here</a>.<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8b2360ef699290fbb27a7aed333ff95f%2Fimg5.jpg?generation=1602507277962407&amp;alt=media\" alt=\"\"></p>\n<h1>Memorization GAN</h1>\n<p>What happens when we build a CGAN with Feature Matching and increase the number of classes to equal the number of images? i.e. we have 20000 classes with every dog in its own class. And what if we match features not on layer 4 nor 3 nor 2 nor 1 but on <code>layer 0</code>, the pixel layer? Then you get a Memorization GAN! Of course memorizing images and regurgitating them isn't a valid solution but it makes you wonder at what point does a CGAN with Feature Matching turn invalid? </p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2Fd1badfa0f343f0e2cf988f20beb0029e%2Fimg6.jpg?generation=1602507292297882&amp;alt=media\" alt=\"\"></p>\n<p>A Memorization GAN is posted <a href=\"https://www.kaggle.com/cdeotte/dog-memorizer-gan\" target=\"_blank\">here</a>. The Discriminator learns the training images ahead of time but it could learn the images while the Generator learns like a typical CGAN with Feature Matching training.</p>\n<p>If a Memorization GAN is invalid, can we start with a Memorization GAN, then drop the class labels and drop feature matching, and continue training it as a usual basic GAN? If so, how many epochs of additional training make it valid?</p>",
      "rawMarkdown": "# Basic GAN\n## Real Images\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F3faca66b6ada321ba1833658b2913b44%2Fimg1.jpg?generation=1602507212344417&alt=media)\n## Fake Images\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8744346a500b57317b79e2b6887b43d2%2Fimg2.jpg?generation=1602507224756646&alt=media)\n## Summary\nAfter a GAN is trained, we can input a random vector (seed) of length 100 into a Generator and we get a dog image out. But how can we teach a Generator to output realistic dog images? We repeatedly have it output a dog image and input that into a Discriminator. The Discriminator will output the probability of that image being real, `Pr(Real)`. We would like `Pr(Real)=1` and here's where the math comes in.\n  \nThe Generator's image is completely determined by it weights. Weights are numbers, call them `x`. When the Generator makes an image, the Discriminator gives it a score, `Pr(Real)`. Call that `y`. We want `y=1` but we have `y &lt; 1`. From calculus, we know how to increase `y` by changing `x` (the **generator weights**). Move `x` in the direction of the derivative `dy/dx`, so `x_new = x_old + lr * dy/dx` (where lr = learning rate).\n\nThe Discriminator wants `Pr(Real)=0` for fake and `Pr(Real)=1` for real, so the Discriminator changes it's weights (the **discriminator weights**) in the direction that will accomplish this.\n\n# Feature Matching\nThe Generator and Discriminator repeatedly update their weights and we hope that the Generator starts to draw realistic dogs. We can improve GANs by changing the architecture of the Generator and/or changing the \"score\" (the `y` from above) that the generator uses to update its weights. A [basic GAN][1] doesn't actually use `y`, instead it minimizes `error = -log(y)` by updating its weights as `x_new = x_old + lr * Gradient(error)` which is binary cross entropy (or negative log likelihood).\n\n[DCGAN][2] improves GAN with a better architecture, namely deep convolutional net. [RaGAN][5] improves GAN with a better error function. [LSGAN][4] improves with a better error function. [Feature Matching][6] also uses a better error function.\n\nFeature Matching works by defining `error = ||layer_K_fake - layer_K_real||^2`. Note that if we use `k=4` then we have a basic GAN. If we use `k=3` then we are comparing layer 3 activations of what real dogs look like versus layer 3 activations of fake dogs. See Ian Goodfellow's paper [here][6].\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8f10b58c8e93c3f4aa098b166ea3f411%2Fimg3.jpg?generation=1602507244576959&alt=media)\n# Conditional GAN\nA [CGAN][7] (conditional GAN) uses image class information. For example, when we give our Generator a random vector Z, we can also give it the name of a breed, C. Then the Discriminator will evaluate how well the Generator draws a dog of breed C. And we use that error to update the Generator's weights (which includes new weights to accommodate the input C).\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F486f86b5b5feb3dadbe3e04f1bab2f09%2Fimg4.jpg?generation=1602507260984478&alt=media)\n# CGAN with Feature Matching\nWe can combine these two ideas as Ian Goodfellow does in his paper [here][6].\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8b2360ef699290fbb27a7aed333ff95f%2Fimg5.jpg?generation=1602507277962407&alt=media)\n# Memorization GAN\nWhat happens when we build a CGAN with Feature Matching and increase the number of classes to equal the number of images? i.e. we have 20000 classes with every dog in its own class. And what if we match features not on layer 4 nor 3 nor 2 nor 1 but on `layer 0`, the pixel layer? Then you get a Memorization GAN! Of course memorizing images and regurgitating them isn't a valid solution but it makes you wonder at what point does a CGAN with Feature Matching turn invalid? \n  \n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2Fd1badfa0f343f0e2cf988f20beb0029e%2Fimg6.jpg?generation=1602507292297882&alt=media)\n\nA Memorization GAN is posted [here][8]. The Discriminator learns the training images ahead of time but it could learn the images while the Generator learns like a typical CGAN with Feature Matching training.\n\nIf a Memorization GAN is invalid, can we start with a Memorization GAN, then drop the class labels and drop feature matching, and continue training it as a usual basic GAN? If so, how many epochs of additional training make it valid?\n\n[1]: https://arxiv.org/abs/1406.2661\n[2]: https://arxiv.org/abs/1511.06434\n[4]: https://arxiv.org/abs/1611.04076\n[5]: https://arxiv.org/abs/1807.00734\n[6]: https://arxiv.org/abs/1606.03498\n[7]: https://arxiv.org/abs/1411.1784\n[8]: https://www.kaggle.com/cdeotte/dog-memorizer-gan",
      "votes": 157
    },
    {
      "id": 571438,
      "postDate": "2019-07-09T15:36:10.487Z",
      "content": "<p>Good Explanation. Simple! Elegant! Your contributions in this competitions are unparalleled learning a lot of things from you. keep it up 👍 </p>\n\n<p>Remind me of a famous quote\n<img src=\"http://i.imgur.com/uqxffAz.jpg\" alt=\"\"></p>",
      "rawMarkdown": "Good Explanation. Simple! Elegant! Your contributions in this competitions are unparalleled learning a lot of things from you. keep it up 👍 \n\nRemind me of a famous quote\n![](http://i.imgur.com/uqxffAz.jpg)",
      "votes": 15,
      "replies": [
        {
          "id": 571494,
          "postDate": "2019-07-09T17:03:34.223Z",
          "content": "<p>Maybe I don't understand it because it's badly explained.</p>",
          "rawMarkdown": "Maybe I don't understand it because it's badly explained.",
          "votes": -2
        },
        {
          "id": 573134,
          "postDate": "2019-07-11T20:22:51.100Z",
          "content": "<p>Thank you Aman.cyberia</p>",
          "rawMarkdown": "Thank you Aman.cyberia",
          "votes": 2
        }
      ]
    },
    {
      "id": 591446,
      "postDate": "2019-08-03T17:31:38.293Z",
      "content": "<p>Thanks again for your amazing explanation Chris.</p>",
      "rawMarkdown": "Thanks again for your amazing explanation Chris.",
      "votes": 3
    },
    {
      "id": 574584,
      "postDate": "2019-07-14T06:14:58.090Z",
      "content": "<p>Thanks Chris. Really appreciate your work. Like always your explanations are clear and amazing.</p>",
      "rawMarkdown": "Thanks Chris. Really appreciate your work. Like always your explanations are clear and amazing.",
      "votes": 3
    },
    {
      "id": 592613,
      "postDate": "2019-08-05T15:06:31.327Z",
      "content": "<p>Really great explanation. Thanks for helping me wrap my mind around this. 👍 </p>",
      "rawMarkdown": "Really great explanation. Thanks for helping me wrap my mind around this. 👍 ",
      "votes": 1
    },
    {
      "id": 591373,
      "postDate": "2019-08-03T15:25:17.480Z",
      "content": "<p>That's an amazing explanation.. It's really amazing &amp; helpful. Thank you.</p>",
      "rawMarkdown": "That's an amazing explanation.. It's really amazing &amp; helpful. Thank you.",
      "votes": 1
    },
    {
      "id": 588562,
      "postDate": "2019-07-30T18:41:08.993Z",
      "content": "<p>wow. Nicely explained👍 \ncheck this article about GAN models.\n <a href=\"https://blogs.nvidia.com/blog/2019/03/18/gaugan-photorealistic-landscapes-nvidia-research/\">https://blogs.nvidia.com/blog/2019/03/18/gaugan-photorealistic-landscapes-nvidia-research/</a></p>",
      "rawMarkdown": "wow. Nicely explained👍 \ncheck this article about GAN models.\n https://blogs.nvidia.com/blog/2019/03/18/gaugan-photorealistic-landscapes-nvidia-research/",
      "votes": 1
    },
    {
      "id": 582920,
      "postDate": "2019-07-23T19:21:21.153Z",
      "content": "<p>Nice post. Thanks for explaining it in simple form.</p>",
      "rawMarkdown": "Nice post. Thanks for explaining it in simple form.",
      "votes": 1
    },
    {
      "id": 581292,
      "postDate": "2019-07-21T18:06:10.770Z",
      "content": "<p>great piece of info.. got to know about memorization GAN from this.</p>",
      "rawMarkdown": "great piece of info.. got to know about memorization GAN from this.",
      "votes": 1
    },
    {
      "id": 580986,
      "postDate": "2019-07-21T07:55:28.450Z",
      "content": "<p>Awesome introduction to the idea of memorization GAN and how to get there from a basic GAN.\nThanks for sharing this explanation.  </p>",
      "rawMarkdown": "Awesome introduction to the idea of memorization GAN and how to get there from a basic GAN.\nThanks for sharing this explanation.  ",
      "votes": 1,
      "replies": [
        {
          "id": 581176,
          "postDate": "2019-07-21T14:59:21.897Z",
          "content": "<p>Thanks Yassine</p>",
          "rawMarkdown": "Thanks Yassine",
          "votes": 1
        }
      ]
    },
    {
      "id": 580242,
      "postDate": "2019-07-19T22:01:53.493Z",
      "content": "<p>this is very good explanation. \nI am thankful to you</p>",
      "rawMarkdown": "this is very good explanation. \nI am thankful to you",
      "votes": 1,
      "replies": [
        {
          "id": 580276,
          "postDate": "2019-07-20T00:00:48.703Z",
          "content": "<p>Thank you</p>",
          "rawMarkdown": "Thank you",
          "votes": 1
        }
      ]
    },
    {
      "id": 578688,
      "postDate": "2019-07-18T03:03:21.933Z",
      "content": "<p>That's an amazing explanation.. It's really amazing. Thank you.</p>",
      "rawMarkdown": "That's an amazing explanation.. It's really amazing. Thank you.",
      "votes": 1,
      "replies": [
        {
          "id": 578991,
          "postDate": "2019-07-18T11:46:05.207Z",
          "content": "<p>Thank you</p>",
          "rawMarkdown": "Thank you",
          "votes": 1
        }
      ]
    },
    {
      "id": 576837,
      "postDate": "2019-07-16T04:45:07.423Z",
      "content": "<p>Fantastic! Thanks for posting this, <a href=\"/cdeotte\">@cdeotte</a>.</p>",
      "rawMarkdown": "Fantastic! Thanks for posting this, @cdeotte.",
      "votes": 1,
      "replies": [
        {
          "id": 577080,
          "postDate": "2019-07-16T10:22:17.687Z",
          "content": "<p>Thank you</p>",
          "rawMarkdown": "Thank you"
        }
      ]
    },
    {
      "id": 574895,
      "postDate": "2019-07-14T16:48:58.427Z",
      "content": "<p>Thanks. good refresher.</p>",
      "rawMarkdown": "Thanks. good refresher.",
      "votes": 1,
      "replies": [
        {
          "id": 575209,
          "postDate": "2019-07-15T07:09:14.010Z",
          "content": "<p>This post is really amazing initially I have no idea how can I measure the speed of bandwidth also how can I save our system bandwidth but after reading this post my all doubts disappeared.\n<a href=\"https://errorcode0x.com/resolve-epson-scanner-communication-error/\">Epson scanner communication error</a></p>",
          "rawMarkdown": "This post is really amazing initially I have no idea how can I measure the speed of bandwidth also how can I save our system bandwidth but after reading this post my all doubts disappeared.\n[Epson scanner communication error](https://errorcode0x.com/resolve-epson-scanner-communication-error/)"
        }
      ]
    },
    {
      "id": 573345,
      "postDate": "2019-07-12T06:27:50.607Z",
      "content": "<p>It was a nice one from you, Chris</p>",
      "rawMarkdown": "It was a nice one from you, Chris",
      "votes": 1
    },
    {
      "id": 573122,
      "postDate": "2019-07-11T20:07:22.737Z",
      "content": "<p>Super useful explanation! </p>",
      "rawMarkdown": "Super useful explanation! ",
      "votes": 1,
      "replies": [
        {
          "id": 573130,
          "postDate": "2019-07-11T20:22:02.173Z",
          "content": "<p>Thank you</p>",
          "rawMarkdown": "Thank you"
        }
      ]
    },
    {
      "id": 572483,
      "postDate": "2019-07-11T01:46:01.950Z",
      "content": "<p>nice</p>",
      "rawMarkdown": "nice",
      "votes": 1
    },
    {
      "id": 572253,
      "postDate": "2019-07-10T17:29:08.460Z",
      "content": "<p>Amazing like always! I will definitely spend time on CGAN. Thank you</p>",
      "rawMarkdown": "Amazing like always! I will definitely spend time on CGAN. Thank you\n",
      "votes": 1,
      "replies": [
        {
          "id": 573131,
          "postDate": "2019-07-11T20:22:20.483Z",
          "content": "<p>Thanks Francois</p>",
          "rawMarkdown": "Thanks Francois",
          "votes": 1
        }
      ]
    },
    {
      "id": 572249,
      "postDate": "2019-07-10T17:18:40.913Z",
      "content": "<p>Good Explanation</p>",
      "rawMarkdown": "Good Explanation",
      "votes": 1
    },
    {
      "id": 571841,
      "postDate": "2019-07-10T06:29:10.827Z",
      "content": "<p>Good Explanation</p>",
      "rawMarkdown": "Good Explanation",
      "votes": 1
    },
    {
      "id": 571771,
      "postDate": "2019-07-10T04:41:01.663Z",
      "content": "<p>Thank you for this write-up, it gives a lot of insights. </p>",
      "rawMarkdown": "Thank you for this write-up, it gives a lot of insights. ",
      "votes": 1,
      "replies": [
        {
          "id": 573133,
          "postDate": "2019-07-11T20:22:31.927Z",
          "content": "<p>Thank you</p>",
          "rawMarkdown": "Thank you",
          "votes": 1
        }
      ]
    },
    {
      "id": 571666,
      "postDate": "2019-07-10T00:31:32.943Z",
      "content": "<p>Thank you for the explanation. I will study a lot.</p>",
      "rawMarkdown": "Thank you for the explanation. I will study a lot.",
      "votes": 1
    },
    {
      "id": 571488,
      "postDate": "2019-07-09T16:48:30.200Z",
      "content": "<p>Thanks a lot <a href=\"/cdeotte\">@cdeotte</a> for this! Learning a lot from you</p>",
      "rawMarkdown": "Thanks a lot @cdeotte for this! Learning a lot from you",
      "votes": 1
    },
    {
      "id": 2498631,
      "postDate": "2023-10-25T12:31:01Z",
      "content": "<p>I'm new to this GAN and stuff, thanks for the amazing explanation!</p>",
      "rawMarkdown": "I'm new to this GAN and stuff, thanks for the amazing explanation!"
    },
    {
      "id": 1084606,
      "postDate": "2020-11-20T07:49:26.347Z",
      "content": "<p>Amazing Explanation, Thanks I needed this.</p>",
      "rawMarkdown": "Amazing Explanation, Thanks I needed this."
    },
    {
      "id": 573362,
      "postDate": "2019-07-12T07:00:35.387Z",
      "rawMarkdown": "",
      "votes": 1,
      "isDeleted": true
    },
    {
      "id": 593327,
      "postDate": "2019-08-06T13:06:07.187Z",
      "content": "<p>nice explanation, thanks!</p>",
      "rawMarkdown": "nice explanation, thanks!",
      "votes": 1
    },
    {
      "id": 581142,
      "postDate": "2019-07-21T13:59:52.063Z",
      "content": "<p>Thank you for sharing!</p>",
      "rawMarkdown": "Thank you for sharing!",
      "votes": 1
    },
    {
      "id": 579959,
      "postDate": "2019-07-19T13:02:47.360Z",
      "content": "<p>great explanation thanks!</p>",
      "rawMarkdown": "great explanation thanks!",
      "votes": 1
    },
    {
      "id": 579072,
      "postDate": "2019-07-18T13:06:28.860Z",
      "content": "<p>Thanks</p>",
      "rawMarkdown": "Thanks",
      "votes": 1
    },
    {
      "id": 578591,
      "postDate": "2019-07-17T22:24:05.507Z",
      "content": "<p>thanks for sharing thisexplanation.</p>",
      "rawMarkdown": "thanks for sharing thisexplanation.",
      "votes": 1
    },
    {
      "id": 575597,
      "postDate": "2019-07-15T17:48:00.263Z",
      "content": "<p>Thanks</p>",
      "rawMarkdown": "Thanks\n",
      "votes": 1
    },
    {
      "id": 574785,
      "postDate": "2019-07-14T13:38:20.803Z",
      "content": "<p>Thanks a lot, nice explanation.</p>",
      "rawMarkdown": "Thanks a lot, nice explanation.",
      "votes": 1
    },
    {
      "id": 573870,
      "postDate": "2019-07-12T21:52:36.313Z",
      "content": "<p>Thanks! Very useful.</p>",
      "rawMarkdown": "Thanks! Very useful.",
      "votes": 1
    },
    {
      "id": 572513,
      "postDate": "2019-07-11T02:44:48.680Z",
      "content": "<p>Thanks, I learned a lot :)</p>",
      "rawMarkdown": "Thanks, I learned a lot :)",
      "votes": 1
    },
    {
      "id": 572289,
      "postDate": "2019-07-10T18:16:52.700Z",
      "content": "<p>Thanks!</p>",
      "rawMarkdown": "Thanks!",
      "votes": 1
    }
  ],
  "comments": [
    {
      "id": 571438,
      "author_name": "cyberia",
      "author_url": "",
      "post_date": "2019-07-09T15:36:10.487000",
      "content": "<p>Good Explanation. Simple! Elegant! Your contributions in this competitions are unparalleled learning a lot of things from you. keep it up 👍 </p>\n\n<p>Remind me of a famous quote\n<img src=\"http://i.imgur.com/uqxffAz.jpg\" alt=\"\"></p>",
      "votes": 15,
      "replies": [
        {
          "id": 571494,
          "author_name": "JM100",
          "author_url": "",
          "post_date": "2019-07-09T17:03:34.223000",
          "content": "<p>Maybe I don't understand it because it's badly explained.</p>",
          "votes": -2,
          "replies": []
        },
        {
          "id": 573134,
          "author_name": "Chris Deotte",
          "author_url": "",
          "post_date": "2019-07-11T20:22:51.100000",
          "content": "<p>Thank you Aman.cyberia</p>",
          "votes": 2,
          "replies": []
        }
      ]
    },
    {
      "id": 591446,
      "author_name": "torch",
      "author_url": "",
      "post_date": "2019-08-03T17:31:38.293000",
      "content": "<p>Thanks again for your amazing explanation Chris.</p>",
      "votes": 3,
      "replies": []
    },
    {
      "id": 574584,
      "author_name": "torch",
      "author_url": "",
      "post_date": "2019-07-14T06:14:58.090000",
      "content": "<p>Thanks Chris. Really appreciate your work. Like always your explanations are clear and amazing.</p>",
      "votes": 3,
      "replies": []
    },
    {
      "id": 592613,
      "author_name": "Jared Savage",
      "author_url": "",
      "post_date": "2019-08-05T15:06:31.327000",
      "content": "<p>Really great explanation. Thanks for helping me wrap my mind around this. 👍 </p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 591373,
      "author_name": "Harun-Ur-Rashid",
      "author_url": "",
      "post_date": "2019-08-03T15:25:17.480000",
      "content": "<p>That's an amazing explanation.. It's really amazing &amp; helpful. Thank you.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 588562,
      "author_name": "Genos",
      "author_url": "",
      "post_date": "2019-07-30T18:41:08.993000",
      "content": "<p>wow. Nicely explained👍 \ncheck this article about GAN models.\n <a href=\"https://blogs.nvidia.com/blog/2019/03/18/gaugan-photorealistic-landscapes-nvidia-research/\">https://blogs.nvidia.com/blog/2019/03/18/gaugan-photorealistic-landscapes-nvidia-research/</a></p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 582920,
      "author_name": "Bob",
      "author_url": "",
      "post_date": "2019-07-23T19:21:21.153000",
      "content": "<p>Nice post. Thanks for explaining it in simple form.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 581292,
      "author_name": "pankaj_j",
      "author_url": "",
      "post_date": "2019-07-21T18:06:10.770000",
      "content": "<p>great piece of info.. got to know about memorization GAN from this.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 580986,
      "author_name": "Yassine Alouini",
      "author_url": "",
      "post_date": "2019-07-21T07:55:28.450000",
      "content": "<p>Awesome introduction to the idea of memorization GAN and how to get there from a basic GAN.\nThanks for sharing this explanation.  </p>",
      "votes": 1,
      "replies": [
        {
          "id": 581176,
          "author_name": "Chris Deotte",
          "author_url": "",
          "post_date": "2019-07-21T14:59:21.897000",
          "content": "<p>Thanks Yassine</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 580242,
      "author_name": "batu bayraktar",
      "author_url": "",
      "post_date": "2019-07-19T22:01:53.493000",
      "content": "<p>this is very good explanation. \nI am thankful to you</p>",
      "votes": 1,
      "replies": [
        {
          "id": 580276,
          "author_name": "Chris Deotte",
          "author_url": "",
          "post_date": "2019-07-20T00:00:48.703000",
          "content": "<p>Thank you</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 578688,
      "author_name": "Vishnu Subramanian",
      "author_url": "",
      "post_date": "2019-07-18T03:03:21.933000",
      "content": "<p>That's an amazing explanation.. It's really amazing. Thank you.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 578991,
          "author_name": "Chris Deotte",
          "author_url": "",
          "post_date": "2019-07-18T11:46:05.207000",
          "content": "<p>Thank you</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 576837,
      "author_name": "M. Marrow",
      "author_url": "",
      "post_date": "2019-07-16T04:45:07.423000",
      "content": "<p>Fantastic! Thanks for posting this, <a href=\"/cdeotte\">@cdeotte</a>.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 577080,
          "author_name": "Chris Deotte",
          "author_url": "",
          "post_date": "2019-07-16T10:22:17.687000",
          "content": "<p>Thank you</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 574895,
      "author_name": "Salim Alzahrani",
      "author_url": "",
      "post_date": "2019-07-14T16:48:58.427000",
      "content": "<p>Thanks. good refresher.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 575209,
          "author_name": "angilina005",
          "author_url": "",
          "post_date": "2019-07-15T07:09:14.010000",
          "content": "<p>This post is really amazing initially I have no idea how can I measure the speed of bandwidth also how can I save our system bandwidth but after reading this post my all doubts disappeared.\n<a href=\"https://errorcode0x.com/resolve-epson-scanner-communication-error/\">Epson scanner communication error</a></p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 573345,
      "author_name": "Udit Deo",
      "author_url": "",
      "post_date": "2019-07-12T06:27:50.607000",
      "content": "<p>It was a nice one from you, Chris</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 573122,
      "author_name": "Aishwarya Turuvekere",
      "author_url": "",
      "post_date": "2019-07-11T20:07:22.737000",
      "content": "<p>Super useful explanation! </p>",
      "votes": 1,
      "replies": [
        {
          "id": 573130,
          "author_name": "Chris Deotte",
          "author_url": "",
          "post_date": "2019-07-11T20:22:02.173000",
          "content": "<p>Thank you</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 572483,
      "author_name": "sepuluh terakhir",
      "author_url": "",
      "post_date": "2019-07-11T01:46:01.950000",
      "content": "<p>nice</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 572253,
      "author_name": "François",
      "author_url": "",
      "post_date": "2019-07-10T17:29:08.460000",
      "content": "<p>Amazing like always! I will definitely spend time on CGAN. Thank you</p>",
      "votes": 1,
      "replies": [
        {
          "id": 573131,
          "author_name": "Chris Deotte",
          "author_url": "",
          "post_date": "2019-07-11T20:22:20.483000",
          "content": "<p>Thanks Francois</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 572249,
      "author_name": "Sani Kamal",
      "author_url": "",
      "post_date": "2019-07-10T17:18:40.913000",
      "content": "<p>Good Explanation</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 571841,
      "author_name": "Marek Nurzynski",
      "author_url": "",
      "post_date": "2019-07-10T06:29:10.827000",
      "content": "<p>Good Explanation</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 571771,
      "author_name": "yukiya",
      "author_url": "",
      "post_date": "2019-07-10T04:41:01.663000",
      "content": "<p>Thank you for this write-up, it gives a lot of insights. </p>",
      "votes": 1,
      "replies": [
        {
          "id": 573133,
          "author_name": "Chris Deotte",
          "author_url": "",
          "post_date": "2019-07-11T20:22:31.927000",
          "content": "<p>Thank you</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 571666,
      "author_name": "mochidan",
      "author_url": "",
      "post_date": "2019-07-10T00:31:32.943000",
      "content": "<p>Thank you for the explanation. I will study a lot.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 571488,
      "author_name": "Srihari Pramod",
      "author_url": "",
      "post_date": "2019-07-09T16:48:30.200000",
      "content": "<p>Thanks a lot <a href=\"/cdeotte\">@cdeotte</a> for this! Learning a lot from you</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 2498631,
      "author_name": "Ridho Pandhu",
      "author_url": "",
      "post_date": "2023-10-25T12:31:01",
      "content": "<p>I'm new to this GAN and stuff, thanks for the amazing explanation!</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1084606,
      "author_name": "Light Yagami",
      "author_url": "",
      "post_date": "2020-11-20T07:49:26.347000",
      "content": "<p>Amazing Explanation, Thanks I needed this.</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 573362,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-07-12T07:00:35.387000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 593327,
      "author_name": "boran zhou",
      "author_url": "",
      "post_date": "2019-08-06T13:06:07.187000",
      "content": "<p>nice explanation, thanks!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 581142,
      "author_name": "makogarei",
      "author_url": "",
      "post_date": "2019-07-21T13:59:52.063000",
      "content": "<p>Thank you for sharing!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 579959,
      "author_name": "saewonYang",
      "author_url": "",
      "post_date": "2019-07-19T13:02:47.360000",
      "content": "<p>great explanation thanks!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 579072,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-07-18T13:06:28.860000",
      "content": "<p>Thanks</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 578591,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-07-17T22:24:05.507000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 575597,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-07-15T17:48:00.263000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 574785,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-07-14T13:38:20.803000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 573870,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-07-12T21:52:36.313000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 572513,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-07-11T02:44:48.680000",
      "content": "",
      "votes": 1,
      "replies": []
    },
    {
      "id": 572289,
      "author_name": "",
      "author_url": "",
      "post_date": "2019-07-10T18:16:52.700000",
      "content": "",
      "votes": 1,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "571415": "# Basic GAN\n## Real Images\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F3faca66b6ada321ba1833658b2913b44%2Fimg1.jpg?generation=1602507212344417&alt=media)\n## Fake Images\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8744346a500b57317b79e2b6887b43d2%2Fimg2.jpg?generation=1602507224756646&alt=media)\n## Summary\nAfter a GAN is trained, we can input a random vector (seed) of length 100 into a Generator and we get a dog image out. But how can we teach a Generator to output realistic dog images? We repeatedly have it output a dog image and input that into a Discriminator. The Discriminator will output the probability of that image being real, `Pr(Real)`. We would like `Pr(Real)=1` and here's where the math comes in.\n  \nThe Generator's image is completely determined by it weights. Weights are numbers, call them `x`. When the Generator makes an image, the Discriminator gives it a score, `Pr(Real)`. Call that `y`. We want `y=1` but we have `y &lt; 1`. From calculus, we know how to increase `y` by changing `x` (the **generator weights**). Move `x` in the direction of the derivative `dy/dx`, so `x_new = x_old + lr * dy/dx` (where lr = learning rate).\n\nThe Discriminator wants `Pr(Real)=0` for fake and `Pr(Real)=1` for real, so the Discriminator changes it's weights (the **discriminator weights**) in the direction that will accomplish this.\n\n# Feature Matching\nThe Generator and Discriminator repeatedly update their weights and we hope that the Generator starts to draw realistic dogs. We can improve GANs by changing the architecture of the Generator and/or changing the \"score\" (the `y` from above) that the generator uses to update its weights. A [basic GAN][1] doesn't actually use `y`, instead it minimizes `error = -log(y)` by updating its weights as `x_new = x_old + lr * Gradient(error)` which is binary cross entropy (or negative log likelihood).\n\n[DCGAN][2] improves GAN with a better architecture, namely deep convolutional net. [RaGAN][5] improves GAN with a better error function. [LSGAN][4] improves with a better error function. [Feature Matching][6] also uses a better error function.\n\nFeature Matching works by defining `error = ||layer_K_fake - layer_K_real||^2`. Note that if we use `k=4` then we have a basic GAN. If we use `k=3` then we are comparing layer 3 activations of what real dogs look like versus layer 3 activations of fake dogs. See Ian Goodfellow's paper [here][6].\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8f10b58c8e93c3f4aa098b166ea3f411%2Fimg3.jpg?generation=1602507244576959&alt=media)\n# Conditional GAN\nA [CGAN][7] (conditional GAN) uses image class information. For example, when we give our Generator a random vector Z, we can also give it the name of a breed, C. Then the Discriminator will evaluate how well the Generator draws a dog of breed C. And we use that error to update the Generator's weights (which includes new weights to accommodate the input C).\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F486f86b5b5feb3dadbe3e04f1bab2f09%2Fimg4.jpg?generation=1602507260984478&alt=media)\n# CGAN with Feature Matching\nWe can combine these two ideas as Ian Goodfellow does in his paper [here][6].\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2F8b2360ef699290fbb27a7aed333ff95f%2Fimg5.jpg?generation=1602507277962407&alt=media)\n# Memorization GAN\nWhat happens when we build a CGAN with Feature Matching and increase the number of classes to equal the number of images? i.e. we have 20000 classes with every dog in its own class. And what if we match features not on layer 4 nor 3 nor 2 nor 1 but on `layer 0`, the pixel layer? Then you get a Memorization GAN! Of course memorizing images and regurgitating them isn't a valid solution but it makes you wonder at what point does a CGAN with Feature Matching turn invalid? \n  \n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F1723677%2Fd1badfa0f343f0e2cf988f20beb0029e%2Fimg6.jpg?generation=1602507292297882&alt=media)\n\nA Memorization GAN is posted [here][8]. The Discriminator learns the training images ahead of time but it could learn the images while the Generator learns like a typical CGAN with Feature Matching training.\n\nIf a Memorization GAN is invalid, can we start with a Memorization GAN, then drop the class labels and drop feature matching, and continue training it as a usual basic GAN? If so, how many epochs of additional training make it valid?\n\n[1]: https://arxiv.org/abs/1406.2661\n[2]: https://arxiv.org/abs/1511.06434\n[4]: https://arxiv.org/abs/1611.04076\n[5]: https://arxiv.org/abs/1807.00734\n[6]: https://arxiv.org/abs/1606.03498\n[7]: https://arxiv.org/abs/1411.1784\n[8]: https://www.kaggle.com/cdeotte/dog-memorizer-gan",
    "571438": "Good Explanation. Simple! Elegant! Your contributions in this competitions are unparalleled learning a lot of things from you. keep it up 👍 \n\nRemind me of a famous quote\n![](http://i.imgur.com/uqxffAz.jpg)",
    "591446": "Thanks again for your amazing explanation Chris.",
    "574584": "Thanks Chris. Really appreciate your work. Like always your explanations are clear and amazing.",
    "592613": "Really great explanation. Thanks for helping me wrap my mind around this. 👍 ",
    "591373": "That's an amazing explanation.. It's really amazing &amp; helpful. Thank you.",
    "588562": "wow. Nicely explained👍 \ncheck this article about GAN models.\n https://blogs.nvidia.com/blog/2019/03/18/gaugan-photorealistic-landscapes-nvidia-research/",
    "582920": "Nice post. Thanks for explaining it in simple form.",
    "581292": "great piece of info.. got to know about memorization GAN from this.",
    "580986": "Awesome introduction to the idea of memorization GAN and how to get there from a basic GAN.\nThanks for sharing this explanation.  ",
    "580242": "this is very good explanation. \nI am thankful to you",
    "578688": "That's an amazing explanation.. It's really amazing. Thank you.",
    "576837": "Fantastic! Thanks for posting this, @cdeotte.",
    "574895": "Thanks. good refresher.",
    "573345": "It was a nice one from you, Chris",
    "573122": "Super useful explanation! ",
    "572483": "nice",
    "572253": "Amazing like always! I will definitely spend time on CGAN. Thank you\n",
    "572249": "Good Explanation",
    "571841": "Good Explanation",
    "571771": "Thank you for this write-up, it gives a lot of insights. ",
    "571666": "Thank you for the explanation. I will study a lot.",
    "571488": "Thanks a lot @cdeotte for this! Learning a lot from you",
    "2498631": "I'm new to this GAN and stuff, thanks for the amazing explanation!",
    "1084606": "Amazing Explanation, Thanks I needed this.",
    "573362": "",
    "593327": "nice explanation, thanks!",
    "581142": "Thank you for sharing!",
    "579959": "great explanation thanks!",
    "579072": "Thanks",
    "578591": "thanks for sharing thisexplanation.",
    "575597": "Thanks\n",
    "574785": "Thanks a lot, nice explanation.",
    "573870": "Thanks! Very useful.",
    "572513": "Thanks, I learned a lot :)",
    "572289": "Thanks!"
  }
}