<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://vasumenon.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://vasumenon.com/" rel="alternate" type="text/html" /><updated>2026-10-18T12:14:29+00:00</updated><id>https://vasumenon.com/feed.xml</id><title type="html">Vasu Menon</title><subtitle>Vasu Menon&apos;s personal site</subtitle><author><name>Vasu Menon</name></author><entry><title type="html">Outward Reality</title><link href="https://vasumenon.com/2026/04/21/reality.html" rel="alternate" type="text/html" title="Outward Reality" /><published>2026-04-21T00:00:00+00:00</published><updated>2026-04-21T00:00:00+00:00</updated><id>https://vasumenon.com/2026/04/21/reality</id><content type="html" xml:base="https://vasumenon.com/2026/04/21/reality.html"><![CDATA[<figure style="max-width:960px;margin-left:auto;margin-right:auto;">
  <img src="/assets/images/paintings/Dali-GiraffeAvignon.jpg" alt="Giraffe Avignon by Salvador Dalí, 1975" title="Giraffe Avignon by Salvador Dalí, 1975" loading="lazy" />
  <figcaption>Giraffe Avignon by Salvador Dalí, 1975, private collection</figcaption>
</figure>

<p>Last night I dreamed I was standing among a family of burning giraffes. I felt the heat piercing my skin, the stench of burning flesh in my nostrils, and the fumes frying my eyes so much that I had to squint just to see. I was completely convinced. It was only upon waking that I realized how wrong my sense of <em>reality</em> had been.</p>

<p>This is an essential problem: our reality is never observed indubitably, it is <em>perceived</em>.</p>

<p>Reality as we know it is not fully real. But it is real enough (for now).</p>

<p>Consider how few tools we are given. We have exactly five senses, and no more. A platypus, on the other hand, can detect the electric fields generated by muscle contractions in its prey, a sense called electroreception. Imagine what we might do with it. The following example may help illustrate this:</p>

<p>Suppose I visit a friend who asks whether I like his new haircut. I say yes, it looks great. With electroreception, he reads the deep contractions in my muscles and knows immediately that I am lying. His haircut is, in fact, ugly, and now he knows it. In this way, we have removed dishonesty from human interaction. Court testimony, negotiation, things that ought to be truthful, can no longer be done “asynchronously”. A written paper can lie in ways a living voice cannot. Perhaps then scientific peer review becomes a live event, some sort of academic sermon that has to be performed before publication.</p>

<p>However, we were not given the gift of electroreception, but our lack of senses may be what drove us to build something remarkable in its place.</p>

<p>We invented mathematics, not just as a counting tool, but as a language for reasoning about the invisible. We built instruments that extend our perception with it: microscopes, telescopes, sensors that detect what no eye could see unaided. We developed statistics to tell us how much to trust what we observe, and the scientific method to ask whether our hypotheses adhere to reality. These are like prosthetics for us limited creatures, but so far, they have worked extraordinarily well. No other species we know of has come close to this kind of understanding.</p>

<p>But yet, these tools only provide mere approximations (extraordinarily good ones, but still approximations). Our models of the universe fit the data we have gathered, but not the universe itself.</p>

<p>This brings us back to the giraffes. How confident can we be, standing in what we call the waking world, that we are not still dreaming? We are doing the best we can with what we have. But who is to say it is enough?</p>]]></content><author><name>Vasu Menon</name></author><summary type="html"><![CDATA[How we don't know what's real.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://vasumenon.com/assets/images/art/Dali-GiraffeAvignon.jpg" /><media:content medium="image" url="https://vasumenon.com/assets/images/art/Dali-GiraffeAvignon.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">A 1.58-Dimensional Object</title><link href="https://vasumenon.com/2026/04/17/fractal-dimensions.html" rel="alternate" type="text/html" title="A 1.58-Dimensional Object" /><published>2026-04-17T00:00:00+00:00</published><updated>2026-04-17T00:00:00+00:00</updated><id>https://vasumenon.com/2026/04/17/fractal-dimensions</id><content type="html" xml:base="https://vasumenon.com/2026/04/17/fractal-dimensions.html"><![CDATA[<p>My favorite Numberphile video, <a href="https://www.youtube.com/watch?v=FnRhnZbDprE&amp;t=74s"><em>A 1.58-Dimensional Object</em></a>, explores what I think is one of the coolest ideas in mathematics: that the dimension of an object doesn’t have to be an integer. A line is 1-dimension, a square is 2D, and a cube is 3D. But consider the <a href="https://en.wikipedia.org/wiki/Sierpi%C5%84ski_triangle">Sierpiński triangle</a>. It looks like a 2D shape, but it’s punctured with so many holes (seemingly an infinite amount). Does a shape like this deserve to be called 2-dimensional? It turns out that in fact, its dimension is xxMATHPROTECTxx0xx.</p>

<p>This post is my attempt to unpack this idea.</p>

<h2 id="what-does-dimension-mean">What Does Dimension Mean?</h2>

<p>A common intuition is that dimension indicates how many numbers is needed to specify a point. For example, a point on a line needs 1, a point in the plane needs 2, and a point in (our) space needs 3. This is the <a href="https://en.wikipedia.org/wiki/Lebesgue_covering_dimension">topological dimension</a>.</p>

<p>But there’s another way to think about it, based on <em>scaling</em>. If you double the side length of a line segment, you get xxMATHPROTECTxx1xx copies. Doubling the side of a square gives you xxMATHPROTECTxx2xx copies, and doubling the side of a cube yields xxMATHPROTECTxx3xx copies.</p>

<p>Clearly, there’s a pattern. If scaling by a factor xxMATHPROTECTxx4xx gives xxMATHPROTECTxx5xx self-similar copies, then:</p>

<p>xxMATHPROTECTxx6xx</p>

<p>For ordinary shapes this gives exactly the integer dimension we expect, but for self-similar fractals, xxMATHPROTECTxx7xx does not have to be an integer.</p>

<h2 id="the-hausdorff-dimension">The Hausdorff Dimension</h2>

<p>This scaling argument is made rigorous by the <a href="https://en.wikipedia.org/wiki/Hausdorff_dimension">Hausdorff dimension</a>, introduced by Felix Hausdorff in 1918.</p>

<p>Instead of scaling up (like doubling the side lengths of a square), we can instead think about scaling <em>down</em>. Suppose we take a shape and break it into xxMATHPROTECTxx8xx smaller copies of itself, each scaled down by a factor xxMATHPROTECTxx9xx. In 1D, lengths scale by xxMATHPROTECTxx10xx. In 2D, areas scale by xxMATHPROTECTxx11xx. In 3D, volumes scale by xxMATHPROTECTxx12xx. So in general, for a xxMATHPROTECTxx13xx-dimensional object, “size” scales by xxMATHPROTECTxx14xx. That means each small copy has xxMATHPROTECTxx15xx times the size of the original. If we say the original shape had size xxMATHPROTECTxx16xx, then since there are xxMATHPROTECTxx17xx smaller copies making up the whole, we must have:</p>

<p>xxMATHPROTECTxx18xx</p>

<p>Solving for xxMATHPROTECTxx19xx get us:</p>

<p>xxMATHPROTECTxx20xx</p>

<h2 id="sierpinski-triangle">The Sierpiński Triangle: xxMATHPROTECTxx21xx</h2>

<p>Take an equilateral triangle. Divide it into four congruent smaller triangles and remove the central one. Repeat forever on each remaining triangle.</p>

<figure style="max-width:480px;margin-left:auto;margin-right:auto;">
  <img src="https://upload.wikimedia.org/wikipedia/commons/4/45/Sierpinski_triangle.svg" alt="Sierpiński triangle" title="Sierpiński triangle" loading="lazy" />
  <figcaption>The Sierpiński triangle.</figcaption>
</figure>

<p>At each step, each triangle becomes xxMATHPROTECTxx22xx copies, each scaled by xxMATHPROTECTxx23xx. Plugging in:</p>

<p>xxMATHPROTECTxx24xx</p>

<p>It’s more than a curve but less than a surface. Its area must be zero, since at each iteration keeps only xxMATHPROTECTxx25xx of what remained, so after xxMATHPROTECTxx26xx steps the area is xxMATHPROTECTxx27xx, but it’s not 1-dimensional either. The number xxMATHPROTECTxx28xx captures exactly how much of the plane it occupies.</p>

<p>We can also construct this shape via a game:</p>
<ol>
  <li>Pick the three vertices of a triangle.</li>
  <li>Start at any point inside.</li>
  <li>Pick a random vertex, move halfway toward it, plot the point.</li>
  <li>Repeat forever.</li>
</ol>

<p>Despite the randomness, this procedure <em>converges</em> to the Sierpiński triangle.</p>

<h2 id="imaginary-cubes">Imaginary Cubes</h2>

<p>This is the part of the Numberphile video that blew my mind.</p>

<p>The <strong>Sierpiński tetrahedron</strong> is the 3D analogue of the Sierpiński triangle: shrink a tetrahedron to half size, make 4 copies, connect them at their corners, and repeat. Its Hausdorff dimension is:</p>

<p>xxMATHPROTECTxx29xx</p>

<p>This is weird. The shape is clearly a 3D construction, yet it has the same dimension as a flat surface? It gets weirder.</p>

<p>When you project the Sierpiński tetrahedron onto a plane perpendicular to one of its axes, its shadow exactly fills a square. Every point in the square is covered, with no gaps and no overlaps. A fully 3D hollow fractal casting a completely solid 2D shadow.</p>

<p>We’ll call this an <a href="https://www.i.h.kyoto-u.ac.jp/users/tsuiki/icube/index-e.html">imaginary cube</a>.</p>

<p>Here’s an interactive demo of a Sierpiński tetrahedron<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>. Drag it around and see if you can find angle where it looks like a full 2D square.</p>

<div id="fractal-explorer" style="margin:2rem auto;border-radius:12px;overflow:hidden;border:1px solid var(--border-secondary);background:var(--bg-secondary);max-width:480px;">
  <canvas id="fe-c" width="480" height="480" style="width:100%;cursor:grab;display:block;"></canvas>
  <p style="margin:0;padding:9px 16px;font-size:10.5px;letter-spacing:0.05em;color:var(--text-tertiary);font-family:system-ui,sans-serif;border-top:1px solid var(--border-tertiary);">Sierpiński tetrahedron &nbsp;·&nbsp; <em>d</em> = log 4 / log 2 = 2 &nbsp;·&nbsp; drag to rotate</p>
</div>

<script>
(function () {
  const cv = document.getElementById('fe-c');
  const ctx = cv.getContext('2d');
  const W = cv.width, H = cv.height;

  // rotX=0, rotY=0 → identity → view along z-axis
  // Tetrahedron vertices project to the four corners of a square: the imaginary cube view
  let rotX = 0, rotY = 0, dragging = false, lx = 0, ly = 0;
  let autoSpin = false;
  let idleTimer = setTimeout(() => { autoSpin = true; }, 5000);

  // ── Theme colors: read CSS variables, re-read on data-theme toggle ────────
  let bgCol, colR, colG, colB;
  function readTheme() {
    const cs = getComputedStyle(document.documentElement);
    bgCol = cs.getPropertyValue('--bg-secondary').trim() || '#f5f5f5';
    const ac = cs.getPropertyValue('--accent-primary').trim() || '#163313';
    colR = parseInt(ac.slice(1, 3), 16);
    colG = parseInt(ac.slice(3, 5), 16);
    colB = parseInt(ac.slice(5, 7), 16);
  }
  readTheme();
  new MutationObserver(readTheme).observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });

  // ── IFS: Sierpiński tetrahedron ───────────────────────────────────────────
  // Vertices = alternating corners of a cube, normalized to unit sphere
  const V = [[1,1,1],[1,-1,-1],[-1,1,-1],[-1,-1,1]].map(v => {
    const s = Math.sqrt(3); return [v[0]/s, v[1]/s, v[2]/s];
  });
  const N = 40000;
  const pts = new Float32Array(N * 3);
  { let px=0, py=0, pz=0;
    for (let i=0, sk=300; i<N+sk; i++) {
      const v = V[Math.random()*4|0];
      px=(px+v[0])*.5; py=(py+v[1])*.5; pz=(pz+v[2])*.5;
      if (i>=sk) { pts[(i-sk)*3]=px; pts[(i-sk)*3+1]=py; pts[(i-sk)*3+2]=pz; }
    }
  }

  // Pre-allocated projection arrays
  const PRX = new Float32Array(N), PRY = new Float32Array(N), PRZ = new Float32Array(N);
  const BUCKETS = 12;
  const bkt = Array.from({ length: BUCKETS }, () => []);

  // ── Draw ──────────────────────────────────────────────────────────────────
  function draw() {
    ctx.fillStyle = bgCol;
    ctx.fillRect(0, 0, W, H);

    const cx2=Math.cos(rotX), sx2=Math.sin(rotX), cy2=Math.cos(rotY), sy2=Math.sin(rotY);
    // Rotation matrix Ry·Rx, stored row-major
    const M = [cy2, 0, sy2,  sx2*sy2, cx2, -sx2*cy2,  -cx2*sy2, sx2, cx2*cy2];
    const sc = W * 0.72, cX = W/2, cY = H/2;

    let zlo = Infinity, zhi = -Infinity;
    for (let i=0; i<N; i++) {
      const px=pts[i*3], py=pts[i*3+1], pz=pts[i*3+2];
      PRX[i] = M[0]*px + M[1]*py + M[2]*pz;
      PRY[i] = M[3]*px + M[4]*py + M[5]*pz;
      PRZ[i] = M[6]*px + M[7]*py + M[8]*pz;
      if (PRZ[i] < zlo) zlo = PRZ[i];
      if (PRZ[i] > zhi) zhi = PRZ[i];
    }
    const zr = zhi - zlo + 1e-4;

    // Bucket points by depth (painter's order: far first, near last)
    for (let b=0; b<BUCKETS; b++) bkt[b].length = 0;
    for (let i=0; i<N; i++) {
      bkt[Math.min(BUCKETS-1, (PRZ[i]-zlo)/zr * BUCKETS | 0)].push(i);
    }
    for (let b=0; b<BUCKETS; b++) {
      const a = (0.04 + (b+0.5)/BUCKETS * 0.74).toFixed(3);
      ctx.fillStyle = `rgba(${colR},${colG},${colB},${a})`;
      for (const i of bkt[b]) ctx.fillRect(cX+PRX[i]*sc-.7, cY-PRY[i]*sc-.7, 1.4, 1.4);
    }
  }

  // ── Loop ──────────────────────────────────────────────────────────────────
  (function loop() {
    if (autoSpin && !dragging) rotY += 0.004;
    draw();
    requestAnimationFrame(loop);
  })();

  // ── Interaction ───────────────────────────────────────────────────────────
  const ex = e => e.touches ? e.touches[0].clientX : e.clientX;
  const ey = e => e.touches ? e.touches[0].clientY : e.clientY;

  cv.addEventListener('mousedown', e => {
    dragging = true; cv.style.cursor = 'grabbing'; lx = ex(e); ly = ey(e);
    autoSpin = false; clearTimeout(idleTimer);
  });
  cv.addEventListener('touchstart', e => {
    e.preventDefault(); dragging = true; lx = ex(e); ly = ey(e);
    autoSpin = false; clearTimeout(idleTimer);
  }, { passive: false });
  window.addEventListener('mousemove', e => {
    if (!dragging) return;
    rotY += (ex(e)-lx)*.012; rotX += (ey(e)-ly)*.012;
    rotX = Math.max(-1.5, Math.min(1.5, rotX)); lx = ex(e); ly = ey(e);
  });
  window.addEventListener('touchmove', e => {
    if (!dragging) return; e.preventDefault();
    rotY += (ex(e)-lx)*.012; rotX += (ey(e)-ly)*.012;
    rotX = Math.max(-1.5, Math.min(1.5, rotX)); lx = ex(e); ly = ey(e);
  }, { passive: false });
  window.addEventListener('mouseup',  () => { dragging = false; cv.style.cursor = 'grab'; idleTimer = setTimeout(()=>{ autoSpin = true; }, 4000); });
  window.addEventListener('touchend', () => { dragging = false; idleTimer = setTimeout(()=>{ autoSpin = true; }, 4000); });
})();
</script>

<p>This the kind of beautiful mathematics I can’t stop thinking about.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>Special thanks to Claude Sonnet 4.6 for graciously generating the code for this demo. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Vasu Menon</name></author><summary type="html"><![CDATA[Exploring fractal dimensions from my favorite Numberphile video.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://vasumenon.com/assets/images/art/Sierpinski_triangle.png" /><media:content medium="image" url="https://vasumenon.com/assets/images/art/Sierpinski_triangle.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Arguments</title><link href="https://vasumenon.com/2026/01/11/arguments.html" rel="alternate" type="text/html" title="Arguments" /><published>2026-01-11T00:00:00+00:00</published><updated>2026-01-11T00:00:00+00:00</updated><id>https://vasumenon.com/2026/01/11/arguments</id><content type="html" xml:base="https://vasumenon.com/2026/01/11/arguments.html"><![CDATA[<figure style="max-width:960px;margin-left:auto;margin-right:auto;">
  <img src="/assets/images/paintings/Argument-Leonora Carrington-1978-McNayArt.jpg" alt="Argument by Leonora Carrington, 1978" title="Argument by Leonora Carrington, 1978" loading="lazy" />
  <figcaption>Argument by Leonora Carrington, 1978, McNay Art Museum</figcaption>
</figure>

<h2 id="change-your-mind">Change Your Mind</h2>

<p>I’m a firm believer in changing your mind. When arguing, I find that a lot of people have their egos attached to the argument. Winning an argument raises their egos and losing drops it. In cases like this, arguments end up being a fight between humans. I find that this approach is flawed. Instead, arguments should be a battle between ideas, with the humans administering the fight.</p>

<p>If, while arguing, one finds that the opposing idea seems to be winning, it’s in their best interest to change their mind, since, upon doing so, means that they have now taken a more “winning” position. Aligning with this new position means that they have a higher chance in winning subsequent arguments, so long as the original “winning” points are still kept. Ideally, if everyone follows this heuristic, then all humans will then converge on the “ultimate” idea, and they can then be sure that this idea is better than all other ones (until an even better idea is formed); however, in practice, this is likely not the case. Oftentimes, winning is not always aligned with truth, and arguments aren’t good tests for truthful ideas. Ideas can win because they appeal to rhetoric, exploit biases, are more simple, etc. Also, it’s very possible that the audience simply lacks background knowledge. Here, arguments win just because they exploit the fact that humans <em>perceive</em> victory, instead of impartially judging of an argument’s evidential strength. In a way, <a href="https://en.wikipedia.org/wiki/Goodhart%27s_law">Goodhart’s Law</a> is a great application here: when winning an argument becomes the target, truth ceases to be the measure. In general, humans aren’t perfect, and argument environments aren’t perfect<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>. Not everyone has equal information, and they don’t always argue in good faith or are exposes to the same global counterarguments. “Convergence” is thus oftentimes local, which is why I think super smart communities of people can still disagree for long periods. Also, some ideas are super hard to argue in general, such as ethics, metaphysics. Humans just don’t have the tools to reliably obtain indubitable evidence in these disciplines.</p>

<p>Nonetheless, I do believe that generally following this heuristic would increase the probability of humans moving toward more robust beliefs over time.</p>

<h2 id="updating-on-bad-arguments">Updating on Bad Arguments</h2>

<p>I would also like to reject an interesting epistemological argument I saw recently about <a href="https://guive.substack.com/p/updating-on-bad-arguments">updating on bad arguments</a>. It argues that although intuitively it may make sense that hearing a bad argument for some idea should not change your degree of belief in the view, it actually turns out that hearing a bad argument when you expected to hear a good one should provide evidence against the view. It uses a probabilistic argument as follows:</p>

<h3 id="the-argument">The Argument:</h3>

<p>Let xxMATHPROTECTxx0xx be the hypothesis my friend is arguing for, and suppose my prior xxMATHPROTECTxx1xx. Let xxMATHPROTECTxx2xx denote the event that my friend provides good evidence for xxMATHPROTECTxx3xx. The <a href="https://en.wikipedia.org/wiki/Law_of_total_probability">law of total probability</a> suggests that</p>

<p>xxMATHPROTECTxx4xx</p>

<p>If I believed in advance that xxMATHPROTECTxx5xx, then since the prior is a weighted average of the two conditional probabilities, it follows that</p>

<p>xxMATHPROTECTxx6xx</p>

<p>In Bayesian updating, the <a href="https://en.wikipedia.org/wiki/Law_of_total_expectation">law of total expectation</a> implies that the prior is equal to the expectation of the posterior, which implies that observing xxMATHPROTECTxx7xx must push the posterior below the prior if observing xxMATHPROTECTxx8xx would have pushed it above, and thus, my friend’s failure in providing a good argument provides evidence against xxMATHPROTECTxx9xx.</p>

<h3 id="counterargument">Counterargument:</h3>

<p>However, I disagree with this idea. I think that a bad argument being provided should be considered as no observation rather than as negative evidence. The above argument assumes that xxMATHPROTECTxx10xx, but I claim that instead, we should consider that xxMATHPROTECTxx11xx. If that holds, then we have that xxMATHPROTECTxx12xx and thus, no update is needed. My friend providing a bad argument should result in an update to my own belief about my friend’s reliability on this particular topic rather than a negative update on the idea itself.</p>

<h2 id="arguments-are-hard">Arguments are Hard</h2>
<p>Arguments are very noisy systems. Humans are also very noisy. Still, I do think that arguments, even when treated as imperfect, are still one of our best tools for refining our beliefs, but the important thing is that people do refine their beliefs. We should always consider the noisiness in such a system and the reliability of the arguer among other things, but we should <em>always</em> be willing to revise our positions when the ideas themselves (not the recitation of it) demand it. We should try to detach our egos and identities from the beliefs we believe.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>This post is itself an imperfect argument and should be treated accordingly. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Vasu Menon</name></author><summary type="html"><![CDATA[My thoughts on arguments.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://vasumenon.com/assets/images/paintings/Argument-Leonora%20Carrington-1978-McNayArt.jpg" /><media:content medium="image" url="https://vasumenon.com/assets/images/paintings/Argument-Leonora%20Carrington-1978-McNayArt.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The Three Gods Riddle</title><link href="https://vasumenon.com/2025/12/30/three-gods-riddle.html" rel="alternate" type="text/html" title="The Three Gods Riddle" /><published>2025-12-30T00:00:00+00:00</published><updated>2025-12-30T00:00:00+00:00</updated><id>https://vasumenon.com/2025/12/30/three-gods-riddle</id><content type="html" xml:base="https://vasumenon.com/2025/12/30/three-gods-riddle.html"><![CDATA[<figure style="max-width:960px;margin-left:auto;margin-right:auto;">
  <img src="/assets/images/paintings/ThreeStudiesforFiguresattheBaseofaCrucifixion_FrancisBacon.jpg" alt="Three Studies for Figures at the Base of a Crucifixion by Francis Bacon, 1944" title="Three Studies for Figures at the Base of a Crucifixion by Francis Bacon, 1944" loading="lazy" />
  <figcaption>Three Studies for Figures at the Base of a Crucifixion by Francis Bacon, 1944, Tate</figcaption>
</figure>

<p>I will aim to explain the solution to the <a href="https://en.wikipedia.org/wiki/The_Hardest_Logic_Puzzle_Ever">Three Gods Riddle</a>.</p>

<p>We have 3 Gods: T, F, and R.<br />
T always tells the truth. F always lies. R provides a random answer each time.<br />
Each of these Gods will only give you one response, either “Ozo” or “Ulu”, signifying either Yes or No. Unfortunately, we do not know which is which. We are allowed to ask 3 questions total to any of the Gods. How can we deduce which God is which?</p>

<p>The key to this problem is asking the Gods a conditional statement. Consider the following question:</p>

<blockquote>
  <p>If I asked whether 1+1=2, would you answer Ozo?</p>
</blockquote>

<p>Suppose Ozo = Yes. If T was asked whether xxMATHPROTECTxx0xx, it knows it would respond with the affirmative, Ozo. When asked whether or not it would answer Ozo to the question, his final response is Ozo. If F was asked whether xxMATHPROTECTxx1xx, it knows it would respond with the negative, Ulu. When asked whether or not it would answer Ozo to the question, his final response would be the affirmative, since it is a liar. Thus, both T and F would respond with Ozo.</p>

<p>Suppose Ozo = No. If T was asked whether xxMATHPROTECTxx2xx, it knows it would respond with the affirmative, Ulu. When asked whether or not it would answer Ozo to the question, it would respond with the negative, Ozo.<br />
If F was asked whether xxMATHPROTECTxx3xx, it knows it would respond with the negative, Ozo. When asked whether or not it would answer Ozo to the question, it would respond with the negative, Ozo.</p>

<p>Thus, regardless of what Ozo means, when asked the carefully constructed question above, both T and F would respond with Ozo.</p>

<p>To further see the power of such a question, consider another question:</p>

<blockquote>
  <p>If I asked whether 1+1=3, would you answer Ozo?</p>
</blockquote>

<p>It can be shown that regardless of what Ozo and Ulu mean, both T and F would respond with Ulu. In this way, we can deduce the truth value of the antecedent of our conditional, xxMATHPROTECTxx4xx or xxMATHPROTECTxx5xx, based on the response of either T or F.</p>

<p><strong>If they respond with Ozo, then we know the antecedent is true. If they respond with Ulu, the antecedent is false.</strong></p>

<!-- % If I asked whether 1+1=3, would you answer Ozo?

--------- Ozo = True ---------
T: Well, 1+1=3 is false, so I would answer with no = Ulu to that question.
So would I answer with Ozo? No , so  Ulu.

F: Well, 1+1=3 is false, so I would answer with yes = Ozo to that question.
So would I answer with Ozo? I mean yes I would, but I'm going to lie, so No, so Ulu

--------- Ozo = False ---------
T: Well, 1+1=3 is false, so I would answer with no = Ozo to that question.
So would I answer with Ozo? Yes , so  Ulu.

F: Well, 1+1=3 is false, so I would answer with yes = Ozo to that question. So would I answer with Ozo? I mean no, I wouldn't, but I'm going to lie, so Yes, so Ulu. -->

<p>Now, we need to utilize this property to our advantage.</p>

<p>First, ask the alien in the middle the following question:</p>

<blockquote>
  <p>If I asked you whether the alien on the left is R, would you answer Ozo?</p>
</blockquote>

<p>If they respond with Ozo, we have two scenarios: either we have asked this question to R, or we asked it to T/F.<br />
Assume this question was asked to either T or F. Due to our powerful property, we can then deduce the truth value of our antecedent: whether the alien on the left is R. Since they responded with Ozo, then the alien to the left must be R.</p>

<p>Assume this question was asked to R. His response does not matter, but under this assumption, the alien in the middle is R. Under both exhaustive assumptions, we can deduce that the alien to the right is not R.</p>

<p>Similarly, if they respond with Ulu, we again have the two scenarios: either we have asked this question to R, or we asked it to T/F.<br />
Assume this question was asked to either T or F. We can then deduce the truth value of our antecedent: whether the alien on the left is R. Since they responded with Ulu, then the alien to the left is not R.<br />
Assume this question was asked to R. His response does not matter, but under this assumption, the alien in the middle is R. Under both exhaustive assumptions, we can deduce that the alien to the left is not R.</p>

<p>Thus, the answer to this first question will reveal to us a God that is not R, a God that is either T or F. Then we can ask another one of our carefully constructed conditionals to this God to deduce the truth value of its antecedent.</p>

<p>For our second question, we will ask the following question to that God:</p>

<blockquote>
  <p>If I asked “are you F?” would you answer Ozo?</p>
</blockquote>

<p>If they answer Ulu, then we know it is T that responded. If they answer Ozo, then we know it is F that responded.</p>

<p>For our third and final question, we will ask the same God the following:</p>

<blockquote>
  <p>If I asked “is the center alien R?” would you answer Ozo?</p>
</blockquote>

<p>If they answer Ulu, then we know that the center alien is not R. If they answer Ozo, then we know that the center alien is R.</p>

<p>We can deduce one god is either T or F (from Q1). We can identify which of T or F it is (from Q2). We can determine if the middle god is R or not (Q3). Therefore, we can deduce all roles by elimination.</p>]]></content><author><name>Vasu Menon</name></author><summary type="html"><![CDATA[Explaining the solution to the Three Gods Riddle.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://vasumenon.com/assets/images/paintings/ThreeStudiesforFiguresattheBaseofaCrucifixion_FrancisBacon.jpg" /><media:content medium="image" url="https://vasumenon.com/assets/images/paintings/ThreeStudiesforFiguresattheBaseofaCrucifixion_FrancisBacon.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Hypergraph Theory</title><link href="https://vasumenon.com/2025/12/23/hypergraphs.html" rel="alternate" type="text/html" title="Hypergraph Theory" /><published>2025-12-23T00:00:00+00:00</published><updated>2025-12-23T00:00:00+00:00</updated><id>https://vasumenon.com/2025/12/23/hypergraphs</id><content type="html" xml:base="https://vasumenon.com/2025/12/23/hypergraphs.html"><![CDATA[<p>During my semester in Budapest, I took <em>Combinatorics 2</em>, which the syllabus labeled as <em>Combinatorics on Set Systems</em>, but which in reality was a course on <em>hypergraph theory</em>. The course was taught by a sweet man named <a href="https://en.wikipedia.org/wiki/Andr%C3%A1s_Gy%C3%A1rf%C3%A1s">András Gyárfás</a>, whom I later learned was one of the most frequent collaborators of <a href="https://en.wikipedia.org/wiki/Paul_Erd%C5%91s">Paul Erdős</a>. It seemed to me like one of those classes that not many people take (even though they easily could), yet it contains some of the most influential and essential pieces of mathematics.</p>

<p>I aim to provide a brief introduction of this topic here and hope to build to the Erdős–Ko–Rado Theorem.</p>

<h2 id="brief-introduction">Brief Introduction</h2>

<p>In graph theory, we have a set of vertices and a set of edges with each edge “connecting” two vertices. Formally, we say that a graph xxMATHPROTECTxx0xx, where xxMATHPROTECTxx1xx is a set of vertices and xxMATHPROTECTxx2xx is a set of edges. In graph theory, edges only involve two vertices.</p>

<p>A hypergraph is a basic generalization of graphs. Each edge can “connect” any number of vertices. Formally, a hypergraph xxMATHPROTECTxx3xx where xxMATHPROTECTxx4xx is a set of vertices and xxMATHPROTECTxx5xx. Drawing hypergraphs quickly becomes extremely difficult, so it’s worth thinking of them as “set systems” instead of visualizable graphs (hence the name “Combinatorics on Set Systems”).</p>

<p>We say a hypergraph is xxMATHPROTECTxx6xx-uniform if every edge is connected to xxMATHPROTECTxx7xx vertices. In other words, xxMATHPROTECTxx8xx. Here, this can also be thought of as collections of xxMATHPROTECTxx9xx-element subsets. This also allows us to characterize graphs as just xxMATHPROTECTxx10xx-uniform hypergraphs. A canonical example of a xxMATHPROTECTxx11xx-uniform hypergraph is the <a href="https://en.wikipedia.org/wiki/Fano_plane">Fano plane</a>.</p>

<p>We can then define a family xxMATHPROTECTxx12xx is <em>intersecting</em> if:</p>

<p>xxMATHPROTECTxx13xx</p>

<p>Note that xxMATHPROTECTxx14xx denotes the set xxMATHPROTECTxx15xx.</p>

<p>If you imagine a graph where vertices represent xxMATHPROTECTxx16xx sized sets and edges represent “disjointness”, then this intersecting idea represents independent sets. If edges represent disjointness, then an “independent set” (vertices that share no edges) implies that no two sets are disjoint, which means that they all intersect. This is often called a <a href="https://en.wikipedia.org/wiki/Kneser_graph"><em>Kneser Graph</em></a>.</p>

<p>Now, fix an element xxMATHPROTECTxx17xx. If we let xxMATHPROTECTxx18xx, then we have that every pair here intersects, and xxMATHPROTECTxx19xx. This is called a <em>star</em>.</p>

<p>It turns out, this is the largest possible size, and this is precisely the Erdős–Ko–Rado Theorem (1961).</p>

<h2 id="erdőskorado-theorem-1961">Erdős–Ko–Rado Theorem (1961)</h2>
<p>The theorem states: 
If xxMATHPROTECTxx20xx, then any intersecting family xxMATHPROTECTxx21xx satisfies</p>

<p>xxMATHPROTECTxx22xx</p>

<p>Moreover, if xxMATHPROTECTxx23xx, equality holds <em>only</em> for stars.</p>

<p>Note that we need xxMATHPROTECTxx24xx because if xxMATHPROTECTxx25xx, any two sets of size xxMATHPROTECTxx26xx must intersect by Pigeonhole Principle, meaning the entire set of xxMATHPROTECTxx27xx is intersecting.</p>

<p>The intuition behind the theorem is that if a family is not “anchored” by a single element (like a star), the sets are forced to “spread out” across the domain. This spreading increases the likelihood of disjointedness, preventing the family from reaching that maximum size.</p>

<p>In the future, I may include a full proof, but I hope that this brief introduction was sufficient in showcasing the complexity and overall vibe of hypergraph theory. Moving from graphs (xxMATHPROTECTxx28xx) to hypergraphs (xxMATHPROTECTxx29xx) causes the difficulty in studying these structures to explode, but it allows us to come up with so many fascinating results. To me, generalizing edges in this way was like opening up Pandora’s box.</p>]]></content><author><name>Vasu Menon</name></author><summary type="html"><![CDATA[An introduction to hypergraph theory and the Erdős–Ko–Rado Theorem.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://vasumenon.com/assets/images/art/fano_plane.jpg" /><media:content medium="image" url="https://vasumenon.com/assets/images/art/fano_plane.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Art Gallery</title><link href="https://vasumenon.com/2025/12/22/art-gallery.html" rel="alternate" type="text/html" title="Art Gallery" /><published>2025-12-22T00:00:00+00:00</published><updated>2025-12-22T00:00:00+00:00</updated><id>https://vasumenon.com/2025/12/22/art-gallery</id><content type="html" xml:base="https://vasumenon.com/2025/12/22/art-gallery.html"><![CDATA[<p>A curated collection of artworks I saw in the Kunsthistorisches Museum in Vienna that have caught my attention and inspired me.</p>

<hr />

<h2 id="samuel-van-hoogstraten---old-man-at-a-window-c-1653">Samuel van Hoogstraten - <em>Old Man at a Window</em> (c. 1653)</h2>

<div class="gallery-item">
    <img src="/assets/images/paintings/Samuel_van_Hoogstraten,_Kunsthistorisches_Museum_Wien,_Gem%C3%A4ldegalerie_-_Alter_Mann_im_Fenster_-_GG_378_-_Kunsthistorisches_Museum.jpg" alt="Old Man at a Window by Samuel van Hoogstraten" title="Old Man at a Window by Samuel van Hoogstraten" loading="lazy" />
    <!-- <p class="artwork-details">
        Description here
    </p> -->
</div>

<hr />

<h2 id="pieter-bruegel-the-elder---the-peasant-and-the-nest-robber-1568">Pieter Bruegel the Elder - <em>The Peasant and the Nest Robber</em> (1568)</h2>

<div class="gallery-item">
    <img src="/assets/images/paintings/The_Peasant_and_the_Birdnester_Pieter_Bruegel_the_Elder_1568.jpeg" alt="The Peasant and the Nest Robber by Pieter Bruegel the Elder" title="The Peasant and the Nest Robber by Pieter Bruegel the Elder" loading="lazy" />
    <!-- <p class="artwork-details">
        Description here
    </p> -->
</div>

<hr />

<h2 id="johannes-vermeer---the-art-of-painting-c-1666-1668">Johannes Vermeer - <em>The Art of Painting</em> (c. 1666-1668)</h2>

<div class="gallery-item">
    <img src="/assets/images/paintings/Jan_Vermeer_-_The_Art_of_Painting_-_Google_Art_Project.jpg" alt="The Art of Painting by Johannes Vermeer" title="The Art of Painting by Johannes Vermeer" loading="lazy" />
    <!-- <p class="artwork-details">
        Description here
    </p> -->
</div>

<hr />

<h2 id="jacobus-vrel---woman-at-a-window-c-1654-1662">Jacobus Vrel - <em>Woman at a Window</em> (c. 1654-1662)</h2>

<div class="gallery-item">
    <img src="/assets/images/paintings/Vrel_-_Frau_am_Fenster_-_KHM.jpg" alt="Woman at a Window by Jacobus Vrel" title="Woman at a Window by Jacobus Vrel" loading="lazy" />
    <!-- <p class="artwork-details">
        Description here
    </p> --></div>

<hr />

<h2 id="rembrandt-van-rijn---portrait-of-an-old-woman-1654">Rembrandt van Rijn - <em>Portrait of an Old Woman</em> (1654)</h2>

<div class="gallery-item">
    <img src="/assets/images/paintings/Rembrandt_Harmensz_van_Rijn,_,_Kunsthistorisches_Museum_Wien,_Gem%C3%A4ldegalerie_-_Die_Prophetin_Hanna_-_GG_408_-_Kunsthistorisches_Museum.jpg" alt="Portrait of an Old Woman by Rembrandt" title="Portrait of an Old Woman by Rembrandt" loading="lazy" />
    <!-- <p class="artwork-details">
        Description here
    </p> --></div>

<hr />

<style>
.gallery-item {
    margin: 2em 0;
}

.gallery-item img {
    width: 100%;
    max-width: 800px;
    height: auto;
    display: block;
    margin: 1em 0;
    border: 1px solid #ddd;
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}

.artwork-details {
    font-size: 0.95em;
    color: #555;
    font-style: italic;
    margin: 0.5em 0;
}
</style>]]></content><author><name>Vasu Menon</name></author><summary type="html"><![CDATA[A curated collection of artworks I saw in the Kunsthistorisches Museum in Vienna that have caught my attention and inspired me.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://vasumenon.com/assets/images/paintings/Jan_Vermeer_-_The_Art_of_Painting_-_Google_Art_Project.jpg" /><media:content medium="image" url="https://vasumenon.com/assets/images/paintings/Jan_Vermeer_-_The_Art_of_Painting_-_Google_Art_Project.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Solving PDEs with Neural Networks</title><link href="https://vasumenon.com/2025/05/12/pinn-attempt1.html" rel="alternate" type="text/html" title="Solving PDEs with Neural Networks" /><published>2025-05-12T00:00:00+00:00</published><updated>2025-05-12T00:00:00+00:00</updated><id>https://vasumenon.com/2025/05/12/pinn-attempt1</id><content type="html" xml:base="https://vasumenon.com/2025/05/12/pinn-attempt1.html"><![CDATA[<p>These types of neural networks are called Physics-Informed Neural Networks (PINNs) <a class="citation" href="#RAISSI2019686">(Raissi et al., 2019)</a>.</p>

<p>Let’s define a simple PDE to show how this works:</p>

<p>xxMATHPROTECTxx0xx</p>

<p>This is known as the 1-D heat equation. To solve this, the idea is to essentially define a neural network with differentiable activation functions xxMATHPROTECTxx1xx which approximates the solution. Let’s denote xxMATHPROTECTxx2xx. Since the network is differentiable, we can compute xxMATHPROTECTxx3xx and xxMATHPROTECTxx4xx easily. We now need to train the parameters xxMATHPROTECTxx5xx such that we minimize the residual, that is, we minimize the error between xxMATHPROTECTxx6xx and xxMATHPROTECTxx7xx. Mathematically, this is:</p>

<p>xxMATHPROTECTxx8xx</p>

<p>where xxMATHPROTECTxx9xx are sampled points in the domain and xxMATHPROTECTxx10xx is the PDE residual (difference between LHS and RHS of the PDE) at those points.</p>

<p>We also need to learn the initial condition, so we can define another loss function as follows:</p>

<p>xxMATHPROTECTxx11xx</p>

<p>Now, we define our final loss:</p>

<p>xxMATHPROTECTxx12xx</p>

<p>and all we need to do is to optimize xxMATHPROTECTxx13xx such that xxMATHPROTECTxx14xx is minimized. Note that if we had boundary conditions, we would add yet another loss, xxMATHPROTECTxx15xx, to account for that as well.</p>

<p>In practice, to solve this, I defined a fully connected neural network with input xxMATHPROTECTxx16xx and output xxMATHPROTECTxx17xx, given by:</p>

<p>xxMATHPROTECTxx18xx</p>

<p>where each xxMATHPROTECTxx19xx and xxMATHPROTECTxx20xx is applied element-wise.</p>

<p>The network parameters are optimized by minimizing the loss function above using the Adam optimizer. I also used PyTorch’s <code class="language-plaintext highlighter-rouge">autograd.grad()</code> feature to compute the derivatives. Here are my results (at xxMATHPROTECTxx21xx), it’s crazy how this literally works:</p>

<figure>
  <img src="/assets/images/projects/pinn/pinn_heateqn_sol.png" alt="Comparison between the predicted solution and exact solution at t=0.25" title="Comparison between the predicted solution and exact solution at t=0.25" loading="lazy" />
  <figcaption>Comparison of the predicted solution xxMATHPROTECTxx22xx from the PINN and the exact solution of the 1D heat equation at xxMATHPROTECTxx23xx. The initial condition is xxMATHPROTECTxx24xx and the exact solution is xxMATHPROTECTxx25xx.</figcaption>
</figure>

<hr />

<h2 id="references">References</h2>

<ol class="bibliography"><li><span class="bibliography-item"><span id="RAISSI2019686">Raissi, M., Perdikaris, P., &amp; Karniadakis, G. E. (2019). Physics-informed neural networks: A deep learning framework for solving forward and inverse problems involving nonlinear partial differential equations. <i>Journal of Computational Physics</i>, <i>378</i>, 686–707. https://doi.org/https://doi.org/10.1016/j.jcp.2018.10.045</span></span>
</li></ol>]]></content><author><name>Vasu Menon</name></author><summary type="html"><![CDATA[Physics-Informed Neural Networks approach to solving the 1D heat equation by minimizing PDE residuals and initial condition losses.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://vasumenon.com/assets/images/projects/pinn/pinn_heateqn_sol.png" /><media:content medium="image" url="https://vasumenon.com/assets/images/projects/pinn/pinn_heateqn_sol.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Face Generator with GANs</title><link href="https://vasumenon.com/2025/05/09/gan-attempt1.html" rel="alternate" type="text/html" title="Face Generator with GANs" /><published>2025-05-09T00:00:00+00:00</published><updated>2025-05-09T00:00:00+00:00</updated><id>https://vasumenon.com/2025/05/09/gan-attempt1</id><content type="html" xml:base="https://vasumenon.com/2025/05/09/gan-attempt1.html"><![CDATA[<p>I’ve been working on a small project involving Generative Adversarial Networks (GANs) <a class="citation" href="#goodfellow2014generativeadversarialnetworks">(Goodfellow et al., 2014)</a>. A GAN is a machine learning framework designed to generate new data that resembles a given dataset. It consists of two neural networks: a Generator xxMATHPROTECTxx0xx and a Discriminator xxMATHPROTECTxx1xx, which are trained in competition with one another.</p>

<p>The Generator takes a random noise vector xxMATHPROTECTxx2xx as input and produces a 64×64 image, xxMATHPROTECTxx3xx. The Discriminator receives an image (either real from the dataset or generated by xxMATHPROTECTxx4xx) and outputs a probability xxMATHPROTECTxx5xx indicating whether the image is real (from the dataset) or fake (produced by the Generator).</p>

<p>Training alternates between improving the Discriminator and the Generator. The Discriminator is trained to maximize the probability of assigning the correct label to both real and fake images. Its loss function is:</p>

<p>xxMATHPROTECTxx6xx</p>

<p>Here, xxMATHPROTECTxx7xx is a real image from the dataset, and xxMATHPROTECTxx8xx is a fake image produced from noise.</p>

<p>The Generator, on the other hand, tries to fool the Discriminator by producing images that it classifies as real. Its loss function is:</p>

<p>xxMATHPROTECTxx9xx</p>

<p>Training proceeds iteratively. First, I sample a random noise vector, generate a fake image, and evaluate it with the Discriminator to compute the <code class="language-plaintext highlighter-rouge">loss_fake</code>. Then, I pass a real image through the Discriminator to compute the <code class="language-plaintext highlighter-rouge">loss_real</code>. The total Discriminator loss is the sum of these two. After updating xxMATHPROTECTxx10xx, I sample new noise, generate another fake image, and compute the Generator loss by treating the fake image as if it were real, encouraging the Generator to improve.</p>

<p>Over time, this adversarial process improves both models. The Discriminator becomes better at distinguishing real from fake, and the Generator becomes better at producing realistic images. Eventually, the Generator can produce samples that are nearly indistinguishable from the real dataset, and we use it to generate new images.</p>

<p>Now, let’s see what this is like in practice. I have a dataset of ~200k celebrity faces <a class="citation" href="#liu2015faceattributes">(Liu et al., 2015)</a>, and I have a deep convolutional model for both the Generator and Discriminator. This is therefore called a DCGAN (Deep Convolutional GAN) <a class="citation" href="#radford2016unsupervisedrepresentationlearningdeep">(Radford et al., 2016)</a>. Here are the architectures:</p>

<hr />

<h3 id="dcgan-generator-architecture"><strong>DCGAN Generator Architecture</strong></h3>

<table>
  <thead>
    <tr>
      <th>Layer</th>
      <th>In Ch.</th>
      <th>Out Ch.</th>
      <th>Kernel / Stride / Pad</th>
      <th>Activation</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>ConvTranspose2d</td>
      <td>100</td>
      <td>512</td>
      <td>4 / 1 / 0</td>
      <td>ReLU</td>
    </tr>
    <tr>
      <td>BatchNorm2d</td>
      <td>–</td>
      <td>512</td>
      <td>–</td>
      <td>–</td>
    </tr>
    <tr>
      <td>ConvTranspose2d</td>
      <td>512</td>
      <td>256</td>
      <td>4 / 2 / 1</td>
      <td>ReLU</td>
    </tr>
    <tr>
      <td>BatchNorm2d</td>
      <td>–</td>
      <td>256</td>
      <td>–</td>
      <td>–</td>
    </tr>
    <tr>
      <td>ConvTranspose2d</td>
      <td>256</td>
      <td>128</td>
      <td>4 / 2 / 1</td>
      <td>ReLU</td>
    </tr>
    <tr>
      <td>BatchNorm2d</td>
      <td>–</td>
      <td>128</td>
      <td>–</td>
      <td>–</td>
    </tr>
    <tr>
      <td>ConvTranspose2d</td>
      <td>128</td>
      <td>64</td>
      <td>4 / 2 / 1</td>
      <td>ReLU</td>
    </tr>
    <tr>
      <td>BatchNorm2d</td>
      <td>–</td>
      <td>64</td>
      <td>–</td>
      <td>–</td>
    </tr>
    <tr>
      <td>ConvTranspose2d</td>
      <td>64</td>
      <td>3</td>
      <td>4 / 2 / 1</td>
      <td>Tanh</td>
    </tr>
  </tbody>
</table>

<hr />

<h3 id="dcgan-discriminator-architecture">DCGAN Discriminator Architecture</h3>

<table>
  <thead>
    <tr>
      <th>Layer</th>
      <th>In Ch.</th>
      <th>Out Ch.</th>
      <th>Kernel / Stride / Pad</th>
      <th>Activation</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Conv2d</td>
      <td>3</td>
      <td>64</td>
      <td>4 / 2 / 1</td>
      <td>LeakyReLU (0.2)</td>
    </tr>
    <tr>
      <td>Conv2d</td>
      <td>64</td>
      <td>128</td>
      <td>4 / 2 / 1</td>
      <td>LeakyReLU (0.2)</td>
    </tr>
    <tr>
      <td>BatchNorm2d</td>
      <td>–</td>
      <td>128</td>
      <td>–</td>
      <td>–</td>
    </tr>
    <tr>
      <td>Conv2d</td>
      <td>128</td>
      <td>256</td>
      <td>4 / 2 / 1</td>
      <td>LeakyReLU (0.2)</td>
    </tr>
    <tr>
      <td>BatchNorm2d</td>
      <td>–</td>
      <td>256</td>
      <td>–</td>
      <td>–</td>
    </tr>
    <tr>
      <td>Conv2d</td>
      <td>256</td>
      <td>512</td>
      <td>4 / 2 / 1</td>
      <td>LeakyReLU (0.2)</td>
    </tr>
    <tr>
      <td>BatchNorm2d</td>
      <td>–</td>
      <td>512</td>
      <td>–</td>
      <td>–</td>
    </tr>
    <tr>
      <td>Conv2d</td>
      <td>512</td>
      <td>1</td>
      <td>4 / 1 / 0</td>
      <td>Sigmoid</td>
    </tr>
  </tbody>
</table>

<hr />

<p>As mentioned before, I used the Binary Cross-Entropy (BCE) loss function to train both the generator and discriminator. This is defined as:</p>

<p>xxMATHPROTECTxx11xx</p>

<p>where xxMATHPROTECTxx12xx is the predicted probability and xxMATHPROTECTxx13xx is the ground truth label.</p>

<p>I used the Adam optimizer for both the generator and the discriminator, with learning rate xxMATHPROTECTxx14xx and momentum parameters xxMATHPROTECTxx15xx, xxMATHPROTECTxx16xx. These are commonly used hyperparameters in GAN training.</p>

<p>I ended up training the models with a batch size of 128 across 20 epochs. It took quite a while, but after 15 epochs, here are the results:</p>

<figure>
  <img src="/assets/images/projects/gan/epoch_015.png" alt="Generator outputs using 16 different noisy inputs after 15 epochs" title="Generator outputs using 16 different noisy inputs after 15 epochs" loading="lazy" />
  <figcaption>Generator outputs using 16 different noisy inputs after 15 epochs. The generated faces are starting to form, with the model learning features like eyes, hair, facial structure, and jaw. Discriminator loss: 0.3211, Generator loss: 3.1851.</figcaption>
</figure>

<p>The generated faces are starting to form. The model is slowly learning how to create features like eyes, hair, facial structure, jaw, etc. I think at this point, I had a Discriminator loss of <code class="language-plaintext highlighter-rouge">0.3211</code> and a Generator loss of <code class="language-plaintext highlighter-rouge">3.1851</code>, which is pretty standard. Ideally, these losses should keep fluctuating. One model cannot win (because that spoils the adversarial part of the training).</p>

<p>Interestingly, however, after the full 20 epochs, we get the following:</p>

<figure>
  <img src="/assets/images/projects/gan/epoch_020.png" alt="Generator outputs using 16 different noisy inputs after 20 epochs" title="Generator outputs using 16 different noisy inputs after 20 epochs" loading="lazy" />
  <figcaption>Generator outputs after 20 epochs showing mode collapse. The Generator produces the same output repeatedly, and the Discriminator is no longer fooled. Discriminator loss: 0.000, Generator loss: 64.0911.</figcaption>
</figure>

<p>Upon inspecting the losses, we have a Discriminator loss of <code class="language-plaintext highlighter-rouge">0.000</code> and a Generator loss of <code class="language-plaintext highlighter-rouge">64.0911</code>. It seems like the Generator decided to output this one weird image all the time, and the Discriminator was not fooled. This is known as <em>mode collapse</em>. This happens when the Generator finds one output that consistently fools the Discriminator (until it doesn’t anymore) <a class="citation" href="#salimans2016improvedtechniquestraininggans">(Salimans et al., 2016)</a>. I will try to figure out how to fix this later.</p>

<hr />

<h2 id="references">References</h2>

<ol class="bibliography"><li><span class="bibliography-item"><span id="goodfellow2014generativeadversarialnetworks">Goodfellow, I. J., Pouget-Abadie, J., Mirza, M., Xu, B., Warde-Farley, D., Ozair, S., Courville, A., &amp; Bengio, Y. (2014). <i>Generative Adversarial Networks</i>. https://arxiv.org/abs/1406.2661</span></span>
</li>
<li><span class="bibliography-item"><span id="liu2015faceattributes">Liu, Z., Luo, P., Wang, X., &amp; Tang, X. (2015, December). Deep Learning Face Attributes in the Wild. <i>Proceedings of International Conference on Computer Vision (ICCV)</i>.</span></span>
</li>
<li><span class="bibliography-item"><span id="radford2016unsupervisedrepresentationlearningdeep">Radford, A., Metz, L., &amp; Chintala, S. (2016). <i>Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks</i>. https://arxiv.org/abs/1511.06434</span></span>
</li>
<li><span class="bibliography-item"><span id="salimans2016improvedtechniquestraininggans">Salimans, T., Goodfellow, I., Zaremba, W., Cheung, V., Radford, A., &amp; Chen, X. (2016). <i>Improved Techniques for Training GANs</i>. https://arxiv.org/abs/1606.03498</span></span>
</li></ol>]]></content><author><name>Vasu Menon</name></author><summary type="html"><![CDATA[Using Deep Convolutional GANs to generate realistic celebrity face images, trained on 200,000 samples with PyTorch.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://vasumenon.com/assets/images/projects/gan/epoch_020.png" /><media:content medium="image" url="https://vasumenon.com/assets/images/projects/gan/epoch_020.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>