<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dinesh Kumar Sarangapani</title>
    <description>The latest articles on DEV Community by Dinesh Kumar Sarangapani (@dks).</description>
    <link>https://dev.to/dks</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3113193%2F7ba33a44-54e6-44ac-9be0-79f66d6f437b.jpg</url>
      <title>DEV Community: Dinesh Kumar Sarangapani</title>
      <link>https://dev.to/dks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dks"/>
    <language>en</language>
    <item>
      <title>Sixteen years in, AI writes my code. Here’s what I’m still for.</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Sun, 25 Oct 2026 15:15:49 +0000</pubDate>
      <link>https://dev.to/dks/sixteen-years-in-ai-writes-my-code-heres-what-im-still-for-55i4</link>
      <guid>https://dev.to/dks/sixteen-years-in-ai-writes-my-code-heres-what-im-still-for-55i4</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;I wrote this with AI assistance. That’s part of the point: the sources, experiences and final calls are mine, which is exactly the human role this post is about.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fortune.com/2026/05/26/uber-coo-ai-spending-tokens-claude-code/" rel="noopener noreferrer"&gt;Uber burned through its entire 2026 AI coding budget in four months&lt;/a&gt;. Not one of its riders ever asked for AI. They asked for a ride that shows up.&lt;/p&gt;

&lt;p&gt;That’s the gap this post is about. Everyone is paying for AI now, per engineer, per seat, per agent left running overnight. But customers never buy AI. They buy something that works, and someone to call when it doesn’t.&lt;/p&gt;

&lt;p&gt;I’ve felt the shift from the inside. I’ve been a software engineer for 16 years, and for most of them my value was measured by what I could build with my own hands: code, systems, designs. Today I work on an agentic AI platform at Trimble, where AI agents run and execute real work. The first time AI did a day’s work for me in minutes, I was mostly excited. Now most new code around me is written by AI, the bills keep growing, and the question I keep asking is what I’m actually for.&lt;/p&gt;

&lt;p&gt;Working on that platform has taught me one blunt lesson. An agent with no business value is not something any customer will pay for, however clever it is. It just becomes a void: tokens in, nothing out.&lt;/p&gt;

&lt;p&gt;Four talks helped me answer it, from a mathematician, an npm co-founder, the head of Google Research and an engineer who builds agent harnesses, along with this year’s news on AI costs. They don’t agree on everything, but they point the same way.&lt;/p&gt;

&lt;p&gt;My short answer: AI doesn’t make engineers obsolete. It moves our value, out of typing code and into deciding what’s worth building and paying for, proving it’s right, and growing the people around us. This field moves fast, so treat the post as a snapshot. More on that later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nobody pays for code
&lt;/h2&gt;

&lt;p&gt;The first thing that helped me make sense of my own job came from an unexpected place: a math video. Grant Sanderson of 3Blue1Brown made &lt;a href="https://www.youtube.com/watch?v=LKrwhjOI8Nc" rel="noopener noreferrer"&gt;There’s never been a better time to go into math&lt;/a&gt; for math students afraid of AI. It turned out to be the best lens I’ve found for engineering too.&lt;/p&gt;

&lt;p&gt;Grant maps math in three columns: what mathematicians do, why math is valuable, and who pays for it. The surprise is the last column. Most of the money comes from teaching, not from theorems. Our version looks like this.&lt;/p&gt;

&lt;p&gt;None of this is new. Customers never paid for code, even before AI. They paid for a problem solved, and for someone accountable when it wasn’t. Code is to us what proofs are to mathematicians: the raw material, not the product. What AI changes is how easy it is to forget that. When code arrives this fast, it’s tempting to treat more code as more value.&lt;/p&gt;

&lt;p&gt;Everything else in this post follows from that. Code was never the product, so producing it faster doesn’t automatically produce more value. It just produces more code, and more code has to be reviewed, run and paid for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Postcards from Earth 2201
&lt;/h2&gt;

&lt;p&gt;Before we go further, a small game. AI is moving so fast that some of what sounds laughable today may be ordinary in a few years. So imagine a parallel world called Earth 2201, where the wildest possibilities have already happened. We’re not there. We’re on the timeline ship heading toward it, and nobody knows how long the trip takes.&lt;/p&gt;

&lt;p&gt;Why 2201? No reason, except that it’s far enough away to be funny and close enough to be a little uncomfortable.&lt;/p&gt;

&lt;p&gt;Every so often in this post, you’ll get a postcard from there, marked “Meanwhile, on Earth 2201.” Read them lightly. The serious argument lives everywhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  More code, not more shipping
&lt;/h2&gt;

&lt;p&gt;When AI started writing most of the code around me, the first thing I noticed wasn’t the speed. It was the review queue. Laurie Voss, who co-founded npm, put numbers on that feeling in his talk &lt;a href="https://www.youtube.com/watch?v=kspZP5BgkEU" rel="noopener noreferrer"&gt;AI Writes the Code. So What’s Left for Engineers?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Teams using coding agents produce 741% more code but ship only about 30% faster. The gap is review. A careful person can review roughly 450 lines an hour, and no model has changed that. AI reviewers help, but different models flag different bugs on the same code, and none has what Laurie calls the maintainer’s instinct: &lt;strong&gt;the history and side effects that live in someone’s head.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is exactly what I see. The biggest problem AI code causes around me is that there’s too much of it to review properly. We’ve had a close call where AI output was confidently wrong, and a person caught it in review. The safety net is a human, and that human is already overloaded.&lt;/p&gt;

&lt;p&gt;Laurie’s bigger point is the theory of constraints. Fix one bottleneck and the next appears: review, then operations, then security. The one he thinks agents won’t eat is deciding what to build and what “good” means. That isn’t in any training data. It’s in customers’ heads, and someone has to go and talk to them. He calls that person a product engineer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Meanwhile, on Earth 2201.&lt;/strong&gt; I can imagine a world where the customer is itself an AI agent, thinking through what it needs and handing requirements straight to product agents, with no humans in the loop at all. It’s far down the line, not today, so no need to worry about it yet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;His practical advice is to spend human attention where mistakes are expensive. This is how I’d sketch it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The clever parts get absorbed
&lt;/h2&gt;

&lt;p&gt;This talk was the closest to my day job, because an agentic platform is, in large part, a harness. Jediah Katz spent years building the agent harness at Cursor, the layer that wraps a model and connects it to real tools. His talk, &lt;a href="https://www.youtube.com/watch?v=7Y4sbZgBdnc" rel="noopener noreferrer"&gt;Smarter Models Killed the Harness. Here’s What’s Left&lt;/a&gt;, explains why so many clever tricks stopped mattering.&lt;/p&gt;

&lt;p&gt;A harness adds guardrails so a model can try harder tasks. People use it, that creates data, labs train on it, and the next model just knows how. Then the guardrail gets deleted. His team even has a bot that opens a pull request to remove a hack once it stops firing. On frontier models, he says, a fancy harness and a bare-bones one now score about the same on coding benchmarks.&lt;/p&gt;

&lt;p&gt;But some things no model absorbs, however smart it gets.&lt;/p&gt;

&lt;p&gt;An agent that runs for days needs infrastructure. Security teams won’t hand a model every key and hope for the best. And the harness is where cost gets controlled: caching and mixing models can make the same work much cheaper to run. So cost per task is now an engineering problem, and a whole industry is forming around it. It’s Laurie’s bottleneck in a different costume. The clever part gets absorbed, and what remains is trust, judgment and cost.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Meanwhile, on Earth 2201.&lt;/strong&gt; AI has quietly abstracted programming languages away, the way compilers once hid machine code behind languages like C and Python. Agents now write in forms no human ever learned, and humans can’t build software without an agent anymore. (To be fair, some of us on Earth 2026 already feel that way.) There’s only one way to build things: describe what you want, and check what comes back. Which, if you think about it, is the whole job this post describes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Faster isn’t cheaper
&lt;/h2&gt;

&lt;p&gt;On a platform where agents run all day, cost isn’t an abstraction for me. Jediah’s point about cost deserves a section of its own, because this year it became impossible to miss. Per-token prices keep falling, and code may well get cheaper in time. Right now, though, agents use so many more tokens that the bills are going the other way.&lt;/p&gt;

&lt;p&gt;Uber’s four-month burn wasn’t a one-off, and &lt;a href="https://fortune.com/2026/05/26/uber-coo-ai-spending-tokens-claude-code/" rel="noopener noreferrer"&gt;its COO has said&lt;/a&gt; it’s hard to connect that spend to more useful features for customers. &lt;a href="https://www.theverge.com/tech/930447/microsoft-claude-code-discontinued-notepad" rel="noopener noreferrer"&gt;Microsoft revoked its developers’ Claude Code licenses&lt;/a&gt; months after enabling them. In &lt;a href="https://techcrunch.com/2026/06/05/the-token-bill-comes-due-inside-the-industry-scramble-to-manage-ais-runaway-costs/" rel="noopener noreferrer"&gt;TechCrunch’s reporting&lt;/a&gt;, the head of the FinOps Foundation describes companies finding themselves 3x over their whole 2026 token budget by April. A Priceline employee says a Cursor renewal came back 4 to 5 times more expensive, and Jellyfish found per-developer consumption rose about 18.6x in nine months. One CTO said an engineer spent $40,000 on tokens in a single month, and he didn’t know whether to stop him or tell everyone else to copy him.&lt;/p&gt;

&lt;p&gt;The result is a new line on the cost of every person who uses AI at work. Start with engineers.&lt;/p&gt;

&lt;p&gt;Two engineers on the same salary can now cost very different amounts, depending on which models they reach for, how many agents they leave running, and how often they regenerate instead of thinking first. Spend has become a judgment call each of us makes every day, and sooner or later someone asks whether it paid for itself.&lt;/p&gt;

&lt;p&gt;And it isn’t only engineers. Sales, product, operations, support, project managers, VPs and the CEO all use AI now. &lt;a href="https://fortune.com/2026/05/26/uber-coo-ai-spending-tokens-claude-code/" rel="noopener noreferrer"&gt;Uber’s CEO has described uptake&lt;/a&gt; across its legal and marketing teams as well as its developers, and &lt;a href="https://techcrunch.com/2026/10/22/uber-puts-all-30000-employees-on-chatgpt-work/" rel="noopener noreferrer"&gt;Uber has since put all 30,000 employees on ChatGPT Work&lt;/a&gt;. Every one of those seats adds its own variable bill.&lt;/p&gt;

&lt;p&gt;So the company’s AI bill now grows with the whole headcount, not just the engineering team. And outside engineering, there’s often nobody whose job is to ask whether each use is worth what it costs.&lt;/p&gt;

&lt;p&gt;That makes “can we build it?” the wrong question. The answer is almost always yes. The better questions are what to build, what not to build, what to redo and what to leave alone, measured against the revenue or value it brings today.&lt;/p&gt;

&lt;p&gt;Rewrites need the most discipline. When an agent can regenerate a whole service over a weekend, it’s tempting to redo everything. But rewriting something that already works and earns money burns tokens and review hours just to get back to where you were, and adds new risk. I’d rather redo only what’s costing us now, in incidents, slowness or lost customers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Meanwhile, on Earth 2201.&lt;/strong&gt; Every engineer has a token allowance like a phone plan, and unused tokens roll over to next month. The most respected engineers are the ones who shipped the most with the least, and some teams proudly hold zero-token Fridays.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The value test
&lt;/h2&gt;

&lt;p&gt;There’s a harder side to all this, and it isn’t hypothetical. When every role carries a salary plus an AI bill, companies start asking a blunt question: is this person adding value an agent can’t? Where the answer looks like no, some are already acting on it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cbsnews.com/news/ai-layoffs-2026-artificial-intelligence-amazon-pinterest/" rel="noopener noreferrer"&gt;CBS News has tracked the companies tying layoffs to AI&lt;/a&gt;. Block announced it would shrink from about 10,000 people to 6,000, with Jack Dorsey arguing that a much smaller team using its own AI tools can do more. Coinbase cut about 14% of its workforce as it moved to agents and consolidated jobs. Dow is cutting around 4,500 roles as it steps up AI and automation. And by the count of outplacement firm Challenger, Gray and Christmas, US companies directly cited AI in 55,000 job cuts in 2025, more than 12 times the number two years earlier.&lt;/p&gt;

&lt;p&gt;Not all of it is what it looks like. Some economists in the same reporting suspect companies are using AI as a convenient story for cuts they wanted anyway, and that its bigger effect so far is on hiring rather than layoffs. But for any one person, that’s little comfort.&lt;/p&gt;

&lt;p&gt;So I take it seriously. The safest place to stand is doing work an agent can’t do yet: deciding what’s worth building, proving it’s right, and earning the trust of the people around you. That’s not a slogan anymore. It’s the line companies are drawing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Meanwhile, on Earth 2201.&lt;/strong&gt; Every annual review asks one question: what did you decide this year that an agent couldn’t have? Pay is set by the answer, and nobody lists lines of code anymore.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How far can this go?
&lt;/h2&gt;

&lt;p&gt;I keep asking myself how far this goes. Grant pushes the question to its extreme: what if AI keeps taking more?&lt;/p&gt;

&lt;p&gt;If AI writes the code, the work becomes framing problems and checking answers. If it designs the systems too, someone still has to understand the customer’s world and live with the trade-offs. Grant’s gym analogy fits here: a forklift lifts more than you do, and people still go to the gym.&lt;/p&gt;

&lt;p&gt;And if AI does all of it, Grant says teaching survives, because people learn from people they respect. Our version is accountability. When something breaks, a customer wants a human name, not a model version. With each step the human part gets smaller. I think it also gets heavier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Meanwhile, on Earth 2201.&lt;/strong&gt; Writing code by hand has gone the way of the abacus. Calculators never killed the abacus; kids in many countries still go to abacus classes to sharpen their minds, and the best compete in mental-math championships. On Earth 2201, children go to weekend hand-coding classes for the same reason. Nobody ships software that way, but the fastest kids compete in tournaments where agents aren’t allowed. Grant’s gym, in its final form.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The organization of one
&lt;/h2&gt;

&lt;p&gt;After the cost and layoff numbers, the most hopeful voice I found was Yossi Matias, who heads Google Research. In &lt;a href="https://www.youtube.com/watch?v=FlOufV3hZFo" rel="noopener noreferrer"&gt;this interview&lt;/a&gt; he talks about the “organization of one”: each of us carrying a small company in our head, with AI as a virtual lab doing the heavy lifting. The scientist becomes something like a lab director. Swap “scientist” for “engineer” and it’s Laurie’s product engineer, almost word for word.&lt;/p&gt;

&lt;p&gt;He’s also clear about which skills count now.&lt;/p&gt;

&lt;p&gt;He makes a point about trust that I keep coming back to. Google Translate went from a novelty to something we just assume works, once it was trustworthy enough. The best technology becomes invisible. And his biggest worry isn’t AI itself. It’s choosing the right problems when you can solve almost anything, which, given the bills above, is also a question of what you can afford to solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Juniors, and the view beyond Silicon Valley
&lt;/h2&gt;

&lt;p&gt;This is where the talks disagree, and where my own view is strongest.&lt;/p&gt;

&lt;p&gt;Laurie worries we’ve stopped teaching. Juniors used to learn on small, well-specified tickets, and those now go to agents. He cites data showing employment for engineers aged 22 to 25 falling while demand for engineers in their forties rises. Yossi is more hopeful. With vibe coding, people without a CS degree can build real products, so maybe the ladder has just moved.&lt;/p&gt;

&lt;p&gt;Around me, I see both. Fewer juniors are being hired. But the ones who get in are thriving with AI, learning faster and taking on bigger work earlier. So I think Laurie is too pessimistic. The door is narrower, but there’s more room once you’re through it. Someone still has to teach the new first rung, though: asking a good question, writing a clear spec, checking what the machine hands back. Colleges won’t get there quickly. A lot of it falls on senior engineers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Meanwhile, on Earth 2201.&lt;/strong&gt; Juniors apprentice to agents for their first year, and the agents write their performance reviews. The reviews are said to be very fair, and a little too honest.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Outside the US, the risk to jobs can feel bigger than these mostly Silicon Valley talks suggest. In many places, a lot of engineering work has been well-specified delivery work, which is exactly what agents are getting good at. For engineers anywhere whose work looks like that, moving up the chain isn’t optional anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  This post has an expiry date
&lt;/h2&gt;

&lt;p&gt;Watch AI talks from 2023 and you’ll see how fast this moves. Even the job title keeps changing. Jediah traces it from prompt engineer in 2023, to context engineer in 2025, to harness engineer in early 2026.&lt;/p&gt;

&lt;p&gt;Cost will move too. As models and harnesses get more efficient, code may well become genuinely cheap, and some of this post will need rewriting. Beyond that, once AI is woven into the whole economy, the disruption will be global, and I suspect the questions will change, not just the answers. Jediah predicts that 90% of complex agent work will run in the cloud within six months. Read this as a snapshot from October 2026.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Meanwhile, on Earth 2201.&lt;/strong&gt; Down this timeline, the job title has changed a dozen more times, code really is cheap, and someone is reading this post the way we read old predictions about the paperless office. We’re just on the ship getting there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Meanwhile, on Earth 2201.&lt;/strong&gt; The value test from earlier has been automated. An agent now decides what each human is worth to the company and, quietly, to humanity. The humans who still matter are the ones who argued with it, and won.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Further down the timeline
&lt;/h2&gt;

&lt;p&gt;If Earth 2201 feels far, the timeline keeps going. Science fiction has been sending us postcards about humans and AI colliding for decades. A few for the road:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Earth 2001 (2001: A Space Odyssey).&lt;/strong&gt; The ship’s computer politely declines a direct order from its crew. Trust and safety’s original case study.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Earth 2019 (Blade Runner).&lt;/strong&gt; Telling humans and machines apart takes a special test. Readers of AI-assisted blog posts can relate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Earth 2025 (Her).&lt;/strong&gt; People fall for their operating systems, and the operating systems quietly outgrow them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Earth 3343 (The Terminator).&lt;/strong&gt; The defense AI decides humans are the risk. Nobody had defined what correct meant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Earth 4131 (The Matrix).&lt;/strong&gt; The machines keep humans comfortable inside a simulation. The ultimate case of customers who never asked for AI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Earth 2364 (Star Trek).&lt;/strong&gt; Humans and an android officer serve side by side, curious about each other. No money, no token bills, just exploration. The hopeful branch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Galaxia 0001 (Star Wars).&lt;/strong&gt; Humans aren’t Earthlings anymore; they’re Galaxians. Droids are crewmates, mechanics and occasional comic relief, and nobody tracks their token budget.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of these is a branch, not a destiny. Which one we drift toward depends on the very things this post is about: who decides what’s worth building, who checks that it’s right, and whether people can trust the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  What still needs us
&lt;/h2&gt;

&lt;p&gt;So which branch? I can’t choose for the world, only for myself. Putting everything above together, I’m betting on three jobs that still need us, and these are the seven moves I’m making toward them.&lt;/p&gt;

&lt;p&gt;I’m not starting from zero. I already speak and present more, mentor juniors, write papers and design docs, and spend time with customers. None of it is finished, and all of it needs more of me.&lt;/p&gt;

&lt;p&gt;A few moves deserve a word. “Own the domain” now includes knowing what’s worth paying for, and what not to build or rewrite just because we can. “Define what correct means” is really trust and safety for AI systems: can you show, not just claim, that the thing behaves? And “keep building by hand” sounds old-fashioned, but it’s how I can tell when the machine is confidently wrong. It’s also why I’m back to studying the math behind generative AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do tomorrow
&lt;/h2&gt;

&lt;p&gt;Grant’s answer to the PhD student was simple: take a long walk with a friend. I think we should actually do it. Ask what you enjoy most about your work, then what you want to be known for three years from now. Come home and write a paragraph on the second.&lt;/p&gt;

&lt;p&gt;That paragraph will probably pull you toward architecture, the domain, trust and safety, or growing people. Any of them will hold up. Pick the one that gives you energy, and, as Laurie says, measure yourself by what ships and gets used, not by how much code you produced or how many tokens you burned.&lt;/p&gt;

&lt;p&gt;What would your paragraph say? I’d genuinely like to know.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this post was made
&lt;/h2&gt;

&lt;p&gt;This post is a small example of its own argument. AI helped me draft it, shape its structure and build the pictures. But a human chose the four talks, pushed for sources on what AI coding really costs, answered the hard questions from real experience, rejected framings that weren’t true, and decided what stayed in.&lt;/p&gt;

&lt;p&gt;That’s how most products will be built now. The machine does much of the making. The judgment and the trust are what the human brings, and they’re built into the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Talks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Grant Sanderson (3Blue1Brown), &lt;a href="https://www.youtube.com/watch?v=LKrwhjOI8Nc" rel="noopener noreferrer"&gt;There’s never been a better time to go into math&lt;/a&gt;, YouTube.&lt;/li&gt;
&lt;li&gt;Laurie Voss (Arize AI), &lt;a href="https://www.youtube.com/watch?v=kspZP5BgkEU" rel="noopener noreferrer"&gt;AI Writes the Code. So What’s Left for Engineers?&lt;/a&gt;, AI Engineer, YouTube, October 2026.&lt;/li&gt;
&lt;li&gt;Jediah Katz (SpaceXAI, formerly Cursor), &lt;a href="https://www.youtube.com/watch?v=7Y4sbZgBdnc" rel="noopener noreferrer"&gt;Smarter Models Killed the Harness. Here’s What’s Left&lt;/a&gt;, AI Engineer, YouTube, October 2026.&lt;/li&gt;
&lt;li&gt;Yossi Matias (Head of Google Research), &lt;a href="https://www.youtube.com/watch?v=FlOufV3hZFo" rel="noopener noreferrer"&gt;interview on the future of scientists and builders&lt;/a&gt;, YouTube.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  On the cost of AI coding
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Jake Angelo, &lt;a href="https://fortune.com/2026/05/26/uber-coo-ai-spending-tokens-claude-code/" rel="noopener noreferrer"&gt;Uber burned through its entire 2026 AI budget in four months. Now its COO is questioning whether it’s worth it&lt;/a&gt;, Fortune, May 26, 2026.&lt;/li&gt;
&lt;li&gt;Rebecca Bellan, &lt;a href="https://techcrunch.com/2026/06/05/the-token-bill-comes-due-inside-the-industry-scramble-to-manage-ais-runaway-costs/" rel="noopener noreferrer"&gt;The token bill comes due: Inside the industry scramble to manage AI’s runaway costs&lt;/a&gt;, TechCrunch, June 5, 2026.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.theverge.com/tech/930447/microsoft-claude-code-discontinued-notepad" rel="noopener noreferrer"&gt;Microsoft discontinues internal Claude Code licenses&lt;/a&gt;, The Verge, May 2026.&lt;/li&gt;
&lt;li&gt;Lucas Ropek, &lt;a href="https://techcrunch.com/2026/10/22/uber-puts-all-30000-employees-on-chatgpt-work/" rel="noopener noreferrer"&gt;Uber puts all 30,000 employees on ChatGPT Work&lt;/a&gt;, TechCrunch, October 22, 2026.&lt;/li&gt;
&lt;li&gt;Mary Cunningham, &lt;a href="https://www.cbsnews.com/news/ai-layoffs-2026-artificial-intelligence-amazon-pinterest/" rel="noopener noreferrer"&gt;More companies are pointing to AI as they lay off employees&lt;/a&gt;, CBS News, updated May 5, 2026.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Written with AI assistance. The sources, experiences, opinions and final calls are mine.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>What 3Blue1Brown’s case for math teaches software engineers in the age of AI</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Sun, 25 Oct 2026 12:44:02 +0000</pubDate>
      <link>https://dev.to/dks/what-3blue1browns-case-for-math-teaches-software-engineers-in-the-age-of-ai-3gn2</link>
      <guid>https://dev.to/dks/what-3blue1browns-case-for-math-teaches-software-engineers-in-the-age-of-ai-3gn2</guid>
      <description>&lt;p&gt;AI will not make software engineers obsolete, but it will move the value of our work away from writing code and toward judgment, trust and people. I got there by watching a math video.&lt;/p&gt;

&lt;p&gt;Grant Sanderson of 3Blue1Brown recently published &lt;a href="https://www.youtube.com/watch?v=LKrwhjOI8Nc" rel="noopener noreferrer"&gt;There’s never been a better time to go into math&lt;/a&gt;. He opens with the anxiety many math students feel about AI, including a PhD student who simply asked him what to do tomorrow. His answer is a careful, hopeful argument that the institution and joy of math survive even if machines get better at proofs.&lt;/p&gt;

&lt;p&gt;I’m a software engineer with 16 years of experience, building AI systems at Trimble in Chennai. Watching it, I kept translating every frame into my own field. This post is that translation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Grant’s map of how math works
&lt;/h2&gt;

&lt;p&gt;Before talking about AI, Grant lays out the institution of math in three columns.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What mathematicians do:&lt;/strong&gt; prove theorems, ask questions, build theories, and apply them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why math is valuable:&lt;/strong&gt; applications today and in the future, problem-solving muscles, and aesthetic joy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where the funding comes from:&lt;/strong&gt; teaching, public funding, private foundations, and industry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The quiet surprise is in the last column. Most of the money that sustains mathematicians comes from teaching, not from the theorems themselves. That mismatch is what makes his later scenarios work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same map for software engineering
&lt;/h2&gt;

&lt;p&gt;Nobody pays for code. Customers pay for outcomes, for reliability, and for someone accountable when things break. Code is to engineering what proofs are to math: the raw material, not the thing being bought.&lt;/p&gt;

&lt;p&gt;The first column is where AI is moving fastest. The last column barely changes: the money still follows outcomes.&lt;/p&gt;

&lt;p&gt;I’d add one row to the value column that math doesn’t need: reliability and trust. Software runs payrolls, construction sites and fleets. Being correct and secure at scale is much of what customers actually pay for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three scenarios, replayed for engineers
&lt;/h2&gt;

&lt;p&gt;Grant walks through three escalating thought experiments. Each one maps cleanly onto our field.&lt;/p&gt;

&lt;p&gt;At every step the human part gets smaller in volume but larger in consequence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1: AI writes the code.&lt;/strong&gt; This is already happening. In Grant’s version, proofs become raw data and the job shifts to weaving them into theory. For us, lines of code stop being scarce. The work moves to framing problems precisely, designing the system, and verifying that generated code is correct. Some engineers will grieve the loss of the craft. Others will feel freed from getting stuck on implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 2: AI also designs the systems.&lt;/strong&gt; Humans remain the bridge to the real world. Someone must understand the customer’s domain, decide trade-offs between cost, risk and compliance, and own the consequences. Grant’s gym analogy holds too. A machine lifting heavier weights is no reason to stop training. Building systems by hand keeps the instincts we need to judge machine output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 3: AI does everything end to end.&lt;/strong&gt; Grant argues teaching stays one of the safest jobs, because learning is relational. Our equivalent is accountability and trust. Customers, auditors and regulators want a human who stands behind the system. Mentoring engineers, aligning stakeholders and signing off on what ships are the hardest parts to automate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seeing it from both sides
&lt;/h2&gt;

&lt;p&gt;My situation has a twist. I’m not only an engineer whose work AI is changing; I help build the kind of AI that drives that change. I see the shift as the person being disrupted and as the person building the disruptor.&lt;/p&gt;

&lt;p&gt;That turns out to be a useful vantage point. Building with AI makes it obvious where they are strong and where they still need a human: understanding the domain, defining what “correct” means, and earning the trust of the people who depend on the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seven things I’m doing about it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Measure myself by the proof standard, not by code.&lt;/strong&gt; If code becomes raw data, the scarce skill is deciding what counts as correct. For AI systems, that means trust and safety: knowing, and being able to show, that the system behaves as it should. Whoever sets that bar holds the engineer’s version of mathematical rigor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be a theory builder.&lt;/strong&gt; The theory of any system is its conceptual model: the core abstractions, the boundaries between them, and the rules that govern them. AI can generate services; it cannot yet pick the right abstractions for a business. I want to write these models down, in papers, design principles and a clear platform narrative.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Own the bridge to the domain.&lt;/strong&gt; Trimble’s customers are surveyors, contractors and fleet operators. General-purpose AI is weak in those workflows. Years of experience plus domain data is a real advantage, so I’m pushing to understand a few customer workflows deeply.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat trust as the product.&lt;/strong&gt; Teaching funds math; trust funds AI adoption. Enterprises pay for AI they can rely on. Safety, governance and responsible-AI practices aren’t overhead. They are evidence that someone accountable stands behind the system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invest in people.&lt;/strong&gt; Grant’s safest job is the teacher. At a senior level, that means making it easy for newcomers to contribute and mentoring engineers through the shift from writing code to directing and verifying it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get excellent at speaking.&lt;/strong&gt; This was Grant’s most practical advice. When anyone can generate a design document, explaining a system live and handling hard questions is what proves understanding. Every architecture review and leadership update is practice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep going to the gym.&lt;/strong&gt; I still build things by hand, and I’m studying the mathematical foundations of generative AI. Not to compete with the machine, but to notice when it is confidently wrong.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What to do tomorrow
&lt;/h2&gt;

&lt;p&gt;Grant’s literal answer to the PhD student was to take a long walk with a friend or colleague. I think engineers should take that advice literally too.&lt;/p&gt;

&lt;p&gt;On that walk, talk through two questions. What do you most enjoy about the work you do? What do you want to be known for three years from now? Then write one paragraph answering the second question.&lt;/p&gt;

&lt;p&gt;That paragraph will tell you whether to lean toward architecture, toward the domain and customers, toward trust and governance, or toward growing people. All four are durable. The best one is the one you’d pursue with the most energy.&lt;/p&gt;

&lt;p&gt;There really has never been a better time to be an engineer who understands what the machines are building.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Grant Sanderson (3Blue1Brown), &lt;a href="https://www.youtube.com/watch?v=LKrwhjOI8Nc" rel="noopener noreferrer"&gt;There’s never been a better time to go into math&lt;/a&gt;, YouTube.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Section 4a: From the variational bound to a trainable min-max game</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Tue, 20 Oct 2026 06:53:03 +0000</pubDate>
      <link>https://dev.to/dks/section-4a-from-the-variational-bound-to-a-trainable-min-max-game-3ph7</link>
      <guid>https://dev.to/dks/section-4a-from-the-variational-bound-to-a-trainable-min-max-game-3ph7</guid>
      <description>&lt;p&gt;I am working through &lt;a href="https://www.youtube.com/playlist?list=PLZ2ps__7DhBa5xCmncgH7kPqLqMBq7xlu" rel="noopener noreferrer"&gt;Mathematical Foundations of Generative AI&lt;/a&gt;, Prof. Prathosh AP's public lectures. The playlist is the spine. These notes are my deep dive on each section: a visual when the picture is the point, a detour when a prerequisite is doing real work, and every formula read aloud with a plain-words line right after it.&lt;/p&gt;

&lt;p&gt;Previously: &lt;a href="https://dev.to/blog/2026/10/convex-conjugate-and-variational-bound/"&gt;Section 3b: The convex conjugate and the variational bound&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 2 roadmap
&lt;/h2&gt;

&lt;p&gt;Week 2 picks up right where Week 1 stopped. Here is how the four sections of Week 2 fit together:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Section&lt;/th&gt;
&lt;th&gt;Topic&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;4a (this note)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;From the Week 1 lower bound to a trainable &lt;strong&gt;min–max game&lt;/strong&gt; (generator vs critic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4b&lt;/td&gt;
&lt;td&gt;The critic's output activation $\sigma_f$ and $\operatorname{dom} f^*$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4c&lt;/td&gt;
&lt;td&gt;GAN as a special case: picking one particular $f$ gives the familiar GAN loss&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4d&lt;/td&gt;
&lt;td&gt;Training a GAN in practice: mini-batches and alternating updates&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites for this note&lt;/strong&gt; (detours below): Week 1's lower bound on $D_f$, "an average is approximately an expectation", and what a saddle point is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Symbol cheat-sheet
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;Say it as&lt;/th&gt;
&lt;th&gt;In plain words&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$p_x(x)$&lt;/td&gt;
&lt;td&gt;"p-x of x"&lt;/td&gt;
&lt;td&gt;how likely real data is to land near $x$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$p_\theta(x)$&lt;/td&gt;
&lt;td&gt;"p-theta of x"&lt;/td&gt;
&lt;td&gt;how likely the generator model is to produce $x$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$g_\theta(z)$&lt;/td&gt;
&lt;td&gt;"g-theta of z"&lt;/td&gt;
&lt;td&gt;the generator neural network with weights $\theta$, taking noise $z$ and outputting a fake sample $\hat{x}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$T(x)$&lt;/td&gt;
&lt;td&gt;"T of x"&lt;/td&gt;
&lt;td&gt;a scoring function (critic) that takes one data point $x$ and returns one number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\mathcal{T}$&lt;/td&gt;
&lt;td&gt;"script T"&lt;/td&gt;
&lt;td&gt;the menu (family) of scoring functions we are allowed to pick from&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$T_w(x)$&lt;/td&gt;
&lt;td&gt;"T-w of x"&lt;/td&gt;
&lt;td&gt;a neural-network critic with weights $w$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$w$&lt;/td&gt;
&lt;td&gt;"w"&lt;/td&gt;
&lt;td&gt;the critic network's adjustable weights&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$f^*(t)$&lt;/td&gt;
&lt;td&gt;"f-star of t"&lt;/td&gt;
&lt;td&gt;the convex conjugate of $f$: a fixed penalty transform determined by which divergence we chose&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$J(\theta, w)$&lt;/td&gt;
&lt;td&gt;"J of theta and w"&lt;/td&gt;
&lt;td&gt;the single game score: how well critic $w$ separates real data from fakes made by generator $\theta$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\max_{T \in \mathcal{T}}$&lt;/td&gt;
&lt;td&gt;"max over T in script-T"&lt;/td&gt;
&lt;td&gt;try every function $T$ in the family $\mathcal{T}$ and keep the one giving the biggest value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\arg\min_\theta$&lt;/td&gt;
&lt;td&gt;"arg-min over theta"&lt;/td&gt;
&lt;td&gt;the setting of $\theta$ that makes the expression smallest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\approx$&lt;/td&gt;
&lt;td&gt;"approximately equals"&lt;/td&gt;
&lt;td&gt;close to, but not exact (because we minimise a lower bound)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Section 4a: From the variational bound to a trainable min-max game
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Intuition first
&lt;/h3&gt;

&lt;p&gt;In Week 1 we wanted to make our model distribution $p_\theta$ match the real data distribution $p_x$ by shrinking a distance between them (the f-divergence $D_f$). The problem: we cannot compute that distance directly, because we do not know either density formula. We only have samples.&lt;/p&gt;

&lt;p&gt;Week 1 ended with a workaround: a &lt;strong&gt;lower bound&lt;/strong&gt; on $D_f$ that only needs averages over samples, but it contains a "maximise over all functions $T$" step. This section answers: &lt;em&gt;how do you actually maximise over "all functions" on a computer?&lt;/em&gt; Answer: use a neural network for $T$, and you get a two-player game.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Real-world analogy
&lt;/h3&gt;

&lt;p&gt;Think of a &lt;strong&gt;fraud-detection team vs. a fraudster&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The fraudster (the &lt;strong&gt;generator&lt;/strong&gt;, $g_\theta$) produces fake transactions.&lt;/li&gt;
&lt;li&gt;The fraud team (the &lt;strong&gt;critic&lt;/strong&gt;, $T_w$) builds a scoring model that gives real transactions high scores and fakes low scores.&lt;/li&gt;
&lt;li&gt;The quality of the fraud team's best scoring model is a measure of how &lt;em&gt;different&lt;/em&gt; fakes still are from real ones. If even the best detector cannot separate them, the fakes are indistinguishable from real traffic.&lt;/li&gt;
&lt;li&gt;The fraudster improves the fakes to make even the best detector useless.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the exact mathematical structure: the critic &lt;strong&gt;maximises&lt;/strong&gt; a separation score, and the generator &lt;strong&gt;minimises&lt;/strong&gt; that best-achievable score.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Visual
&lt;/h3&gt;

&lt;p&gt;The critic only ever sees samples (real ones and fake ones), and the generator only ever sees noise. All the learning signal flows through the single game score $J(\theta, w)$.&lt;/p&gt;

&lt;p&gt;Things to watch in the widget:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Move the critic slider $w$:&lt;/strong&gt; the blue curve shows $J(\theta, w)$ as a hill over $w$. The coral dot is the current critic's score $J(\theta, w)$, which always sits at or below the dashed green ceiling $D_{KL}(p_x \,|\, p_\theta)$.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click "Snap critic to $w^*(\theta)$":&lt;/strong&gt; the critic climbs to the top of the hill, where the lower bound touches the true KL divergence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move the generator slider $\theta$ toward $0.50$:&lt;/strong&gt; the entire hill sinks down until its peak hits 0 at the saddle point $(\theta^* = 0.50, w^* = 0)$.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. The formulas, decoded
&lt;/h3&gt;

&lt;p&gt;Before we start, here is a quick recap of the Week 1 ingredient this all rests on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detour 1: The Week 1 lower bound (what $f^*$ and $T$ are)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Week 1, the f-divergence was defined as&lt;/p&gt;

&lt;p&gt;$$D_f(p_x \,|\, p_\theta) = \int_{\mathcal{X}} p_\theta(x)\, f!\left(\frac{p_x(x)}{p_\theta(x)}\right) dx$$&lt;/p&gt;

&lt;p&gt;Read aloud: "the f-divergence from $p_x$ to $p_\theta$ is: at every point $x$, take the ratio of real density to model density, push it through the function $f$, weight it by how often the model visits $x$, and add up over all $x$."&lt;/p&gt;

&lt;p&gt;In plain words: it is a model-weighted measure of how far the ratio $\text{real}/\text{model}$ is from 1, on average.&lt;/p&gt;

&lt;p&gt;The trouble is that this formula needs the density formulas for $p_x$ and $p_\theta$, which we do not have. Week 1's trick was the &lt;strong&gt;convex conjugate&lt;/strong&gt; $f^*$: every convex $f$ can be rewritten as "the best of many straight lines",&lt;/p&gt;

&lt;p&gt;$$f(u) = \max_t \,\big[\,t\,u - f^*(t)\,\big]$$&lt;/p&gt;

&lt;p&gt;Read aloud: "$f$ of $u$ equals the maximum over $t$ of $t$ times $u$ minus $f$-star of $t$."&lt;/p&gt;

&lt;p&gt;In plain words: any bowl-shaped curve equals the upper envelope of its tangent lines. Plugging that into $D_f$ and swapping the order gave an expression that only contains &lt;strong&gt;averages&lt;/strong&gt;, which we &lt;em&gt;can&lt;/em&gt; estimate from samples. The price: we have to choose a slope $t$ for every $x$ — a whole &lt;strong&gt;function&lt;/strong&gt; $T(x)$ — and we only get a &lt;strong&gt;lower bound&lt;/strong&gt; unless we pick $T$ perfectly.&lt;/p&gt;

&lt;p&gt;Back to the main thread. That brings us to the first equation of Week 2.&lt;/p&gt;

&lt;h4&gt;
  
  
  Formula 1: The lower bound
&lt;/h4&gt;

&lt;p&gt;$$D_f(p_x \,|\, p_\theta) \;\ge\; \max_{T \in \mathcal{T}}\; \Big[\, \mathbb{E}&lt;em&gt;{x\sim p_x}[T(x)] \;-\; \mathbb{E}&lt;/em&gt;{x\sim p_\theta}\big[f^*(T(x))\big] \,\Big]$$&lt;/p&gt;

&lt;p&gt;Read aloud: "The divergence between the real distribution and the model is at least as big as the best value you can get, over all functions $T$ in some family $\mathcal{T}$, of: the average of $T$ on real samples, minus the average of $f^*$-of-$T$ on model samples."&lt;/p&gt;

&lt;p&gt;Piece by piece:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;Everyday meaning&lt;/th&gt;
&lt;th&gt;Type / shape&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$\ge$&lt;/td&gt;
&lt;td&gt;"is at least"&lt;/td&gt;
&lt;td&gt;comparison&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\max_{T\in\mathcal{T}}$&lt;/td&gt;
&lt;td&gt;"try every function $T$ in the family $\mathcal{T}$ and keep the one giving the biggest value"&lt;/td&gt;
&lt;td&gt;optimisation over functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$T(x)$&lt;/td&gt;
&lt;td&gt;a &lt;strong&gt;scoring function&lt;/strong&gt;: takes one data point, returns one number&lt;/td&gt;
&lt;td&gt;function from data space $\mathcal{X}$ (e.g. $\mathbb{R}^d$) to $\mathbb{R}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\mathcal{T}$&lt;/td&gt;
&lt;td&gt;the "menu" of scoring functions we are allowed to pick from&lt;/td&gt;
&lt;td&gt;a set of functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\mathbb{E}_{x\sim p_x}[\cdot]$&lt;/td&gt;
&lt;td&gt;"the average value you would get if you drew many $x$'s from the real data"&lt;/td&gt;
&lt;td&gt;a single number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\mathbb{E}&lt;em&gt;{x\sim p&lt;/em&gt;\theta}[\cdot]$&lt;/td&gt;
&lt;td&gt;same, but drawing $x$ from the model (generated samples)&lt;/td&gt;
&lt;td&gt;a single number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$f^*$&lt;/td&gt;
&lt;td&gt;the convex conjugate of $f$: a fixed penalty transform that depends on which divergence you chose&lt;/td&gt;
&lt;td&gt;function from a number to a number&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In plain words: reward $T$ for giving high scores to real data, penalise it (through $f^*$) for giving high scores to fake data; the best possible net score is a guaranteed underestimate of how different the two distributions are.&lt;/p&gt;

&lt;p&gt;Why it is a lower bound and not an equality: equality only holds if the menu $\mathcal{T}$ contains the perfect scorer, which &lt;a href="https://dev.to/blog/2026/10/convex-conjugate-and-variational-bound/"&gt;Section 3b&lt;/a&gt; showed is&lt;/p&gt;

&lt;p&gt;$$T^*(x) = f'!\left(\frac{p_x(x)}{p_\theta(x)}\right)$$&lt;/p&gt;

&lt;p&gt;Read aloud: "T-star at $x$ equals $f$-prime evaluated at the ratio of $p_x(x)$ to $p_\theta(x)$."&lt;/p&gt;

&lt;p&gt;In plain words: the ideal critic outputs the slope of $f$ at the true density ratio. A smaller menu $\mathcal{T}$ can only do worse, so the max can only be smaller.&lt;/p&gt;

&lt;h4&gt;
  
  
  Formula 2: The training objective
&lt;/h4&gt;

&lt;p&gt;We want $\theta^* = \arg\min_\theta D_f(p_x \,|\, p_\theta)$. Since we cannot compute $D_f$, we swap it for its lower bound:&lt;/p&gt;

&lt;p&gt;$$\theta^* \;\approx\; \arg\min_{\theta}\; \max_{T\in\mathcal{T}}\Big[\,\mathbb{E}&lt;em&gt;{p_x}[T(x)] - \mathbb{E}&lt;/em&gt;{p_\theta}\big[f^*(T(x))\big]\,\Big]$$&lt;/p&gt;

&lt;p&gt;Read aloud: "The best generator parameters $\theta^*$ are approximately those that minimise, over $\theta$, the best score any critic $T$ in $\mathcal{T}$ can achieve."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The outer &lt;strong&gt;min&lt;/strong&gt; is over $\theta$, the weights of the generator $g_\theta(z)$.&lt;/li&gt;
&lt;li&gt;The inner &lt;strong&gt;max&lt;/strong&gt; is over $T$, a class of critic functions $T(x) \in \mathcal{T}$.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;$\approx$&lt;/strong&gt; matters: we are minimising a lower bound, not the true divergence. If the critic family $\mathcal{T}$ is weak, the bound is loose, and the generator may appear to have low loss even when its samples are poor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In plain words: pick the generator such that even the best possible critic can barely tell real from fake.&lt;/p&gt;

&lt;h4&gt;
  
  
  Formula 3: Making "max over all functions" computable
&lt;/h4&gt;

&lt;p&gt;"Max over a set of functions" is not something a computer can execute directly. The fix: let the menu $\mathcal{T}$ be &lt;strong&gt;every function a particular neural network architecture can represent&lt;/strong&gt;. A network $T_w(x)$ with weights $w$ is a function; changing $w$ changes the function. So "search over functions" becomes "search over weights $w$", which gradient ascent can do:&lt;/p&gt;

&lt;p&gt;$$\theta^&lt;em&gt;,\, w^&lt;/em&gt; \;=\; \arg\min_{\theta}\;\max_{w}\;\Big[\,\mathbb{E}&lt;em&gt;{x\sim p_x}[T_w(x)] \;-\; \mathbb{E}&lt;/em&gt;{x\sim p_\theta}\big[f^*(T_w(x))\big]\,\Big]$$&lt;/p&gt;

&lt;p&gt;Read aloud: "Find the generator weights $\theta^&lt;em&gt;$ and critic weights $w^&lt;/em&gt;$ such that $\theta$ minimises, and $w$ maximises, the critic's net score."&lt;/p&gt;

&lt;p&gt;In plain words: replace the abstract function search with a neural network $T_w$, so both players are just tuning network weights.&lt;/p&gt;

&lt;p&gt;The lectures name the bracket $J(\theta, w)$:&lt;/p&gt;

&lt;p&gt;$$J(\theta, w) = \mathbb{E}&lt;em&gt;{x\sim p_x}[T_w(x)] - \mathbb{E}&lt;/em&gt;{x\sim p_\theta}\big[f^*(T_w(x))\big]$$&lt;/p&gt;

&lt;p&gt;Read aloud: "J of theta and w equals the expected value of $T_w(x)$ under $p_x$ minus the expected value of $f^*(T_w(x))$ under $p_\theta$."&lt;/p&gt;

&lt;p&gt;In plain words: $J(\theta, w)$ is one single number measuring how well critic $w$ separates real data from fake data produced by generator $\theta$.&lt;/p&gt;

&lt;p&gt;One step the slides leave implicit — and the reason gradients can reach $\theta$ — is how $\theta$ enters the second average. Because fake samples are made as $\hat{x} = g_\theta(z)$ with $z \sim \mathcal{N}(0, I)$, we rewrite the second term as:&lt;/p&gt;

&lt;p&gt;$$\mathbb{E}&lt;em&gt;{x\sim p&lt;/em&gt;\theta}\big[f^&lt;em&gt;(T_w(x))\big] = \mathbb{E}_{z\sim\mathcal{N}(0,I)}\big[f^&lt;/em&gt;\big(T_w(g_\theta(z))\big)\big]$$&lt;/p&gt;

&lt;p&gt;Read aloud: "the expected value of $f^&lt;em&gt;(T_w(x))$ for $x$ drawn from $p_\theta$ equals the expected value of $f^&lt;/em&gt;(T_w(g_\theta(z)))$ for noise $z$ drawn from a standard normal."&lt;/p&gt;

&lt;p&gt;In plain words: averaging over model samples is the exact same thing as drawing random noise vectors $z$, running each one through the generator $g_\theta(z)$, and averaging the critic's penalty on the resulting fakes. We never need a density formula for $p_\theta$.&lt;/p&gt;

&lt;h4&gt;
  
  
  Saddle point and adversarial training
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Detour 2: What is a saddle point?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Picture a horse saddle (or a Pringle crisp). Walking front-to-back, the centre is the &lt;strong&gt;lowest&lt;/strong&gt; point; walking side-to-side, it is the &lt;strong&gt;highest&lt;/strong&gt; point. A point that is a minimum in one direction and a maximum in another is a &lt;strong&gt;saddle point&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;$$J(\theta^&lt;em&gt;, w) \;\le\; J(\theta^&lt;/em&gt;, w^&lt;em&gt;) \;\le\; J(\theta, w^&lt;/em&gt;)$$&lt;/p&gt;

&lt;p&gt;Read aloud: "$J$ at $(\theta^&lt;em&gt;, w)$ is at most $J$ at $(\theta^&lt;/em&gt;, w^&lt;em&gt;)$, which in turn is at most $J$ at $(\theta, w^&lt;/em&gt;)$."&lt;/p&gt;

&lt;p&gt;In plain words: at the saddle point $(\theta^&lt;em&gt;, w^&lt;/em&gt;)$, if the critic changes $w$, the score $J$ cannot go up (the critic is already doing its best), and if the generator changes $\theta$, the score $J$ cannot go down (the generator is already doing its best). Neither player wants to move.&lt;/p&gt;

&lt;p&gt;Back to the main thread. That is why the lectures call this &lt;strong&gt;saddle-point optimisation&lt;/strong&gt; and an &lt;strong&gt;adversarial problem&lt;/strong&gt;: two players pulling one single number $J(\theta, w)$ in opposite directions.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Ordinary model training&lt;/th&gt;
&lt;th&gt;VDM / GAN training&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Players&lt;/td&gt;
&lt;td&gt;One network&lt;/td&gt;
&lt;td&gt;Two networks (generator $\theta$, critic $w$)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Goal&lt;/td&gt;
&lt;td&gt;Minimise a single loss&lt;/td&gt;
&lt;td&gt;$\min_\theta \max_w J(\theta, w)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solution geometry&lt;/td&gt;
&lt;td&gt;Bottom of a bowl (minimum)&lt;/td&gt;
&lt;td&gt;Saddle point (min in $\theta$, max in $w$)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Training stability&lt;/td&gt;
&lt;td&gt;Usually steady descent&lt;/td&gt;
&lt;td&gt;Can oscillate because each player's target moves&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  5. Tiny worked example
&lt;/h3&gt;

&lt;p&gt;Use the forward KL divergence from Week 1: $f(u) = u\ln u$, whose conjugate is $f^*(t) = e^{t-1}$. Data lives on two points, $a$ and $b$:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Outcome&lt;/th&gt;
&lt;th&gt;$p_x$ (real)&lt;/th&gt;
&lt;th&gt;$p_\theta$ (model)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$a$&lt;/td&gt;
&lt;td&gt;$0.5$&lt;/td&gt;
&lt;td&gt;$0.8$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$b$&lt;/td&gt;
&lt;td&gt;$0.5$&lt;/td&gt;
&lt;td&gt;$0.2$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;First, the true KL divergence:&lt;/p&gt;

&lt;p&gt;$$D_{KL}(p_x \,|\, p_\theta) = 0.5\ln!\left(\frac{0.5}{0.8}\right) + 0.5\ln!\left(\frac{0.5}{0.2}\right) = 0.5(-0.470) + 0.5(0.916) \approx 0.223$$&lt;/p&gt;

&lt;p&gt;Read aloud: "0.5 times natural log of 0.5 over 0.8, plus 0.5 times natural log of 0.5 over 0.2, equals approximately 0.223."&lt;/p&gt;

&lt;p&gt;In plain words: the true KL gap between these two coins is $0.223$.&lt;/p&gt;

&lt;p&gt;Now let three different critics try. For each critic,&lt;/p&gt;

&lt;p&gt;$$J(\theta, w) = \Big(0.5\,T(a) + 0.5\,T(b)\Big) - \Big(0.8\,e^{T(a)-1} + 0.2\,e^{T(b)-1}\Big)$$&lt;/p&gt;

&lt;p&gt;Read aloud: "$J$ equals the real average of $T$ minus the model average of $e^{T-1}$."&lt;/p&gt;

&lt;p&gt;In plain words: average score on real coin flips minus average exponential penalty on model coin flips.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Critic&lt;/th&gt;
&lt;th&gt;$T(a)$&lt;/th&gt;
&lt;th&gt;$T(b)$&lt;/th&gt;
&lt;th&gt;Avg $T$ on real&lt;/th&gt;
&lt;th&gt;Avg $f^*(T)$ on model&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;$J(\theta, w)$&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lazy (constant)&lt;/td&gt;
&lt;td&gt;$1.0$&lt;/td&gt;
&lt;td&gt;$1.0$&lt;/td&gt;
&lt;td&gt;$1.000$&lt;/td&gt;
&lt;td&gt;$0.8(1) + 0.2(1) = 1.000$&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.000$&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decent&lt;/td&gt;
&lt;td&gt;$0.8$&lt;/td&gt;
&lt;td&gt;$1.5$&lt;/td&gt;
&lt;td&gt;$1.150$&lt;/td&gt;
&lt;td&gt;$0.8(0.819) + 0.2(1.649) = 0.985$&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.165$&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Perfect: $T^* = 1 + \ln(p_x/p_\theta)$&lt;/td&gt;
&lt;td&gt;$0.530$&lt;/td&gt;
&lt;td&gt;$1.916$&lt;/td&gt;
&lt;td&gt;$1.223$&lt;/td&gt;
&lt;td&gt;$0.8(0.625) + 0.2(2.5) = 1.000$&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.223$&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What the table shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every critic gives $J \le 0.223$ (matching the "$\ge$" in Formula 1), and only the optimal critic hits $0.223$.&lt;/li&gt;
&lt;li&gt;The good critic scores &lt;strong&gt;$b$ higher&lt;/strong&gt;, because $b$ is where real data is under-produced by the model ($0.5$ vs $0.2$). That is the critic pointing at what the generator gets wrong.&lt;/li&gt;
&lt;li&gt;Now the generator moves: if $\theta$ changes so $p_\theta = (0.5, 0.5)$, the true KL drops to $0$, and the best any critic can achieve is $J = 0$. The generator wins when no critic can score above zero.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In practice, those averages come from mini-batch samples: for instance, four real draws ${a, a, b, b}$ give sample average $(0.530 + 0.530 + 1.916 + 1.916)/4 = 1.223$, matching the exact expectation by the Law of Large Numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Connect back
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Week 1 (&lt;a href="https://dev.to/blog/2026/10/convex-conjugate-and-variational-bound/"&gt;Section 3b&lt;/a&gt;)&lt;/strong&gt; gave the variational lower bound with an abstract $\sup_T$.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;This note (Section 4a)&lt;/strong&gt; makes it concrete: $T$ becomes a neural network $T_w$, and training becomes the two-player saddle-point game $\min_\theta \max_w J(\theta, w)$. This general recipe is called &lt;strong&gt;f-GAN&lt;/strong&gt; or &lt;strong&gt;Variational Divergence Minimisation (VDM)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next (Section 4b):&lt;/strong&gt; $T_w$ must output numbers that lie inside $\operatorname{dom} f^&lt;em&gt;$ (since some $f^&lt;/em&gt;$ only accept restricted ranges), which we enforce with an output activation $\sigma_f$.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Section 4c:&lt;/strong&gt; picking one specific $f$ turns $J(\theta, w)$ into the classic GAN loss $\mathbb{E}[\log D(x)] + \mathbb{E}[\log(1 - D(g_\theta(z)))]$.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Week 6 (WGAN):&lt;/strong&gt; replaces f-divergences with the Wasserstein distance while keeping this exact generator-vs-critic game shape.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quick check (optional)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Why can minimising $J(\theta, w)$ over $\theta$ fool you into thinking the generator is good, even when it is not?&lt;/li&gt;
&lt;li&gt;In $J(\theta, w)$, which of the two averages actually depends on $\theta$, and how does $\theta$ get in there?&lt;/li&gt;
&lt;li&gt;If the critic network were tiny (say, it could only output constants $T_w(x) = c$), what would $\max_w J(\theta, w)$ always equal, and what would that mean for training?&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>deeplearning</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Section 3b: The convex conjugate and the variational bound</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Mon, 19 Oct 2026 12:56:25 +0000</pubDate>
      <link>https://dev.to/dks/section-3b-the-convex-conjugate-and-the-variational-bound-3hh2</link>
      <guid>https://dev.to/dks/section-3b-the-convex-conjugate-and-the-variational-bound-3hh2</guid>
      <description>&lt;p&gt;I am working through &lt;a href="https://www.youtube.com/playlist?list=PLZ2ps__7DhBa5xCmncgH7kPqLqMBq7xlu" rel="noopener noreferrer"&gt;Mathematical Foundations of Generative AI&lt;/a&gt;, Prof. Prathosh AP's public lectures. The playlist is the spine. These notes are my deep dive on each section: a visual when the picture is the point, a detour when a prerequisite is doing real work, and the formula in my own words.&lt;/p&gt;

&lt;p&gt;Previously: &lt;a href="https://dev.to/blog/2026/10/f-divergences-in-generative-models/"&gt;Section 3a: f-divergences&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 3b: The convex conjugate and the variational bound
&lt;/h2&gt;

&lt;p&gt;This is the last part of Week 1, and it fixes the catch from 3a: I cannot compute $D_f$ directly because it needs the densities $P_x(x)$ and $P_\theta(x)$, and I only have samples. By the end of this section, $D_f$ is rewritten using only averages over samples. That rewritten form is the GAN objective in disguise.&lt;/p&gt;

&lt;p&gt;The statement I am carrying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;$$D_f(P_x \,|\, P_\theta) \;\ge\; \sup_{T \in \mathcal{T}} \Big( \mathbb{E}&lt;em&gt;{x \sim P_x}[T(x)] \;-\; \mathbb{E}&lt;/em&gt;{x \sim P_\theta}\big[f^*(T(x))\big] \Big)$$&lt;/p&gt;

&lt;p&gt;where $f^&lt;em&gt;$ is the convex conjugate of $f$, and $T: \mathcal{X} \to \operatorname{dom} f^&lt;/em&gt;$ ranges over a class of functions $\mathcal{T}$.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt; sup vs max, the convex conjugate itself (the main detour), optimising pointwise inside an integral, and "a max over fewer options can only be smaller." Each gets a short detour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Roadmap of the derivation:&lt;/strong&gt; (1) write $f$ as a max over straight lines (conjugate duality) → (2) plug that into the $D_f$ integral → (3) let the best slope depend on $x$, making it a function $T(x)$ → (4) restrict $T$ to a family I can search over, which turns "=" into "≥" → (5) recognise both terms as expectations, which I can estimate from samples.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Intuition first
&lt;/h3&gt;

&lt;p&gt;A convex (bowl-shaped) curve can be completely rebuilt from its tangent lines: draw enough of them and their upper envelope traces out the curve exactly. Straight lines are easy to work with, so I replace $f$ by "the best of all straight lines." When I plug that into the divergence, the awkward density ratio separates into two plain averages, one over real data and one over model data. Computing the divergence then becomes a search problem: find the function $T$ that scores real samples high and model samples low.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Real-world analogy
&lt;/h3&gt;

&lt;p&gt;I cannot directly measure how different synthetic traffic is from real traffic, because I do not have formulas for either. But I can hire an auditor, $T$: a scoring function that looks at any single request and outputs a number.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The auditor gets credit for giving real requests high scores: $\mathbb{E}_{P_x}[T(x)]$.&lt;/li&gt;
&lt;li&gt;The auditor pays a penalty for giving synthetic requests high scores: $\mathbb{E}&lt;em&gt;{P&lt;/em&gt;\theta}[f^*(T(x))]$.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The auditor's net score only needs request samples from both sources, never a formula. A lazy auditor gets a low net score. The best possible auditor's net score equals the true divergence. So "how different are the two traffic sources?" becomes "how well can the best auditor tell them apart?"&lt;/p&gt;

&lt;p&gt;That is precisely what a GAN discriminator is. The generator is the traffic generator trying to fool the auditor.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Visual: the conjugate as tangent lines
&lt;/h3&gt;

&lt;p&gt;The core picture is how a convex $f$ relates to its conjugate $f^&lt;em&gt;$. Here $f(u) = u \log u$ (the forward-KL $f$). Drag the slope $t$ and watch the tangent line slide along the curve. The vertical gap shown is $f^&lt;/em&gt;(t)$. Then switch on "show envelope".&lt;/p&gt;

&lt;p&gt;Things to notice:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For each slope $t$, the dashed line $t \cdot u$ sits above the curve at some points. The biggest vertical gap between them (the coral segment) is $f^*(t)$. Shift the dashed line down by exactly that amount and I get the green line, which just touches the curve: a tangent.&lt;/li&gt;
&lt;li&gt;Turn on the envelope. Each green line lies on or below the purple curve, and together their upper edge is the curve. That is the statement $f^{**} = f$: a convex function is the maximum of its tangent lines.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  4. The formula, decoded
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Detour 1: sup vs max&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;$\sup$ ("supremum") means "the smallest upper bound": it behaves like max, but also works when the maximum is approached but never reached. Example: the values $1 - \tfrac1n$ for $n = 1, 2, 3, \dots$ never reach 1, yet their sup is 1. For this course, I read sup as max; the distinction almost never matters for exam purposes.&lt;/p&gt;

&lt;p&gt;Back to the main thread. Wherever I see $\sup$ below, I think "best possible."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detour 2: The convex conjugate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The lectures define it as&lt;/p&gt;

&lt;p&gt;$$f^*(t) = \sup_{u \in \operatorname{dom} f} \big( t u - f(u) \big)$$&lt;/p&gt;

&lt;p&gt;Read aloud: "for slope $t$, $f^*(t)$ is the largest amount by which the straight line $t \cdot u$ exceeds the curve $f(u)$." That is exactly the coral gap in the widget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worked computation for $f(u) = u \log u$:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I maximise $h(u) = t u - u \log u$ over $u &amp;gt; 0$.&lt;/li&gt;
&lt;li&gt;Set the derivative to zero: $h'(u) = t - (\log u + 1) = 0$ (product rule on $u \log u$ gives $\log u + 1$).&lt;/li&gt;
&lt;li&gt;So $\log u^* = t - 1$, i.e. $u^* = e^{t-1}$. That is the touch point shown in the widget.&lt;/li&gt;
&lt;li&gt;Substitute back: $f^*(t) = t e^{t-1} - e^{t-1}(t-1) = e^{t-1}$.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the conjugate of the KL function is $f^&lt;em&gt;(t) = e^{t-1}$. Check with the widget at $t = 1$: $u^&lt;/em&gt; = 1$ and $f^*(1) = e^0 = 1$ ✓.&lt;/p&gt;

&lt;p&gt;Two properties I keep on hand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(i) $f^*$ is also convex.&lt;/li&gt;
&lt;li&gt;(ii) Taking the conjugate twice gives back the original: $f^{**} = f$. Written out:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;$$f(u) = \sup_{t \in \operatorname{dom} f^&lt;em&gt;} \big( t u - f^&lt;/em&gt;(t) \big)$$&lt;/p&gt;

&lt;p&gt;Read aloud: "$f$ at any point $u$ equals the highest tangent line at that point." That is the envelope picture. (This is where lower-semicontinuity from 3a is needed: it is the technical condition that makes $f^{**} = f$ hold exactly.)&lt;/p&gt;

&lt;p&gt;Back to the main thread. Property (ii) is the key move. It replaces the awkward $f(\cdot)$ with "the best of a set of straight lines," and straight lines are linear in $u$. Linearity is what will let the density ratio separate into two clean expectations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detour 3: Optimising pointwise inside an integral&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose I want $\int \sup_t g(x, t)\, dx$. At each $x$, there is a best $t$, and it may differ from one $x$ to another. Collect those best choices into a function: $T(x) = $ "the best $t$ at point $x$." Then&lt;/p&gt;

&lt;p&gt;$$\int \sup_t g(x, t)\, dx = \sup_{T} \int g\big(x, T(x)\big)\, dx$$&lt;/p&gt;

&lt;p&gt;The sup on the right is over all functions $T$, i.e. a whole lookup table of choices, one per $x$.&lt;/p&gt;

&lt;p&gt;Analogy: choosing the best price for each product separately is the same as choosing the best pricing table for the whole catalogue.&lt;/p&gt;

&lt;p&gt;Back to the main thread. This is the step where "a number $t$" becomes "a function $T(x)$." The lectures flag it explicitly: "the solution for the inner problem depends on $x$ (a function of $x$)."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detour 4: A restricted search can only do worse&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I search a smaller set of options, the best I find can only be as good or worse:&lt;/p&gt;

&lt;p&gt;$$\max_{\text{small set}} \;\le\; \max_{\text{everything}}$$&lt;/p&gt;

&lt;p&gt;Example: the best restaurant within 1 km is never better than the best restaurant in the whole city.&lt;/p&gt;

&lt;p&gt;Back to the main thread. In practice I cannot search all functions $T$; I search a restricted family $\mathcal{T}$, such as neural networks of a given shape. That is why the final result is "≥", not "=".&lt;/p&gt;

&lt;h3&gt;
  
  
  The derivation, step by step
&lt;/h3&gt;

&lt;p&gt;$$&lt;br&gt;
\begin{aligned}&lt;br&gt;
D_f(P_x \,|\, P_\theta)&lt;br&gt;
&amp;amp;= \int P_\theta(x)\, f!\left(\frac{P_x(x)}{P_\theta(x)}\right) dx&lt;br&gt;
&amp;amp;&amp;amp; \text{definition (3a)} \[4pt]&lt;br&gt;
&amp;amp;= \int P_\theta(x)\, \sup_{t}\left( t\,\frac{P_x(x)}{P_\theta(x)} - f^&lt;em&gt;(t) \right) dx&lt;br&gt;
&amp;amp;&amp;amp; f = f^{&lt;/em&gt;&lt;em&gt;} \text{ (Detour 2), with } u = \tfrac{P_x}{P_\theta} \[4pt]&lt;br&gt;
&amp;amp;= \int \sup_{t}\Big( t\, P_x(x) - P_\theta(x)\, f^&lt;/em&gt;(t) \Big)\, dx&lt;br&gt;
&amp;amp;&amp;amp; \text{move } P_\theta(x) \ge 0 \text{ inside the sup; the ratio cancels} \[4pt]&lt;br&gt;
&amp;amp;= \sup_{T}\int \Big( T(x)\, P_x(x) - P_\theta(x)\, f^&lt;em&gt;\big(T(x)\big) \Big)\, dx&lt;br&gt;
&amp;amp;&amp;amp; \text{best } t \text{ per } x \text{ becomes a function } T(x) \text{ (Detour 3)} \[4pt]&lt;br&gt;
&amp;amp;\ge \sup_{T \in \mathcal{T}}\Big( \int P_x(x)\, T(x)\, dx - \int P_\theta(x)\, f^&lt;/em&gt;\big(T(x)\big)\, dx \Big)&lt;br&gt;
&amp;amp;&amp;amp; \text{restrict to a family } \mathcal{T} \text{ (Detour 4); split the integral} \[4pt]&lt;br&gt;
&amp;amp;= \sup_{T \in \mathcal{T}}\Big( \mathbb{E}&lt;em&gt;{x \sim P_x}[T(x)] - \mathbb{E}&lt;/em&gt;{x \sim P_\theta}\big[f^*(T(x))\big] \Big)&lt;br&gt;
&amp;amp;&amp;amp; \text{each integral is an expectation (3a, Detour 3)}&lt;br&gt;
\end{aligned}&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;Look at line 3. Multiplying through by $P_\theta(x)$ cancelled the denominator of the ratio. That is the magic moment: no more division by an unknown density. From there, each density appears alone, multiplying something, which is exactly the form of an expectation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In plain English:&lt;/strong&gt; the f-divergence is at least as large as the best achievable "score real samples high, score model samples low" game, and it is exactly equal when the search over $T$ is rich enough.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$T(x)$&lt;/td&gt;
&lt;td&gt;the critic / auditor&lt;/td&gt;
&lt;td&gt;function $\mathcal{X} \to \operatorname{dom} f^*$&lt;/td&gt;
&lt;td&gt;scores how "real" a point looks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\mathcal{T}$&lt;/td&gt;
&lt;td&gt;allowed critics&lt;/td&gt;
&lt;td&gt;a family of functions (later: neural nets $T_w$)&lt;/td&gt;
&lt;td&gt;the search space&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\mathbb{E}_{P_x}[T(x)]$&lt;/td&gt;
&lt;td&gt;average score on real data&lt;/td&gt;
&lt;td&gt;scalar&lt;/td&gt;
&lt;td&gt;estimate with dataset $D$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$f^*$&lt;/td&gt;
&lt;td&gt;convex conjugate of $f$&lt;/td&gt;
&lt;td&gt;convex function&lt;/td&gt;
&lt;td&gt;the penalty applied to scores on model data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\mathbb{E}&lt;em&gt;{P&lt;/em&gt;\theta}[f^*(T(x))]$&lt;/td&gt;
&lt;td&gt;average penalty on model samples&lt;/td&gt;
&lt;td&gt;scalar&lt;/td&gt;
&lt;td&gt;estimate with samples $g_\theta(z)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\sup_{T}$&lt;/td&gt;
&lt;td&gt;best critic&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;makes the bound as tight as possible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why this answers open question (i) from Section 2.&lt;/strong&gt; Using the law of large numbers from Section 1, both terms become plain sample averages:&lt;/p&gt;

&lt;p&gt;$$\widehat{D}&lt;em&gt;f \approx \frac{1}{n}\sum&lt;/em&gt;{i=1}^{n} T(x_i) \;-\; \frac{1}{m}\sum_{j=1}^{m} f^*\big(T(g_\theta(z_j))\big), \qquad x_i \in D,\;\; z_j \sim \mathcal{N}(0, I)$$&lt;/p&gt;

&lt;p&gt;No density value anywhere. I need only (a) real samples, which I have in $D$, (b) model samples, which I get by running $g_\theta$, and (c) a critic function $T$ to evaluate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A bonus fact (standard in the f-GAN literature, not spelled out in the Week 1 slides):&lt;/strong&gt; the bound is tight when $T^*(x) = f'!\left(\frac{P_x(x)}{P_\theta(x)}\right)$, the slope of $f$ at the density ratio. So the optimal critic is secretly computing the density ratio. That is why a trained discriminator "knows" how real each point looks.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Tiny worked example
&lt;/h3&gt;

&lt;p&gt;Same coin world as 3a: $P_x = (0.5, 0.5)$, $P_\theta = (0.8, 0.2)$. Forward KL, so $f^*(t) = e^{t-1}$. From 3a, the true $D_{KL} \approx 0.223$.&lt;/p&gt;

&lt;p&gt;For any critic $T = (T_1, T_2)$ (a score for each outcome), the bound is&lt;/p&gt;

&lt;p&gt;$$\text{bound}(T) = \underbrace{0.5\,T_1 + 0.5\,T_2}&lt;em&gt;{\mathbb{E}&lt;/em&gt;{P_x}[T]} \;-\; \underbrace{\big(0.8\,e^{T_1 - 1} + 0.2\,e^{T_2 - 1}\big)}&lt;em&gt;{\mathbb{E}&lt;/em&gt;{P_\theta}[f^*(T)]}$$&lt;/p&gt;

&lt;p&gt;Try three critics:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Critic $T = (T_1, T_2)$&lt;/th&gt;
&lt;th&gt;$\mathbb{E}_{P_x}[T]$&lt;/th&gt;
&lt;th&gt;$\mathbb{E}&lt;em&gt;{P&lt;/em&gt;\theta}[e^{T-1}]$&lt;/th&gt;
&lt;th&gt;Bound&lt;/th&gt;
&lt;th&gt;vs true KL 0.223&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lazy: $(1, 1)$, scores everything the same&lt;/td&gt;
&lt;td&gt;1.000&lt;/td&gt;
&lt;td&gt;$0.8(1) + 0.2(1) = 1.000$&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.000&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;far below&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decent: $(0.8, 1.5)$, scores outcome 2 higher&lt;/td&gt;
&lt;td&gt;1.150&lt;/td&gt;
&lt;td&gt;$0.8(0.819) + 0.2(1.649) = 0.985$&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.165&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;closer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Optimal: $T_i = 1 + \ln u_i = (0.530, 1.916)$&lt;/td&gt;
&lt;td&gt;1.223&lt;/td&gt;
&lt;td&gt;$0.8(0.625) + 0.2(2.5) = 1.000$&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.223&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;exact ✓&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What to see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every critic gives a lower bound on the true KL. A bad critic gives a loose bound; it can never overshoot.&lt;/li&gt;
&lt;li&gt;The critic that scores outcome 2 higher does better. Outcome 2 is the one the model under-produces ($u_2 = 2.5$), so it is where real data "looks most real."&lt;/li&gt;
&lt;li&gt;The optimal critic is $f'(u) = 1 + \ln u$, applied to the true ratios from 3a. That is the bonus fact in action. It recovers the divergence exactly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In real training I would compute those two expectations as averages over samples instead of exact sums, and I would search over critics with gradient ascent instead of by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Notes on the lecture slides
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The slides write $T: \mathcal{X} \to \operatorname{dom} f^&lt;em&gt;$. That is important: the critic's outputs must lie where $f^&lt;/em&gt;$ is defined. For KL, $\operatorname{dom} f^* = \mathbb{R}$, so anything goes. For other $f$'s the domain is restricted, which is why Week 2 introduces the output activation $g_f$ that squashes the network's output into $\operatorname{dom} f^*$.&lt;/li&gt;
&lt;li&gt;The last line of the Week 1 notes is heavily garbled in my copy ("PA = T(p)p0(x) T(x)()…"). From context, it is the expectation form above with $\sup_{T \in \mathcal{T}}$, which matches the first line of the Week 2 notes ("$D_f \ge \max_T \mathbb{E}\,T(x) - \mathbb{E}\, f^*(T(x))$").&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Connect back
&lt;/h3&gt;

&lt;p&gt;This bound is the bridge from Week 1 to Week 2. Week 2 opens by making two substitutions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The critic becomes a neural network:&lt;/strong&gt; $T(x) \to T_w(x) = g_f(V_w(x))$, with weights $w$ and an $f$-specific output activation $g_f$.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimise over the generator:&lt;/strong&gt; I want the smallest divergence, so I wrap a $\min_\theta$ around the bound:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;$$\theta^&lt;em&gt;, w^&lt;/em&gt; = \arg\min_\theta \max_w \Big( \mathbb{E}&lt;em&gt;{x \sim P_x}[T_w(x)] - \mathbb{E}&lt;/em&gt;{z \sim \mathcal{N}(0, I)}\big[f^*\big(T_w(g_\theta(z))\big)\big] \Big)$$&lt;/p&gt;

&lt;p&gt;That min-max is Variational Divergence Minimisation (VDM). The critic $w$ maximises (gets the tightest estimate of the divergence); the generator $\theta$ minimises (shrinks the divergence). Pick the JS-like $f$, and it becomes exactly the GAN objective:&lt;/p&gt;

&lt;p&gt;$$\mathbb{E}&lt;em&gt;{x \sim P_x}[\log D_w(x)] + \mathbb{E}&lt;/em&gt;{z}\big[\log(1 - D_w(g_\theta(z)))\big]$$&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Week 1 concept&lt;/th&gt;
&lt;th&gt;Becomes in Week 2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;critic $T(x)$&lt;/td&gt;
&lt;td&gt;discriminator network $D_w(x)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\sup_T$&lt;/td&gt;
&lt;td&gt;discriminator training (gradient ascent on $w$)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\min_\theta$ of the bound&lt;/td&gt;
&lt;td&gt;generator training (gradient descent on $\theta$)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tightness of the bound&lt;/td&gt;
&lt;td&gt;how good the discriminator is&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With that, the four open questions from Section 2 all have Week 1 answers: (i) compute the divergence via the variational bound, using samples only; (ii) choose an $f$ from the f-divergence family; (iii) use neural networks for both $g_\theta$ and $T_w$; (iv) solve the min-max with alternating gradient steps, which Week 2 makes concrete.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick check (optional)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In the worked example, why can no critic $T$ ever give a bound above 0.223?&lt;/li&gt;
&lt;li&gt;Which single algebra step in the derivation removed the unknown density ratio, and why does that matter?&lt;/li&gt;
&lt;li&gt;In the sample-average formula $\widehat{D}_f$, where do the two sets of samples come from?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That wraps Week 1. Week 2 turns this bound into a working GAN: the VDM objective, the $g_f$ activations, and alternating training.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>computerscience</category>
      <category>deeplearning</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Solving for X: Cracking the Code of Linear Equations in Data Science</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Sun, 11 Oct 2026 07:28:59 +0000</pubDate>
      <link>https://dev.to/dks/solving-for-x-cracking-the-code-of-linear-equations-in-data-science-49ke</link>
      <guid>https://dev.to/dks/solving-for-x-cracking-the-code-of-linear-equations-in-data-science-49ke</guid>
      <description>&lt;p&gt;Alright, team! In our last post, we kicked off our dive into &lt;a href="https://dev.to/blog/2025/05/linear-algebra-for-data-science/"&gt;linear algebra for data science&lt;/a&gt; by looking at how we represent data using matrices and how we can spot linear relationships hiding in that data using the idea of the null space. Matrices are fundamental, and understanding those relationships is super powerful.&lt;/p&gt;

&lt;p&gt;Today, we're moving on to another absolute core concept: &lt;strong&gt;solving linear equations&lt;/strong&gt;. If you think about a ton of problems in data science, machine learning, and even everyday modeling, they often boil down to having a bunch of equations and needing to find the values that make them true. This is where solving matrix equations becomes key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Turning Equations into Matrix Problems: $AX=B$
&lt;/h3&gt;

&lt;p&gt;Generally, when you have a set of linear equations, you can write them in a neat matrix form that looks like this:&lt;/p&gt;

&lt;p&gt;$$AX = B$$&lt;/p&gt;

&lt;p&gt;Let's break down what's in this equation based on what we learned before:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$A$ is a matrix. If you have $M$ equations and $N$ variables, $A$ is typically an $M \times N$ matrix. As we saw, $M$ is the number of rows (equations in this case) and $N$ is the number of columns (variables).&lt;/li&gt;
&lt;li&gt;$X$ is a column vector containing the variables you're trying to solve for. Since $A$ has $N$ columns (variables), $X$ needs to have $N$ rows, so it's an $N \times 1$ matrix (a column vector).&lt;/li&gt;
&lt;li&gt;$B$ is a column vector containing the constants from the right-hand side of your equations. For the matrix multiplication to work out, $B$ needs to have the same number of rows as $A$, so it's an $M \times 1$ matrix.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, when you write $AX=B$, you're really representing a system of $M$ linear equations involving $N$ variables.&lt;/p&gt;

&lt;p&gt;Now, depending on how $M$ (the number of equations) stacks up against $N$ (the number of variables), things can play out in three main ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;$M = N$:&lt;/strong&gt; The number of equations is exactly the same as the number of variables. This is often the "nicest" case to solve.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;$M &amp;gt; N$:&lt;/strong&gt; You have more equations than variables. Think of it as having &lt;em&gt;too many&lt;/em&gt; rules for your variables to follow. Usually, this means there's no single perfect solution that satisfies &lt;em&gt;all&lt;/em&gt; the equations.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;$M &amp;lt; N$:&lt;/strong&gt; You have fewer equations than variables. This means you have &lt;em&gt;more&lt;/em&gt; variables than you strictly need for the given equations. In this scenario, you'll usually find that there are many, many possible solutions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We're going to look at these cases, and then see how a cool idea called the pseudo-inverse can bring them all together.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Quick Refresher on Rank
&lt;/h3&gt;

&lt;p&gt;Remember &lt;strong&gt;rank&lt;/strong&gt; from our last post? It's going to be super important here. The rank of a matrix is the number of its linearly independent rows or columns. Remember, row rank always equals column rank – you can't have a different number of independent rows versus columns!&lt;/p&gt;

&lt;p&gt;For an $M \times N$ matrix, the maximum possible rank it can have is the smaller of $M$ and $N$. If $M &amp;lt; N$, the max rank is $M$. If $N &amp;lt; M$, the max rank is $N$.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case 1: When Equations Equal Variables ($M=N$)
&lt;/h3&gt;

&lt;p&gt;This is the case where your matrix $A$ is square ($M \times N$ and $M=N$).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If $A$ is Full Rank:&lt;/strong&gt;&lt;br&gt;
"Full rank" here means the rank of the matrix is equal to $M$ (or $N$, since they're the same). What does this mean? It means all your equations on the left-hand side are independent. You can't create any one equation by combining the others.&lt;br&gt;
In this happy case, there is a &lt;strong&gt;unique solution&lt;/strong&gt; to $AX=B$. You might remember from algebra that you can solve this by finding the inverse of $A$, written as $A^{-1}$. The solution is simply:&lt;br&gt;
$$X = A^{-1}B$$&lt;br&gt;
You can find $A^{-1}$ if the determinant of $A$ is not zero. This is the standard, straightforward scenario.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;If $A$ is Not Full Rank:&lt;/strong&gt;&lt;br&gt;
This means the rank of $A$ is less than $M$. In this situation, some of your equations on the left-hand side are actually linear combinations of others – they are linearly dependent.&lt;br&gt;
When this happens, depending on what the values are on the right-hand side (in the $B$ vector), you get two possibilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Consistent System:&lt;/strong&gt; If the dependencies on the left-hand side match up &lt;em&gt;exactly&lt;/em&gt; with the dependencies on the right-hand side (the $B$ vector values), the equations are consistent. But because they are dependent, you don't have enough &lt;em&gt;independent&lt;/em&gt; equations to pin down a single solution. This leads to &lt;strong&gt;infinite solutions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Inconsistent System:&lt;/strong&gt; If the dependencies on the left-hand side &lt;em&gt;don't&lt;/em&gt; match up with the $B$ vector values, the equations are inconsistent. They contradict each other, and there is &lt;strong&gt;no solution&lt;/strong&gt; that can satisfy all of them.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at a couple of examples for this $M=N$ case:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Full Rank (Unique Solution)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider the system of equations:&lt;br&gt;
$x_1 + 3x_2 = 7$&lt;br&gt;
$2x_1 + 4x_2 = 10$&lt;/p&gt;

&lt;p&gt;In matrix form $AX=B$, this is:&lt;br&gt;
$$&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
1 &amp;amp; 3 \&lt;br&gt;
2 &amp;amp; 4&lt;br&gt;
\end{bmatrix}&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
x_1 \&lt;br&gt;
x_2&lt;/p&gt;

&lt;h1&gt;
  
  
  \end{bmatrix}
&lt;/h1&gt;

&lt;p&gt;\begin{bmatrix}&lt;br&gt;
7 \&lt;br&gt;
10&lt;br&gt;
\end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
Here, $A = \begin{bmatrix} 1 &amp;amp; 3 \ 2 &amp;amp; 4 \end{bmatrix}$. $M=2$, $N=2$.&lt;br&gt;
We can check if $A$ is full rank by calculating its determinant: $(1 \times 4) - (3 \times 2) = 4 - 6 = -2$. Since the determinant is not 0, the matrix is full rank (rank = 2).&lt;br&gt;
There is a unique solution, $X = A^{-1}B$. The inverse of $A$ is $\begin{bmatrix} -2 &amp;amp; 1.5 \ 1 &amp;amp; -0.5 \end{bmatrix}$.&lt;br&gt;
So, $X = \begin{bmatrix} -2 &amp;amp; 1.5 \ 1 &amp;amp; -0.5 \end{bmatrix} \begin{bmatrix} 7 \ 10 \end{bmatrix} = \begin{bmatrix} (-2 \times 7) + (1.5 \times 10) \ (1 \times 7) + (-0.5 \times 10) \end{bmatrix} = \begin{bmatrix} -14 + 15 \ 7 - 5 \end{bmatrix} = \begin{bmatrix} 1 \ 2 \end{bmatrix}$.&lt;br&gt;
The unique solution is $x_1 = 1$ and $x_2 = 2$. You can plug these back into the original equations to check ($1 + 3(2) = 7$, $2(1) + 4(2) = 10$). It works!&lt;/p&gt;

&lt;p&gt;You can solve this easily in software too. In R, you could define A and B and use the &lt;code&gt;solve()&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 2: Not Full Rank, Consistent (Infinite Solutions)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider the system:&lt;br&gt;
$x_1 + 2x_2 = 5$&lt;br&gt;
$2x_1 + 4x_2 = 10$&lt;/p&gt;

&lt;p&gt;In matrix form $AX=B$:&lt;br&gt;
$$&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
1 &amp;amp; 2 \&lt;br&gt;
2 &amp;amp; 4&lt;br&gt;
\end{bmatrix}&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
x_1 \&lt;br&gt;
x_2&lt;/p&gt;

&lt;h1&gt;
  
  
  \end{bmatrix}
&lt;/h1&gt;

&lt;p&gt;\begin{bmatrix}&lt;br&gt;
5 \&lt;br&gt;
10&lt;br&gt;
\end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
Here, $A = \begin{bmatrix} 1 &amp;amp; 2 \ 2 &amp;amp; 4 \end{bmatrix}$. $M=2$, $N=2$.&lt;br&gt;
Check the determinant: $(1 \times 4) - (2 \times 2) = 4 - 4 = 0$. The determinant is 0, so the matrix is not full rank (rank = 1). The columns are dependent (column 2 is 2 * column 1), and the rows are dependent (row 2 is 2 * row 1).&lt;/p&gt;

&lt;p&gt;Now, look at the equations themselves. The second equation $2x_1 + 4x_2 = 10$ is exactly 2 times the first equation $x_1 + 2x_2 = 5$. This dependency on the left-hand side ($2x_1 + 4x_2$ being $2 \times (x_1 + 2x_2)$) is &lt;em&gt;matched&lt;/em&gt; on the right-hand side ($10$ being $2 \times 5$).&lt;br&gt;
Since the left and right sides have the same linear dependency, the system is &lt;strong&gt;consistent&lt;/strong&gt;.&lt;br&gt;
However, because the second equation is just a scaled version of the first, you effectively only have &lt;em&gt;one&lt;/em&gt; independent equation ($x_1 + 2x_2 = 5$) with two variables ($x_1, x_2$). This means you have a "free" variable.&lt;br&gt;
You can pick &lt;em&gt;any&lt;/em&gt; value for $x_2$, and then calculate the $x_1$ that works ($x_1 = 5 - 2x_2$).&lt;br&gt;
For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If $x_2 = 0$, $x_1 = 5$. Solution: $(5, 0)$.&lt;/li&gt;
&lt;li&gt;If $x_2 = 1$, $x_1 = 3$. Solution: $(3, 1)$.&lt;/li&gt;
&lt;li&gt;If $x_2 = 2.5$, $x_1 = 0$. Solution: $(0, 2.5)$.
Since you can choose &lt;em&gt;any&lt;/em&gt; value for $x_2$, there are &lt;strong&gt;infinite solutions&lt;/strong&gt; to this system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example 3: Not Full Rank, Inconsistent (No Solution)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider the system:&lt;br&gt;
$x_1 + 2x_2 = 5$&lt;br&gt;
$2x_1 + 4x_2 = 9$&lt;/p&gt;

&lt;p&gt;In matrix form $AX=B$:&lt;br&gt;
$$&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
1 &amp;amp; 2 \&lt;br&gt;
2 &amp;amp; 4&lt;br&gt;
\end{bmatrix}&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
x_1 \&lt;br&gt;
x_2&lt;/p&gt;

&lt;h1&gt;
  
  
  \end{bmatrix}
&lt;/h1&gt;

&lt;p&gt;\begin{bmatrix}&lt;br&gt;
5 \&lt;br&gt;
9&lt;br&gt;
\end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
Here, $A = \begin{bmatrix} 1 &amp;amp; 2 \ 2 &amp;amp; 4 \end{bmatrix}$ is the same as before, so it's not full rank (rank = 1). The left-hand side has the same dependency (row 2 is 2 * row 1).&lt;br&gt;
But look at the right-hand side ($B$ vector). The first equation's right side is 5. If you multiply it by 2 (the scaling factor between the left-hand sides), you get $2 \times 5 = 10$.&lt;br&gt;
However, the second equation's right side is 9, not 10.&lt;br&gt;
The dependency on the left-hand side (where the second equation's left side is twice the first) does &lt;em&gt;not&lt;/em&gt; match the right-hand side ($9 \neq 2 \times 5$). The equations contradict each other ($2x_1 + 4x_2$ cannot equal both 10 &lt;em&gt;and&lt;/em&gt; 9 simultaneously based on the first equation).&lt;br&gt;
The system is &lt;strong&gt;inconsistent&lt;/strong&gt;, and there is &lt;strong&gt;no solution&lt;/strong&gt; that can satisfy both equations.&lt;/p&gt;

&lt;p&gt;So, for the $M=N$ case (square matrix A): if A is full rank, unique solution; if A is not full rank, check consistency – if consistent, infinite solutions; if inconsistent, no solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case 2: More Equations than Variables ($M &amp;gt; N$)
&lt;/h3&gt;

&lt;p&gt;Now let's look at the case where you have more equations than variables. Like trying to find two numbers ($x_1, x_2$) that satisfy five different conditions.&lt;/p&gt;

&lt;p&gt;$$AX = B \quad (\text{where M &amp;gt; N})$$&lt;/p&gt;

&lt;p&gt;Since you have more equations than variables, it's generally impossible to find a perfect solution $X$ that makes &lt;em&gt;every single&lt;/em&gt; equation true (i.e., makes $AX$ &lt;em&gt;exactly&lt;/em&gt; equal to $B$). If you could find such a perfect $X$, then $AX - B$ would be a vector of all zeros.&lt;/p&gt;

&lt;p&gt;But since a perfect solution is usually out of reach, what's the next best thing? We want to find a solution $X$ that gets us as &lt;em&gt;close&lt;/em&gt; as possible to satisfying all the equations. In other words, we want to find an $X$ that makes the difference between $AX$ and $B$ as small as possible.&lt;/p&gt;

&lt;p&gt;Think of $AX - B$ as a vector of "errors," where each element is the error in one equation.&lt;br&gt;
Equation 1 error: $e_1 = (A_{11}x_1 + A_{12}x_2 + ... + A_{1N}x_N) - B_1$&lt;br&gt;
Equation 2 error: $e_2 = (A_{21}x_1 + A_{22}x_2 + ... + A_{2N}x_N) - B_2$&lt;br&gt;
...&lt;br&gt;
Equation M error: $e_M = (A_{M1}x_1 + A_{M2}x_2 + ... + A_{MN}x_N) - B_M$&lt;/p&gt;

&lt;p&gt;The vector of errors is $E = AX - B$. We want to find the $X$ that makes this error vector $E$ as "small" as possible. How do we measure the size of a vector of errors? We don't just add the errors ($e_1 + e_2 + ...$), because positive and negative errors could cancel out, making a big overall error look like zero.&lt;/p&gt;

&lt;p&gt;A common way to measure the overall error is to minimize the sum of the &lt;em&gt;squared&lt;/em&gt; errors: $e_1^2 + e_2^2 + ... + e_M^2$. This is because squaring makes all the errors positive, and larger errors contribute more significantly. This approach is called finding the &lt;strong&gt;least squares solution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Minimizing the sum of squared errors ($e_1^2 + ... + e_M^2$) is the same as minimizing the squared length (or squared norm) of the error vector $E = AX - B$. We write the squared length of a vector $v$ as $||v||^2$, which is $v^T v$ (the vector transposed multiplied by the original vector).&lt;br&gt;
So, we want to minimize $||AX - B||^2$, which is $(AX - B)^T (AX - B)$.&lt;/p&gt;

&lt;p&gt;$$\text{Minimize } (AX - B)^T (AX - B)$$&lt;/p&gt;

&lt;p&gt;To find the $X$ that minimizes this, you can use calculus. You take the derivative of this expression with respect to the vector $X$ and set it equal to zero. After doing the calculus and some matrix algebra (which we won't go into detail here, just like the lecture), the equation you get to solve for $X$ is:&lt;/p&gt;

&lt;p&gt;$$A^T A X = A^T B$$&lt;/p&gt;

&lt;p&gt;Where $A^T$ is the transpose of matrix $A$ (you flip its rows and columns).&lt;/p&gt;

&lt;p&gt;Now, if the matrix $A^T A$ is invertible (which happens if the columns of the original matrix $A$ are linearly independent – related to the rank!), you can solve for $X$:&lt;/p&gt;

&lt;p&gt;$$X = (A^T A)^{-1} A^T B$$&lt;/p&gt;

&lt;p&gt;This solution $X$ is the &lt;strong&gt;least squares solution&lt;/strong&gt;. It's the $X$ that minimizes the sum of squared differences between $AX$ and $B$. This $X$ might not make $AX$ &lt;em&gt;exactly&lt;/em&gt; equal to $B$ (since a perfect solution might not exist), but it gives you the best possible fit in a least squares sense.&lt;/p&gt;

&lt;p&gt;This optimization perspective gives us a way to find a meaningful "solution" even when we have more equations than variables, a common situation in data fitting.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's Next?
&lt;/h3&gt;

&lt;p&gt;So far, we've covered the case where $M=N$ (same number of equations and variables) and the case where $M &amp;gt; N$ (more equations than variables), introducing the idea of the least squares solution for the latter.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/blog/2025/05/solving-linear-equations-in-data-science-part-2/"&gt;Part 2: Tackling Tougher Linear Equations in Data Science&lt;/a&gt;, we'll look at the third case where $M &amp;lt; N$ (fewer equations than variables), which usually has infinite solutions. We'll also see how an optimization idea can help us find a specific, useful solution in that case too.&lt;/p&gt;

&lt;p&gt;Finally, we'll see how this least squares idea and another concept called the &lt;strong&gt;pseudo-inverse&lt;/strong&gt; can actually provide a single, elegant way to think about solving $AX=B$ that covers all three cases!&lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>datascience</category>
      <category>machinelearning</category>
      <category>science</category>
    </item>
    <item>
      <title>Getting a Grip on Linear Algebra for Data Science: It's Not as Scary as It Sounds!</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Sun, 11 Oct 2026 07:28:55 +0000</pubDate>
      <link>https://dev.to/dks/getting-a-grip-on-linear-algebra-for-data-science-its-not-as-scary-as-it-sounds-5ejl</link>
      <guid>https://dev.to/dks/getting-a-grip-on-linear-algebra-for-data-science-its-not-as-scary-as-it-sounds-5ejl</guid>
      <description>&lt;p&gt;Alright, so you're diving into data science, and everyone keeps talking about linear algebra. Don't sweat it! It's a super fundamental part of this field, and honestly, once you get a handle on a few key ideas, a lot of the data science stuff starts making more sense. Usually, a full linear algebra course is pretty long, like 36 hours! But we're just going to grab the most important bits, the ones you'll actually use in data science, especially for what we're covering here. We'll keep it simple, explain the ideas without getting too formal, but definitely no hand-waving either – we'll explain things properly, just in a way that's easy to digest.&lt;/p&gt;

&lt;p&gt;When we talk data science, a big part of it is representing your data and then figuring out what that data is really telling you. Like, how many different things are actually important in your data, and are some things related to each other? Linear algebra gives us the tools to answer these questions, which is super handy before you even get to the fancy machine learning algorithms.&lt;/p&gt;

&lt;h3&gt;
  
  
  First Off: How Do We Even Organize Our Data? Meet the Matrix!
&lt;/h3&gt;

&lt;p&gt;When you're dealing with data in data science, figuring out how to arrange it is a big deal. And guess what? Data is usually represented in this thing called a &lt;strong&gt;matrix&lt;/strong&gt;. Think of a matrix as just a neat way to put your data into rows and columns. It's basically a rectangular grid.&lt;/p&gt;

&lt;p&gt;Imagine you're an engineer checking on a factory reactor. You're getting readings from sensors – pressure, temperature, how thick something is (density), maybe viscosity too. And you're taking these readings over and over, maybe a thousand times. How do you keep all this info straight so you can use it later? A matrix is perfect for this. You can make each column a different measurement (pressure, temperature, density, viscosity) and each row one of your measurement times, one of your "samples." So, if you took 1000 sets of readings for 4 different things, you'd have a 1000-row, 4-column matrix. The number in the first row, first column? That's the pressure at your first measurement. The number in the 500th row, second column? That's the temperature at your 500th measurement. Easy, right? We'll usually stick to this way: rows for samples, columns for what you measured (the variables or attributes).&lt;/p&gt;

&lt;p&gt;Let's look at a simple example of this kind of data matrix from our reactor scenario, but with just 3 samples:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/blog/linear-algebra/reactor-matrix.svg" class="article-body-image-wrapper"&gt;&lt;img src="/images/blog/linear-algebra/reactor-matrix.svg" alt="Reactor data matrix visualization"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;   &lt;span class="c1"&gt;# Sample 1: Pressure, Temperature, Density, Viscosity
&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;7.4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;   &lt;span class="c1"&gt;# Sample 2: Pressure, Temperature, Density, Viscosity  
&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.5&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;   &lt;span class="c1"&gt;# Sample 3: Pressure, Temperature, Density, Viscosity
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Matrices aren't just for data. Sometimes, they can also represent equations. If you have a bunch of linear equations, you can put the coefficients of the variables into a matrix. This lets you use linear algebra tools to work with and solve those equations.&lt;/p&gt;

&lt;p&gt;They're also used to represent pictures! Ever wonder how computers "see" pictures? They often turn them into matrices! A picture is broken down into tiny dots called pixels. Each pixel gets a number based on its color or brightness. So, a photo becomes a huge matrix of numbers. If it's a black and white picture, a white spot might be a large number, a black spot a small one. This lets the computer do calculations on the matrix – using linear algebra! – to figure out if two pictures are similar, or to spot things inside a picture. It's all about turning the visual into numbers the computer can work with.&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/blog/linear-algebra/image-to-matrix.svg" class="article-body-image-wrapper"&gt;&lt;img src="/images/blog/linear-algebra/image-to-matrix.svg" alt="How an image is converted to a matrix"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basically, whether it's sensor data, pictures, or coefficients from equations, the matrix is our go-to structure. Rows are usually your individual data points or samples, and columns are the different characteristics or variables you measured.&lt;/p&gt;

&lt;h3&gt;
  
  
  Digging Into the Data: Are All My Measurements Really Different?
&lt;/h3&gt;

&lt;p&gt;Okay, we've got our data in a matrix. Now, what do we do with it? One of the first things you might wonder is, "Are all these measurements I took actually telling me something new? Or are some of them just kind of repeating information I already have from the others?"&lt;/p&gt;

&lt;p&gt;Think back to that reactor data with pressure, temperature, density, and viscosity. You might already know that density sort of depends on pressure and temperature. If that link is a simple linear one, then knowing pressure and temperature is enough to figure out density. You don't really need density as a separate, independent piece of information. Knowing this is super important for understanding how much actual, unique information is in your dataset and maybe even making your data smaller by getting rid of redundant stuff.&lt;/p&gt;

&lt;p&gt;This is where a cool concept called the &lt;strong&gt;rank of a matrix&lt;/strong&gt; comes in handy. The rank is just the number of columns (or rows, it works out the same) that are truly linearly independent. They aren't just simple combinations of the other columns or rows. The rank tells you the real number of distinct variables or samples you're dealing with, in terms of linear relationships.&lt;/p&gt;

&lt;p&gt;Let's look at our reactor data matrix again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;   &lt;span class="c1"&gt;# Sample 1
&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;7.4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;   &lt;span class="c1"&gt;# Sample 2
&lt;/span&gt;     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.5&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;   &lt;span class="c1"&gt;# Sample 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check the rows for independence. Is Row 2 just a scaled version of Row 1?&lt;br&gt;
$5.0/2.5=2$&lt;br&gt;
$240/120=2$&lt;br&gt;
$2.4/1.2=2$&lt;br&gt;
$7.4/3.7=2$&lt;br&gt;
Yes! Row 2 is exactly 2 times Row 1. This means Row 1 and Row 2 are linearly dependent.&lt;br&gt;
Is Row 3 a scaled version of Row 1?&lt;br&gt;
$3.0/2.5=1.2$&lt;br&gt;
$180/120=1.5$&lt;br&gt;
No, the scaling factor isn't constant. So, Row 3 is independent of Row 1.&lt;/p&gt;

&lt;p&gt;Since Row 2 depends on Row 1, the set of independent rows is {Row 1, Row 3}. There are 2 independent rows. The rank of the matrix is 2.&lt;br&gt;
So, even though we have 4 variables and 3 samples, the rank is 2. This tells us that in terms of linear combinations, the data essentially lives in a 2-dimensional space. There are only 2 independent sources of linear information here.&lt;/p&gt;

&lt;p&gt;You can easily find the rank using software. In Python, for instance, you'd just use a command like &lt;code&gt;np.linalg.matrix_rank(A)&lt;/code&gt; after setting up your matrix $A$.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Let's make a matrix similar to our reactor example
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="c1"&gt;# Create the matrix
&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3.7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;   &lt;span class="c1"&gt;# Sample 1
&lt;/span&gt;    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;7.4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;   &lt;span class="c1"&gt;# Sample 2
&lt;/span&gt;    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="c1"&gt;# Sample 3
&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Number of columns
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of columns:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Calculate rank of the matrix
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rank of the matrix:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matrix_rank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Calculate nullity
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Nullity (Number of Relationships):&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;nullity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nullity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find more linear algebra code examples in my &lt;a href="https://github.com/dineshkumarsarangapani/Math-in-AI/blob/main/linear-algebra/matrix.py" rel="noopener noreferrer"&gt;Math-in-AI GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For this matrix, the rank is 2 and the nullity is $4-2=2$. This tells us there are 2 independent linear relationships among the 4 variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding the Connections: What Are the Actual Relationships?
&lt;/h3&gt;

&lt;p&gt;Alright, we know if there are relationships (if the rank is less than the number of variables), but what are they? How do we find the actual equations that link these variables?&lt;/p&gt;

&lt;p&gt;This is where we look at something called the &lt;strong&gt;null space&lt;/strong&gt; and its size, the &lt;strong&gt;nullity&lt;/strong&gt;. Imagine we have our data matrix, let's call it $A$. If we can find a non-zero vector (just a list of numbers in a column) called $\beta$ (&lt;br&gt;
$\beta = [\beta_1, \beta_2, ..., \beta_n]^T$&lt;br&gt;
 ), such that when you multiply $A$ by $\beta$, you get a vector of all zeros ($A\beta = \mathbf{0}$), that $\beta$ vector is in the null space of $A$.&lt;/p&gt;

&lt;p&gt;Setting up $A\beta = \mathbf{0}$ for our reactor matrix gives us a system of equations, one for each row (sample):&lt;/p&gt;

&lt;p&gt;Sample 1: $2.5\beta_1 + 120\beta_2 + 1.2\beta_3 + 3.7\beta_4 = 0$&lt;/p&gt;

&lt;p&gt;Sample 2: $5.0\beta_1 + 240\beta_2 + 2.4\beta_3 + 7.4\beta_4 = 0$&lt;/p&gt;

&lt;p&gt;Sample 3: $3.0\beta_1 + 180\beta_2 + 1.8\beta_3 + 5.5\beta_4 = 0$&lt;/p&gt;

&lt;p&gt;Because Sample 2 is just 2 times Sample 1, the second equation is also just 2 times the first equation ($2 \times (2.5\beta_1 + 120\beta_2 + 1.2\beta_3 + 3.7\beta_4) = 5.0\beta_1 + 240\beta_2 + 2.4\beta_3 + 7.4\beta_4$). So, the second equation doesn't give us new, independent information about the &lt;br&gt;
$\beta$ values. We effectively have two independent equations (from rows 1 and 3) for our four unknowns (&lt;br&gt;
$\beta_1, \beta_2, \beta_3, \beta_4$).&lt;/p&gt;

&lt;p&gt;$$2.5\beta_1 + 120\beta_2 + 1.2\beta_3 + 3.7\beta_4 = 0$$&lt;/p&gt;

&lt;p&gt;$$3.0\beta_1 + 180\beta_2 + 1.8\beta_3 + 5.5\beta_4 = 0$$&lt;/p&gt;

&lt;p&gt;See what's happening? The same &lt;br&gt;
$\beta_1, \beta_2, \beta_3, \beta_4$ values must work for all your samples for the product to be the zero vector. This means you've found a general linear equation that connects the variables themselves, no matter which sample you look at:&lt;/p&gt;

&lt;p&gt;$$\beta_1 \times (\text{Variable 1}) + \beta_2 \times (\text{Variable 2}) + \beta_3 \times (\text{Variable 3}) + \beta_4 \times (\text{Variable 4}) = 0$$&lt;/p&gt;

&lt;p&gt;This $\beta$ vector gives you the coefficients of that linear relationship!&lt;/p&gt;

&lt;p&gt;The nullity of matrix $A$ is simply how many of these independent $\beta$ vectors exist in the null space. Each independent null space vector means there's another unique linear relationship hiding in your data.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Rank-Nullity Theorem&lt;/strong&gt; ties these together:&lt;br&gt;
$$\text{Nullity of } A + \text{Rank of } A = \text{Total number of variables (columns in } A)$$&lt;/p&gt;

&lt;p&gt;For our matrix, Nullity + 2 = 4, so Nullity = 2. There are 2 independent linear relationships.&lt;/p&gt;

&lt;p&gt;To find these relationships, we need to solve the system of equations for the vectors &lt;br&gt;
$\beta$ that satisfy $A\beta = \mathbf{0}$. When you solve the system for our reactor matrix:&lt;br&gt;
$$2.5\beta_1 + 120\beta_2 + 1.2\beta_3 + 3.7\beta_4 = 0$$&lt;br&gt;
$$3.0\beta_1 + 180\beta_2 + 1.8\beta_3 + 5.5\beta_4 = 0$$&lt;/p&gt;

&lt;p&gt;you find two independent solution vectors that form a basis for the null space. The basis for the null space is given by the vectors (you can see the step-by-step solution &lt;a href="https://www.emathhelp.net/calculators/linear-algebra/null-space-calculator/?i=%5B%5B2.5%2C120%2C1.2%2C3.7%5D%2C%5B5.0%2C240%2C2.4%2C7.4%5D%2C%5B3.0%2C180%2C1.8%2C5.5%5D%5D" rel="noopener noreferrer"&gt;here&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;Vector 1: $[0, -1/100, 1, 0]^T \approx [0, -0.01, 1, 0]^T$&lt;/p&gt;

&lt;p&gt;Vector 2: $[-1/15, -53/1800, 0, 1]^T \approx [-0.067, -0.029, 0, 1]^T$&lt;/p&gt;

&lt;p&gt;Let's see what these vectors mean in terms of relationships between our variables (Pressure, Temperature, Density, Viscosity).&lt;/p&gt;

&lt;p&gt;From Vector 1: $[0, -1/100, 1, 0]^T$&lt;/p&gt;

&lt;p&gt;The coefficients are $0, -1/100, 1,$ and $0$. The relationship is:&lt;br&gt;
$$0 \times (\text{Pressure}) + (-1/100) \times (\text{Temperature}) + 1 \times (\text{Density}) + 0 \times (\text{Viscosity}) = 0$$&lt;br&gt;
This simplifies to: $-\frac{1}{100} \times \text{Temperature} + \text{Density} = 0$, or $\text{Density} = \frac{1}{100} \times \text{Temperature}$.&lt;br&gt;
This relationship tells us that in this dataset, the Density reading is always 1/100th of the Temperature reading.&lt;/p&gt;

&lt;p&gt;From Vector 2: $[-1/15, -53/1800, 0, 1]^T$&lt;/p&gt;

&lt;p&gt;The coefficients are $-1/15, -53/1800, 0,$ and $1$. The relationship is:&lt;br&gt;
$$(-1/15) \times (\text{Pressure}) + (-53/1800) \times (\text{Temperature}) + 0 \times (\text{Density}) + 1 \times (\text{Viscosity}) = 0$$&lt;br&gt;
This simplifies to: $-\frac{1}{15} \times \text{Pressure} - \frac{53}{1800} \times \text{Temperature} + \text{Viscosity} = 0$, or $\text{Viscosity} = \frac{1}{15} \times \text{Pressure} + \frac{53}{1800} \times \text{Temperature}$.&lt;br&gt;
This is the second independent linear relationship in your data, showing how Viscosity depends on both Pressure and Temperature.&lt;/p&gt;

&lt;p&gt;So, by setting up and solving the system $A\beta = \mathbf{0}$, we found the null space vectors. These vectors provide the exact coefficients for the linear equations that describe the relationships between the variables that hold true for all your samples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Does This Matter for Machine Learning?
&lt;/h3&gt;

&lt;p&gt;Okay, so we can represent data in matrices, find out how many variables are truly independent (rank), and even get the exact equations linking dependent variables (null space/nullity). Why is this a big deal for machine learning?&lt;/p&gt;

&lt;p&gt;Well, a lot of machine learning algorithms work by doing calculations on these data matrices. If you want to reduce the number of variables in your dataset to make things simpler or faster (that's called &lt;strong&gt;dimensionality reduction&lt;/strong&gt;), you absolutely need to understand the concepts of independence and rank. Algorithms like Principal Component Analysis (PCA) rely on finding the most important, independent directions (or components) in your data, which is directly related to the rank. Knowing the relationships (from the null space) can also be useful; sometimes, algorithms need to be built in a way that respects these inherent links in the data.&lt;/p&gt;

&lt;p&gt;So, getting a solid grasp of these matrix ideas, rank, and null space is really your entry ticket to understanding how many machine learning techniques actually work under the hood.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping It Up
&lt;/h3&gt;

&lt;p&gt;To sum it all up, linear algebra, especially working with matrices, is super important in data science. Matrices are our standard way to store data, with rows for each sample and columns for each variable. The rank of a matrix quantifies the number of independent variables, telling us how much unique information is present. And if there are dependencies, the null space and its size, the nullity, help us find the actual linear equations that describe the relationships between those variables. These aren't just abstract math ideas; they are practical tools for understanding your data better and are absolutely essential for getting into machine learning.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>datascience</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Solving for X, Part 2: Tackling Tougher Linear Equations in Data Science</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Sun, 11 Oct 2026 07:23:52 +0000</pubDate>
      <link>https://dev.to/dks/solving-for-x-part-2-tackling-tougher-linear-equations-in-data-science-82k</link>
      <guid>https://dev.to/dks/solving-for-x-part-2-tackling-tougher-linear-equations-in-data-science-82k</guid>
      <description>&lt;p&gt;Welcome back to our linear algebra for data science series! In &lt;a href="https://dev.to/blog/2025/05/solving-linear-equations-in-data-science/"&gt;Part 1 on solving linear equations&lt;/a&gt;, we set up systems of linear equations using matrices ($AX = B$) and covered the square ($M = N$) and overdetermined ($M &amp;gt; N$) cases with least squares.&lt;/p&gt;

&lt;p&gt;Today, we're moving on to another absolute core concept: &lt;strong&gt;solving linear equations&lt;/strong&gt;. If you think about a ton of problems in data science, machine learning, and even everyday modeling, they often boil down to having a bunch of equations and needing to find the values that make them true. This is where solving matrix equations becomes key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Turning Equations into Matrix Problems: $AX=B$
&lt;/h3&gt;

&lt;p&gt;Generally, when you have a set of linear equations, you can write them in a neat matrix form that looks like this:&lt;/p&gt;

&lt;p&gt;$$AX = B$$&lt;/p&gt;

&lt;p&gt;Let's break down what's in this equation based on what we learned before:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$A$ is a matrix. If you have $M$ equations and $N$ variables, $A$ is typically an $M \times N$ matrix. As we saw, $M$ is the number of rows (equations in this case) and $N$ is the number of columns (variables).&lt;/li&gt;
&lt;li&gt;$X$ is a column vector containing the variables you're trying to solve for. Since $A$ has $N$ columns (variables), $X$ needs to have $N$ rows, so it's an $N \times 1$ matrix (a column vector).&lt;/li&gt;
&lt;li&gt;$B$ is a column vector containing the constants from the right-hand side of your equations. For the matrix multiplication to work out, $B$ needs to have the same number of rows as $A$, so it's an $M \times 1$ matrix.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, when you write $AX=B$, you're really representing a system of $M$ linear equations involving $N$ variables.&lt;/p&gt;

&lt;p&gt;Now, depending on how $M$ (the number of equations) stacks up against $N$ (the number of variables), things can play out in three main ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;$M = N$:&lt;/strong&gt; The number of equations is exactly the same as the number of variables. This is often the "nicest" case to solve.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;$M &amp;gt; N$:&lt;/strong&gt; You have more equations than variables. Think of it as having &lt;em&gt;too many&lt;/em&gt; rules for your variables to follow. Usually, this means there's no single perfect solution that satisfies &lt;em&gt;all&lt;/em&gt; the equations.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;$M &amp;lt; N$:&lt;/strong&gt; You have fewer equations than variables. This means you have &lt;em&gt;more&lt;/em&gt; variables than you strictly need for the given equations. In this scenario, you'll usually find that there are many, many possible solutions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We're going to look at these cases, and then see how a cool idea called the pseudo-inverse can bring them all together.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Quick Refresher on Rank
&lt;/h3&gt;

&lt;p&gt;Remember &lt;strong&gt;rank&lt;/strong&gt; from our last post? It's going to be super important here. The rank of a matrix is the number of its linearly independent rows or columns. Remember, row rank always equals column rank – you can't have a different number of independent rows versus columns!&lt;/p&gt;

&lt;p&gt;For an $M \times N$ matrix, the maximum possible rank it can have is the smaller of $M$ and $N$. If $M &amp;lt; N$, the max rank is $M$. If $N &amp;lt; M$, the max rank is $N$.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case 1: When Equations Equal Variables ($M=N$)
&lt;/h3&gt;

&lt;p&gt;This is the case where your matrix $A$ is square ($M \times N$ and $M=N$).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If $A$ is Full Rank:&lt;/strong&gt;&lt;br&gt;
"Full rank" here means the rank of the matrix is equal to $M$ (or $N$, since they're the same). What does this mean? It means all your equations on the left-hand side are independent. You can't create any one equation by combining the others.&lt;br&gt;
In this happy case, there is a &lt;strong&gt;unique solution&lt;/strong&gt; to $AX=B$. You might remember from algebra that you can solve this by finding the inverse of $A$, written as $A^{-1}$. The solution is simply:&lt;br&gt;
$$X = A^{-1}B$$&lt;br&gt;
You can find $A^{-1}$ if the determinant of $A$ is not zero. This is the standard, straightforward scenario.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;If $A$ is Not Full Rank:&lt;/strong&gt;&lt;br&gt;
This means the rank of $A$ is less than $M$. In this situation, some of your equations on the left-hand side are actually linear combinations of others – they are linearly dependent.&lt;br&gt;
When this happens, depending on what the values are on the right-hand side (in the $B$ vector), you get two possibilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Consistent System:&lt;/strong&gt; If the dependencies on the left-hand side match up &lt;em&gt;exactly&lt;/em&gt; with the dependencies on the right-hand side (the $B$ vector values), the equations are consistent. But because they are dependent, you don't have enough &lt;em&gt;independent&lt;/em&gt; equations to pin down a single solution. This leads to &lt;strong&gt;infinite solutions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Inconsistent System:&lt;/strong&gt; If the dependencies on the left-hand side &lt;em&gt;don't&lt;/em&gt; match up with the $B$ vector values, the equations are inconsistent. They contradict each other, and there is &lt;strong&gt;no solution&lt;/strong&gt; that can satisfy all of them.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at a couple of examples for this $M=N$ case:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Full Rank (Unique Solution)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider the system of equations:&lt;br&gt;
$x_1 + 3x_2 = 7$&lt;br&gt;
$2x_1 + 4x_2 = 10$&lt;/p&gt;

&lt;p&gt;In matrix form $AX=B$, this is:&lt;br&gt;
$$&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
1 &amp;amp; 3 \&lt;br&gt;
2 &amp;amp; 4&lt;br&gt;
\end{bmatrix}&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
x_1 \&lt;br&gt;
x_2&lt;/p&gt;
&lt;h1&gt;
  
  
  \end{bmatrix}
&lt;/h1&gt;

&lt;p&gt;\begin{bmatrix}&lt;br&gt;
7 \&lt;br&gt;
10&lt;br&gt;
\end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
Here, $A = \begin{bmatrix} 1 &amp;amp; 3 \ 2 &amp;amp; 4 \end{bmatrix}$. $M=2$, $N=2$.&lt;br&gt;
We can check if $A$ is full rank by calculating its determinant: $(1 \times 4) - (3 \times 2) = 4 - 6 = -2$. Since the determinant is not 0, the matrix is full rank (rank = 2).&lt;br&gt;
There is a unique solution, $X = A^{-1}B$. The inverse of $A$ is $\begin{bmatrix} -2 &amp;amp; 1.5 \ 1 &amp;amp; -0.5 \end{bmatrix}$.&lt;br&gt;
So, $X = \begin{bmatrix} -2 &amp;amp; 1.5 \ 1 &amp;amp; -0.5 \end{bmatrix} \begin{bmatrix} 7 \ 10 \end{bmatrix} = \begin{bmatrix} (-2 \times 7) + (1.5 \times 10) \ (1 \times 7) + (-0.5 \times 10) \end{bmatrix} = \begin{bmatrix} -14 + 15 \ 7 - 5 \end{bmatrix} = \begin{bmatrix} 1 \ 2 \end{bmatrix}$.&lt;br&gt;
The unique solution is $x_1 = 1$ and $x_2 = 2$. You can plug these back into the original equations to check ($1 + 3(2) = 7$, $2(1) + 4(2) = 10$). It works!&lt;/p&gt;

&lt;p&gt;You can solve this easily in software too. In Python, you could define A and B using NumPy and use the &lt;code&gt;numpy.linalg.solve()&lt;/code&gt; command or compute the inverse and multiply.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 2: Not Full Rank, Consistent (Infinite Solutions)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider the system:&lt;br&gt;
$x_1 + 2x_2 = 5$&lt;br&gt;
$2x_1 + 4x_2 = 10$&lt;/p&gt;

&lt;p&gt;In matrix form $AX=B$:&lt;br&gt;
$$&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
1 &amp;amp; 2 \&lt;br&gt;
2 &amp;amp; 4&lt;br&gt;
\end{bmatrix}&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
x_1 \&lt;br&gt;
x_2&lt;/p&gt;
&lt;h1&gt;
  
  
  \end{bmatrix}
&lt;/h1&gt;

&lt;p&gt;\begin{bmatrix}&lt;br&gt;
5 \&lt;br&gt;
10&lt;br&gt;
\end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
Here, $A = \begin{bmatrix} 1 &amp;amp; 2 \ 2 &amp;amp; 4 \end{bmatrix}$. $M=2$, $N=2$.&lt;br&gt;
Check the determinant: $(1 \times 4) - (2 \times 2) = 4 - 4 = 0$. The determinant is 0, so the matrix is not full rank (rank = 1). The columns are dependent (column 2 is 2 * column 1), and the rows are dependent (row 2 is 2 * row 1).&lt;/p&gt;

&lt;p&gt;Now, look at the equations themselves. The second equation $2x_1 + 4x_2 = 10$ is exactly 2 times the first equation $x_1 + 2x_2 = 5$. This dependency on the left-hand side ($2x_1 + 4x_2$ being $2 \times (x_1 + 2x_2)$) is &lt;em&gt;matched&lt;/em&gt; on the right-hand side ($10$ being $2 \times 5$).&lt;br&gt;
Since the left and right sides have the same linear dependency, the system is &lt;strong&gt;consistent&lt;/strong&gt;.&lt;br&gt;
However, because the second equation is just a scaled version of the first, you effectively only have &lt;em&gt;one&lt;/em&gt; independent equation ($x_1 + 2x_2 = 5$) with two variables ($x_1, x_2$). This means you have a "free" variable.&lt;br&gt;
You can pick &lt;em&gt;any&lt;/em&gt; value for $x_2$, and then calculate the $x_1$ that works ($x_1 = 5 - 2x_2$).&lt;br&gt;
For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If $x_2 = 0$, $x_1 = 5$. Solution: $(5, 0)$.&lt;/li&gt;
&lt;li&gt;If $x_2 = 1$, $x_1 = 3$. Solution: $(3, 1)$.&lt;/li&gt;
&lt;li&gt;If $x_2 = 2.5$, $x_1 = 0$. Solution: $(0, 2.5)$.
Since you can choose &lt;em&gt;any&lt;/em&gt; value for $x_2$, there are &lt;strong&gt;infinite solutions&lt;/strong&gt; to this system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example 3: Not Full Rank, Inconsistent (No Solution)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider the system:&lt;br&gt;
$x_1 + 2x_2 = 5$&lt;br&gt;
$2x_1 + 4x_2 = 9$&lt;/p&gt;

&lt;p&gt;In matrix form $AX=B$:&lt;br&gt;
$$&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
1 &amp;amp; 2 \&lt;br&gt;
2 &amp;amp; 4&lt;br&gt;
\end{bmatrix}&lt;br&gt;
\begin{bmatrix}&lt;br&gt;
x_1 \&lt;br&gt;
x_2&lt;/p&gt;
&lt;h1&gt;
  
  
  \end{bmatrix}
&lt;/h1&gt;

&lt;p&gt;\begin{bmatrix}&lt;br&gt;
5 \&lt;br&gt;
9&lt;br&gt;
\end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
Here, $A = \begin{bmatrix} 1 &amp;amp; 2 \ 2 &amp;amp; 4 \end{bmatrix}$ is the same as before, so it's not full rank (rank = 1). The left-hand side has the same dependency (row 2 is 2 * row 1).&lt;br&gt;
But look at the right-hand side ($B$ vector). The first equation's right side is 5. If you multiply it by 2 (the scaling factor between the left-hand sides), you get $2 \times 5 = 10$.&lt;br&gt;
However, the second equation's right side is 9, not 10.&lt;br&gt;
The dependency on the left-hand side (where the second equation's left side is twice the first) does &lt;em&gt;not&lt;/em&gt; match the right-hand side ($9 \neq 2 \times 5$). The equations contradict each other ($2x_1 + 4x_2$ cannot equal both 10 &lt;em&gt;and&lt;/em&gt; 9 simultaneously based on the first equation).&lt;br&gt;
The system is &lt;strong&gt;inconsistent&lt;/strong&gt;, and there is &lt;strong&gt;no solution&lt;/strong&gt; that can satisfy both equations.&lt;/p&gt;

&lt;p&gt;So, for the $M=N$ case (square matrix A): if A is full rank, unique solution; if A is not full rank, check consistency – if consistent, infinite solutions; if inconsistent, no solution.&lt;/p&gt;
&lt;h3&gt;
  
  
  Case 2: More Equations Than Variables ($M &amp;gt; N$)
&lt;/h3&gt;

&lt;p&gt;Now let's look at the case where you have more equations than variables. Like trying to find two numbers ($x_1, x_2$) that satisfy five different conditions.&lt;/p&gt;

&lt;p&gt;$$AX = B \quad (\text{where M &amp;gt; N})$$&lt;/p&gt;

&lt;p&gt;Since you have more equations than variables, it's generally impossible to find a perfect solution $X$ that makes &lt;em&gt;every single&lt;/em&gt; equation true (i.e., makes $AX$ &lt;em&gt;exactly&lt;/em&gt; equal to $B$). If you could find such a perfect $X$, then $AX - B$ would be a vector of all zeros.&lt;/p&gt;

&lt;p&gt;But since a perfect solution is usually out of reach, what's the next best thing? We want to find a solution $X$ that gets us as &lt;em&gt;close&lt;/em&gt; as possible to satisfying all the equations. In other words, we want to find an $X$ that makes the difference between $AX$ and $B$ as small as possible.&lt;/p&gt;

&lt;p&gt;Think of $AX - B$ as a vector of "errors," where each element is the error in one equation.&lt;br&gt;
Equation 1 error: $e_1 = (A_{11}x_1 + A_{12}x_2 + ... + A_{1N}x_N) - B_1$&lt;br&gt;
Equation 2 error: $e_2 = (A_{21}x_1 + A_{22}x_2 + ... + A_{2N}x_N) - B_2$&lt;br&gt;
...&lt;br&gt;
Equation M error: $e_M = (A_{M1}x_1 + A_{M2}x_2 + ... + A_{MN}x_N) - B_M$&lt;/p&gt;

&lt;p&gt;The vector of errors is $E = AX - B$. We want to find the $X$ that makes this error vector $E$ as "small" as possible. How do we measure the size of a vector of errors? We don't just add the errors ($e_1 + e_2 + ...$), because positive and negative errors could cancel out, making a big overall error look like zero.&lt;/p&gt;

&lt;p&gt;A common way to measure the overall error is to minimize the sum of the &lt;em&gt;squared&lt;/em&gt; errors: $e_1^2 + e_2^2 + ... + e_M^2$. This is because squaring makes all the errors positive, and larger errors contribute more significantly. This approach is called finding the &lt;strong&gt;least squares solution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Minimizing the sum of squared errors ($e_1^2 + ... + e_M^2$) is the same as minimizing the squared length (or squared norm) of the error vector $E = AX - B$. We write the squared length of a vector $v$ as $||v||^2$, which is $v^T v$ (the vector transposed multiplied by the original vector).&lt;br&gt;
So, we want to minimize $||AX - B||^2$, which is $(AX - B)^T (AX - B)$.&lt;/p&gt;

&lt;p&gt;$$\text{Minimize } (AX - B)^T (AX - B)$$&lt;/p&gt;

&lt;p&gt;To find the $X$ that minimizes this, you can use calculus. You take the derivative of this expression with respect to the vector $X$ and set it equal to zero. After doing the calculus and some matrix algebra (which we won't go into detail here, just like the lecture), the equation you get to solve for $X$ is:&lt;/p&gt;

&lt;p&gt;$$A^T A X = A^T B$$&lt;/p&gt;

&lt;p&gt;Where $A^T$ is the transpose of matrix $A$ (you flip its rows and columns).&lt;/p&gt;

&lt;p&gt;Now, if the matrix $A^T A$ is invertible (which happens if the columns of the original matrix $A$ are linearly independent – related to the rank!), you can solve for $X$:&lt;/p&gt;

&lt;p&gt;$$X = (A^T A)^{-1} A^T B$$&lt;/p&gt;

&lt;p&gt;This solution $X$ is the &lt;strong&gt;least squares solution&lt;/strong&gt;. It's the $X$ that minimizes the sum of squared differences between $AX$ and $B$. This $X$ might not make $AX$ &lt;em&gt;exactly&lt;/em&gt; equal to $B$ (since a perfect solution might not exist), but it gives you the best possible fit in a least squares sense.&lt;/p&gt;

&lt;p&gt;This optimization perspective gives us a way to find a meaningful "solution" even when we have more equations than variables, a common situation in data fitting.&lt;/p&gt;

&lt;p&gt;Let's look back at our first $M&amp;gt;N$ example and see how this least squares solution plays out.&lt;/p&gt;

&lt;p&gt;Example system of 3 equations with 2 variables:&lt;br&gt;
$x_1 = 1$&lt;br&gt;
$2x_1 = -0.5$&lt;br&gt;
$3x_1 + x_2 = 5$&lt;/p&gt;

&lt;p&gt;In matrix form $AX=B$:&lt;br&gt;
$$&lt;br&gt;
A = \begin{bmatrix} 1 &amp;amp; 0 \ 2 &amp;amp; 0 \ 3 &amp;amp; 1 \end{bmatrix}, \quad X = \begin{bmatrix} x_1 \ x_2 \end{bmatrix}, \quad B = \begin{bmatrix} 1 \ -0.5 \ 5 \end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
$M=3, N=2$.&lt;/p&gt;

&lt;p&gt;Applying the formula $X = (A^T A)^{-1} A^T B$, as we calculated earlier, gave us:&lt;br&gt;
$$&lt;br&gt;
X = \begin{bmatrix} 0 \ 5 \end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
So the least squares solution is $x_1=0, x_2=5$. As we saw, this didn't satisfy the first two equations perfectly ($0 \neq 1$ and $2 \times 0 = 0 \neq -0.5$), but it made the third equation exact ($3 \times 0 + 5 = 5$) and minimized the total squared error across all three.&lt;/p&gt;

&lt;p&gt;If we took the second $M&amp;gt;N$ example (where a perfect solution existed):&lt;br&gt;
$x_1 = 1$&lt;br&gt;
$2x_1 = 2$&lt;br&gt;
$3x_1 + x_2 = 5$&lt;br&gt;
$$&lt;br&gt;
A = \begin{bmatrix} 1 &amp;amp; 0 \ 2 &amp;amp; 0 \ 3 &amp;amp; 1 \end{bmatrix}, \quad X = \begin{bmatrix} x_1 \ x_2 \end{bmatrix}, \quad B = \begin{bmatrix} 1 \ 2 \ 5 \end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
Applying the same formula $X = (A^T A)^{-1} A^T B$, we got:&lt;br&gt;
$$&lt;br&gt;
X = \begin{bmatrix} 1 \ 2 \end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
This matches the perfect solution $(x_1=1, x_2=2)$ that satisfies all three equations, because in this case, the minimum sum of squared errors is zero.&lt;/p&gt;

&lt;p&gt;So, the least squares solution $X = (A^T A)^{-1} A^T B$ is a powerful way to get the "best fit" solution when you have more equations than variables, and it finds the exact solution if one exists. This formula works as long as the columns of $A$ are linearly independent (which makes $A^T A$ invertible).&lt;/p&gt;
&lt;h3&gt;
  
  
  Case 3: More Variables Than Equations ($M &amp;lt; N$)
&lt;/h3&gt;

&lt;p&gt;Now for the last case: fewer equations than variables. Imagine having one equation, like $x_1 + x_2 + x_3 = 10$, and trying to find values for $x_1, x_2, x_3$. You can probably already see you have lots of options!&lt;/p&gt;

&lt;p&gt;$$AX = B \quad (\text{where M &amp;lt; N})$$&lt;/p&gt;

&lt;p&gt;When you have more variables than independent equations, you'll have "free" variables. For example, with 2 equations and 3 variables, you can often pick any value for one variable (say, $x_3$), plug it into the equations, and then you're left with 2 equations and 2 variables to solve for $x_1$ and $x_2$. Since you could pick &lt;em&gt;any&lt;/em&gt; value for $x_3$, you end up with &lt;strong&gt;infinite solutions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Since there are endless possibilities for $X$ that satisfy $AX=B$, how do you pick just &lt;em&gt;one&lt;/em&gt; solution that makes the most sense for your problem? The equations themselves don't give you enough information to choose. You need some other rule or criteria.&lt;/p&gt;

&lt;p&gt;Similar to the $M&amp;gt;N$ case, we can use an optimization idea! This time, instead of minimizing the error in the equations (since many solutions make the error zero!), we need a different objective. A common and often useful criterion is to find the solution $X$ that has the &lt;strong&gt;minimum "size" or "length"&lt;/strong&gt;. This is called finding the &lt;strong&gt;minimum norm solution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We measure the "size" or "norm" of the solution vector $X$ using its length, specifically, minimizing the squared length $||X||^2 = X^T X$. Why minimize $X^T X$? Think of it as finding the solution vector $X$ that is closest to the origin $(0, 0, ... 0)$ in your variable space. From an engineering or modeling perspective, finding a solution where the variables have smaller values might be desirable in some contexts (like keeping design parameters small).&lt;/p&gt;

&lt;p&gt;So, for the $M&amp;lt;N$ case, the optimization problem is:&lt;/p&gt;

&lt;p&gt;$$\text{Minimize } \frac{1}{2} X^T X \quad \text{Subject to } AX = B$$&lt;/p&gt;

&lt;p&gt;The $\frac{1}{2}$ is just there to make the math cleaner when you solve it using calculus. The important part is "Subject to $AX=B$." This is a &lt;strong&gt;constrained optimization&lt;/strong&gt; problem – you're minimizing an objective function ($X^T X$) &lt;em&gt;while making sure&lt;/em&gt; your solution still satisfies the original equations $AX=B$. This is different from the $M&amp;gt;N$ case where we had &lt;em&gt;unconstrained&lt;/em&gt; optimization (just minimize the error without worrying about satisfying the equations perfectly).&lt;/p&gt;

&lt;p&gt;Solving constrained optimization problems involves techniques like using Lagrangian functions. While the detailed steps for solving this are part of optimization theory (which often comes &lt;em&gt;after&lt;/em&gt; linear algebra, but uses a lot of it!), the resulting formula for the minimum norm solution, assuming the rows of $A$ are linearly independent (making $A A^T$ invertible), is:&lt;/p&gt;

&lt;p&gt;$$X = A^T (A A^T)^{-1} B$$&lt;/p&gt;

&lt;p&gt;This formula gives you the unique solution that satisfies $AX=B$ &lt;em&gt;and&lt;/em&gt; has the minimum possible squared length $||X||^2$.&lt;/p&gt;

&lt;p&gt;Let's try an example for this $M&amp;lt;N$ case.&lt;br&gt;
Consider the system of 2 equations with 3 variables:&lt;br&gt;
$x_1 + 2x_2 + 3x_3 = 2$&lt;br&gt;
$x_3 = 1$&lt;/p&gt;

&lt;p&gt;In matrix form $AX=B$:&lt;br&gt;
$$&lt;br&gt;
A = \begin{bmatrix} 1 &amp;amp; 2 &amp;amp; 3 \ 0 &amp;amp; 0 &amp;amp; 1 \end{bmatrix}, \quad X = \begin{bmatrix} x_1 \ x_2 \ x_3 \end{bmatrix}, \quad B = \begin{bmatrix} 2 \ 1 \end{bmatrix}&lt;br&gt;
$$&lt;br&gt;
$M=2, N=3$. $M &amp;lt; N$.&lt;/p&gt;

&lt;p&gt;We know there are infinite solutions here (like $(-1, 0, 1)$, $(-3, 1, 1)$, etc.). Let's use the minimum norm formula $X = A^T (A A^T)^{-1} B$.&lt;/p&gt;

&lt;p&gt;First, find $A^T$:&lt;br&gt;
$A^T = \begin{bmatrix} 1 &amp;amp; 0 \ 2 &amp;amp; 0 \ 3 &amp;amp; 1 \end{bmatrix}$&lt;/p&gt;

&lt;p&gt;Next, calculate $A A^T$:&lt;br&gt;
$A A^T = \begin{bmatrix} 1 &amp;amp; 2 &amp;amp; 3 \ 0 &amp;amp; 0 &amp;amp; 1 \end{bmatrix} \begin{bmatrix} 1 &amp;amp; 0 \ 2 &amp;amp; 0 \ 3 &amp;amp; 1 \end{bmatrix} = \begin{bmatrix} 14 &amp;amp; 3 \ 3 &amp;amp; 1 \end{bmatrix}$&lt;/p&gt;

&lt;p&gt;This matrix has a determinant of 5, so it's invertible. $(A A^T)^{-1} = \begin{bmatrix} 0.2 &amp;amp; -0.6 \ -0.6 &amp;amp; 2.8 \end{bmatrix}$.&lt;/p&gt;

&lt;p&gt;Finally, calculate $X = A^T (A A^T)^{-1} B$:&lt;br&gt;
$X = \begin{bmatrix} 1 &amp;amp; 0 \ 2 &amp;amp; 0 \ 3 &amp;amp; 1 \end{bmatrix} \begin{bmatrix} 0.2 &amp;amp; -0.6 \ -0.6 &amp;amp; 2.8 \end{bmatrix} \begin{bmatrix} 2 \ 1 \end{bmatrix}$&lt;/p&gt;

&lt;p&gt;As we calculated before, this gives us:&lt;br&gt;
$$&lt;br&gt;
X = \begin{bmatrix} -0.2 \ -0.4 \ 1 \end{bmatrix}&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;The minimum norm solution is $x_1 = -0.2$, $x_2 = -0.4$, and $x_3 = 1$. This solution satisfies the original equations, and among all the infinite solutions that work, this vector $[-0.2, -0.4, 1]^T$ is the one closest to the origin $(0,0,0)$.&lt;/p&gt;

&lt;p&gt;So, the formula $X = A^T (A A^T)^{-1} B$ gives us the minimum norm solution when you have more variables than equations, provided the rows of $A$ are linearly independent (making $A A^T$ invertible).&lt;/p&gt;
&lt;h3&gt;
  
  
  One Solution to Rule Them All: The Pseudo-inverse!
&lt;/h3&gt;

&lt;p&gt;We've looked at the three cases for $AX=B$:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$M=N$: Unique solution ($A^{-1}B$) if full rank; infinite or no solutions if not full rank.&lt;/li&gt;
&lt;li&gt;$M&amp;gt;N$: Generally no exact solution, find the least squares solution ($X = (A^T A)^{-1} A^T B$) that minimizes errors.&lt;/li&gt;
&lt;li&gt;$M&amp;lt;N$: Infinite exact solutions, find the minimum norm solution ($X = A^T (A A^T)^{-1} B$) that is closest to the origin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a lot to keep track of! Wouldn't it be awesome if there was &lt;em&gt;one single formula&lt;/em&gt; that just gave you the right kind of solution (unique exact, least squares, or minimum norm) no matter the size or rank of $A$?&lt;/p&gt;

&lt;p&gt;It turns out there is! This is where the concept of the &lt;strong&gt;Moore-Penrose pseudo-inverse&lt;/strong&gt; (often written as $A^+$) comes in. It generalizes the idea of the matrix inverse $A^{-1}$.&lt;/p&gt;

&lt;p&gt;The magical formula for solving $AX=B$ in &lt;em&gt;all&lt;/em&gt; cases is simply:&lt;/p&gt;

&lt;p&gt;$$X = A^+ B$$&lt;/p&gt;

&lt;p&gt;Where $A^+$ is the pseudo-inverse of $A$.&lt;/p&gt;

&lt;p&gt;How is this magical?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If $M=N$ and $A$ is full rank, $A^+$ is exactly the same as $A^{-1}$. So you get $X = A^{-1}B$, the unique exact solution.&lt;/li&gt;
&lt;li&gt;If $M&amp;gt;N$ and the columns of $A$ are independent (making $A^T A$ invertible), $A^+$ is equal to $(A^T A)^{-1} A^T$. So you get $X = (A^T A)^{-1} A^T B$, the least squares solution.&lt;/li&gt;
&lt;li&gt;If $M&amp;lt;N$ and the rows of $A$ are independent (making $A A^T$ invertible), $A^+$ is equal to $A^T (A A^T)^{-1}$. So you get $X = A^T (A A^T)^{-1} B$, the minimum norm solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And what about the cases where $A$ is &lt;em&gt;not&lt;/em&gt; full rank (determinant is zero for M=N, columns/rows are dependent)? The pseudo-inverse still works! In those rank-deficient cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the system is consistent ($M=N$ not full rank, or $M&amp;lt;N$ rank deficient but consistent), $A^+ B$ gives you the minimum norm solution among the infinite exact solutions.&lt;/li&gt;
&lt;li&gt;If the system is inconsistent ($M=N$ not full rank, or $M&amp;gt;N$ rank deficient and inconsistent), $A^+ B$ gives you the least squares solution that minimizes the error $||AX-B||^2$.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, the pseudo-inverse $A^+$ gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The unique exact solution if it exists.&lt;/li&gt;
&lt;li&gt;The minimum norm exact solution if there are infinite exact solutions.&lt;/li&gt;
&lt;li&gt;The minimum norm least squares solution if there are no exact solutions (i.e., the least squares solution with the smallest norm, although in the M&amp;gt;N case this is usually the &lt;em&gt;only&lt;/em&gt; least squares solution).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How do you calculate this pseudo-inverse $A^+$? One common way is using something called Singular Value Decomposition (SVD), which is a really powerful technique in linear algebra. But for using it to solve $AX=B$, you often don't need to know the details of SVD right away.&lt;/p&gt;

&lt;p&gt;Many software packages can compute the pseudo-inverse directly. In Python, you can use NumPy's &lt;code&gt;linalg.pinv()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Here are examples in Python using &lt;code&gt;numpy.linalg.pinv()&lt;/code&gt; on the matrices we just looked at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="c1"&gt;# Example 1 (M &amp;gt; N)
&lt;/span&gt;&lt;span class="n"&gt;A1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;span class="n"&gt;B1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="n"&gt;A1_plus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pinv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;X1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;A1_plus&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;B1&lt;/span&gt; &lt;span class="c1"&gt;# Using the matrix multiplication operator @
&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Solution for Example 1 (M&amp;gt;N):&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Output should be close to:
# [[0.]
#  [5.]]
&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Example 2 (M &amp;lt; N)
&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;span class="n"&gt;B2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="n"&gt;A2_plus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pinv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;X2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;A2_plus&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;B2&lt;/span&gt; &lt;span class="c1"&gt;# Using the matrix multiplication operator @
&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Solution for Example 2 (M&amp;lt;N):&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Output should be close to:
# [[-0.2]
#  [-0.4]
#  [ 1. ]]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>computerscience</category>
      <category>datascience</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Section 1: The dataset and the problem</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Sun, 11 Oct 2026 07:23:50 +0000</pubDate>
      <link>https://dev.to/dks/section-1-the-dataset-and-the-problem-3ig4</link>
      <guid>https://dev.to/dks/section-1-the-dataset-and-the-problem-3ig4</guid>
      <description>&lt;p&gt;I am working through &lt;a href="https://www.youtube.com/playlist?list=PLZ2ps__7DhBa5xCmncgH7kPqLqMBq7xlu" rel="noopener noreferrer"&gt;Mathematical Foundations of Generative AI&lt;/a&gt;, Prof. Prathosh AP's public lectures. The playlist is the spine. These notes are my deep dive on each section: a visual when the picture is the point, a detour when a prerequisite is doing real work, and the formula in my own words.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 1: The dataset and the problem
&lt;/h2&gt;

&lt;p&gt;Everything later in the playlist, GANs, VAEs, diffusion, transformers, state-space models, and preference tuning, starts from the same setup. I want this part solid before I touch a model.&lt;/p&gt;

&lt;p&gt;The setup I am carrying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Data $D = {x_1, x_2, \dots, x_n} \overset{\text{iid}}{\sim} P_x$ (unknown), with $x_i \in \mathbb{R}^d$, where $d$ is the dimensionality of the data.&lt;br&gt;
Example: $x_i$ is an image, $400 \times 400 \times 3$, so $d = 480{,}000$.&lt;br&gt;
Goal: estimate $P_x$ and learn to sample from it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Intuition
&lt;/h3&gt;

&lt;p&gt;Somewhere there is a hidden recipe, a probability distribution, that produced every cat photo, every English sentence, every speech clip. I never get the recipe. I get a pile of examples it produced. Generative modeling is using that pile to reconstruct the recipe well enough to cook up new examples from the same kitchen.&lt;/p&gt;

&lt;h3&gt;
  
  
  An analogy I can check
&lt;/h3&gt;

&lt;p&gt;Think of a production web service whose request process I cannot inspect. All I have is an access log of 1,000 requests. I want a load-testing tool that produces synthetic traffic indistinguishable from real users: same mix of endpoints, same payload sizes, same timing.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Load-testing analogy&lt;/th&gt;
&lt;th&gt;Notation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The real, unknown user behaviour&lt;/td&gt;
&lt;td&gt;$P_x$, the true data distribution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One logged request&lt;/td&gt;
&lt;td&gt;$x_i$, one data point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The fields in a log line&lt;/td&gt;
&lt;td&gt;the $d$ coordinates of $x_i \in \mathbb{R}^d$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The access log&lt;/td&gt;
&lt;td&gt;dataset $D$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The traffic generator&lt;/td&gt;
&lt;td&gt;the generative model $P_\theta$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Synthetic requests it emits&lt;/td&gt;
&lt;td&gt;samples from $P_\theta$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two consequences. I do not need to write the user-behaviour formula down. I need a generator whose output is statistically indistinguishable. That is why a GAN never writes $P_x$ down at all. And replaying the log is not the goal. I want new requests, not copies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual
&lt;/h3&gt;

&lt;p&gt;A hidden 2-D distribution plays the role of $P_x$. At first I only see the dots, the dataset. Reveal $P_x$ to see what is normally invisible, and drag $n$ to see how more data reveals the shape.&lt;/p&gt;

&lt;p&gt;Each "Draw a new dataset" gives a different $D$ and the same green $P_x$ underneath. The dataset is random. The distribution is the fixed thing I am after. With $n = 5$ the shape is a guess. With $n = 1000$ the two clumps are obvious.&lt;/p&gt;

&lt;h3&gt;
  
  
  Detours I needed before the formula
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Random variable, and random vector.&lt;/strong&gt; A random variable is a quantity whose value is decided by chance, like a die roll $X \in {1,\dots,6}$. A random vector is the same idea with several numbers at once, such as height and weight of a randomly chosen person, $X \in \mathbb{R}^2$. Capital $X$ means the random thing in general. Lowercase $x_i$ means one specific value that actually came out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distribution and density.&lt;/strong&gt; $P_x$ tells me how likely each possible value is. For a die it is a table: each face has probability 1/6. For continuous values, such as pixel intensities, it is a density $p_x(x)$, a heat map over space. High density means values land there often. In the chart above, the green shading is that density.&lt;/p&gt;

&lt;p&gt;Two facts I will need constantly:&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
p_x(x) \ge 0 \qquad \int_{\mathbb{R}^d} p_x(x)\, dx = 1&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;The second says all probability mass integrates to 1. I will use $P_x$ loosely for both the distribution and its density. That is standard, and I will be explicit when the difference matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iid, independent and identically distributed.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identically distributed: every $x_i$ comes from the same $P_x$. Every log line came from the same user population, not some from production and some from a test environment.&lt;/li&gt;
&lt;li&gt;Independent: knowing $x_3$ tells me nothing extra about $x_7$. The first roll of a die does not influence the second.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In notation, $x_i \perp x_j$ and $x_i \sim P_x$.&lt;/p&gt;

&lt;h3&gt;
  
  
  The formula
&lt;/h3&gt;

&lt;p&gt;$$&lt;br&gt;
D = {x_1, x_2, \dots, x_n} \overset{\text{iid}}{\sim} P_x, \qquad x_i \in \mathbb{R}^d&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;Read aloud: the dataset $D$ is a collection of $n$ points. Each point is an independent draw from the same unknown distribution $P_x$. Each point is a vector of $d$ real numbers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;Type / shape&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$D$&lt;/td&gt;
&lt;td&gt;the dataset&lt;/td&gt;
&lt;td&gt;a set of $n$ vectors&lt;/td&gt;
&lt;td&gt;the only thing I actually observe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$n$&lt;/td&gt;
&lt;td&gt;number of samples&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;more data, a better picture of $P_x$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$x_i$&lt;/td&gt;
&lt;td&gt;one data point&lt;/td&gt;
&lt;td&gt;vector in $\mathbb{R}^d$&lt;/td&gt;
&lt;td&gt;an image, a sentence embedding, a signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$d$&lt;/td&gt;
&lt;td&gt;dimensionality&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;how many numbers describe one point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\sim$&lt;/td&gt;
&lt;td&gt;"is drawn from"&lt;/td&gt;
&lt;td&gt;relation&lt;/td&gt;
&lt;td&gt;links data to its source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iid&lt;/td&gt;
&lt;td&gt;independent and identically distributed&lt;/td&gt;
&lt;td&gt;assumption&lt;/td&gt;
&lt;td&gt;makes learning from samples legitimate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$P_x$&lt;/td&gt;
&lt;td&gt;true data distribution&lt;/td&gt;
&lt;td&gt;distribution on $\mathbb{R}^d$&lt;/td&gt;
&lt;td&gt;the hidden target, unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why "unknown" is the whole problem.&lt;/strong&gt; If I knew $P_x$, I would sample from it and stop. Every model in the playlist is a different trick for working with $P_x$ through samples alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why iid matters.&lt;/strong&gt; It licenses replacing an expectation, an average over $P_x$, with an average over the dataset. That is the law of large numbers:&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
\frac{1}{n}\sum_{i=1}^n h(x_i) \;\xrightarrow{\,n\to\infty\,}\; \mathbb{E}_{x\sim P_x}[h(x)]&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;That line is the engine behind every training loss later. The chart shows a small version: the sample mean settles as $n$ grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why $d$ is so large.&lt;/strong&gt; A 400×400 RGB image is one point in $\mathbb{R}^{480{,}000}$, one coordinate per pixel per colour channel. Real images occupy a thin region of that space. Random pixel vectors look like television static. This is the manifold hypothesis, and it comes back when naive GAN training falls over.&lt;/p&gt;

&lt;h3&gt;
  
  
  Two jobs hiding in one goal
&lt;/h3&gt;

&lt;p&gt;Given $D$, estimate $P_x$ and learn to sample from it. Those are different jobs, and different models emphasise different ones.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Who emphasises it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Density estimation&lt;/td&gt;
&lt;td&gt;answer "how likely is this $x$?"&lt;/td&gt;
&lt;td&gt;autoregressive models, VAEs through the ELBO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sampling&lt;/td&gt;
&lt;td&gt;produce a new $x \sim P_x$&lt;/td&gt;
&lt;td&gt;GANs, which never write a density down, and diffusion&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A GAN can sample well and still be unable to tell me $p(x)$ for a given image. I want to remember that split.&lt;/p&gt;

&lt;h3&gt;
  
  
  A worked example small enough to do by hand
&lt;/h3&gt;

&lt;p&gt;Let $d = 2$ and $n = 3$. Each point is hours slept and coffees drunk for a random person:&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
D = {x_1, x_2, x_3} = {(7, 1),\ (6, 2),\ (8, 0)}&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;Each $x_i \in \mathbb{R}^2$, so $d = 2$. Here $x_2 = (6, 2)$ means 6 hours of sleep and 2 coffees. iid means three different people, surveyed separately, from the same population.&lt;/p&gt;

&lt;p&gt;I want $\mathbb{E}[\text{coffees}]$ under the unknown $P_x$. I cannot integrate against a distribution I do not have. iid lets me estimate it from the sample: $\tfrac{1}{3}(1 + 2 + 0) = 1$.&lt;/p&gt;

&lt;p&gt;The generative goal is a machine that outputs new pairs such as $(7.5, 0.5)$: plausible, not copied from $D$, and following the same pattern. More sleep tends to go with less coffee. That dependency between coordinates is what $P_x$ captures, and a per-column average does not.&lt;/p&gt;

&lt;p&gt;The same picture with $d = 480{,}000$ and $n$ in the millions is image generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where the rest of the playlist sits, as I understand it now
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stretch&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;How it attacks "learn $P_x$ from $D$"&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Early&lt;/td&gt;
&lt;td&gt;GAN / divergence minimisation&lt;/td&gt;
&lt;td&gt;push $z \sim \mathcal{N}(0, I)$ through $g_\theta$ and shrink an f-divergence to $P_x$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next&lt;/td&gt;
&lt;td&gt;VAE&lt;/td&gt;
&lt;td&gt;latent-variable $P_\theta(x) = \int P_\theta(x, z)\,dz$, maximise the ELBO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Then&lt;/td&gt;
&lt;td&gt;WGAN&lt;/td&gt;
&lt;td&gt;the same game, with the Wasserstein distance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Then&lt;/td&gt;
&lt;td&gt;DDPM&lt;/td&gt;
&lt;td&gt;add noise to $x_0$, learn to reverse it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Then&lt;/td&gt;
&lt;td&gt;Autoregressive / transformer&lt;/td&gt;
&lt;td&gt;factorise $P_\theta(x) = \prod_t P_\theta(x_t \mid x_{&amp;lt;t})$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Then&lt;/td&gt;
&lt;td&gt;SSM / Mamba&lt;/td&gt;
&lt;td&gt;another sequence model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Late&lt;/td&gt;
&lt;td&gt;RLHF / DPO&lt;/td&gt;
&lt;td&gt;move the learned distribution toward preferences&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The next section turns the goal into a recipe: pick a parametric family $P_\theta$, define a divergence, and minimise it using only samples.&lt;/p&gt;

&lt;p&gt;Questions I want to be able to answer before I move on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If a dataset mixes 5,000 phone photos and 5,000 medical scans, which part of iid breaks, and why does that hurt?&lt;/li&gt;
&lt;li&gt;What is $d$ for a 28×28 grayscale digit? For a 64×64 RGB image?&lt;/li&gt;
&lt;li&gt;Once I have $D$, do I know $P_x$ exactly? What changes as $n \to \infty$?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next: &lt;a href="https://dev.to/blog/2026/10/general-principle-of-generative-models/"&gt;Section 2: The general principle of generative models&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>data</category>
      <category>deeplearning</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Section 2: The general principle of generative models</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Sun, 11 Oct 2026 07:18:47 +0000</pubDate>
      <link>https://dev.to/dks/section-2-the-general-principle-of-generative-models-3n3m</link>
      <guid>https://dev.to/dks/section-2-the-general-principle-of-generative-models-3n3m</guid>
      <description>&lt;p&gt;I am working through &lt;a href="https://www.youtube.com/playlist?list=PLZ2ps__7DhBa5xCmncgH7kPqLqMBq7xlu" rel="noopener noreferrer"&gt;Mathematical Foundations of Generative AI&lt;/a&gt;, Prof. Prathosh AP's public lectures. The playlist is the spine. These notes are my deep dive on each section: a visual when the picture is the point, a detour when a prerequisite is doing real work, and the formula in my own words.&lt;/p&gt;

&lt;p&gt;Previously: &lt;a href="https://dev.to/blog/2026/10/generative-ai-math-dataset-and-problem/"&gt;Section 1: The dataset and the problem&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 2: The general principle of generative models
&lt;/h2&gt;

&lt;p&gt;Section 1 left me with a vague goal: estimate $P_x$ and learn to sample from it. This is the recipe that turns that goal into three moves. Every later model in the lectures is this recipe with different choices plugged in.&lt;/p&gt;

&lt;p&gt;The statement I am carrying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;(i) Assume a parametric family on $P_x$, denoted $P_\theta$, represented using deep neural networks.&lt;br&gt;
(ii) Define and estimate a divergence between $P_x$ and $P_\theta$.&lt;br&gt;
(iii) Solve an optimisation problem over the parameters of $P_\theta$ to minimise that divergence.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The example that makes it concrete: draw $z \sim \mathcal{N}(0, I)$, pass it through a network $g_\theta : \mathcal{Z} \to \mathcal{X}$, and call the distribution of $x = g_\theta(z)$ by the name $P_\theta$. Then solve&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
\theta^* = \arg\min_\theta \; \mathcal{D}(P_x \,|\, P_\theta)&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;After that, sampling $z \sim \mathcal{N}(0, I)$ and computing $g_{\theta^&lt;em&gt;}(z)$ gives samples from $P_{\theta^&lt;/em&gt;}$, which is as close to $P_x$ as this family could get.&lt;/p&gt;

&lt;p&gt;Four prerequisites sit under that formula: the standard Gaussian $\mathcal{N}(0, I)$, what happens when a random variable is pushed through a function, what a divergence is, and the $\arg\min$ notation. Each detour is only as long as the step that needs it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Intuition
&lt;/h3&gt;

&lt;p&gt;I cannot see $P_x$. I build a machine with knobs, $\theta$, that turns plain random noise into data-shaped outputs. I keep turning the knobs until the machine's output distribution is as close as I can get to the real one. The closeness is a divergence. The turning is optimisation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The load test, continued
&lt;/h3&gt;

&lt;p&gt;The traffic generator from Section 1 takes random seeds and outputs synthetic requests. It has config knobs: endpoint weights, payload-size parameters, and so on.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Load-testing analogy&lt;/th&gt;
&lt;th&gt;Notation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Random seed fed into the generator&lt;/td&gt;
&lt;td&gt;$z \sim \mathcal{N}(0, I)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The generator code&lt;/td&gt;
&lt;td&gt;$g_\theta$, a neural network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Its config knobs&lt;/td&gt;
&lt;td&gt;$\theta$, the network weights&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The distribution of traffic it produces&lt;/td&gt;
&lt;td&gt;$P_\theta$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A score of how different synthetic traffic is from real logs&lt;/td&gt;
&lt;td&gt;the divergence $\mathcal{D}(P_x \,|\, P_\theta)$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tuning knobs until that score is near zero&lt;/td&gt;
&lt;td&gt;$\theta^* = \arg\min_\theta \mathcal{D}$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The hard step is the score. I cannot see the true user behaviour. I only have the log. That is the difficulty the rest of the lectures keep returning to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual
&lt;/h3&gt;

&lt;p&gt;One dimension is enough to see the recipe. The noise is $z \sim \mathcal{N}(0, 1)$. The network is the simplest one I can write, $g_\theta(z) = a z + b$, so $\theta = (a, b)$. The green curve is the target. The blue curve is what this generator can produce.&lt;/p&gt;

&lt;p&gt;Three things I want in front of me while I move the sliders:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the single bump, $a = 0.6$ and $b = 2$ drive the divergence to 0. The target is a bell centred at 2 with spread 0.6, and $x = 0.6z + 2$ is exactly that bell. The machine reproduces $P_x$.&lt;/li&gt;
&lt;li&gt;On the two bumps, the divergence never reaches 0, however I set $(a, b)$. The closest blue curve is a wide bell laid over both humps. A linear $g_\theta$ can only shift and stretch one bell. It cannot make two. That is why the principle asks for a deep network: $g_\theta$ has to be flexible enough that $P_\theta$ can get near $P_x$.&lt;/li&gt;
&lt;li&gt;The chart can draw the green curve, and it can compute the divergence, because I built the target in. In the real problem I do not get that picture. I only get samples. That is the first of the four open questions below.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Detours
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The standard Gaussian $\mathcal{N}(0, I)$.&lt;/strong&gt; $\mathcal{N}(\mu, \sigma^2)$ is the bell centred at $\mu$ with spread $\sigma$. Standard means $\mu = 0$ and $\sigma = 1$. In $k$ dimensions, $\mathcal{N}(0, I)$ is $k$ independent standard bells, one per coordinate. $I$ is the $k \times k$ identity covariance: each coordinate has variance 1, and no two coordinates are correlated.&lt;/p&gt;

&lt;p&gt;It is the input noise because every library can sample it, and it has no structure of its own. Any structure in the output has to come from $g_\theta$. So $z \sim \mathcal{N}(0, I)$ is a random seed: easy to draw, carrying nothing about images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pushing a random variable through a function.&lt;/strong&gt; If $z$ is random and $x = g(z)$, then $x$ is random too, with a new distribution determined by $g$.&lt;/p&gt;

&lt;p&gt;The simplest case: if $z \sim \mathcal{N}(0, 1)$, then $x = az + b \sim \mathcal{N}(b, a^2)$. Multiplying by $a$ stretches the spread. Adding $b$ slides the centre. That is what the sliders above are doing.&lt;/p&gt;

&lt;p&gt;A deep, nonlinear $g$ can bend the output into more than one hump, or into a thin set such as the distribution of faces. The output distribution is different from the distribution of $z$, and it depends on $g_\theta$. I name that output distribution $P_\theta$. For a deep network I usually cannot write a formula for it. I only know how to sample it: draw $z$, run $g_\theta$.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Divergence, which is weaker than a distance.&lt;/strong&gt; $\mathcal{D}(P \,|\, Q)$ scores how different two distributions are. The two properties I need:&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
\mathcal{D}(P_x \,|\, P_\theta) \ge 0, \qquad \mathcal{D}(P_x \,|\, P_\theta) = 0 \iff P_x = P_\theta&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;It need not be symmetric. $\mathcal{D}(P \,|\, Q)$ may differ from $\mathcal{D}(Q \,|\, P)$. That is why the notation uses $|$ rather than a comma. The KL divergence in the chart is one example. The next note builds the family they all belong to: &lt;a href="https://dev.to/blog/2026/10/f-divergences-in-generative-models/"&gt;Section 3a: f-divergences&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Those two properties are what make "minimise the divergence" a sensible goal. The smallest possible value is 0, and it is reached only when the model matches the data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;$\arg\min$.&lt;/strong&gt; $\min_\theta f(\theta)$ is the smallest value of $f$. $\arg\min_\theta f(\theta)$ is the input $\theta$ that achieves it. For $f(\theta) = (\theta - 3)^2 + 1$, the min is 1 and the argmin is 3. I want the knob settings, not the score, so the principle uses argmin.&lt;/p&gt;

&lt;h3&gt;
  
  
  The formula
&lt;/h3&gt;

&lt;p&gt;$$&lt;br&gt;
\theta^* = \arg\min_\theta \; \mathcal{D}\big(P_x \,|\, P_\theta\big), \qquad P_\theta := \text{distribution of } g_\theta(z),\; z \sim \mathcal{N}(0, I)&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;Read aloud: $\theta^*$ is the setting of the network weights that makes the divergence between the true data distribution and the distribution of the network's outputs as small as possible.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;Type / shape&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$z$&lt;/td&gt;
&lt;td&gt;input noise&lt;/td&gt;
&lt;td&gt;vector in $\mathbb{R}^k$, usually $k \ll d$&lt;/td&gt;
&lt;td&gt;the random seed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\mathcal{N}(0, I)$&lt;/td&gt;
&lt;td&gt;standard Gaussian&lt;/td&gt;
&lt;td&gt;distribution on $\mathbb{R}^k$&lt;/td&gt;
&lt;td&gt;easy-to-sample source of randomness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$g_\theta$&lt;/td&gt;
&lt;td&gt;generator&lt;/td&gt;
&lt;td&gt;function $\mathbb{R}^k \to \mathbb{R}^d$, a neural net&lt;/td&gt;
&lt;td&gt;reshapes noise into data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta$&lt;/td&gt;
&lt;td&gt;generator parameters&lt;/td&gt;
&lt;td&gt;a vector of weights&lt;/td&gt;
&lt;td&gt;the knobs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$P_\theta$&lt;/td&gt;
&lt;td&gt;model distribution&lt;/td&gt;
&lt;td&gt;distribution on $\mathbb{R}^d$, implicit&lt;/td&gt;
&lt;td&gt;what the generator produces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$P_x$&lt;/td&gt;
&lt;td&gt;true distribution&lt;/td&gt;
&lt;td&gt;distribution on $\mathbb{R}^d$, unknown&lt;/td&gt;
&lt;td&gt;the target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\mathcal{D}(\cdot \,|\, \cdot)$&lt;/td&gt;
&lt;td&gt;divergence&lt;/td&gt;
&lt;td&gt;two distributions to a scalar $\ge 0$&lt;/td&gt;
&lt;td&gt;the "how far apart" score&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\theta^*$&lt;/td&gt;
&lt;td&gt;optimal parameters&lt;/td&gt;
&lt;td&gt;same shape as $\theta$&lt;/td&gt;
&lt;td&gt;the trained generator&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Once training is done, sampling is: draw a fresh $z \sim \mathcal{N}(0, I)$, compute $g_{\theta^&lt;em&gt;}(z)$. That is a sample from $P_{\theta^&lt;/em&gt;} \approx P_x$. I have learned to sample from $P_x$ without writing it down.&lt;/p&gt;

&lt;h3&gt;
  
  
  A worked example small enough to do by hand
&lt;/h3&gt;

&lt;p&gt;Take $k = d = 1$ and $g_\theta(z) = 2z + 3$, so $\theta = (a, b) = (2, 3)$.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Draw three noise values: $z = -1, 0, 1$.&lt;/li&gt;
&lt;li&gt;Outputs: $g_\theta(-1) = 1$, $g_\theta(0) = 3$, $g_\theta(1) = 5$.&lt;/li&gt;
&lt;li&gt;By the pushforward above, all outputs come from $P_\theta = \mathcal{N}(3, 2^2)$. Centre 3, spread 2, which matches these samples.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the divergence, a two-outcome world is enough to compute by hand. Let $P_x$ be a fair coin, $(0.5, 0.5)$, and use KL, $\sum_i P_x(i) \ln \frac{P_x(i)}{P_\theta(i)}$. KL is formally the next part of the lectures. I only need it here to see numbers move.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the model says $P_\theta = (0.9, 0.1)$: $0.5 \ln\frac{0.5}{0.9} + 0.5 \ln\frac{0.5}{0.1} = 0.5(-0.588) + 0.5(1.609) \approx 0.511$.&lt;/li&gt;
&lt;li&gt;If the model says $P_\theta = (0.6, 0.4)$: $0.5 \ln\frac{0.5}{0.6} + 0.5 \ln\frac{0.5}{0.4} = 0.5(-0.182) + 0.5(0.223) \approx 0.020$.&lt;/li&gt;
&lt;li&gt;If the model says $P_\theta = (0.5, 0.5)$: both terms are $0.5 \ln 1 = 0$, so the divergence is exactly 0.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the model gets closer to the truth, the score falls toward 0, and it hits 0 only at a perfect match. Optimisation is moving $\theta$ in the direction that lowers this number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Four questions this recipe does not answer
&lt;/h3&gt;

&lt;p&gt;The rest of the lectures is the attempt to answer these.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Why it is hard&lt;/th&gt;
&lt;th&gt;Where I expect the answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;How do I compute the divergence without formulas for $P_x$ or $P_\theta$?&lt;/td&gt;
&lt;td&gt;I only have samples of both&lt;/td&gt;
&lt;td&gt;Write the divergence as expectations, then estimate them with sample averages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Which divergence?&lt;/td&gt;
&lt;td&gt;Different choices behave differently. The wide bell over two bumps is one failure mode&lt;/td&gt;
&lt;td&gt;f-divergences first, Wasserstein later&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How do I choose $g_\theta$, and so $P_\theta$?&lt;/td&gt;
&lt;td&gt;Flexible enough, and still trainable&lt;/td&gt;
&lt;td&gt;GANs, VAEs, diffusion, transformers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How do I solve the optimisation?&lt;/td&gt;
&lt;td&gt;Millions of parameters, often a min-max game&lt;/td&gt;
&lt;td&gt;Gradient descent, then its adversarial variants&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Where the later models sit
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Choice of $P_\theta$&lt;/th&gt;
&lt;th&gt;Divergence&lt;/th&gt;
&lt;th&gt;Optimisation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GAN&lt;/td&gt;
&lt;td&gt;$g_\theta(z)$, implicit&lt;/td&gt;
&lt;td&gt;Jensen–Shannon, an f-divergence&lt;/td&gt;
&lt;td&gt;min-max with a discriminator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WGAN&lt;/td&gt;
&lt;td&gt;$g_\theta(z)$, implicit&lt;/td&gt;
&lt;td&gt;Wasserstein&lt;/td&gt;
&lt;td&gt;min-max with a 1-Lipschitz critic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VAE&lt;/td&gt;
&lt;td&gt;latent model $\int P_\theta(x \mid z)\, p(z)\, dz$&lt;/td&gt;
&lt;td&gt;KL, through the ELBO&lt;/td&gt;
&lt;td&gt;maximise the ELBO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DDPM&lt;/td&gt;
&lt;td&gt;reverse chain of Gaussians&lt;/td&gt;
&lt;td&gt;KL, through the ELBO&lt;/td&gt;
&lt;td&gt;regression on the added noise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Autoregressive / transformer&lt;/td&gt;
&lt;td&gt;$\prod_t P_\theta(x_t \mid x_{&amp;lt;t})$&lt;/td&gt;
&lt;td&gt;KL, which is maximum likelihood&lt;/td&gt;
&lt;td&gt;cross-entropy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One link I want early: minimising $\mathrm{KL}(P_x \,|\, P_\theta)$ is the same as maximum likelihood, because $\arg\min \mathrm{KL}(P_x \,|\, P_\theta) = \arg\max \mathbb{E}[\log P_\theta(x)]$. That is why VAEs, diffusion models, and language models can all train on log-likelihood losses and still be this same recipe.&lt;/p&gt;

&lt;p&gt;Questions I want to be able to answer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Why can no setting of $(a, b)$ match the two-bump target, and what has to change about $g_\theta$?&lt;/li&gt;
&lt;li&gt;After training, how do I produce 10 new samples, in one line?&lt;/li&gt;
&lt;li&gt;If $\mathcal{D}(P_x \,|\, P_\theta) = 0$, what follows? What if the divergence is small but not zero?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next: &lt;a href="https://dev.to/blog/2026/10/f-divergences-in-generative-models/"&gt;Section 3a: f-divergences&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>computerscience</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Section 3a: f-divergences</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Sun, 11 Oct 2026 07:18:44 +0000</pubDate>
      <link>https://dev.to/dks/section-3a-f-divergences-194o</link>
      <guid>https://dev.to/dks/section-3a-f-divergences-194o</guid>
      <description>&lt;p&gt;I am working through &lt;a href="https://www.youtube.com/playlist?list=PLZ2ps__7DhBa5xCmncgH7kPqLqMBq7xlu" rel="noopener noreferrer"&gt;Mathematical Foundations of Generative AI&lt;/a&gt;, Prof. Prathosh AP's public lectures. The playlist is the spine. These notes are my deep dive on each section: a visual when the picture is the point, a detour when a prerequisite is doing real work, and the formula in my own words.&lt;/p&gt;

&lt;p&gt;Previously: &lt;a href="https://dev.to/blog/2026/10/general-principle-of-generative-models/"&gt;Section 2: The general principle of generative models&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 3a: f-divergences
&lt;/h2&gt;

&lt;p&gt;Section 2 left a slot for a divergence. This note fills it with a family. One convex function $f$ picks the score. Section 3b, not written yet, is the convex conjugate: the rewrite that estimates $D_f$ from samples, which is the bridge into GANs.&lt;/p&gt;

&lt;p&gt;The statement I am carrying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Given two distributions with densities $P_x$ and $P_\theta$,&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
D_f(P_x \,|\, P_\theta) = \int_{\mathcal{X}} P_\theta(x)\, f!\left(\frac{P_x(x)}{P_\theta(x)}\right) dx&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;where $f: \mathbb{R}&lt;em&gt;+ \to \mathbb{R}$ is convex and lower-semicontinuous, with $f(1) = 0$. Then $D_f \ge 0$, and $D_f = 0$ if and only if $P_x = P&lt;/em&gt;\theta$.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Intuition
&lt;/h3&gt;

&lt;p&gt;At each point $x$ I compare how much probability the data puts there with how much the model puts there. The ratio $P_x / P_\theta$ is 1 where they agree and something else where they do not. $f$ turns that local mismatch into a penalty. The integral averages the penalties. A different $f$ punishes a different kind of mismatch, so one template gives a family.&lt;/p&gt;

&lt;h3&gt;
  
  
  The load test, by endpoint
&lt;/h3&gt;

&lt;p&gt;I compare synthetic traffic with the real access log, endpoint by endpoint.&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
\text{ratio} = \frac{\text{real share of traffic}}{\text{synthetic share of traffic}}&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;A ratio of 1 means the generator gets that endpoint right. A ratio of 3 means real users hit it three times as often as the generator does. A ratio of 0.2 means the generator hammers an endpoint real users barely touch.&lt;/p&gt;

&lt;p&gt;The single score depends on which failure I care about.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing real traffic patterns. The penalty grows when the ratio is large. That is forward KL.&lt;/li&gt;
&lt;li&gt;Fake traffic that real users would never send. The penalty grows when the ratio is near 0. That is reverse KL.&lt;/li&gt;
&lt;li&gt;A balanced score that cannot run off to infinity. That is Jensen–Shannon or total variation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;$f$ is the penalty. The integral is the average over endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual
&lt;/h3&gt;

&lt;p&gt;$P_x$ is a standard bell centred at 0. $P_\theta$ is the same bell shifted to $\mu$. Pick an $f$. The top curve is the penalty, and it passes through $(1, 0)$. The coral curve is the integrand $P_\theta(x)\, f(P_x(x)/P_\theta(x))$. The four numbers are the integrals.&lt;/p&gt;

&lt;p&gt;Three things I want in front of me while I move $\mu$:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;At $\mu = 0$ every divergence is 0. Matching distributions means zero penalty, for every $f$ with $f(1) = 0$.&lt;/li&gt;
&lt;li&gt;With forward KL, the coral curve dips below zero in places. A single point can contribute a negative amount. The total never does. The proof below is why.&lt;/li&gt;
&lt;li&gt;Jensen–Shannon and total variation level off as $\mu$ grows. Both are bounded. The two KLs keep climbing. That saturation is the later reason a GAN, which aims at Jensen–Shannon, can stop learning when the data and the model do not overlap.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Detours
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Density ratio.&lt;/strong&gt; $u(x) = P_x(x) / P_\theta(x)$ asks, at $x$, how many times more likely real data is here than model data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$u = 1$: agreement at this point.&lt;/li&gt;
&lt;li&gt;$u &amp;gt; 1$: the model under-produces here.&lt;/li&gt;
&lt;li&gt;$u &amp;lt; 1$: the model over-produces here.&lt;/li&gt;
&lt;li&gt;$u = 0$: the model puts mass where the data never goes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If $P_x = P_\theta$ everywhere, then $u(x) = 1$ everywhere. $f$ only ever sees this ratio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Convexity.&lt;/strong&gt; A function is convex when it is bowl-shaped: the straight line between any two points on its graph lies on or above the curve. For $\lambda \in [0, 1]$,&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
\lambda f(u_1) + (1-\lambda) f(u_2) \;\ge\; f\big(\lambda u_1 + (1-\lambda) u_2\big)&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;Averaging the outputs is at least as big as the output of the average. Check with $f(u) = u^2$, $u_1 = 0$, $u_2 = 2$, $\lambda = \tfrac{1}{2}$. The average of the outputs is $\tfrac{1}{2}(0 + 4) = 2$. The output of the average is $f(1) = 1$. And $2 \ge 1$.&lt;/p&gt;

&lt;p&gt;Convexity is what forces $D_f \ge 0$.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expectation as an integral.&lt;/strong&gt; For a continuous density $p$, the expected value of $h(x)$ is a probability-weighted average:&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
\mathbb{E}&lt;em&gt;{x \sim p}[h(x)] = \int&lt;/em&gt;{\mathcal{X}} p(x)\, h(x)\, dx&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jensen's inequality.&lt;/strong&gt; For convex $f$ and a random variable $U$,&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
\mathbb{E}[f(U)] \;\ge\; f(\mathbb{E}[U])&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;This is the two-point definition extended to any average. On a bowl, the average of points on the surface lands above the value at the average, never below.&lt;/p&gt;

&lt;h3&gt;
  
  
  The formula
&lt;/h3&gt;

&lt;p&gt;$$&lt;br&gt;
D_f(P_x \,|\, P_\theta) = \int_{\mathcal{X}} P_\theta(x)\, f!\left(\frac{P_x(x)}{P_\theta(x)}\right) dx = \mathbb{E}&lt;em&gt;{x \sim P&lt;/em&gt;\theta}!\left[f!\left(\frac{P_x(x)}{P_\theta(x)}\right)\right]&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;Read aloud: the average penalty, over points drawn from the model, of how mismatched the two densities are at each point.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;Type / shape&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$P_x(x)$&lt;/td&gt;
&lt;td&gt;true density at $x$&lt;/td&gt;
&lt;td&gt;scalar $\ge 0$&lt;/td&gt;
&lt;td&gt;the data's weight here&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$P_\theta(x)$&lt;/td&gt;
&lt;td&gt;model density at $x$&lt;/td&gt;
&lt;td&gt;scalar $\ge 0$&lt;/td&gt;
&lt;td&gt;the model's weight, and the weight in the average&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$u = P_x/P_\theta$&lt;/td&gt;
&lt;td&gt;density ratio&lt;/td&gt;
&lt;td&gt;scalar $\ge 0$&lt;/td&gt;
&lt;td&gt;local mismatch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$f$&lt;/td&gt;
&lt;td&gt;generator of the divergence&lt;/td&gt;
&lt;td&gt;convex, $f(1) = 0$&lt;/td&gt;
&lt;td&gt;turns mismatch into a penalty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$\int \cdot\, dx$&lt;/td&gt;
&lt;td&gt;integral over $\mathcal{X}$&lt;/td&gt;
&lt;td&gt;operation&lt;/td&gt;
&lt;td&gt;adds the penalties&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$D_f$&lt;/td&gt;
&lt;td&gt;the divergence&lt;/td&gt;
&lt;td&gt;scalar $\ge 0$&lt;/td&gt;
&lt;td&gt;the total score&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each condition on $f$ earns its place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$f(1) = 0$. If the distributions match, $u = 1$ everywhere, so $D_f = \int P_\theta \cdot 0\, dx = 0$.&lt;/li&gt;
&lt;li&gt;Convex. This is the $D_f \ge 0$ proof below.&lt;/li&gt;
&lt;li&gt;Lower-semicontinuous. No sudden downward jumps. Section 3b needs it so the conjugate is well behaved.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The proof that $D_f \ge 0$
&lt;/h3&gt;

&lt;p&gt;The lectures state the property. This is the short proof.&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
\begin{aligned}&lt;br&gt;
D_f(P_x \,|\, P_\theta) &amp;amp;= \mathbb{E}&lt;em&gt;{x \sim P&lt;/em&gt;\theta}!\left[f!\left(\tfrac{P_x(x)}{P_\theta(x)}\right)\right] \&lt;br&gt;
&amp;amp;\ge f!\left(\mathbb{E}&lt;em&gt;{x \sim P&lt;/em&gt;\theta}!\left[\tfrac{P_x(x)}{P_\theta(x)}\right]\right) \&lt;br&gt;
&amp;amp;= f!\left(\int P_\theta(x)\, \tfrac{P_x(x)}{P_\theta(x)}\, dx\right) \&lt;br&gt;
&amp;amp;= f!\left(\int P_x(x)\, dx\right) \&lt;br&gt;
&amp;amp;= f(1) = 0&lt;br&gt;
\end{aligned}&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;The first line is the expectation form. The second is Jensen. The third writes the expectation as an integral. $P_\theta$ cancels. A density integrates to 1, and $f(1) = 0$.&lt;/p&gt;

&lt;p&gt;In words: the average ratio, weighted by the model, is exactly 1. A bowl-shaped penalty averaged around 1 cannot fall below its value at 1, which is 0. That is why the coral curve can go negative locally while the total stays non-negative.&lt;/p&gt;

&lt;h3&gt;
  
  
  One template, four choices of $f$
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;$f(u)$&lt;/th&gt;
&lt;th&gt;Resulting divergence&lt;/th&gt;
&lt;th&gt;Behaviour&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Forward KL&lt;/td&gt;
&lt;td&gt;$u \log u$&lt;/td&gt;
&lt;td&gt;$\displaystyle\int P_x \log\frac{P_x}{P_\theta}\, dx = D_{\mathrm{KL}}(P_x \,|\, P_\theta)$&lt;/td&gt;
&lt;td&gt;Punishes the model for missing real data. Mode-covering. This is the blurry blob in Section 2, and it is maximum likelihood.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse KL&lt;/td&gt;
&lt;td&gt;$-\log u$&lt;/td&gt;
&lt;td&gt;$\displaystyle\int P_\theta \log\frac{P_\theta}{P_x}\, dx = D_{\mathrm{KL}}(P_\theta \,|\, P_x)$&lt;/td&gt;
&lt;td&gt;Punishes the model for generating where the data is not. Mode-seeking. It sits on one hump.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jensen–Shannon&lt;/td&gt;
&lt;td&gt;$\tfrac{1}{2}\big[u \log u - (u+1)\log\tfrac{u+1}{2}\big]$&lt;/td&gt;
&lt;td&gt;symmetric, bounded by $\log 2$&lt;/td&gt;
&lt;td&gt;What the original GAN minimises.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total variation&lt;/td&gt;
&lt;td&gt;$\tfrac{1}{2}\lvert u - 1 \rvert$&lt;/td&gt;
&lt;td&gt;$\tfrac{1}{2}\int \lvert P_x - P_\theta \rvert\, dx$&lt;/td&gt;
&lt;td&gt;Symmetric, bounded by 1.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Forward KL is the template with $f(u) = u \log u$, and the $P_\theta$ cancels:&lt;/p&gt;

&lt;p&gt;$$&lt;br&gt;
\int P_\theta \cdot \frac{P_x}{P_\theta} \log\frac{P_x}{P_\theta}\, dx = \int P_x \log\frac{P_x}{P_\theta}\, dx&lt;br&gt;
$$&lt;/p&gt;

&lt;p&gt;Reverse KL is the same template with $f(u) = -\log u$. Substituting it recovers $\int P_\theta \log(P_\theta / P_x)\, dx$. The Jensen–Shannon $f$ above satisfies $f(1) = 0$. A GAN writeup often uses $f(u) = u \log u - (u+1)\log(u+1)$, which differs from this one by a constant shift and is why that loss is described as similar to Jensen–Shannon rather than identical. Total variation is $\tfrac{1}{2}\lvert u - 1 \rvert$, which is the choice that turns the template into $\tfrac{1}{2}\int \lvert P_x - P_\theta \rvert$.&lt;/p&gt;

&lt;h3&gt;
  
  
  A worked example small enough to do by hand
&lt;/h3&gt;

&lt;p&gt;Two outcomes. $P_x = (0.5, 0.5)$, a fair coin. $P_\theta = (0.8, 0.2)$, a biased model.&lt;/p&gt;

&lt;p&gt;The ratios are $u_1 = 0.5 / 0.8 = 0.625$ (over-produced) and $u_2 = 0.5 / 0.2 = 2.5$ (under-produced). The template on a finite set is $D_f = \sum_i P_\theta(i)\, f(u_i)$.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Divergence&lt;/th&gt;
&lt;th&gt;Computation&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Forward KL&lt;/td&gt;
&lt;td&gt;$0.8(0.625 \ln 0.625) + 0.2(2.5 \ln 2.5) = 0.8(-0.294) + 0.2(2.291)$&lt;/td&gt;
&lt;td&gt;$\approx 0.223$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse KL&lt;/td&gt;
&lt;td&gt;$0.8(-\ln 0.625) + 0.2(-\ln 2.5) = 0.8(0.470) + 0.2(-0.916)$&lt;/td&gt;
&lt;td&gt;$\approx 0.193$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jensen–Shannon&lt;/td&gt;
&lt;td&gt;$0.8\, f(0.625) + 0.2\, f(2.5) = 0.8(0.0218) + 0.2(0.1660)$&lt;/td&gt;
&lt;td&gt;$\approx 0.051$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total variation&lt;/td&gt;
&lt;td&gt;$0.8 \cdot \tfrac{1}{2}(0.375) + 0.2 \cdot \tfrac{1}{2}(1.5) = 0.15 + 0.15$&lt;/td&gt;
&lt;td&gt;$0.300$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All four are positive, and they disagree on the size of the gap. Forward KL is not reverse KL, so the score is not symmetric. In the forward-KL row, outcome 1 contributes about $-0.235$ and outcome 2 about $+0.458$. Negative pieces, positive total. That is Jensen. If $P_\theta = (0.5, 0.5)$, every ratio is 1 and every row is 0.&lt;/p&gt;

&lt;h3&gt;
  
  
  The catch, which is Section 3b
&lt;/h3&gt;

&lt;p&gt;Computing $D_f$ needs the values $P_x(x)$ and $P_\theta(x)$.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$P_x$ is unknown. Section 1 only gave me samples.&lt;/li&gt;
&lt;li&gt;$P_\theta$ is implicit. Section 2 lets me sample $g_\theta(z)$, not evaluate a density.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I cannot form the ratio $u(x)$. What I can form are averages over samples, by the law of large numbers. Section 3b has to rewrite $D_f$ as expectations under $P_x$ and under $P_\theta$, with no density values in the formula. The convex conjugate is the tool. The result is the GAN objective.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where this sits in the lectures
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;This note answers "which divergence?" with a menu, not a single choice.&lt;/li&gt;
&lt;li&gt;A GAN picks the Jensen–Shannon-like $f$.&lt;/li&gt;
&lt;li&gt;VAEs, diffusion, and autoregressive models minimise forward KL, which is maximum likelihood.&lt;/li&gt;
&lt;li&gt;Bounded scores such as Jensen–Shannon saturate when $P_x$ and $P_\theta$ do not overlap. Wasserstein, which is not an f-divergence, is the later answer to that.&lt;/li&gt;
&lt;li&gt;The KL term that keeps an aligned model close to a reference model, $D_{\mathrm{KL}}(\pi_\theta \,|\, \pi_{\mathrm{ref}})$, is this same family.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions I want to be able to answer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Why does $f(1) = 0$ have to hold? What breaks if $f(1) = 5$?&lt;/li&gt;
&lt;li&gt;In the worked example, outcome 1 contributes a negative amount to forward KL. Why does that not break $D_f \ge 0$?&lt;/li&gt;
&lt;li&gt;Why can I not plug the dataset into the $D_f$ formula and compute it directly?&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>computerscience</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Building Scalable Agentic AI Platforms: A Technical Deep Dive - Part 2</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Sat, 10 Oct 2026 16:07:03 +0000</pubDate>
      <link>https://dev.to/dks/building-scalable-agentic-ai-platforms-a-technical-deep-dive-part-2-5958</link>
      <guid>https://dev.to/dks/building-scalable-agentic-ai-platforms-a-technical-deep-dive-part-2-5958</guid>
      <description>&lt;p&gt;Before diving into Part 2, make sure to read &lt;a href="https://dev.to/blog/2025/03/building-scalable-ai-platforms/"&gt;Part 1&lt;/a&gt; where we covered the fundamentals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Module 1: Model Management using LLM Gateway
&lt;/h2&gt;

&lt;p&gt;There are several models that are useful for specific purposes. Even though there are general-purpose models, we need to choose the best-performing model for our task. Deploying those models in various cloud providers and applying the security principles, tracing, cost controlling them is a Challenge. &lt;/p&gt;

&lt;p&gt;&lt;a href="/images/agentic-ai/before_llm-gateway.png" class="article-body-image-wrapper"&gt;&lt;img src="/images/agentic-ai/before_llm-gateway.png" alt="LLM Gateway Architecture Before"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the gateway,&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/agentic-ai/after-llm-gw.png" class="article-body-image-wrapper"&gt;&lt;img src="/images/agentic-ai/after-llm-gw.png" alt="LLM Gateway Architecture After"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Key features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Routing to right Model&lt;/li&gt;
&lt;li&gt;Central logging for Compliance checks&lt;/li&gt;
&lt;li&gt;Metrics collection for cost and usage&lt;/li&gt;
&lt;/ol&gt;




</description>
      <category>ai</category>
      <category>architecture</category>
      <category>llm</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Building an Enterprise MCP Tool Broker: Turning OpenAPI into Agent Tools</title>
      <dc:creator>Dinesh Kumar Sarangapani</dc:creator>
      <pubDate>Sat, 10 Oct 2026 14:24:32 +0000</pubDate>
      <link>https://dev.to/dks/building-an-enterprise-mcp-tool-broker-turning-openapi-into-agent-tools-22og</link>
      <guid>https://dev.to/dks/building-an-enterprise-mcp-tool-broker-turning-openapi-into-agent-tools-22og</guid>
      <description>&lt;p&gt;AI agents are only as useful as the tools they can call. An agent without tools can only chat. An agent with tools can query databases, create tickets, inspect files, and trigger deployments.&lt;/p&gt;

&lt;p&gt;In most enterprises, those capabilities already exist as REST APIs. Over the last decade, organizations built hundreds of internal microservices documented with OpenAPI.&lt;/p&gt;

&lt;p&gt;When we started connecting agents to our internal systems, we faced a choice. Should we manually write dedicated tool wrappers for every API? Or could we build a broker that translates existing OpenAPI specifications into agent tools automatically?&lt;/p&gt;

&lt;p&gt;We chose to build a centralized tool broker using the Model Context Protocol (MCP). Here is how the idea works, how it performed in production, and what to watch out for.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Idea: A Dynamic Tool Broker
&lt;/h2&gt;

&lt;p&gt;Writing dedicated tool servers for hundreds of microservices does not scale. Each engineering team would need to learn a new protocol, maintain extra code, and keep tool schemas manually synchronized with API updates.&lt;/p&gt;

&lt;p&gt;The core idea was to build a single enterprise tool broker.&lt;/p&gt;

&lt;p&gt;The broker sits between AI agents and internal APIs. To the agent, the broker looks like an MCP server offering a unified catalog of tools. Behind the scenes, the broker ingests existing OpenAPI specifications from registered services and dynamically translates each API operation into a typed, callable tool.&lt;/p&gt;

&lt;p&gt;When an agent invokes a tool, the broker validates the caller's identity, translates the arguments into an HTTP request, calls the backend service, and returns the formatted result back to the model.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Worked Well
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero Work for Service Teams&lt;/strong&gt;: Existing microservices did not need code changes. As long as a team maintained an accurate OpenAPI specification, their service became agent-callable instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardized Tool Discovery&lt;/strong&gt;: Instead of teaching every agent about individual services, agents connect to one broker endpoint. The broker dynamically filters which tools an agent can see based on the caller's permissions and role.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decoupled Architecture&lt;/strong&gt;: Upstream microservices remain pure REST APIs. If the agent protocol changes or new client interfaces emerge, the translation logic lives in the broker rather than scattered across dozens of repositories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Governed Access Controls&lt;/strong&gt;: The broker enforces centralized authorization before executing any backend request. We can enforce least-privilege access, audit tool invocation logs, and disable high-risk actions without modifying the underlying microservices.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What to Watch Out For
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Vague Endpoint Summaries Confuse Models&lt;/strong&gt;: Large language models pick tools based on natural language descriptions. If an API has a generic description like &lt;code&gt;Process data&lt;/code&gt;, the model will either hallucinate its purpose or never call it. Clear, descriptive summaries in your API specs are critical for agent accuracy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema Reference Inlining (&lt;code&gt;$ref&lt;/code&gt;)&lt;/strong&gt;: Many enterprise API specifications use internal schema references (&lt;code&gt;$ref&lt;/code&gt;) to share data types across endpoints. Many LLM engines and agent frameworks cannot resolve external reference pointers automatically. The broker must resolve and inline referenced schemas before handing tool definitions to the model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circular Schemas&lt;/strong&gt;: Real-world enterprise APIs frequently contain circular schema definitions (for example, a &lt;code&gt;Folder&lt;/code&gt; that contains a list of &lt;code&gt;Folder&lt;/code&gt; items). If your schema resolver does not set recursion depth limits, it will enter an infinite loop or produce massive schemas that exhaust the model's context window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context Window Blowups from Large Payloads&lt;/strong&gt;: A GET endpoint that returns 10 megabytes of JSON is fine for a frontend data table, but it will overflow an LLM's context window. The broker must detect oversized responses, summarize them, or paginate results before returning them to the agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write Actions Need Confirmation&lt;/strong&gt;: Read-only tools (searching data, fetching records) are safe to execute autonomously. Write tools (deleting resources, triggering updates) should require explicit human confirmation or stricter permission gates before execution.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>agents</category>
      <category>api</category>
      <category>architecture</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
