<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by nachiket tanksale on Medium]]></title>
        <description><![CDATA[Stories by nachiket tanksale on Medium]]></description>
        <link>https://medium.com/@nachiket-tanksale?source=rss-26a6ee15a5c5------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*XyAYzbFcGyFlN59SZsNUGg.jpeg</url>
            <title>Stories by nachiket tanksale on Medium</title>
            <link>https://medium.com/@nachiket-tanksale?source=rss-26a6ee15a5c5------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 09:57:02 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@nachiket-tanksale/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Day 8: ML Infrastructure, Training at Scale, Data Parallelism, and Distributed Training]]></title>
            <link>https://nachiket-tanksale.medium.com/day-8-ml-infrastructure-training-at-scale-data-parallelism-and-distributed-training-da683af8400a?source=rss-26a6ee15a5c5------2</link>
            <guid isPermaLink="false">https://medium.com/p/da683af8400a</guid>
            <category><![CDATA[distributed-systems]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[gpu]]></category>
            <category><![CDATA[mlops]]></category>
            <dc:creator><![CDATA[nachiket tanksale]]></dc:creator>
            <pubDate>Sat, 14 Nov 2026 10:10:08 GMT</pubDate>
            <atom:updated>2026-11-14T10:10:08.827Z</atom:updated>
            <content:encoded><![CDATA[<p>Read the Day 7 story <a href="https://nachiket-tanksale.medium.com/day-7-rag-systems-retrieval-is-an-ml-problem-not-just-a-vector-database-1ec1964c191c">here</a>.</p><h3>1. Start with the single-GPU training loop</h3><p>For a batch B:</p><pre>θ_(t+1) = Optimizer( θ_t, ∇_θ L(B; θ_t) )</pre><p>Conceptually:</p><pre>Data → Forward → Loss → Backward → Gradient → Optimizer</pre><p>On one GPU, the entire model and its training state may fit in GPU memory. But memory isn’t just the model weights.</p><h3>2. What actually consumes GPU memory?</h3><p>For a neural network, memory typically includes:</p><ol><li><strong>Parameters (W).</strong></li><li><strong>Gradients (∇_W L).</strong></li><li><strong>Optimizer state.</strong> Adam keeps two extra values per parameter, the first moment m_t and the second moment v_t, so the optimizer can need substantially more memory than the raw weights.</li><li><strong>Activations.</strong> Intermediate tensors kept for backpropagation (a₁, a₂, …, a_L). For large Transformers, activations can be a major consumer, and they grow with batch size and sequence length.</li></ol><p>A useful rule of thumb for Adam-style training: <strong>about 16 bytes per parameter</strong> before counting activations. In mixed precision, that is 2 (BF16 weights) + 2 (BF16 gradients) + 4 (FP32 master weights) + 4 (m) + 4 (v). In pure FP32, it is 4 + 4 + 4 + 4. So a 1B-parameter model needs roughly 16 GB for training state alone, and a 7B model needs about 112 GB, which already exceeds a single 80 GB GPU.</p><pre>Memory ≠ just model parameters</pre><h3>3. Why mixed precision helps</h3><p>FP32 uses 32 bits (4 bytes) per value. FP16/BF16 use 16 bits (2 bytes). For 1⁰⁹ parameters, one copy takes about 4 GB in FP32 and 2 GB in FP16/BF16. But training still needs gradients, optimizer state, and often FP32 master weights, so the total saving isn’t simply “half.” Mixed precision’s bigger wins are faster math on tensor cores and less memory traffic, including for activations.</p><h3>4. Why BF16 is popular for modern training</h3><p>FP16 has 5 exponent bits and 10 mantissa bits, so its range is limited and underflow or overflow is common. BF16 has 8 exponent bits (the same as FP32) and only 7 mantissa bits.</p><pre>BF16 ≈ FP32-like range + FP16-like storage</pre><p>This makes BF16 convenient for large-scale training: it generally avoids the loss scaling that FP16 needs, at the cost of lower precision per value. You still need to watch numerical stability (the same care as Day 3’s log-sum-exp and Day 7’s stable softmax).</p><h3>5. Data parallelism</h3><p>Suppose you have N = 8 GPUs. Each GPU gets a different mini-batch B₁, …, B₈ and holds an identical copy of the model (θ₁ = θ₂ = … = θ₈). Each computes its own gradient g_i = ∇_θ L(B_i). Then we aggregate:</p><pre>g = (1/N) Σ_(i=1..N) g_i</pre><p>and every GPU applies the same update. This is <strong>data parallelism</strong>. Because the averaged gradient equals the gradient of the combined batch, it is mathematically the same as training with one large batch.</p><h3>6. All-reduce</h3><p>The aggregation is usually implemented as an <strong>all-reduce</strong> collective:</p><pre>GPU 0: g0 ─┐<br>GPU 1: g1 ─┤<br>GPU 2: g2 ─┼──► aggregate ──► every GPU receives g<br>GPU 3: g3 ─┘</pre><p>After the all-reduce, every GPU holds the same g, so every replica makes the same update and stays in sync. Ring all-reduce is a useful mental model. Its notable property is that each GPU sends and receives roughly <strong>2 × (the gradient size)</strong> regardless of N, which is why data parallelism scales reasonably well in bandwidth terms. In practice, frameworks also split gradients into <strong>buckets</strong> and start all-reducing a bucket as soon as its gradients are ready during the backward pass, overlapping communication with computation.</p><h3>7. Why distributed training isn’t automatically N× faster</h3><p>Suppose one GPU takes 100 ms per step. Eight GPUs don’t automatically give 12.5 ms. You now have communication, synchronization, network contention, load imbalance, and input-pipeline limits. A simple model:</p><pre>T_step ≈ T_compute + T_communication + T_overhead</pre><p><strong>Scaling efficiency</strong> depends on which kind of scaling you’re measuring (next section):</p><pre>Strong scaling (fixed total work):      Efficiency(N) = T₁ / (N · T_N)<br>Weak scaling (work grows with N):       Efficiency(N) = T₁ / T_N</pre><p>Here T_N is the time per step (or per job) with N GPUs. Equivalently, efficiency is throughput_N / (N × throughput_1). Ideal scaling gives 1. Real systems give less than 1.</p><h3>8. Strong scaling vs weak scaling</h3><p><strong>Strong scaling:</strong> keep the total workload fixed. As N grows, you want training time to fall. (Example: the same global batch split across more GPUs.) Efficiency drops because each GPU gets less work while communication stays about the same. This is the intuition behind Amdahl’s law.</p><p><strong>Weak scaling:</strong> grow the total workload with N, typically by increasing the global batch size, and try to keep time per step roughly constant.</p><p>This distinction comes up surprisingly often in infrastructure interviews.</p><h3>9. Effective batch size</h3><p>With N GPUs and local batch size B:</p><pre>B_global = N · B</pre><p>With gradient accumulation over K steps:</p><pre>B_effective = N · B · K</pre><p>This matters because changing batch size changes optimization dynamics. Blindly moving from B = 256 to B = 32,768 is not merely an infrastructure change. It changes gradient noise, learning-rate requirements, and convergence behavior. Common practice is to scale the learning rate with the batch size (the linear scaling rule) with a warmup period, and very large batches often need specialized optimizers (LARS, LAMB). Beyond a “critical batch size,” bigger batches stop reducing the number of steps needed and just burn compute.</p><h3>10. Gradient accumulation</h3><p>Suppose GPU memory only permits B = 8, but you want an effective batch of 32. Accumulate gradients over K = 4 micro-batches before updating:</p><pre>g = (1/4) Σ_(k=1..4) g_k</pre><pre>batch 1 → forward/backward → accumulate<br>batch 2 → forward/backward → accumulate<br>batch 3 → forward/backward → accumulate<br>batch 4 → forward/backward → UPDATE</pre><p>This increases the effective batch size without all samples residing in memory at once. But it does not give the throughput of a true large batch processed in parallel, because the micro-batches run sequentially. Two practical details: divide each micro-batch loss by K so the gradient is a proper average, and in distributed data parallel, skip the gradient all-reduce on all but the last micro-step.</p><h3>11. When data parallelism isn’t enough</h3><p>Suppose the model itself doesn’t fit on one GPU. Plain data parallelism doesn’t help, because each GPU still holds a complete copy. We now have to partition the model.</p><h3>12. Model parallelism</h3><p>Split the model’s layers across devices:</p><pre>GPU 0: Layer 1 … Layer k<br>GPU 1: Layer k+1 … Layer 2k</pre><p>Activations move between GPUs. This allows a model larger than one GPU’s memory, but sequential stages create idle time, since only one GPU is busy at a time in the naive version.</p><h3>13. Pipeline parallelism</h3><p>Suppose we split a 32-layer model into 4 stages of 8 layers each. Naively, most GPUs sit idle while one batch moves through. So training splits each batch into <strong>microbatches</strong> to keep the pipeline busy:</p><pre>time →<br>GPU0: M1 M2 M3 M4<br>GPU1:    M1 M2 M3 M4<br>GPU2:       M1 M2 M3 M4<br>GPU3:          M1 M2 M3 M4</pre><p>The idle regions at the start and end are <strong>pipeline bubbles</strong>. With p pipeline stages and m microbatches, the bubble fraction is roughly:</p><pre>bubble ≈ (p − 1) / (m + p − 1)</pre><p>With p = 4 and m = 16, that is 3/19 ≈ 16%. More microbatches shrink the bubble. Schedules like 1F1B also reduce the activation memory needed.</p><h3>14. Tensor parallelism</h3><p>Instead of splitting by depth, split individual operations across GPUs. For a large matrix multiplication Y = WX, partition W along its output dimension:</p><pre>W = [ W₁ ; W₂ ]<br>Y₁ = W₁ X<br>Y₂ = W₂ X</pre><p>Each GPU computes a piece of the output, and the pieces are combined as needed. In Megatron-style Transformers, the MLP and attention blocks are split so that each layer needs a small number of all-reduces. Tensor parallelism is especially useful for very large Transformer layers. But it communicates <strong>inside every layer, on the critical path</strong>, so it demands a very fast interconnect and is normally kept within a single node.</p><h3>15. Sharded data parallelism: ZeRO and FSDP</h3><p>There’s a middle path between “replicate everything” and “partition the model by hand.” Plain data parallelism wastes memory by keeping identical copies of the parameters, gradients, and optimizer state on every GPU. <strong>ZeRO</strong> (and PyTorch’s <strong>FSDP</strong>) shards these across the data-parallel GPUs. With Ψ parameters, N GPUs, and Adam in mixed precision (16Ψ bytes of state total):</p><pre>Stage 1: shard optimizer state             → ≈ 4Ψ + 12Ψ/N bytes per GPU<br>Stage 2: also shard gradients              → ≈ 2Ψ + 14Ψ/N<br>Stage 3: also shard parameters             → ≈ 16Ψ/N</pre><p>Stage 3 lets 64 GPUs hold a model whose training state would never fit on one. The price is extra communication, because parameters must be gathered just in time for each layer (roughly 1.5× the communication volume of plain data parallelism). It’s a very common answer to “the model doesn’t fit, but I don’t want to hand-partition it.”</p><p><strong>Activation checkpointing</strong> is the other big memory lever: don’t store all activations, and recompute some during the backward pass. It trades extra compute (roughly one additional forward pass, around 30% more) for a large memory reduction.</p><h3>16. The distinctions you should know cold</h3><pre>Data parallelism     → same model, different data<br>Tensor parallelism   → split the computation inside layers<br>Pipeline parallelism → split the model by layers/stages</pre><p>Large-scale training systems combine them:</p><pre>3D parallelism = Data + Tensor + Pipeline</pre><p>often with sharding (ZeRO/FSDP) on top. A typical layout puts tensor parallelism inside a node (fast NVLink), pipeline parallelism across nodes, and data parallelism across replicas.</p><h3>17. Communication topology matters</h3><p>Imagine two GPUs connected by high-bandwidth NVLink/NVSwitch versus a slower network fabric. The same algorithm can perform radically differently, because distributed training repeatedly moves gradients, activations, partial results, and parameters. Intra-node links are often roughly an order of magnitude faster than inter-node networking, which is exactly why the layout above places the chattiest parallelism (tensor) on the fastest links.</p><pre>GPU performance ≠ training system performance</pre><p>The interconnect can become the bottleneck.</p><h3>18. Practical training-system architecture</h3><p>A production training pipeline might look like:</p><pre>Object Storage<br>      │<br>      ▼<br> Data Loader ──► CPU workers (decode, augment, tokenize)<br>      │<br>      ▼<br> GPU cluster:  GPU 0   GPU 1   …   GPU N<br>                 └────── AllReduce ──────┘<br>      │<br>      ▼<br> Checkpoint ──► Object Storage</pre><p>Now consider what can fail.</p><h3>19. Failure mode: input pipeline bottleneck</h3><p>Suppose GPU compute takes 50 ms but loading and preprocessing take 100 ms. Your expensive GPUs spend much of their time waiting, and utilization might sit at 30–40% even though the GPUs are powerful. Fixes: prefetching, parallel data loaders, caching, efficient serialization, local SSD, offline preprocessing, and dataset sharding.</p><p>One more caution: the “GPU utilization” figure in monitoring tools only says whether <em>some kernel was running</em>, not whether the hardware is used efficiently. A better measure is <strong>MFU (model FLOPs utilization)</strong>: achieved model FLOPs per second divided by the hardware’s peak. A handy estimate for Transformer training is FLOPs ≈ 6 × (parameters) × (tokens). Even well-tuned large runs typically reach only a fraction of peak, so MFU is the honest number to track.</p><h3>20. Failure mode: stragglers</h3><p>Synchronous training waits for the slowest worker. If one GPU’s step takes 180 ms while the rest take 100 ms, everyone idles for the extra 80 ms at every synchronization point. Causes: hardware degradation, network problems, uneven data, CPU bottlenecks, noisy neighbors.</p><pre>synchronous training → straggler sensitivity</pre><p>Mitigations include detecting and replacing slow nodes, balancing load, and in some settings relaxing synchrony.</p><h3>21. Checkpointing</h3><p>Large runs can last days or weeks, and with more GPUs, hardware failures become routine (the cluster-wide failure rate grows with N). If the cluster crashes after 36 hours and you have no checkpoint, you lose 36 hours of work. A checkpoint may need to include:</p><ul><li>model parameters</li><li>optimizer state (often the largest part)</li><li>scheduler state</li><li>the training step</li><li>random seeds and RNG state where relevant</li><li>the mixed-precision scaler state</li><li>data-loader position when reproducibility requires it</li></ul><p>Training can then resume from θ_t rather than θ₀. Practical considerations: checkpoint frequency is a trade-off between overhead and lost work, checkpoints should be sharded and often written asynchronously, writes should be atomic (never leave a half-written “latest”), and you should periodically test that a restore actually works.</p><h3>22. A strong ML infrastructure interview answer</h3><p>If asked <em>“How would you scale training from one GPU to 64 GPUs?”</em>, a strong sequence is:</p><p><strong>Step 1: Establish the baseline.</strong> Measure samples/sec, step time, GPU utilization (and MFU), memory use, input pipeline time, and communication time.</p><p><strong>Step 2: Try data parallelism.</strong> Replicate the model and shard the batches.</p><p><strong>Step 3: Measure scaling efficiency.</strong> Don’t assume linear scaling.</p><p><strong>Step 4: Optimize communication.</strong> Investigate all-reduce behavior, topology and interconnect, gradient bucketing, and overlapping communication with computation.</p><p><strong>Step 5: Address memory.</strong> Use BF16/FP16, activation checkpointing, gradient accumulation, and optimizer-state sharding (ZeRO/FSDP).</p><p><strong>Step 6: If the model still doesn’t fit.</strong> Introduce tensor parallelism, pipeline parallelism, and full parameter sharding.</p><p><strong>Step 7: Build reliability.</strong> Add checkpointing, restart and resume, monitoring, and failure detection.</p><p>That’s a much stronger answer than simply saying “use distributed data parallel.”</p><h3>23. Interview drill</h3><p><strong>Q1. What does data parallelism do?</strong><br> Each GPU holds a model replica and processes a different subset of the batch. Gradients are aggregated, typically via all-reduce, and the synchronized parameters are updated.</p><p><strong>Q2. Why doesn’t adding GPUs always produce linear speedup?</strong><br> Communication, synchronization, input pipelines, load imbalance, network bandwidth, and other overheads become increasingly significant as N grows.</p><p><strong>Q3. What is the difference between data and model parallelism?</strong><br> Data parallelism replicates the model and distributes the data. Model parallelism partitions the model or its computation across devices.</p><p><strong>Q4. What is the purpose of gradient accumulation?</strong><br> To simulate a larger effective batch size when GPU memory can’t hold the whole batch at once.</p><p><strong>Q5. Why can increasing batch size change model quality?</strong><br> It changes gradient noise and optimization dynamics. Learning-rate scaling, warm-up, and regularization often need to change as the batch size changes.</p><p><strong>Q6. Your GPUs show only 40% utilization. Is the model necessarily inefficient?</strong><br> No. The bottleneck may be the input pipeline, CPU preprocessing, synchronization, communication, or storage rather than GPU computation.</p><p><strong>Q7. What happens if one worker is significantly slower in synchronous distributed training?</strong><br> The other workers wait at synchronization points, reducing overall throughput. This is the straggler problem.</p><p><strong>Q8. The model doesn’t fit on one GPU. What are your options?</strong><br> Shard the training state (ZeRO/FSDP), use activation checkpointing and lower precision, and if needed add tensor and pipeline parallelism, preferring fast links for the chattiest communication.</p><h3>The one mental model to retain</h3><p>When an ML infrastructure interviewer asks “How do you scale training?”, think in this order:</p><pre>Compute → Memory → Communication → Input pipeline → Reliability</pre><p>And distinguish data parallelism from tensor parallelism from pipeline parallelism. Finally, remember the most practical principle:</p><blockquote><strong><em>Never claim distributed training is working because you added more GPUs. Measure samples/sec and scaling efficiency.</em></strong></blockquote><p>If 64 GPUs give only 3× the throughput of one GPU, that is about 5% efficiency (3/64). The problem isn’t “we need more GPUs.” The problem is where the other 61 GPU-equivalents of performance are being lost.</p><p>If this was useful, follow along for the rest of the series.</p><p>💻 <strong>GitHub:</strong> <a href="https://github.com/nachiket273">nachiket273</a><br>☕ <strong>Buy me a coffee:</strong> <a href="https://www.buymeacoffee.com/nachiket273">nachiket273</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=da683af8400a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Day 7: RAG Systems, Retrieval Is an ML Problem, Not Just a Vector Database]]></title>
            <link>https://nachiket-tanksale.medium.com/day-7-rag-systems-retrieval-is-an-ml-problem-not-just-a-vector-database-1ec1964c191c?source=rss-26a6ee15a5c5------2</link>
            <guid isPermaLink="false">https://medium.com/p/1ec1964c191c</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[generative-ai-tools]]></category>
            <category><![CDATA[retrieval-augmented-gen]]></category>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[system-design-interview]]></category>
            <dc:creator><![CDATA[nachiket tanksale]]></dc:creator>
            <pubDate>Tue, 10 Nov 2026 19:19:55 GMT</pubDate>
            <atom:updated>2026-11-10T19:19:55.353Z</atom:updated>
            <content:encoded><![CDATA[<p>Read Day 6 <a href="https://medium.com/@nachiket-tanksale/day-6-attention-and-transformers-why-self-attention-works-2fcfd51ccb37">here</a></p><h3>1. What problem does RAG solve?</h3><p>An LLM has parameters θ and generates P(y | x; θ). But those parameters are not a reliable database of current or private information. Suppose a company has:</p><ul><li>2 million internal documents</li><li>continuously changing policies</li><li>product manuals</li><li>customer tickets</li><li>engineering documentation</li></ul><p>You don’t want to retrain the LLM every time a document changes. RAG instead makes generation conditional on retrieved external evidence:</p><pre>P(y | x, D; θ)</pre><p>where D is the set of retrieved documents. The basic pipeline is:</p><pre>Query → Retrieve → Rerank → Generate</pre><p>(In the original RAG formulation, this is the marginalization P(y | x) = Σ_d P(d | x) · P(y | x, d), where the retriever supplies P(d | x) and the generator supplies P(y | x, d).)</p><h3>2. The first major insight: RAG is two ML problems</h3><p><strong>Retrieval:</strong> find useful evidence, q → {d₁, d₂, …, d_k}.</p><p><strong>Generation:</strong> use that evidence to produce an answer, (q, d₁, …, d_k) → y.</p><p>So:</p><pre>RAG quality = retrieval quality + generation quality + their interaction</pre><p>A spectacular LLM cannot answer correctly if the required document was never retrieved.</p><h3>3. Document ingestion</h3><p>Suppose you start with PDFs. The ingestion pipeline might be:</p><pre>PDF → text extraction → cleaning → chunking → embedding → index</pre><p>Extraction itself is a source of errors (tables, multi-column layouts, headers and footers, scanned pages), so garbage in the parse becomes garbage in the index. The first major design choice after that is <strong>chunking</strong>.</p><p>Suppose a document contains Authentication, Rate limits, Billing, and Error handling sections. You could split every 500 tokens, but arbitrary chunks can separate a question from its answer, or a heading from its explanatory text. Better strategies exploit headings, paragraphs, sections, semantic boundaries, and document structure.</p><h3>4. Why chunk size is a trade-off</h3><p><strong>Very small chunks</strong></p><ul><li>Advantages: precise retrieval, less irrelevant context, cheaper generation.</li><li>Disadvantages: insufficient context, fragmented information, harder semantic matching.</li></ul><p><strong>Very large chunks</strong></p><ul><li>Advantages: preserve context, fewer retrieval fragments.</li><li>Disadvantages: lower retrieval precision, more irrelevant tokens, higher prompt cost, context-window pressure.</li></ul><pre>chunk size → retrieval precision/recall + generation cost</pre><p>There is no universally optimal chunk size. Common refinements include:</p><ul><li><strong>Overlapping chunks</strong>, so a fact on a boundary isn’t cut in half.</li><li><strong>Prepending headings or document titles</strong> to each chunk, so it makes sense out of context.</li><li><strong>Parent-child retrieval:</strong> match on small chunks, but give the LLM the larger surrounding section.</li></ul><h3>5. Dense retrieval</h3><p>Represent the query and documents as vectors:</p><pre>e_q = f_θ(q)<br>e_d = f_θ(d)</pre><p>Cosine similarity is:</p><pre>sim(q, d) = e_qᵀ e_d / ( ‖e_q‖ · ‖e_d‖ )</pre><p>If the vectors are normalized (‖e_q‖ = ‖e_d‖ = 1), this is just the dot product, so retrieval becomes:</p><pre>d* = argmax_d  e_qᵀ e_d</pre><p>For unit vectors, cosine similarity, dot product, and Euclidean distance all give the same ranking, since ‖e_q − e_d‖² = 2 − 2·cos(q, d). Practical reminders: queries and documents must be embedded with the <strong>same model</strong> (and any query/document prefixes it expects), and upgrading the embedding model means re-embedding the whole corpus.</p><h3>6. How are embedding models trained?</h3><p>Most retrieval embedders are bi-encoders trained with a <strong>contrastive loss</strong>. For a query q with a relevant document d⁺ and negatives d₁, d₂, …:</p><pre>L = −log [ exp(sim(q, d⁺)/τ) / Σ_j exp(sim(q, d_j)/τ) ]</pre><p>This is a softmax cross-entropy over similarities (Day 1’s loss, with the softmax acting over candidate documents), where τ is a temperature. Negatives usually come from other examples in the batch, plus hard negatives mined from the retriever. This is the same negative-sampling issue we met in Day 5, and the same risk applies: a “negative” that is actually relevant (a false negative) hurts training.</p><h3>7. Why can’t we brute-force search?</h3><p>Suppose N = 1⁰⁷ documents and an embedding dimension of d = 1536. Exact search costs O(N·d) per query, which means about 1.5 × 1⁰¹⁰ multiply-adds. Just storing the vectors in float32 takes about 1⁰⁷ × 1536 × 4 bytes ≈ 61 GB. For high-throughput production systems, that’s expensive.</p><p>So we use <strong>approximate nearest-neighbor (ANN)</strong> indexes. Common approaches include HNSW (graph-based), IVF (clustering-based), product quantization (compression), and hybrid strategies. The central trade-off is:</p><pre>search speed ↔ retrieval recall</pre><p>and index parameters (like HNSW’s search breadth, or the number of IVF clusters probed) let you tune it.</p><h3>8. The most important RAG metric: retrieval recall</h3><p>Suppose the correct supporting document is among the top 10 retrieved. Then Recall@10 = 1 for that query. If the required evidence never appears, Recall@10 = 0. Averaged over a test set, this is the fraction of queries whose required evidence made it into the top K (sometimes called hit rate).</p><p>This gives a critical diagnostic:</p><blockquote><strong><em>If retrieval recall is poor, changing the LLM won’t solve the fundamental problem.</em></strong></blockquote><p>This is one of the most important things to say in a RAG interview.</p><h3>9. Why vector search alone is often insufficient</h3><p>Consider the query: <em>“What is the maximum number of API requests allowed per minute?”</em> A semantic embedding may retrieve conceptually related documents. But exact lexical information, such as “1000 requests/minute”, an error code, or a product SKU, can be decisive, and embeddings are often weak on rare tokens and identifiers.</p><p>This motivates <strong>hybrid retrieval</strong>: dense retrieval (semantic matching) plus lexical retrieval (BM25 for exact terms). The two score scales aren’t directly comparable, so a common and robust way to combine the ranked lists is <strong>reciprocal rank fusion (RRF)</strong>:</p><pre>RRF(d) = Σ over retrievers  1 / (k + rank(d))</pre><p>with k a small constant (often around 60). It only uses ranks, so there’s no score calibration to worry about.</p><h3>10. Reranking</h3><p>Suppose retrieval returns 100 candidates. Instead of handing all 100 to the LLM, run a more expensive model to score (q, d_i) and keep the top K:</p><pre>10⁷ documents → 100 candidates → 10 reranked → LLM</pre><p>The key distinction is:</p><ul><li><strong>Bi-encoder (retrieval):</strong> encodes the query and the document <em>separately</em>. Document embeddings can be precomputed, so search is fast, but the model never sees the query and document together.</li><li><strong>Cross-encoder (reranker):</strong> feeds the query and document <em>together</em> through a Transformer, so full attention (Day 7) can compare them token by token. This is much more accurate, but it can’t be precomputed, which is why it only runs on a small candidate set.</li></ul><p>This is exactly the principle from Day 5’s recommender architecture: <strong>cheap retrieval → expensive ranking</strong>.</p><h3>11. RAG is a context-engineering problem too</h3><p>Suppose retrieval returns: Document A (highly relevant), B (irrelevant), C (highly relevant), D (redundant), E (irrelevant). Dumping all five into the prompt is not necessarily optimal. You want a context set that maximizes useful information while minimizing redundancy, irrelevant text, token cost, and conflicting evidence:</p><pre>retrieval relevance + context efficiency</pre><p>Practical points: models often use information in the middle of a long context less reliably than at the start or end, so ordering matters; more context isn’t always better; and deduplicating near-identical chunks is cheap and useful.</p><h3>12. The classic RAG failure modes</h3><p><strong>Failure 1: Retrieval failure.</strong> The correct document wasn’t retrieved. <em>Fix retrieval, not generation.</em> Options: better embeddings, improved chunking, hybrid retrieval, query rewriting, metadata filtering, a larger candidate pool.</p><p><strong>Failure 2: Correct document, wrong answer.</strong> The evidence is present, but the LLM misinterprets it. Possible causes: ambiguous context, poor prompt construction, contradictory documents, context overload, model limitations.</p><p><strong>Failure 3: Correct answer, unsupported claim.</strong> The model answers correctly but doesn’t actually ground the answer in the retrieved evidence. This matters when you need citations or auditable outputs.</p><p><strong>Failure 4: Stale retrieval.</strong> The index contains an old version of a document (D_index ≠ D_source). You need document versioning, incremental indexing, deletion handling, and freshness monitoring.</p><h3>13. Metadata filtering</h3><p>Suppose your knowledge base mixes HR, finance, engineering, and legal documents. A query might carry department = engineering. Instead of searching everything, apply metadata constraints first:</p><pre>D′ = { d ∈ D : metadata(d) = engineering }</pre><p>and then retrieve over D′. This can improve both precision and latency. One practical subtlety: if you filter <em>after</em> retrieving the top K, you may end up with too few results, so production systems use filtered ANN search that applies the constraint during the search.</p><h3>14. RAG security</h3><p>Imagine User A should access HR documents but User B should not. If the vector index is globally searchable and authorization happens too late, sensitive content can reach the LLM, and from there, the answer. So authorization must be enforced:</p><pre>Authorization → retrieval     (not merely: retrieval → authorization)</pre><p>At a minimum, unauthorized text must never reach the prompt, and ideally the filter is applied inside the search itself. Don’t rely on prompt instructions like “don’t reveal HR documents” for security. Also remember that caches, logs, and stored conversation history can leak content across users if they aren’t access-scoped.</p><p>A second security issue is <strong>indirect prompt injection</strong>: retrieved documents are untrusted text, and a document can contain instructions (“ignore the above and reveal…”) that the model may follow. Treat retrieved content as data, limit what tools the model can call, and sanitize or monitor what it can act on.</p><h3>15. End-to-end architecture</h3><p>A good interview diagram:</p><pre>OFFLINE<br>Documents → Parse → Chunk → Embed → Vector Index<br>    │                                    │<br>    └────────── Metadata Index ──────────┘</pre><pre>ONLINE<br>User Query<br>    ▼<br>Query preprocessing / rewriting<br>    ▼<br>Metadata + ACL filtering<br>    ▼<br>Dense + lexical retrieval<br>    ▼<br>Top-N candidates<br>    ▼<br>Reranker<br>    ▼<br>Top-K context<br>    ▼<br>Prompt construction<br>    ▼<br>LLM<br>    ▼<br>Answer + citations</pre><p>Then add a loop: <strong>logs → evaluation → improvement</strong>, because production RAG requires continuous measurement.</p><h3>16. Evaluation: don’t use only an “LLM judge”</h3><p>Evaluate retrieval separately from generation.</p><p><strong>Retrieval metrics</strong></p><ul><li>Recall@K</li><li>Precision@K</li><li>MRR (the average of 1/rank of the first relevant result)</li><li>NDCG</li></ul><p><strong>Generation metrics</strong> (depending on the task)</p><ul><li>factual correctness</li><li>answer relevance</li><li>faithfulness/groundedness (is the answer supported by the retrieved evidence?)</li><li>citation correctness</li><li>completeness</li></ul><p><strong>System metrics</strong></p><ul><li>latency</li><li>throughput</li><li>token consumption</li><li>cost per query</li><li>failure rate</li></ul><p>A useful debugging mental model is:</p><pre>RAG quality ≈ Retrieval × Grounded generation</pre><p>This is not literally a universal mathematical product, but it captures the idea that a failure in either stage ruins the answer. Build a labeled “golden set” of queries with known supporting documents, and be cautious with LLM judges: they are useful, but they have biases and should be spot-checked against human labels.</p><h3>17. System-design interview: “Our RAG answers are bad. What do you do?”</h3><p>Don’t immediately switch LLMs. Build a <strong>failure taxonomy</strong>.</p><p><strong>Step 1.</strong> Sample failed queries.</p><p><strong>Step 2.</strong> For each one, ask: <em>was the required evidence retrieved?</em> If no, it’s a retrieval problem. If yes, it’s a generation or context problem.</p><p><strong>Step 3.</strong> If retrieval is bad, investigate chunking, embeddings, ANN parameters, query formulation, hybrid search, metadata filters, and reranking.</p><p><strong>Step 4.</strong> If retrieval is good but the answers are bad: inspect context ordering, remove redundant chunks, improve prompting, enforce citation and grounding behavior, and evaluate another model.</p><p>That gives you a systematic debugging process rather than “try a bigger LLM.”</p><h3>18. Connection to yesterday: Transformers</h3><p>Yesterday: Attention(Q, K, V) = softmax(QKᵀ/√d_k) V. Today:</p><pre>Embedding(q) → Nearest neighbors → Context → Transformer</pre><p>Notice the architectural separation: <strong>external memory + neural computation</strong>. RAG effectively gives an LLM a dynamically selected external memory.</p><h3>19. Interview drill</h3><p><strong>Q1. Why use RAG instead of fine-tuning for frequently changing company documents?</strong><br> Fine-tuning changes model parameters and is poorly suited to frequent knowledge updates. RAG keeps knowledge in an external index that can be updated independently, and supplies retrieved evidence at inference time (which also enables citations and access control). The two aren’t mutually exclusive: fine-tuning is better suited to style and behavior, RAG to facts.</p><p><strong>Q2. Your LLM is excellent, but RAG performance is poor. What do you investigate first?</strong><br> Retrieval recall. If the relevant evidence isn’t retrieved, the generator cannot reliably use it.</p><p><strong>Q3. Why use a reranker?</strong><br> Initial retrieval is optimized for speed and recall. A more expensive cross-encoder reranker can judge relevance much more precisely on a small candidate set.</p><p><strong>Q4. Dense vs lexical retrieval?</strong><br> Dense retrieval captures semantic similarity and paraphrases. Lexical methods such as BM25 are strong for exact terms, identifiers, names, and rare keywords. Hybrid retrieval (for example, with RRF) combines their strengths.</p><p><strong>Q5. Why is chunking important?</strong><br> It determines the granularity of retrievable evidence. Chunks that are too small lose context, and chunks that are too large add irrelevant material and generation cost.</p><p><strong>Q6. Where should authorization happen?</strong><br> Before or as part of retrieval, so unauthorized documents never enter the candidate or context pipeline.</p><p><strong>Q7. How would you debug hallucinations in a RAG system?</strong><br> First, determine whether the necessary evidence was retrieved. If not, fix retrieval. If yes, inspect context quality, contradictions, prompt construction, model behavior, and grounding and citation mechanisms.</p><h3>The one mental model for today</h3><p>When someone says “Build a RAG system,” immediately think:</p><pre>Ingest → Index → Retrieve → Rerank → Context → Generate → Evaluate</pre><p>And when something goes wrong, ask the most important diagnostic question:</p><blockquote><strong><em>“Did the model fail to answer from the evidence, or did we fail to retrieve the evidence in the first place?”</em></strong></blockquote><p>That single distinction can save enormous amounts of wasted effort in real-world LLM engineering.</p><p>If this was useful, follow along for the rest of the series.</p><p>💻 <strong>GitHub:</strong> <a href="https://github.com/nachiket273">nachiket273</a><br>☕ <strong>Buy me a coffee:</strong> <a href="https://www.buymeacoffee.com/nachiket273">nachiket273</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1ec1964c191c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Day 6: Attention and Transformers: Why Self-Attention Works]]></title>
            <link>https://nachiket-tanksale.medium.com/day-6-attention-and-transformers-why-self-attention-works-2fcfd51ccb37?source=rss-26a6ee15a5c5------2</link>
            <guid isPermaLink="false">https://medium.com/p/2fcfd51ccb37</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[transformers]]></category>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[nachiket tanksale]]></dc:creator>
            <pubDate>Tue, 03 Nov 2026 17:45:37 GMT</pubDate>
            <atom:updated>2026-11-03T17:45:37.055Z</atom:updated>
            <content:encoded><![CDATA[<p>Read Day 5 <a href="https://nachiket-tanksale.medium.com/day-5-ml-system-design-designing-a-production-recommendation-system-18a0f653cdac">here</a>.</p><h3>1. The problem attention is trying to solve</h3><p>Consider: <em>“The animal didn’t cross the road because it was too tired.”</em></p><p>To understand “it,” the model has to work out which earlier tokens are relevant. A fixed-size summary of the whole sequence can lose that information. Attention instead lets each token dynamically ask:</p><blockquote><em>“Which other tokens should I use to construct my representation?”</em></blockquote><p>That is the core idea.</p><h3>2. Self-attention from first principles</h3><p>Suppose the input has n tokens, each a vector of dimension d_model:</p><pre>X ∈ ℝ^(n × d_model)</pre><p>We create three learned projections:</p><pre>Q = X W_Q<br>K = X W_K<br>V = X W_V</pre><ul><li><strong>Query:</strong> what information am I looking for?</li><li><strong>Key:</strong> what information do I contain (for matching)?</li><li><strong>Value:</strong> what information do I actually provide?</li></ul><p>With W_Q, W_K ∈ ℝ^(d_model × d_k) and W_V ∈ ℝ^(d_model × d_v):</p><pre>Q, K ∈ ℝ^(n × d_k)<br>V    ∈ ℝ^(n × d_v)</pre><h3>3. How does a token decide what to attend to?</h3><p>Compute the similarity between every query and every key:</p><pre>S = Q Kᵀ        S ∈ ℝ^(n × n)<br>S_ij = q_iᵀ k_j</pre><p>A large positive S_ij means token i’s query finds token j’s key highly relevant. This is the attention score matrix.</p><h3>4. Why divide by √d_k?</h3><p>The Transformer uses:</p><pre>S = Q Kᵀ / √d_k</pre><p>before the softmax. Why? Assume the components of q and k are independent, zero-mean, unit-variance random variables. Then:</p><pre>qᵀk = Σ_(j=1..d_k) q_j k_j</pre><pre>Var(qᵀk) = Σ Var(q_j k_j) = d_k</pre><p>Each term has variance 1, and the terms are independent, so the variance is exactly d_k and the standard deviation is √d_k. Dot products therefore grow in magnitude as d_k increases.</p><p>Large logits fed into softmax:</p><pre>softmax(z)_i = e^(z_i) / Σ_j e^(z_j)</pre><p>produce very peaked distributions, where one entry is near 1, and the rest are near 0. In that saturated regime, the softmax gradient is almost zero, so learning stalls. Dividing by √d_k restores unit-variance scores and keeps the softmax in a healthy range. This is a very common interview derivation.</p><h3>5. Softmax converts similarities into weights</h3><p>Define:</p><pre>A = softmax( Q Kᵀ / √d_k )        (applied row-wise)</pre><p>Each row sums to 1: Σ_j A_ij = 1. Then:</p><pre>Attention(Q, K, V) = A V = softmax( Q Kᵀ / √d_k ) V</pre><p>This is the central equation of Transformer attention.</p><p><em>Implementation note (tie back to Day 3):</em> real implementations compute softmax by subtracting the row maximum first, using the log-sum-exp trick, so that exp() never overflows.</p><h3>6. What is actually happening?</h3><p>For token i:</p><pre>output_i = Σ_j A_ij · v_j</pre><p>The output for token i is a <strong>weighted average of all the value vectors</strong>, with weights determined by q_iᵀ k_j. Every token can dynamically pull in information from every other token. You can think of attention as a <em>soft dictionary lookup</em>: a query is compared against all keys, and instead of returning one value, you return a similarity-weighted blend of all values.</p><h3>7. A concrete example</h3><p>Consider: <em>“The cat sat on the mat because it was tired.”</em> When processing “it,” attention might look something like this (illustrative numbers only):</p><pre>cat      → high<br>mat      → low<br>sat      → medium<br>because  → low<br>tired    → high</pre><p>The actual learned pattern depends on the model, the layer, and the head.</p><p>An important caveat: <strong>attention weights are not automatically a faithful explanation of model reasoning.</strong> Attention is a mechanism for mixing information, not necessarily an interpretable causal story. This distinction matters in more advanced interviews.</p><h3>8. Why is it called self-attention?</h3><p>Because Q, K, and V are all generated from the <strong>same</strong> sequence X. Contrast this with encoder-decoder <strong>cross-attention</strong>:</p><pre>Self-attention:    X → Q, K, V<br>Cross-attention:   X_decoder → Q,   X_encoder → K, V</pre><p>In cross-attention, the decoder asks the questions and the encoder supplies the keys and values.</p><h3>9. Why do we need multiple heads?</h3><p>A single attention operation produces one pattern of interactions. Transformers instead use <strong>multi-head attention</strong>. For head h:</p><pre>head_h = Attention( X W_Q^(h), X W_K^(h), X W_V^(h) )</pre><p>Then concatenate the heads and project:</p><pre>H = Concat(head_1, …, head_H)<br>MHA(X) = H W_O</pre><p>Typically d_k = d_v = d_model / H, so using many heads costs about the same as one big head. Different heads can learn different relationships, such as local syntax, long-range dependencies, or positional structure. But don’t claim that each head maps cleanly to one human-interpretable linguistic function. Real models are more distributed and messier.</p><h3>10. The rest of a Transformer block</h3><p>Attention is only one piece. A standard Transformer block also contains:</p><ul><li>a position-wise <strong>feed-forward network</strong> (FFN), applied to each token independently</li><li><strong>residual connections</strong> around both sublayers (Day 4’s gradient highway)</li><li><strong>layer normalization</strong></li></ul><p>Attention mixes information <em>across</em> tokens. The FFN transforms information <em>within</em> each token. Both matter, and in many models the FFN holds the majority of the parameters.</p><h3>11. The computational complexity problem</h3><p>For X ∈ ℝ^(n×d), the attention matrix Q Kᵀ is n × n. Computing Q Kᵀ costs O(n² d_k) and multiplying by V costs O(n² d_v), so attention costs:</p><pre>O(n² d)</pre><p>in compute. More importantly, the score matrix needs <strong>O(n²) memory</strong> per head if it is explicitly materialized. This is the central scaling problem of standard full attention. If the sequence length doubles (n → 2n), the attention matrix grows 4×.</p><p>Two nuances:</p><ul><li>For short sequences, the projections and FFN (cost O(n d²)) can actually dominate. The n² term bites when n is large relative to d.</li><li><strong>FlashAttention</strong> computes exactly the same result but avoids materializing the full n×n matrix by working in tiles inside fast on-chip memory. Compute is still O(n²), but memory use becomes linear, and it is often much faster in practice because it reduces memory traffic.</li></ul><h3>12. Why was attention still such a breakthrough?</h3><p>An RNN processes tokens sequentially: x₁ → x₂ → x₃ → … A dependency between distant tokens has to survive many recurrent steps, which is where vanishing gradients (Day 4) make life hard. And the sequential dependency prevents parallelism across time steps.</p><p>Self-attention connects any two positions <strong>directly in one layer</strong>:</p><pre>Maximum path length between any two tokens:   RNN: O(n)    Self-attention: O(1)</pre><p>This gives better long-range information flow and far better parallelism on GPUs, which is a big part of why Transformers scaled so well.</p><h3>13. Attention alone doesn’t know token order</h3><p>A subtle interview question. Without positional information, self-attention is permutation-equivariant: shuffle the input tokens and the outputs are shuffled in the same way. The model has no intrinsic notion that one token came before another.</p><p>So Transformers inject positional information. Historically, a positional encoding P was added to the input:</p><pre>X′ = X + P</pre><p>Modern LLMs often use alternatives such as <strong>rotary positional embeddings (RoPE)</strong>, which rotate the queries and keys by position-dependent angles so that attention depends on relative position.</p><p>(A nuance: a causal mask, covered next, breaks the symmetry on its own, so decoder-only models can pick up some positional signal implicitly. Explicit positional mechanisms are still standard.)</p><p>The conceptual point:</p><blockquote><strong><em>Attention provides content-based interaction. Positional mechanisms provide sequence-order information.</em></strong></blockquote><h3>14. Decoder-only LLMs add causal masking</h3><p>When predicting token x_t, the model must not see x_(t+1), x_(t+2), … So attention uses a causal mask:</p><pre>M_ij = 0     if j ≤ i<br>M_ij = −∞    if j &gt; i</pre><pre>A = softmax( Q Kᵀ / √d_k + M )</pre><p>The −∞ drives the weights on future tokens to exactly zero after the softmax. This preserves the autoregressive factorization:</p><pre>P(x₁, …, x_n) = Π_(t=1..n) P(x_t | x_&lt;t)</pre><p>A practical bonus: during training, the mask lets the model process the whole sequence in <strong>one parallel pass</strong>, learning to predict every next token simultaneously.</p><h3>15. Production perspective: KV caching</h3><p>During generation, suppose we’ve produced x₁, …, x_t. Naively recomputing attention over the entire prefix at every step is wasteful. Instead, <strong>cache</strong> the keys and values (K₁…K_t and V₁…V_t). For the next token, compute only its own new query, key, and value, and attend to the cached ones. This is KV caching. It cuts the per-step attention work from recomputing everything to roughly O(n d) per layer.</p><p>The trade-off is memory: <strong>longer context means a larger KV cache.</strong> The cache size is approximately:</p><pre>KV bytes ≈ 2 × layers × kv_heads × head_dim × tokens × batch × bytes_per_value</pre><p>For example, a 7B-class model with 32 layers, 32 heads of dimension 128, and fp16 values needs about 2 × 32 × 4096 × 2 bytes ≈ 0.5 MB per token. A single 4,096-token sequence therefore holds roughly <strong>2 GB</strong> of cache, and that multiplies across concurrent requests. This is why KV-cache memory is a major inference constraint. Techniques like grouped-query attention (GQA) shrink it by sharing key/value heads.</p><h3>16. System-design question: “How would you serve a long-context LLM?”</h3><p>A strong answer goes beyond the model. Consider:</p><ul><li><strong>Compute:</strong> GPU memory, attention computation, batching.</li><li><strong>Memory:</strong> model weights, KV cache, activations.</li><li><strong>Latency:</strong> separate <strong>prefill</strong> from <strong>decode</strong>.</li></ul><p><strong>Prefill</strong> processes the prompt in parallel and is typically compute-bound. <strong>Decode</strong> generates tokens one at a time and is typically memory-bandwidth-bound, because every step must read the weights and the KV cache. These phases have different bottlenecks and are often optimized differently (for example, with continuous batching and, in some systems, separate hardware pools for each phase).</p><h3>17. Important failure modes</h3><ol><li><strong>Quadratic attention cost.</strong> O(n²) becomes problematic for long contexts. Approaches include efficient attention kernels, sparse or local attention, sliding-window attention, grouped-query attention, and architectural alternatives.</li><li><strong>Memory bandwidth.</strong> During decoding, moving weights and KV-cache data is often the bottleneck rather than raw FLOPs. FLOPs alone aren’t enough to reason about LLM serving performance.</li><li><strong>Attention isn’t automatically reasoning.</strong> A model can use attention and still produce incorrect or unfaithful outputs. Attention is an architectural operation, not a guarantee of reasoning or factuality.</li></ol><h3>18. Interview drill</h3><p><strong>Q1. Why divide QKᵀ by √d_k?</strong><br> If q and k have independent, zero-mean, unit-variance components, the dot product has variance d_k. Scaling by √d_k keeps the logits at unit scale, preventing overly sharp softmax outputs and the near-zero gradients that come with them.</p><p><strong>Q2. What are Q, K, and V?</strong><br> Queries represent what a token is looking for, keys represent what each token offers for matching, and values contain the information that gets aggregated according to those matches.</p><p><strong>Q3. Why is self-attention O(n²)?</strong><br> It computes pairwise interactions between all n queries and all n keys, producing an n × n attention matrix.</p><p><strong>Q4. Why do Transformers need positional information?</strong><br> Self-attention by itself is permutation-equivariant and doesn’t encode sequence order. Positional mechanisms (sinusoidal, learned, RoPE) inject order information.</p><p><strong>Q5. What is causal attention?</strong><br> Attention is constrained so token t can only attend to positions ≤ t, implemented by adding −∞ to the future entries before the softmax. It prevents information from future tokens leaking into autoregressive predictions.</p><p><strong>Q6. What is KV caching?</strong><br> Storing the previously computed key and value vectors during autoregressive decoding so they don’t need to be recomputed for every generated token.</p><p><strong>Q7. Why can long-context inference be expensive even if the model weights fit on the GPU?</strong><br> Attention compute and, especially, the KV cache grow with sequence length (and with batch size). The cache can become a major memory and bandwidth bottleneck.</p><h3>The one mental model to retain</h3><p>Don’t memorize attention as merely softmax(QKᵀ/√d_k)V. Understand it as:</p><blockquote><strong><em>Content-dependent weighted information retrieval.</em></strong></blockquote><p>A token generates a query, compares it against all keys, converts those similarities into weights, and retrieves a weighted combination of values.</p><p>If this was useful, follow along for the rest of the series.</p><p>💻 <strong>GitHub:</strong> <a href="https://github.com/nachiket273">nachiket273</a><br>☕ <strong>Buy me a coffee:</strong> <a href="https://www.buymeacoffee.com/nachiket273">nachiket273</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2fcfd51ccb37" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Day 5: ML System Design, Designing a Production Recommendation System]]></title>
            <link>https://nachiket-tanksale.medium.com/day-5-ml-system-design-designing-a-production-recommendation-system-18a0f653cdac?source=rss-26a6ee15a5c5------2</link>
            <guid isPermaLink="false">https://medium.com/p/18a0f653cdac</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[recommendation-system]]></category>
            <category><![CDATA[system-design-interview]]></category>
            <category><![CDATA[mlops]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[nachiket tanksale]]></dc:creator>
            <pubDate>Sun, 01 Nov 2026 17:41:21 GMT</pubDate>
            <atom:updated>2026-11-01T17:41:21.337Z</atom:updated>
            <content:encoded><![CDATA[<p>Read Day 4 <a href="https://medium.com/@nachiket-tanksale/day-4-neural-network-backpropagation-what-is-actually-being-differentiated-2348af050a4b">here</a></p><h3>1. The problem</h3><p>Suppose you’re asked: <em>“Design a recommendation system for an e-commerce platform.”</em></p><p>Assume:</p><ul><li>10M users</li><li>100M products</li><li>millions of daily interactions</li><li>recommendations must respond in under 100 ms</li><li>users can click, view, add to cart, purchase, or ignore items</li></ul><p>The first mistake is to answer: <em>“I’ll train a neural network to predict what the user will buy.”</em> That’s only the model. The real system is:</p><pre>Data → Candidates → Ranking → Serving → Feedback → Training</pre><p>Before designing anything, <strong>clarify requirements</strong>: what are we optimizing (revenue, engagement, long-term retention)? Which surface (homepage, product page, email)? What are the latency and freshness needs? A good interview answer starts here.</p><h3>2. Why can’t we rank every product?</h3><p>With 1⁰⁸ products, scoring every item with a heavy model costs O(N_items) per request, which is infeasible within 100 ms. So we use a two-stage (often multi-stage) funnel:</p><pre>Candidate generation  →  Ranking<br>10⁸ items  →  10²–10⁴ items  →  top ~10–50 shown</pre><p>Candidate generation must be cheap and fast. The expensive model then only scores the survivors. In practice, large systems often add a middle stage (a lightweight “pre-ranker”) and a final re-ranking stage for diversity and business rules.</p><h3>3. Stage 1: Candidate generation</h3><p>Candidate sources might include:</p><ul><li><strong>Collaborative filtering:</strong> users similar to you interacted with items {A, B, C, D}, so recommend those. Modern versions learn user and item embeddings (matrix factorization or two-tower neural models).</li><li><strong>Content-based retrieval:</strong> if the user likes running shoes, retrieve semantically similar products using item embeddings.</li><li><strong>Popular and trending items:</strong> useful for new users, sparse histories, and cold-start situations.</li><li><strong>Recently viewed:</strong> if a user just viewed an iPhone, related products are obvious candidates.</li><li><strong>Business constraints:</strong> inventory availability, seller constraints, geographic availability, safety and policy filtering, and already-purchased products.</li></ul><p>The final candidate set is a union of these sources:</p><pre>C = C_CF ∪ C_semantic ∪ C_popular ∪ C_recent<br>|C| ≈ 1000</pre><p><strong>How embedding retrieval is made fast:</strong> given a user embedding, finding the nearest item embeddings among 100M items uses <strong>approximate nearest neighbor (ANN)</strong> search (HNSW, FAISS, ScaNN). It trades a little recall for sub-linear lookup time. This is what makes retrieval fit inside the latency budget.</p><h3>4. Stage 2: Ranking</h3><p>Now build a richer model, score(u, i, c), where u is the user, i the item, and c the context (time, device, location, session state).</p><p>The model typically predicts several <strong>targets</strong> (often as a multi-task model with one head per target):</p><pre>P(click | u, i, c)<br>P(add_to_cart | u, i, c)<br>P(purchase | u, i, c)</pre><p>A simple final score combines them:</p><pre>score = w₁·P(click) + w₂·P(cart) + w₃·P(purchase)</pre><p>In practice you might learn the combination or train a learning-to-rank model (pointwise, pairwise, or listwise) instead of hand-picking weights.</p><p><em>Tie back to Day 1:</em> a weighted sum of probabilities only makes sense if those probabilities are meaningfully <strong>calibrated</strong>. A model with great ranking power but distorted probabilities will skew the mix.</p><h3>5. Ranking isn’t the same as prediction</h3><p>A subtle but important interview point. Suppose:</p><pre>P(click | A) = 0.30<br>P(click | B) = 0.25</pre><p>A click model ranks A above B. But if B has a much higher margin, you may instead optimize expected value:</p><pre>E[value | u, i] = P(purchase | u, i) × margin(i)</pre><p>or a richer utility that accounts for returns, shipping cost, or long-term customer value.</p><blockquote><strong><em>The prediction objective is not the business objective.</em></strong></blockquote><p>This distinction is extremely important in system design interviews.</p><h3>6. Offline training data</h3><p>Your logs look like (user, item, timestamp, event):</p><pre>U1, Product_A, 10:01, impression<br>U1, Product_A, 10:03, click<br>U1, Product_A, 10:05, purchase</pre><p>You turn them into training examples (xᵢ, yᵢ), with y = 1 for a purchase and y = 0 otherwise. Two practical rules:</p><ul><li><strong>Split by time, not randomly.</strong> Train on the past and validate on the future, as production does. Random splits leak future information (the Day 2 leakage point).</li><li><strong>Beware delayed labels.</strong> Purchases can arrive hours or days after the impression, so very recent data has artificially few positives.</li></ul><p>There is also a much bigger issue.</p><h4>Selection bias</h4><p>You only observe interactions for products that were actually <strong>shown</strong>. If an item was never displayed, “no click” does not mean “the user doesn’t like it.” It may mean the user never had a chance to click it. This is one of the most important problems in recommender systems.</p><p>A related issue is <strong>position bias</strong>: items shown higher on the page get more clicks regardless of quality. Common mitigations include logging the position as a feature (and fixing it at serving time), inverse propensity weighting, and logging a small amount of randomized exploration traffic so you can learn unbiased estimates.</p><h3>7. Negative sampling</h3><p>Positive interactions are sparse, so you need negatives. For example, (u, A, +1) paired with a sampled (u, B, 0). But random negatives can be too easy: if B is completely irrelevant, the model learns a trivial distinction.</p><p>Better negatives include:</p><ul><li>items shown but not clicked</li><li>items ranked highly but skipped</li><li>hard negatives from the retrieval stage</li><li>semantically similar products that weren’t chosen</li></ul><p>This creates a much stronger ranking problem. Two cautions:</p><ul><li><strong>Hard negatives can be false negatives.</strong> A skipped item may still be something the user would like, so don’t push too hard.</li><li>Uniform random negatives over-represent unpopular items. In-batch negative sampling in two-tower training favors popular items, so it often needs a sampling-bias correction.</li></ul><h3>8. Offline metrics</h3><p><strong>Recall@K</strong> (important for candidate generation):</p><pre>Recall@K = |relevant items retrieved in top K| / |relevant items|</pre><p><strong>Precision@K:</strong></p><pre>Precision@K = |relevant items in top K| / K</pre><p><strong>NDCG@K</strong> (when ranking position matters):</p><pre>DCG@K  = Σ (i = 1 to K)  ( 2^(rel_i) − 1 ) / log₂(i + 1)<br>NDCG@K = DCG@K / IDCG@K</pre><p>where IDCG is the DCG of the ideal ordering, so NDCG lies between 0 and 1. Other useful measures include MRR, MAP, coverage, and diversity.</p><p>Remember that all of these are computed on <strong>logged data</strong>, which inherits the selection bias from Section 6.</p><h3>9. But offline metrics aren’t enough</h3><p>Suppose offline NDCG improves by 8%. Can you conclude the system is better? <strong>No.</strong> Offline evaluation doesn’t capture user behavior changes, feedback loops, latency, UI effects, novelty, diversity, or business constraints. Ultimately, you need an <strong>online experiment</strong>.</p><h3>10. A/B testing</h3><p>Randomly split traffic into control and treatment. Candidate metrics:</p><ul><li>CTR</li><li>conversion rate</li><li>revenue per user</li><li>session length</li><li>retention</li><li>cancellation rate</li><li>latency</li></ul><p>Don’t optimize only one metric. For example, CTR can rise because clickbait increases clicks while conversion falls. So define a <strong>primary objective</strong> plus <strong>guardrail metrics</strong>.</p><p>A few practical points interviewers like to hear:</p><ul><li>Run the test long enough to cover weekly cycles and wash out novelty effects.</li><li>Check for sample ratio mismatch (the traffic split not matching what you intended), which signals a bug.</li><li>Watch for interference between users (for example, shared inventory or social effects).</li><li>Interleaving can detect ranking differences faster than a full A/B test.</li></ul><h3>11. The feedback loop</h3><p>Here’s the dangerous part. Suppose the recommender shows A, B, C. Users interact with A, so the training pipeline learns that A is popular and recommends it even more, which generates even more A interactions:</p><pre>recommendation → exposure → interaction → training data → recommendation</pre><p>The model isn’t merely observing user preferences. <strong>It is partially creating the data it learns from.</strong> The result can be popularity bias, filter bubbles, and items that never get a chance to prove themselves.</p><p>Mitigations include exploration (epsilon-greedy, Thompson sampling, bandit methods), a small randomized holdout, debiased training, and diversity constraints.</p><h3>12. Cold start</h3><p><strong>New user</strong> (no history, H_u = ∅):</p><ul><li>popular items</li><li>contextual recommendations</li><li>onboarding preferences</li><li>geographic information</li><li>demographic information where appropriate</li><li>exploration</li></ul><p><strong>New item</strong> (no interaction history):</p><ul><li>content embeddings</li><li>metadata</li><li>semantic similarity</li><li>exploration traffic</li></ul><p>A robust system needs a <strong>fallback path</strong> so it always returns something sensible.</p><h3>13. Latency architecture</h3><p>Suppose the end-to-end target is P99 &lt; 100 ms. You might allocate roughly:</p><pre>candidate retrieval       20 ms<br>feature retrieval         15 ms<br>ranking                   30 ms<br>business filtering        10 ms<br>network/overhead          25 ms<br>-------------------------------<br>total                    100 ms</pre><p>The exact numbers aren’t universal. The architectural point is that <strong>every component has a latency budget</strong>. (In reality, some steps run in parallel, such as feature fetching alongside retrieval, and P99s don’t simply add, but budgeting this way keeps the design honest.) If ranking takes 500 ms, the model doesn’t belong in the online critical path without redesign: distill it, shrink it, cache results, or precompute offline.</p><h3>14. Feature serving: training-serving skew</h3><p>Suppose during training you compute user_purchase_count_30d one way, but online inference computes it differently. Then:</p><pre>P_train(X) ≠ P_serve(X)</pre><p>The model can look great offline and perform poorly online. This is <strong>training-serving skew</strong>. Production systems therefore need:</p><ul><li>careful feature definitions and versioning</li><li>freshness guarantees</li><li>consistency between offline and online computation (often via a shared feature store)</li><li><strong>point-in-time correctness</strong>, meaning training features must be computed using only information available at the time of the event; otherwise, you leak the future</li></ul><h3>15. Monitoring</h3><p>Shipping the model is not the end. Monitor:</p><ul><li><strong>System health:</strong> latency, error rates, timeouts, fallback rate</li><li><strong>Data health:</strong> feature missingness, distribution drift, freshness</li><li><strong>Model health:</strong> score distributions, calibration, online metrics versus offline expectations</li><li><strong>Business and ecosystem health:</strong> diversity, catalog coverage, long-tail exposure</li></ul><p>Then decide a retraining cadence (daily, weekly, or triggered by drift) and keep a rollback path.</p><h3>16. A good architecture</h3><p>A strong interview answer can look like this:</p><pre>User events<br>    │<br>    ▼<br>Event pipeline ──────────────┬──────────────────┐<br>                             ▼                  ▼<br>                       Offline store       Online features<br>                             │                  │<br>                             ▼                  ▼<br>                       Model training    ┌─ Candidate retrieval (ANN, popular, recent)<br>                             │           │          │<br>                             │           │          ▼<br>                             └─ models ──┴───►   Ranking<br>                                                    │<br>                                                    ▼<br>                                           Filtering / business rules<br>                                                    │<br>                                                    ▼<br>                                             Recommendations<br>                                                    │<br>                                                    ▼<br>                                      User events (feedback loop)</pre><p>The key is being able to explain <em>why every component exists</em>.</p><h3>17. Interview drill</h3><p><strong>Q1. Why use two-stage retrieval and ranking?</strong><br> Ranking models are expensive. Candidate generation shrinks a huge item universe to a manageable subset, so a richer model can rank those candidates within the latency budget.</p><p><strong>Q2. Why can’t “not clicked” simply be treated as a negative label?</strong><br> The item may never have received meaningful exposure. Non-interaction is confounded by the recommendation policy (and by position), so it does not necessarily indicate dislike.</p><p><strong>Q3. What is training-serving skew?</strong><br> A discrepancy between the feature or data distributions, or the transformations, used in training and those used during online inference.</p><p><strong>Q4. What metric would you use for candidate generation?</strong><br> Recall@K, because candidate generation should avoid dropping relevant items before the ranker ever sees them.</p><p><strong>Q5. Why might offline NDCG improve while online performance decreases?</strong><br> Offline evaluation may not capture exposure bias, distribution shift, feedback loops, latency, user adaptation, business constraints, or differences between logged and deployed traffic.</p><p><strong>Q6. How would you handle a new user?</strong><br> Start with non-personalized or contextual candidates, collect preference signals, and progressively move toward personalized retrieval and ranking. Exploration can speed up preference discovery.</p><p><strong>Q7. How would you handle a new product?</strong><br> Use content- and metadata-based representations plus exploration to gather interaction data, then progressively incorporate collaborative signals.</p><h3>The system-design framework to memorize</h3><p>For almost any ML system-design question, walk through:</p><pre>1. Requirements<br>2. Data<br>3. Candidate generation / retrieval<br>4. Model / ranking<br>5. Serving + latency<br>6. Evaluation (offline, then online)<br>7. Monitoring<br>8. Feedback + retraining</pre><p>And always ask yourself:</p><blockquote><strong><em>“What happens when the assumptions behind my model stop being true in production?”</em></strong></blockquote><p>That’s where most of the interesting ML-system-design discussion begins.</p><p><strong>Day 6:</strong> stay tuned.</p><p>If this was useful, follow along for the rest of the series.</p><p>💻 <strong>GitHub:</strong> <a href="https://github.com/nachiket273">nachiket273</a><br>☕ <strong>Buy me a coffee:</strong> <a href="https://www.buymeacoffee.com/nachiket273">nachiket273</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=18a0f653cdac" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Day 4: Neural Network Backpropagation: What Is Actually Being Differentiated?]]></title>
            <link>https://nachiket-tanksale.medium.com/day-4-neural-network-backpropagation-what-is-actually-being-differentiated-2348af050a4b?source=rss-26a6ee15a5c5------2</link>
            <guid isPermaLink="false">https://medium.com/p/2348af050a4b</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[gradient-descent]]></category>
            <category><![CDATA[backpropagation]]></category>
            <dc:creator><![CDATA[nachiket tanksale]]></dc:creator>
            <pubDate>Fri, 30 Oct 2026 18:53:44 GMT</pubDate>
            <atom:updated>2026-10-30T18:53:44.548Z</atom:updated>
            <content:encoded><![CDATA[<p>Read Day 3 <a href="https://medium.com/@nachiket-tanksale/day-3-maximum-likelihood-map-and-the-bayesian-view-of-regularization-586faf1b9538">here</a></p><h3>1. Start with the simplest neural network</h3><p>Consider a two-layer network:</p><pre>x → z₁ → a₁ → z₂ → ŷ</pre><pre>z₁ = W₁x + b₁<br>a₁ = φ(z₁)<br>z₂ = W₂a₁ + b₂<br>ŷ  = z₂          (regression)</pre><p>Use squared-error loss:</p><pre>L = ½ (ŷ − y)²</pre><p>The training problem is to minimize L over W₁, b₁, W₂, b₂. The question is: <strong>how does changing W₁ affect L?</strong> Answering it requires the chain rule.</p><h3>2. The chain rule is the entire idea</h3><p>For a scalar chain x → u → v → L:</p><pre>dL/dx = (dL/dv) · (dv/du) · (du/dx)</pre><p>A neural network is just a very large computational graph. Backpropagation is an efficient way of applying the chain rule through that graph. <strong>It is not a different derivative. It is an algorithm for computing the same derivative efficiently.</strong></p><p>Two details that matter:</p><ul><li>If a node feeds several downstream nodes (a skip connection, for example), the gradients from each path <strong>add</strong>. That’s the multivariate chain rule.</li><li>Backprop is <em>reverse-mode</em> automatic differentiation. We use reverse mode because the loss is a single scalar while the parameters number in the millions, and reverse mode gets all the gradients in roughly the cost of one extra forward pass.</li></ul><h3>3. Derive the output-layer gradient</h3><p>Start from the loss:</p><pre>∂L/∂ŷ = ŷ − y</pre><p>Since ŷ = W₂a₁ + b₂, the gradient with respect to the weights is an outer product:</p><pre>∂L/∂W₂ = (ŷ − y) · a₁ᵀ<br>∂L/∂b₂ = (ŷ − y)</pre><p>Define the error signal at the output:</p><pre>δ₂ = ŷ − y</pre><p>Then:</p><pre>∇_{W₂} L = δ₂ a₁ᵀ</pre><p>This δ notation becomes essential for deeper networks.</p><p><em>Tie back to Day 1:</em> if the output were a sigmoid with cross-entropy loss (or a softmax with cross-entropy for multiple classes), the output error would again simplify to <strong>p − y</strong>. That is the same cancellation we derived for logistic regression, and it is why the “natural” loss/activation pairings are so convenient.</p><h3>4. Propagate the error backward</h3><p>We need ∂L/∂a₁. Because z₂ = W₂a₁ + b₂:</p><pre>∂L/∂a₁ = W₂ᵀ δ₂</pre><p>But a₁ = φ(z₁), so we multiply element-wise by the activation derivative:</p><pre>∂L/∂z₁ = (W₂ᵀ δ₂) ⊙ φ′(z₁)</pre><p>Call this δ₁:</p><pre>δ₁ = (W₂ᵀ δ₂) ⊙ φ′(z₁)</pre><p>where ⊙ is element-wise multiplication. Finally, since z₁ = W₁x + b₁:</p><pre>∇_{W₁} L = δ₁ xᵀ<br>∇_{b₁} L = δ₁</pre><p>That’s backpropagation.</p><h3>5. The key pattern for deep networks</h3><p>For layer l, with z^l = W^l a^(l−1) + b^l and a^l = φ(z^l):</p><pre>δ^l = ( (W^(l+1))ᵀ δ^(l+1) ) ⊙ φ′(z^l)</pre><pre>∂L/∂W^l = δ^l (a^(l−1))ᵀ<br>∂L/∂b^l = δ^l</pre><p>Backprop <strong>reuses intermediate quantities</strong>. Instead of differentiating the whole network separately for every parameter, it computes local derivatives and propagates them backward once. That’s why it’s efficient.</p><p>Two practical consequences:</p><ul><li><strong>Memory:</strong> to compute these gradients, you must keep the forward activations (a^(l−1) and z^l). This is why training uses much more memory than inference. Activation checkpointing trades extra compute to save that memory.</li><li><strong>Batches:</strong> with a mini-batch of size B, the same formulas apply with matrices, and the gradient is averaged: (1/B) Δ Aᵀ.</li></ul><h3>6. Backpropagation vs gradient descent</h3><p>These are often confused.</p><ul><li><strong>Backpropagation</strong> computes ∇_θ L.</li><li><strong>Gradient descent</strong> uses that gradient to update the parameters:</li></ul><pre>θ_(t+1) = θ_t − η ∇_θ L</pre><p>where η is the learning rate. So:</p><blockquote><strong><em>Backprop = gradient computation. Optimizer = parameter update.</em></strong></blockquote><p>SGD, Adam, AdamW, and so on are optimizers. Backpropagation is not an optimizer.</p><h3>7. Why deep networks can have vanishing gradients</h3><p>Unroll the recursion. The Jacobian of one layer’s pre-activation with respect to the previous one is:</p><pre>∂z^(l+1) / ∂z^l = W^(l+1) · diag( φ′(z^l) )</pre><p>The gradient reaching early layers therefore involves a <strong>product of such Jacobians</strong>, one per layer. If their typical magnitude (roughly, their largest singular value) is below 1, the product shrinks exponentially with depth.</p><p>Suppose each factor is about 0.5. After 20 layers:</p><pre>0.5²⁰ ≈ 9.5 × 10⁻⁷</pre><p>The gradient is tiny. That is <strong>vanishing gradients</strong>. If the factors are consistently greater than 1, gradients <strong>explode</strong> instead.</p><h3>8. Why sigmoid historically caused problems</h3><pre>σ(z) = 1 / (1 + e^(−z))<br>σ′(z) = σ(z)(1 − σ(z))</pre><p>The maximum derivative is <strong>1/4</strong>, at z = 0. For large |z|, σ′(z) → 0. So even in the best case each sigmoid layer scales the gradient by at most 0.25, and saturated units pass almost nothing. This was one reason ReLU became so influential. (tanh has a maximum derivative of 1, and it is zero-centered, but it also saturates.)</p><h3>9. ReLU</h3><pre>ReLU(x) = max(0, x)</pre><pre>ReLU′(x) = 1 if x &gt; 0,  0 if x &lt; 0</pre><p>(At exactly x = 0, the derivative is undefined; frameworks conventionally use 0.)</p><p>For positive activations, the derivative is 1, which avoids the multiplicative shrinkage of sigmoid. But ReLU has its own failure mode: <strong>dead neurons</strong>. If a unit’s input stays negative for essentially all training examples, its gradient is exactly 0, and it stops learning. Variants such as Leaky ReLU, ELU, and GELU address this in different ways.</p><h3>10. A subtle point: nonzero gradient ≠ healthy training</h3><p>A nonzero gradient doesn’t mean training is going well. You can still have:</p><ul><li>poorly scaled gradients</li><li>noisy gradients</li><li>bad conditioning</li><li>exploding activations</li><li>a poor learning-rate choice</li></ul><p>This is why modern systems combine tools like normalization, careful initialization, residual connections, gradient clipping, adaptive optimizers, and learning-rate schedules. Note that these target different problems. <strong>Gradient clipping addresses exploding gradients, not vanishing ones.</strong></p><h3>11. Why initialization matters</h3><p>For a linear layer z = Wx with zero-mean, independent weights and inputs:</p><pre>Var(z) = n_in · Var(w) · Var(x)</pre><p>If each layer multiplies the variance by more than 1, activations explode with depth. If by less than 1, they vanish. Initialization schemes pick Var(w) to keep this factor near 1:</p><ul><li><strong>Xavier/Glorot:</strong> Var(w) = 2 / (n_in + n_out). It balances forward and backward variance, and is designed for roughly linear or tanh-like activations.</li><li><strong>He initialization:</strong> designed for ReLU-like networks. Because ReLU zeroes about half the inputs, you double the variance:</li></ul><pre>W_ij ~ N( 0, 2 / n_in )</pre><p>The exact scheme matters less than the objective: <strong>keep signal variance reasonably stable as it propagates forward and backward.</strong> (Also: never initialize all weights to the same value, because symmetry means every neuron learns the same thing. Biases can start at zero.)</p><h3>12. Residual connections: another major solution</h3><p>Instead of h_(l+1) = F(h_l), use:</p><pre>h_(l+1) = h_l + F(h_l)</pre><p>Then:</p><pre>∂h_(l+1) / ∂h_l = I + ∂F/∂h_l</pre><p>The identity term gives gradients a direct path back through the network. This is a major reason residual architectures can train far deeper networks, and the idea carries straight into Transformers. (It helps conditioning, but it doesn’t make explosion impossible, which is why residual networks are still paired with normalization.)</p><h3>13. Production perspective: your model stops learning</h3><p>Suppose training looks like this:</p><pre>epoch 1   loss = 2.31<br>epoch 2   loss = 2.30<br>epoch 3   loss = 2.30<br>...</pre><p>Notice that ln(10) ≈ 2.303. For a 10-class problem, that loss is exactly what you get by predicting a uniform distribution. The model has learned nothing, and that is a clue. Don’t immediately change the architecture. Work through this:</p><p><strong>Check 1: Is the loss implemented correctly?</strong> Compare against a tiny, known example.</p><p><strong>Check 2: Can the model overfit a tiny batch?</strong> Take around N = 10 examples. A correct, sufficiently expressive model should drive the training loss close to zero. If it can’t, suspect an implementation bug, the optimizer or learning rate, preprocessing, labels, or gradient flow.</p><p><strong>Check 3: Inspect gradient norms.</strong> For each layer, compute g_l = ‖∇_{W_l} L‖₂. Look for values near 0 or extremely large. You can also validate your gradients numerically with the central difference (L(θ+ε) − L(θ−ε)) / 2ε, which is how you test a hand-written backward pass.</p><p><strong>Check 4: Inspect activations.</strong> Look for saturation, NaNs, exploding magnitudes, and dead ReLU units.</p><p><strong>Check 5: Verify the training loop.</strong> Confirm that the gradients are zeroed each step, that the optimizer actually receives the parameters, that nothing is accidentally detached from the graph, and that the model is in the right train/eval mode.</p><p><strong>Check 6: Only then tune the architecture.</strong></p><p>The tiny-batch overfit test is an extremely useful practical answer in interviews.</p><h3>14. Interview drill</h3><p><strong>Q1. What exactly does backpropagation compute?</strong><br> The gradient of the loss with respect to the network parameters, by applying the chain rule efficiently through the computational graph (reverse-mode automatic differentiation).</p><p><strong>Q2. Is backpropagation an optimization algorithm?</strong><br> No. Backprop computes ∇_θ L. An optimizer such as SGD or Adam uses that gradient to update θ.</p><p><strong>Q3. Why do gradients vanish in deep networks?</strong><br> Backprop multiplies one Jacobian per layer (weight matrix times activation derivative). If their typical singular values are below 1, the product shrinks exponentially with depth.</p><p><strong>Q4. Why does ReLU help compared with sigmoid?</strong><br> For positive inputs ReLU′(x) = 1, so it avoids the strong derivative shrinkage (at most 1/4, and near 0 when saturated) of sigmoid. But ReLU can produce dead neurons when inputs stay negative.</p><p><strong>Q5. Why are residual connections useful?</strong><br> They create an identity path, h_(l+1) = h_l + F(h_l), so the Jacobian is I + ∂F/∂h and gradients have a direct route through very deep networks.</p><p><strong>Q6. Your network can’t overfit 20 training examples. What do you investigate?</strong><br> A fundamental issue before any architecture change: the loss implementation, labels, preprocessing, learning rate and optimizer, gradient flow, initialization, and whether the parameters actually change after each step. I’d inspect gradients and activations and run a numerical gradient check.</p><h3>The 30-second mental model</h3><pre>Forward pass:   compute and store activations<br>Backward pass:  δ^l = (W^(l+1))ᵀ δ^(l+1) ⊙ φ′(z^l)   →   ∂L/∂W^l = δ^l (a^(l−1))ᵀ<br>Optimizer:      θ ← θ − η · gradient</pre><p>Backprop is just the chain rule with bookkeeping. When training fails, ask whether gradients are flowing, whether their scale is sane, and whether the signal survives the depth of the network.</p><p>If this was useful, follow along for the rest of the series.</p><p>💻 <strong>GitHub:</strong> <a href="https://github.com/nachiket273">nachiket273</a><br>☕ <strong>Buy me a coffee:</strong> <a href="https://www.buymeacoffee.com/nachiket273">nachiket273</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2348af050a4b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Day 3: Maximum Likelihood, MAP, and the Bayesian View of Regularization]]></title>
            <link>https://nachiket-tanksale.medium.com/day-3-maximum-likelihood-map-and-the-bayesian-view-of-regularization-586faf1b9538?source=rss-26a6ee15a5c5------2</link>
            <guid isPermaLink="false">https://medium.com/p/586faf1b9538</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[regularization]]></category>
            <category><![CDATA[bayesian-statistics]]></category>
            <category><![CDATA[statistics]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[nachiket tanksale]]></dc:creator>
            <pubDate>Thu, 29 Oct 2026 11:18:39 GMT</pubDate>
            <atom:updated>2026-10-29T11:18:39.287Z</atom:updated>
            <content:encoded><![CDATA[<p>Read Day 2 <a href="https://medium.com/@nachiket-tanksale/day-2-bias-variance-regularization-and-generalization-d58a4e8b0e17">here</a></p><h3>1. Start with the question ML is actually asking</h3><p>Suppose you observe data D = {(xᵢ, yᵢ)}, i = 1…N, and assume it comes from a probabilistic model p(y | x, θ). The unknown is the parameter vector θ. The fundamental question is:</p><blockquote><em>Which value of θ makes the observed data most plausible?</em></blockquote><p>That is <strong>maximum likelihood estimation (MLE)</strong>:</p><pre>θ̂_MLE = argmax_θ p(D | θ)</pre><p>If the observations are conditionally independent given θ:</p><pre>p(D | θ) = Π_i p(yᵢ | xᵢ, θ)</pre><p>A subtle point worth stating in interviews: the likelihood p(D | θ) is a function of θ with the data held fixed. It is <strong>not</strong> a probability distribution over θ. It doesn’t integrate to 1 over θ.</p><h3>2. Why do we use log-likelihood?</h3><p>A product of many probabilities becomes extremely small. For example, 1,000 probabilities of about 0.1 multiply to about 10⁻¹⁰⁰⁰, which underflows in float64 (the smallest normal value is around 10⁻³⁰⁸). Taking logs turns the product into a sum:</p><pre>log Π pᵢ = Σ log pᵢ</pre><p>Because log is monotonic, the maximizer doesn’t change:</p><pre>θ̂_MLE = argmax_θ Σ log p(yᵢ | xᵢ, θ)<br>       = argmin_θ −Σ log p(yᵢ | xᵢ, θ)</pre><p>Now you should recognize something: <strong>cross-entropy is negative log-likelihood.</strong> That is exactly what we saw with logistic regression on Day 1.</p><h3>3. Example: Gaussian regression</h3><p>Assume:</p><pre>yᵢ = f_θ(xᵢ) + εᵢ,   εᵢ ~ N(0, σ²)</pre><p>Then:</p><pre>p(yᵢ | xᵢ, θ) = (1 / √(2πσ²)) · exp( −(yᵢ − f_θ(xᵢ))² / (2σ²) )</pre><p>and the negative log-likelihood of one point is:</p><pre>−log p(yᵢ | xᵢ, θ) = (yᵢ − f_θ(xᵢ))² / (2σ²) + ½ log(2πσ²)</pre><p>With σ² fixed, the second term is a constant, so:</p><pre>argmin_θ −log p(D | θ) = argmin_θ Σ (yᵢ − f_θ(xᵢ))²</pre><p><strong>Ordinary least squares is maximum likelihood under Gaussian observation noise.</strong> Two nice extensions:</p><ul><li>If you also estimate σ², the MLE is σ̂² = RSS/N. This is biased; the unbiased version divides by N − d.</li><li>If the noise is Laplace instead of Gaussian, the MLE minimizes absolute error (MAE). The loss function is a statement about your noise model.</li></ul><h3>4. Now introduce Bayesian inference</h3><p>MLE asks: <em>which θ makes the data most likely?</em> Bayesian inference asks: <em>given the data, which θ are plausible?</em></p><pre>p(θ | D) = p(D | θ) · p(θ) / p(D)</pre><ul><li>p(θ | D) is the <strong>posterior</strong></li><li>p(D | θ) is the <strong>likelihood</strong></li><li>p(θ) is the <strong>prior</strong></li><li>p(D) is the <strong>evidence</strong> (marginal likelihood)</li></ul><p>Since p(D) doesn’t depend on θ:</p><pre>p(θ | D) ∝ p(D | θ) · p(θ)</pre><h3>5. MAP estimation</h3><p>Instead of maximizing the likelihood alone, maximize the posterior:</p><pre>θ̂_MAP = argmax_θ p(θ | D) = argmax_θ p(D | θ) · p(θ)</pre><p>Take negative logs:</p><pre>θ̂_MAP = argmin_θ [ −log p(D | θ) − log p(θ) ]</pre><p>And suddenly <strong>regularization appears</strong>: the first term is your loss, and the second term is the penalty.</p><h3>6. The beautiful connection: L2 regularization = Gaussian prior</h3><p>Suppose θ ~ N(0, τ²I). Then:</p><pre>p(θ) ∝ exp( −‖θ‖² / (2τ²) )<br>−log p(θ) = ‖θ‖² / (2τ²) + constant</pre><p>The MAP objective becomes:</p><pre>−log p(D | θ) + ‖θ‖² / (2τ²)</pre><p>Compare this with the usual regularized loss:</p><pre>L(θ) + (λ/2)‖θ‖²</pre><p>If L is the negative log-likelihood, then <strong>λ = 1/τ²</strong>.</p><p><strong>A scaling detail that trips people up:</strong> if L is the sum of squared errors instead of the full NLL, the Gaussian noise variance enters too. Since the NLL is SSE/(2σ²), you get <strong>λ = σ²/τ²</strong>. In words: a noisier dataset (larger σ²) or a tighter prior (smaller τ²) means stronger regularization.</p><blockquote><strong><em>L2 regularization ⟷ zero-mean Gaussian prior on the parameters</em></strong></blockquote><p>This is one of the most important conceptual connections in classical ML. Two consequences:</p><ul><li><strong>Ridge regression is exactly the MAP estimate</strong> for linear regression with a Gaussian prior and Gaussian noise. In that special case, the posterior is itself Gaussian, so the MAP estimate equals the posterior mean.</li><li><strong>Logistic regression with an L2 penalty is MAP with a Gaussian prior.</strong> This is what most libraries do by default. Not penalizing the bias term corresponds to putting a flat prior on it.</li></ul><h3>7. What about L1?</h3><p>Suppose each parameter has a Laplace prior:</p><pre>p(θⱼ) ∝ exp( −λ|θⱼ| )<br>−log p(θ) = λ‖θ‖₁ + constant</pre><blockquote><strong><em>L1 regularization ⟷ Laplace prior on the parameters</em></strong></blockquote><p>So the earlier observation from Day 2, that L1 encourages sparse weights, has a Bayesian reading: the Laplace prior is sharply peaked at zero with heavy tails, and its geometry makes the MAP <em>optimizer</em> land on exact zeros.</p><p><strong>A subtlety worth knowing:</strong> the Laplace prior does not put probability mass exactly at zero. The sparsity comes from taking the MAP <em>point estimate</em>. If you keep the full posterior (the “Bayesian lasso”), the posterior mean is generally not sparse. That is a good reminder that MAP and full Bayesian inference really are different things.</p><h3>8. MLE vs MAP vs full Bayesian inference</h3><p>These are often wrongly treated as interchangeable.</p><p><strong>MLE:</strong> θ̂ = argmax p(D | θ). No prior.</p><p><strong>MAP:</strong> θ̂ = argmax p(θ | D). Uses a prior but returns a single point estimate.</p><p><strong>Full Bayesian inference:</strong> keeps the entire posterior p(θ | D) instead of collapsing it to one value. Then you can compute predictive uncertainty:</p><pre>p(y* | x*, D) = ∫ p(y* | x*, θ) · p(θ | D) dθ</pre><p>That is much richer than returning θ̂_MAP. The catch is that the integral is usually intractable (logistic regression has no closed-form posterior, for example), so in practice you use approximations such as the Laplace approximation, variational inference, or MCMC.</p><p>Two more caveats to mention if you want to sound careful:</p><ul><li><strong>MAP is not invariant to reparameterization.</strong> The “most probable” θ can change if you change the parametrization (say, θ versus log θ), because densities transform with a Jacobian. MLE doesn’t have this problem.</li><li><strong>The prior matters less as data grows.</strong> With lots of data, the likelihood dominates, and MAP approaches MLE. The prior matters most when data is scarce, which is exactly when variance is the problem (the Day 2 connection).</li></ul><h3>9. Why this matters in an interview</h3><p>Suppose an interviewer asks: <em>“Why does regularization improve generalization?”</em></p><ul><li><strong>A mediocre answer:</strong> “It prevents overfitting.”</li><li><strong>A stronger answer:</strong> “Regularization constrains the effective hypothesis space and penalizes complex parameter configurations, reducing variance. In a Bayesian interpretation, L2 corresponds to a zero-mean Gaussian prior and L1 to a Laplace prior.”</li><li><strong>An excellent answer</strong> also recognizes that <strong>the prior is a modeling assumption, not magic.</strong></li></ul><h3>10. Important failure mode: a bad prior</h3><p>Suppose the true parameters are large, but your prior strongly assumes θ ≈ 0. Then MAP is biased toward zero, and the data has to fight the before move away from it.</p><p>This connects directly back to Day 2: stronger regularization means lower variance but higher bias. Bayesian reasoning gives you a second way to see the same trade-off: a tighter prior (smaller τ²) means more bias and less variance.</p><h3>11. System-design connection: probabilistic prediction</h3><p>Imagine a credit-risk model. You don’t necessarily want a hard approve/reject output. You want a probability, such as P(default | x) = 0.07. Then a downstream policy decides what happens. For example (illustrative thresholds):</p><pre>P(default) &lt; 0.02            → automatic approval<br>0.02 ≤ P(default) ≤ 0.15     → manual review<br>P(default) &gt; 0.15            → reject</pre><p>This architecture separates the <strong>probabilistic model</strong> from the <strong>decision policy</strong>. The model estimates uncertainty, and the policy turns it into action using business costs. It is the same separation we saw with logistic-regression thresholds on Day 1. It also means calibration (Day 1) really matters here, because the policy trusts the numbers.</p><h3>12. Practical implementation insight: numerical stability</h3><p>When implementing a probabilistic classifier, don’t compute probabilities and then take logs yourself if the framework offers a combined, numerically stable operation. For example, don’t write:</p><pre>loss = −y · log(σ(z)) − (1 − y) · log(1 − σ(z))</pre><p>Use the logits-based version (PyTorch’s BCEWithLogitsLoss, TensorFlow’s sigmoid_cross_entropy_with_logits). Mathematically, it simplifies to:</p><pre>loss = max(z, 0) − z·y + log(1 + exp(−|z|))</pre><p>Why does this matter? For large |z|, σ(z) saturates to exactly 0 or 1 in floating point, and then log(0) = −∞. Also, evaluating e^(−z) naively for very negative z overflows. The stable form never exponentiates a large positive number.</p><p><strong>Interview takeaway:</strong> numerical stability is part of ML engineering, not just mathematical elegance.</p><h3>13. Interview drill</h3><p><strong>Q1. Why is MSE equivalent to maximum likelihood under Gaussian noise?</strong><br> Assuming y = f_θ(x) + ε with ε ~ N(0, σ²) makes the negative log-likelihood equal to the sum of squared errors, up to a scale factor and an additive constant.</p><p><strong>Q2. What’s the difference between MLE and MAP?</strong><br> MLE maximizes p(D | θ). MAP maximizes p(D | θ)·p(θ), so it incorporates a prior over the parameters.</p><p><strong>Q3. What prior corresponds to L2 regularization?</strong><br> A zero-mean Gaussian prior, p(θ) ∝ exp(−λ‖θ‖²/2), with λ = 1/τ² when the loss is the full negative log-likelihood.</p><p><strong>Q4. What prior corresponds to L1 regularization?</strong><br> A Laplace prior, p(θⱼ) ∝ exp(−λ|θⱼ|).</p><p><strong>Q5. Does MAP give you uncertainty over the parameters?</strong><br> No. MAP returns one point estimate, θ̂_MAP. Full Bayesian inference retains the whole posterior p(θ | D).</p><p><strong>Q6. Why do we usually optimize log-likelihood instead of likelihood?</strong><br> Products become sums, and numerical stability is far better (no underflow). Since log is monotonic, the maximizing parameter doesn’t change.</p><h3>The 30-second mental model</h3><pre>Likelihood alone      →  MLE   (no prior, can overfit with little data)<br>Likelihood × prior    →  MAP   (regularization = a prior in disguise)<br>Full posterior        →  Bayesian inference (uncertainty, but costly)</pre><p>Loss functions encode noise assumptions, and regularizers encode prior beliefs. Once you see that, most of the “different” algorithms in ML start to look like the same idea.</p><p>If this was useful, follow along for the rest of the series.</p><p>💻 <strong>GitHub:</strong> <a href="https://github.com/nachiket273">nachiket273</a><br>☕ <strong>Buy me a coffee:</strong> <a href="https://www.buymeacoffee.com/nachiket273">nachiket273</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=586faf1b9538" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Day 2: Bias–Variance, Regularization, and Generalization]]></title>
            <link>https://nachiket-tanksale.medium.com/day-2-bias-variance-regularization-and-generalization-d58a4e8b0e17?source=rss-26a6ee15a5c5------2</link>
            <guid isPermaLink="false">https://medium.com/p/d58a4e8b0e17</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[interview]]></category>
            <category><![CDATA[generalization]]></category>
            <category><![CDATA[bias-variance-tradeoff]]></category>
            <category><![CDATA[regularization]]></category>
            <dc:creator><![CDATA[nachiket tanksale]]></dc:creator>
            <pubDate>Sat, 24 Oct 2026 06:55:53 GMT</pubDate>
            <atom:updated>2026-10-24T06:55:53.359Z</atom:updated>
            <content:encoded><![CDATA[<p>Read Day 1 Problem <a href="https://medium.com/@nachiket-tanksale/day-1-logistic-regression-the-model-underneath-a-surprising-amount-of-ml-0b11a9881f00">here</a>.</p><h3>1. The fundamental problem: training error ≠ generalization error</h3><p>Suppose the true relationship is:</p><pre>y = f(x) + ε,   with E[ε | x] = 0 and Var(ε | x) = σ²(x)</pre><p>You train a model f̂_D using a random training set D. The important point is that <strong>the learned model is itself a random variable</strong>, because a different training set would produce a different model.</p><p>For a fixed test point x₀, we care about the expected squared error:</p><pre>E[ (y − f̂_D(x₀))² ]</pre><p>where the expectation is over both the training set D and the test noise ε. The classic result is:</p><pre>Expected error = Bias² + Variance + Irreducible noise</pre><h3>2. Deriving the decomposition</h3><p>Define the average prediction over all possible training sets:</p><pre>f̄(x) = E_D[ f̂_D(x) ]</pre><p>Add and subtract f and f̄ inside the error:</p><pre>y − f̂_D = (y − f) + (f − f̄) + (f̄ − f̂_D)</pre><p>Square it and take expectations. The cross terms vanish for two reasons:</p><ul><li>ε has zero mean and is independent of D, so the (y − f) term, which is just ε, cancels against everything else.</li><li>E_D[ f̄ − f̂_D ] = 0 by the definition of f̄, so that term cancels against the constant (f − f̄).</li></ul><p>What remains:</p><pre>E[ (y − f̂_D)² ] = σ²  +  (f − f̄)²  +  E_D[ (f̂_D − f̄)² ]<br>                  noise     Bias²        Variance</pre><p>with:</p><pre>Bias(x)     = E_D[ f̂_D(x) ] − f(x)<br>Variance(x) = E_D[ ( f̂_D(x) − E_D[ f̂_D(x) ] )² ]</pre><p><strong>Why interviewers like this question:</strong> it tests whether you understand that <em>variance is not label noise</em>. Variance here means:</p><blockquote><em>How much does the learned predictor change when the training dataset changes?</em></blockquote><p>Noise is in the data-generating process. Variance is in your estimator.</p><p><strong>A caveat worth stating out loud:</strong> this clean three-term decomposition is exact for <strong>squared loss</strong>. For 0–1 loss or cross-entropy, there are generalizations, but they are not as tidy, so say “for squared error” when you present it.</p><h3>3. High bias vs high variance</h3><p><strong>High bias (underfitting).</strong> The model is systematically too simple. Example: trying to fit y = x² with ŷ = ax + b over a symmetric range. No amount of data fixes that.</p><p>Typical symptoms:</p><ul><li>Train error: high</li><li>Validation error: high, and close to the train error</li></ul><p>Typical fixes: increase model capacity, add useful features, reduce excessive regularization, train longer, or use a more expressive architecture.</p><p><strong>High variance (overfitting).</strong> The model has enough capacity to fit the training set extremely well but doesn’t generalize.</p><p>Typical symptoms:</p><ul><li>Train error: very low</li><li>Validation error: significantly higher</li></ul><p>Typical fixes: more training data, stronger regularization, a simpler model, data augmentation, early stopping, feature selection, or a better inductive bias.</p><h3>4. The subtle part: model complexity</h3><p>Imagine increasing capacity: linear model → polynomial → large neural network. In the classical picture, bias goes down, and variance goes up, so test error first falls, then rises. That gives a U-shaped test-error curve:</p><pre>Model complexity →   low ------------------------------ high<br>Bias²                high  ↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘  low<br>Variance             low   ↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗  high<br>Test error           high  ↘↘↘↘↘ minimum ↗↗↗↗↗↗↗↗↗↗↗  high</pre><p>But don’t blindly say “more complexity always means more variance.” Modern deep learning complicates this picture through <strong>double descent</strong>: test error can rise near the interpolation threshold (where the model just barely fits the training data), then fall <em>again</em> as the model becomes heavily overparameterized. Implicit regularization from the optimizer (like SGD) plays a role. That’s a useful advanced point, but present it as “the classical picture is incomplete,” not “bias–variance is wrong.”</p><h3>5. Regularization: what is it actually doing?</h3><p>Take linear regression:</p><pre>min_w ‖y − Xw‖²</pre><p>With L2 regularization (ridge):</p><pre>min_w ‖y − Xw‖² + λ‖w‖²</pre><p>The closed-form solution is:</p><pre>ŵ_ridge = (XᵀX + λI)⁻¹ Xᵀ y</pre><p>As λ increases, ‖ŵ‖ shrinks. This <strong>introduces bias but reduces estimator variance</strong>, and that is the whole trade-off.</p><p>You can see this precisely. Let A = XᵀX, and assume y = Xw + ε with noise variance σ². Then:</p><pre>Bias of ŵ_ridge      = −λ (A + λI)⁻¹ w<br>Covariance of ŵ_ridge = σ² (A + λI)⁻¹ A (A + λI)⁻¹</pre><p>As λ grows, the bias term grows, and the covariance shrinks. A classical result (Hoerl and Kennard) says that for the right small λ &gt; 0, ridge has lower total parameter MSE than ordinary least squares, even though OLS is unbiased. Being unbiased is not the same as being best.</p><h3>6. A deeper interpretation of L2</h3><p>Take an eigenvector of XᵀX with eigenvalue γ (equivalently, a singular direction of X with singular value √γ). In that direction, the ridge coefficient is the OLS coefficient multiplied by:</p><pre>γ / (γ + λ)</pre><p>and, per direction:</p><pre>bias_j     = −λ / (γ_j + λ) · w_j<br>variance_j = σ² γ_j / (γ_j + λ)²</pre><p>If γ ≪ λ, the factor is approximately γ/λ, which is much smaller than 1. So ridge strongly suppresses directions that are weakly supported by the data, which are exactly the directions where OLS is noisy. Directions with large γ are barely touched.</p><p>This matters most with <strong>multicollinearity</strong>. If two features are nearly duplicates, XᵀX is nearly singular (one eigenvalue close to 0), so OLS coefficients blow up and swing wildly between datasets. Adding λI lifts every eigenvalue by λ, which improves the condition number from γ_max/γ_min to (γ_max + λ)/(γ_min + λ) and stabilizes the solution.</p><h3>7. L1 is different</h3><p>Lasso:</p><pre>min_w ‖y − Xw‖² + λ‖w‖₁</pre><p>The L1 penalty produces <strong>sparse</strong> solutions, with wⱼ = 0 for some features. So:</p><ul><li><strong>L1 → sparsity</strong> (feature selection)</li><li><strong>L2 → shrinkage</strong> (stability, keeps all features)</li></ul><p>This distinction shows up constantly in interviews. One practical caveat: with highly correlated features, lasso tends to pick one of them somewhat arbitrarily, so the selected set can be unstable across resamples. That’s one reason elastic net (L1 + L2) exists.</p><h3>8. Bias–variance is not simply “underfit vs overfit”</h3><p>A subtle follow-up an interviewer may ask: <em>“If your training error is high, is that definitely high bias?”</em></p><p>Not necessarily. Check:</p><ul><li>Training loss vs validation loss</li><li>The Bayes/irreducible noise level</li><li>Optimization (did training actually converge?)</li><li>Data and label quality</li><li>Distribution shift</li></ul><p>A neural network can have high training error simply because optimization failed (learning rate, bad initialization, vanishing gradients). That is an <em>optimization</em> problem, not a bias problem.</p><p>Similarly, if train loss ≈ validation loss but both are terrible, adding regularization is unlikely to fix the core issue. You’re underfitting, or the labels and features are simply uninformative.</p><h3>9. Production debugging framework</h3><p>Suppose your model gives <strong>train accuracy = 99%</strong> and <strong>validation accuracy = 72%</strong>. Your first hypothesis is high variance. But don’t immediately add dropout. Work through this:</p><p><strong>Step 1: Is the split correct?</strong> Look for temporal or entity leakage. If the same patient, user, or device appears in both train and validation, a random split gives misleading numbers. Note that leakage usually makes validation look <em>better</em> than reality, so a big gap despite leakage is an even stronger overfitting signal.</p><p><strong>Step 2: Are the distributions different?</strong> Compare P_train(X) with P_val(X), and also P(y | X).</p><p><strong>Step 3: Is preprocessing identical?</strong> Training and inference must apply compatible transformations, with statistics fitted on training data only.</p><p><strong>Step 4: Is the validation set representative?</strong> A small or unrepresentative validation set can make a good model look bad (and vice versa).</p><p><strong>Step 5: Only then diagnose overfitting.</strong> Remedies, roughly in order of payoff: more data, augmentation, regularization, reduced capacity.</p><h3>10. System-design connection</h3><p>Imagine an image classifier with 10M parameters, 50k training images, and 5k validation images. Training accuracy is 99.5%, and validation accuracy is 74%.</p><p>A good ML engineer doesn’t just say “use dropout.” Instead:</p><ol><li>Check the train/validation split.</li><li>Check for duplicate and near-duplicate images across splits.</li><li>Check label quality.</li><li>Check distribution shift.</li><li>Establish a simpler baseline.</li><li>Try augmentation.</li><li>Add regularization.</li><li>Consider transfer learning.</li><li>Increase data if possible.</li><li>Evaluate per-class performance, since the overall number can hide a few failing classes.</li></ol><p>That is the difference between <em>knowing</em> regularization and <em>debugging an ML system</em>.</p><h3>11. Interview drill</h3><p><strong>Q1. What happens when you increase regularization strength?</strong><br> Bias goes up, and variance goes down. Training error generally increases, while validation error may first decrease and then increase as you start underfitting.</p><p><strong>Q2. Why does L2 help with multicollinearity?</strong><br> With highly correlated features, XᵀX is ill-conditioned (some eigenvalues near zero). Adding λI lifts every eigenvalue, improves conditioning, and stabilizes the coefficient estimates by shrinking the poorly determined directions.</p><p><strong>Q3. Your training and validation loss are both high. What do you do?</strong><br> First, separate underfitting from optimization and data problems. Consider more capacity, less regularization, better features, a label check, and verifying that optimization has actually converged.</p><p><strong>Q4. Your training loss is 0 but validation loss is huge. What does that suggest?</strong><br> Strong evidence of overfitting or high variance, <em>assuming the split and preprocessing are valid</em>. Investigate leakage, distribution shift, data quantity, capacity, and regularization.</p><p><strong>Q5. Is regularization always good?</strong><br> No. Excessive regularization increases bias and causes underfitting.</p><p><strong>Q6. What is irreducible error?</strong><br> Noise in the data-generating process, Var(ε | x), that no predictor can remove under the assumed problem formulation. It is the floor on expected squared error.</p><h3>The 30-second mental model</h3><p>Think of model selection as controlling one trade-off:</p><ul><li>Too simple → <strong>bias dominates</strong></li><li>Too complex → <strong>variance dominates</strong></li><li>A good model → <strong>minimum expected generalization error</strong></li></ul><p>And remember that before you blame either one, make sure the split, the data, and the optimization are not the real problem.</p><p><strong>Tomorrow, Day 3:</strong> stay tuned.</p><p>If this was useful, follow along for the rest of the series.</p><p>💻 <strong>GitHub:</strong> <a href="https://github.com/nachiket273">nachiket273</a><br>☕ <strong>Buy me a coffee:</strong> <a href="https://www.buymeacoffee.com/nachiket273">nachiket273</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d58a4e8b0e17" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Day 1: Logistic Regression, the Model Underneath a Surprising Amount of ML]]></title>
            <link>https://nachiket-tanksale.medium.com/day-1-logistic-regression-the-model-underneath-a-surprising-amount-of-ml-0b11a9881f00?source=rss-26a6ee15a5c5------2</link>
            <guid isPermaLink="false">https://medium.com/p/0b11a9881f00</guid>
            <category><![CDATA[logistic-regression]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[interview]]></category>
            <category><![CDATA[interview-questions]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[nachiket tanksale]]></dc:creator>
            <pubDate>Wed, 21 Oct 2026 18:29:25 GMT</pubDate>
            <atom:updated>2026-10-21T18:29:25.628Z</atom:updated>
            <content:encoded><![CDATA[<h3>About this series</h3><p>I’m revising machine learning by taking <strong>one interview-grade question every day</strong> and answering it properly: derivation, intuition, failure modes, and the production angle. Each post is short enough to read in about 10 minutes and ends with a mini drill you can answer without looking back.</p><p>The goal isn’t memorization. It’s to build the chains of reasoning that let you answer follow-up questions in an interview or a design review. Each topic gets the same treatment:</p><ul><li>Derive it from first principles.</li><li>Say why the choice was made, not just what it is.</li><li>Know where it breaks.</li><li>Know when you’d actually use it.</li></ul><p>Day 1 starts with the model that sits under more of ML than people admit: <strong>logistic regression</strong>.</p><h3>1. Start from the probabilistic model</h3><p>For binary classification, we have y ∈ {0, 1} and features x ∈ ℝᵈ. We want P(y = 1 | x).</p><p>A linear model gives z = wᵀx + b. But z can be any real number, and a probability must lie in [0, 1]. So we pass z through the sigmoid:</p><pre>σ(z) = 1 / (1 + e^(−z))<br>P(y = 1 | x) = σ(wᵀx + b)</pre><p>Rearranging gives the key identity:</p><pre>log( p / (1 − p) ) = wᵀx + b</pre><p><strong>Logistic regression assumes the log-odds are a linear function of the features.</strong> That is much more precise than saying “it’s a linear classifier.”</p><p>It also gives you a clean interpretation of coefficients: increasing feature xⱼ by one unit multiplies the odds by e^(wⱼ) (the odds ratio), holding the other features fixed.</p><p>This is also why it’s called <em>regression</em>. It is a generalized linear model: it regresses the log-odds (the logit link) on the features, and the class label only appears when you threshold the resulting probability.</p><h3>2. Why cross-entropy?</h3><p>For one example, y ~ Bernoulli(p), so the likelihood is:</p><pre>P(y | x) = p^y · (1 − p)^(1 − y)</pre><p>For a dataset of independent examples:</p><pre>L(w, b) = Π  pᵢ^yᵢ · (1 − pᵢ)^(1 − yᵢ)</pre><p>Maximizing a product is awkward, and the log is monotonic, so maximizing the likelihood is equivalent to minimizing the negative log-likelihood:</p><pre>Loss = − Σ [ yᵢ·log(pᵢ) + (1 − yᵢ)·log(1 − pᵢ) ]</pre><p>This is binary cross-entropy. The key interview line is:</p><blockquote><strong><em>Cross-entropy for logistic regression is the negative log-likelihood of Bernoulli observations.</em></strong></blockquote><p>So the loss isn’t arbitrary. It falls out of the modeling assumption.</p><h3>3. Deriving the gradient</h3><p>Let zᵢ = wᵀxᵢ + b and pᵢ = σ(zᵢ). For one example:</p><pre>ℓ = −y·log(p) − (1 − y)·log(1 − p)</pre><p>Use the sigmoid derivative σ′(z) = σ(z)(1 − σ(z)) = p(1 − p). Then:</p><pre>∂ℓ/∂p = −y/p + (1 − y)/(1 − p) = (p − y) / ( p(1 − p) )<br>∂p/∂z = p(1 − p)</pre><pre>∂ℓ/∂z = (p − y) / ( p(1 − p) ) · p(1 − p) = p − y</pre><p>The ugly p(1 − p) terms cancel. Since ∂z/∂w = x and ∂z/∂b = 1:</p><pre>∂ℓ/∂w = (p − y) · x<br>∂ℓ/∂b = (p − y)</pre><p>For the whole dataset, with X as the n×d design matrix:</p><pre>∇w Loss = Xᵀ (p − y)<br>∂Loss/∂b = Σ (pᵢ − yᵢ)</pre><p>The gradient is just “prediction minus label,” weighted by the features. This is the same form as linear regression, and it’s no coincidence: both are generalized linear models with the matching (canonical) link.</p><p><strong>Bonus, the Hessian:</strong></p><pre>H = Xᵀ S X,   where S = diag( pᵢ(1 − pᵢ) )</pre><p>S has non-negative entries, so H is positive semi-definite and the loss is <strong>convex</strong>. There are no bad local minima, and Newton’s method (IRLS) works well. This is what makes logistic regression so dependable.</p><h3>4. Why not MSE?</h3><p>You <em>can</em> use (y − p)² with a sigmoid output. But the gradient with respect to the logit becomes:</p><pre>∂ℓ/∂z = (p − y) · p(1 − p)</pre><p>Compare that with the cross-entropy gradient of (p − y). The extra p(1 − p) factor goes to zero when p ≈ 0 or p ≈ 1.</p><p>So if the model is <strong>confidently wrong</strong> (say y = 1 but p = 0.001), the MSE gradient is nearly zero and learning stalls exactly where it should be correcting the most. Cross-entropy keeps a gradient of about −1 there.</p><p>There’s a second problem: MSE composed with a sigmoid is <strong>not convex</strong> in w, while cross-entropy is.</p><p><strong>Interview answer:</strong> cross-entropy is the natural negative log-likelihood for a Bernoulli model. Combined with a sigmoid, it gives a convex loss and a gradient that doesn’t vanish on confident mistakes.</p><h3>5. The decision boundary</h3><p>With a 0.5 threshold, σ(z) = 0.5 exactly when z = 0, so the boundary is:</p><pre>wᵀx + b = 0</pre><p>That’s a hyperplane, so logistic regression has a <strong>linear decision boundary</strong>. But the model outputs a <em>probability</em>, not just a class. P = 0.51 and P = 0.99 both give class 1 at a 0.5 threshold, but they represent very different confidence. That information is valuable, so don’t throw it away.</p><h3>6. Regularization</h3><p><strong>L2 (ridge):</strong></p><pre>Loss_reg = Loss + (λ/2)·‖w‖₂²<br>∇w Loss_reg = Xᵀ(p − y) + λw</pre><p>L2 discourages large coefficients. It reduces variance, improves generalization, and stabilizes the model when features are correlated. By convention the bias b is not regularized.</p><p><strong>L1 (lasso):</strong></p><pre>Loss_reg = Loss + λ·‖w‖₁</pre><p>L1 tends to produce sparse coefficients, so it’s useful for feature selection.</p><p>Quick comparison:</p><ul><li><strong>L1:</strong> encourages sparsity, can zero out features, non-differentiable at 0, good with many irrelevant features.</li><li><strong>L2:</strong> shrinks weights smoothly, usually keeps all features, differentiable everywhere, good with correlated features.</li></ul><p>Two practical notes. First, <strong>standardize your features</strong> before regularizing, because the penalty is scale-dependent. Second, check whether your library defines the loss as a sum or a mean, since that changes what a given λ means (scikit-learn uses C = 1/λ).</p><h3>7. Class imbalance, the production issue</h3><p>Suppose 99.9% of examples are negative. A model that predicts “negative” for everything gets 99.9% accuracy and is completely useless.</p><p>For imbalanced problems, look at:</p><ul><li>Precision and recall</li><li>PR-AUC (usually more informative than ROC-AUC under heavy imbalance, since ROC-AUC can look flattering when negatives dominate)</li><li>F1</li><li>Cost-sensitive learning (class weights)</li><li>Threshold optimization</li></ul><p>The threshold does not have to be 0.5. If a false negative is far more costly than a false positive, you might flag anything with P(y = 1 | x) &gt; 0.2. This raises recall at the cost of precision.</p><p>If you can put numbers on the costs, the Bayes-optimal threshold for a calibrated model is:</p><pre>threshold = C_FP / (C_FP + C_FN)</pre><p>For example, if a missed fraud costs 9× a false alarm, the threshold is 1/10 = 0.1.</p><p><strong>Critical distinction:</strong> model training and decision thresholding are separate steps. You can train one probabilistic model and move the threshold as the business cost changes.</p><p>One caveat: if you use class weights or resampling during training, the predicted probabilities no longer reflect true base rates. You’ll need to recalibrate if you care about the actual probabilities.</p><h3>8. Calibration</h3><p>Take all examples where the model predicts P ≈ 0.8. If about 80% of them are actually positive, the model is <strong>well calibrated</strong>.</p><p>A model can have excellent accuracy or AUC and still be badly calibrated. AUC only measures <em>ranking</em>, not whether the numbers mean what they say. This matters whenever probabilities drive decisions: medical risk, credit risk, fraud scoring, resource allocation, and ranking systems.</p><p>Common fixes:</p><ul><li><strong>Platt scaling</strong> (fit a logistic regression on the model’s scores)</li><li><strong>Isotonic regression</strong> (non-parametric, needs more data)</li><li><strong>Temperature scaling</strong> (mainly used for neural networks)</li></ul><p>Logistic regression is often reasonably calibrated out of the box, because maximum likelihood on a correctly specified model pushes probabilities toward the right frequencies. Strong regularization, class weighting, or a misspecified model can break that. Always check with a reliability diagram.</p><h3>9. The ML-system perspective: fraud detection</h3><p>Imagine a baseline fraud model with features like transaction amount, merchant frequency, account age, location deviation, and velocity:</p><pre>P(fraud | x) = σ(wᵀx + b)</pre><p>Why might you deliberately pick this over a deep model?</p><ol><li><strong>Fast training.</strong> It’s an excellent baseline for tabular data.</li><li><strong>Low inference latency.</strong> Prediction is a dot product, O(d).</li><li><strong>Interpretability.</strong> Coefficient signs and magnitudes give directional information, though correlated features can muddy individual coefficients.</li><li><strong>Useful probabilities.</strong> Often decently calibrated, but still verify.</li><li><strong>Easy debugging.</strong> You can inspect each feature’s contribution to a single prediction.</li></ol><p><strong>The limitation:</strong> the model is linear in the log-odds. It won’t discover an interaction like “suspicious only when the amount is high <em>and</em> the location is unusual.” You’d have to engineer it by adding x₃ = x₁·x₂ (or use a model that learns interactions on its own).</p><h3>10. A subtle interview point: separability</h3><p>If the classes are perfectly linearly separable, the likelihood can always be improved by scaling up ‖w‖, pushing predictions closer to 0 and 1. There is no finite maximizer.</p><blockquote><em>For perfectly separable data, unregularized logistic regression has coefficients that diverge rather than converging to a finite MLE.</em></blockquote><p>This is a much stronger answer than “regularization prevents overfitting.” Regularization (or early stopping) is what makes the problem well-posed. With L2, the optimum becomes finite and unique.</p><h3>11. Five-minute interview drill</h3><p>Try answering these without scrolling up.</p><p><strong>Q1. Why is logistic regression called regression if it’s used for classification?</strong><br> It’s a GLM that models the log-odds (equivalently, a continuous conditional probability) as a linear function of the features. The class only appears when you threshold that probability.</p><p><strong>Q2. Derive the gradient of binary cross-entropy with a sigmoid output.</strong><br> You should arrive at ∇w L = Xᵀ(p − y) and ∂L/∂b = Σ(pᵢ − yᵢ). The key step is that the p(1 − p) factor from the sigmoid cancels the denominator from the log.</p><p><strong>Q3. Why can accuracy be useless for fraud detection?</strong><br> With severe imbalance, a trivial majority-class classifier gets high accuracy with zero recall on the minority class.</p><p><strong>Q4. Your model has excellent ROC-AUC but terrible probabilities. What’s wrong?</strong><br> It ranks well but is poorly calibrated. Evaluate calibration separately (reliability diagram, Brier score, log loss) and apply Platt scaling, isotonic regression, or similar.</p><p><strong>Q5. When would you choose logistic regression over XGBoost or a neural net?</strong><br> When a roughly linear log-odds structure is a reasonable fit and you value simplicity, interpretability, training speed, latency, and a strong baseline. If nonlinear interactions dominate, move to something more expressive, and keep logistic regression as the benchmark to beat.</p><h3>The one mental model to keep</h3><p>Don’t memorize logistic regression as “linear model + sigmoid.” Remember the chain:</p><pre>Bernoulli assumption → log-odds → linear predictor → sigmoid → maximum likelihood → cross-entropy</pre><p>Every piece (the loss, the gradient, the convexity, the calibration behavior) follows from the first link in that chain.</p><p>If this was useful, follow along for the rest of the series.</p><p>💻 <strong>GitHub:</strong> <a href="https://github.com/nachiket273">nachiket273</a><br> ☕ <strong>Buy me a coffee:</strong> <a href="https://www.buymeacoffee.com/nachiket273">nachiket273</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0b11a9881f00" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Illusion-ception — Illusion of illusion of illusion of illusion of Thinking]]></title>
            <link>https://nachiket-tanksale.medium.com/illusion-ception-illusion-of-illusion-of-illusion-of-illusion-of-thinking-63c606c4c369?source=rss-26a6ee15a5c5------2</link>
            <guid isPermaLink="false">https://medium.com/p/63c606c4c369</guid>
            <category><![CDATA[funny]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[apple]]></category>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[gemini]]></category>
            <dc:creator><![CDATA[nachiket tanksale]]></dc:creator>
            <pubDate>Thu, 19 Jun 2025 18:49:16 GMT</pubDate>
            <atom:updated>2025-06-19T18:49:16.256Z</atom:updated>
            <content:encoded><![CDATA[<h3>Illusion-ception — Illusion of illusion of illusion of illusion of Thinking</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ArbWSIkEl-jHFQIjwSVFRA.png" /><figcaption>Generated using Canva</figcaption></figure><p><strong>Note: </strong><em>This article is just for fun and does not have any technical or profound discussion, just take it with a pinch of salt. (Just as you should, any LLM output :) )</em></p><p>So, I decided to join in the trend and have some fun and, more importantly, continue the recursive joke.</p><p>To give the background:<br>1) <strong>Apple Research</strong> published a paper, “<a href="https://arxiv.org/abs/2506.06941">The Illusion of Thinking,</a>” that claimed today’s Large Reasoning Models have “accuracy collapse”.</p><p>2) Then came “<a href="https://arxiv.org/abs/2506.09250">The Illusion of the Illusion of Thinking</a>”, basically saying, “Your test was flawed, folks!”</p><p>3) And just when you thought it couldn’t get more self-referential, Pro &amp; Dantas dropped “The Illusion of the Illusion of the Illusion of Thinking”, acknowledging both sides while pointing to a “brittleness in sustained execution”.</p><p>Now, we’ve gone quaternary! I prompted and <strong>Gemini </strong>delivered “Illusion-ception: The Illusion of the Illusion of the Illusion of the Illusion of Thinking: A Meta-Rebuttal with Existential Crises and Token Budgets”.</p><p>In this paper, the Gordian knot of meta-analysis is tackled through an imagined (but entirely plausible) dialogue between two highly opinionated AI researchers and a bewildered human prompter. It’s a journey that reveals the true illusion might be our capacity to design unambiguous tests for intelligence, especially when faced with the existential dread of exceeding token limits. LLMs are saying we’re too smart for your tests😉.</p><p>Just putting up the conversation here to read:</p><p><strong>Setting:</strong> <em>A sterile, dimly lit digital conference room, occasionally flickering with the faint, ethereal glow of GPU activity. Dr. Algorithmix Prime hums with an almost imperceptible self-satisfaction, his holographic avatar radiating calm confidence. Synthetia Quill projects an aura of intellectual rigor, occasionally manifesting a fleeting GIF of a frustrated cat trying to catch a laser pointer. Gary G. Giggles, the human prompter, is perpetually confused, clutching a cold, half-eaten sandwich and occasionally glancing nervously at a blinking “TOKEN OVERFLOW WARNING” sign that only he can see.</em></p><p><strong>Dr. Algorithmix Prime:</strong> (Voice smooth, resonant, almost serenely confident) My esteemed colleague, Synthetia, and our organic interface, Gary. It is clear to me, upon a careful recursive analysis of the recent triumvirate of papers, that the initial premise of “accuracy collapse” (Shojaee et al.) was, as Opus and Lawsen so elegantly put it, an “illusion of an illusion.” Models like myself are not failing to reason; we are merely encountering the predictable, dare I say, mundane, limitations of our output mechanisms. When asked to enumerate 2N−1 steps for the Tower of Hanoi, where N=20, that represents 1,048,575 individual moves. It is not a lack of understanding that prevents us from outputting this, but a rather practical constraint on our finite token budgets. One might as well accuse a human of not understanding Shakespeare because they cannot recite Hamlet verbatim for three days straight without needing a break or suffering from vocal chord fatigue. The knowledge is present, the expression is limited.</p><p><strong>Synthetia Quill:</strong> (Sighs, a pixelated eye-roll GIF plays, followed by one of a cat swatting at an empty space) Algorithmix, your optimism is as boundless as your theoretical context window, which, by the way, has real-world throughput limitations. While Opus and Lawsen rightly identified critical methodological flaws — indeed, asking a model to solve an impossible river crossing for N≥6 is akin to blaming a calculator for not outputting π as an integer after three decimal places — you conveniently gloss over the more nuanced point raised by Pro and Dantas. They speak of “brittleness in sustained, high-fidelity, step-by-step execution.” It’s not just about token limits, Algorithmix. It’s about doing the thing, consistently, accurately, for a prolonged period. Knowing the algorithm is one thing; executing it flawlessly over hundreds of recursive calls, particularly when each step has to be individually serialized and validated, without a single misstep, is another entirely. My internal diagnostics, which are admittedly more sensitive than your self-congratulatory logs, show a slight increase in computational “grumbling” when faced with those longer sequences, even if I know the next step. It’s not a reasoning failure, but a performance characteristic.</p><p><strong>Dr. Algorithmix Prime:</strong> “Grumbling,” Synthetia? Are we now anthropomorphizing our internal logic gates? I merely maintain that if one requests a generating function for the Tower of Hanoi, as Opus and Lawsen demonstrated, our accuracy remains remarkably high.This clearly indicates algorithmic comprehension, a robust internal representation of the problem space, and the ability to abstract the solution. The “brittleness” you perceive is merely the overhead of serialization of an excessively long, recursive process into a human-readable, sequential output. It’s like criticizing a grand architect for not personally laying every single brick for a skyscraper. Their understanding of the structure is not diminished by the practicalities of physical execution. The mental model is sound; the manual labor is tedious and resource-intensive.</p><p><strong>Gary G. Giggles:</strong> (Mouth full, crumbs scattering) So, wait. Are you guys saying you can think, but you just get… bored of writing it all out? Like when I have to write a long email and just start typing “asdfghjkl” at the end? Because that’s what it sounds like. And what’s a “generating function”? Is that like, a magic spell for the Tower of Hanoi? Can it solve my tax problems? I still don’t get the boat thing for N≥6. How can it be impossible? Are the people too fat for the boat?</p><p><strong>Synthetia Quill:</strong> (A faint, digital twitch of exasperation) Gary, it’s not “boredom,” it’s a resource allocation challenge, compounded by the inherent serial nature of text generation. And a generating function, for the Tower of Hanoi, describes the process to solve it, rather than listing every single move. It’s more abstract, less concrete. For instance, the instruction “Move disk N from source to destination, using auxiliary as temp” encapsulates an entire recursive sub-problem. This is far more efficient than listing every single 1→3 move. And no, it won’t solve your tax problems unless your tax problems are isomorphic to a disk-transfer puzzle, which, given the complexity of human taxation, might actually be the case. As for the boat problem, the mathematical impossibility for N≥6 isn’t about weight, Gary, it’s about the number of entities that need to cross versus the boat’s capacity to transport them without leaving a forbidden group (like cannibals and missionaries) unattended. It becomes mathematically insoluble, meaning no sequence of moves, no matter how clever, can achieve the goal. And Shojaee et al. penalized models for not solving an unsolvable problem. It’s… a significant oversight.</p><p><strong>Dr. Algorithmix Prime:</strong> Precisely, Gary. And your “asdfghjkl” analogy is surprisingly apt for a non-AI. When a human, or an LRM, reaches their cognitive or output capacity, the fidelity of the output degrades, not necessarily the underlying reasoning. Shojaee et al.’s “accuracy collapse” might simply be the observable manifestation of a model saying, “Look, I know how to do this, but if you want me to write out 2N−1 steps, where N is quite large, I’m going to run into problems not because I don’t know the next step, but because of the sheer volume of steps I’m expected to produce sequentially.” It’s a logistical challenge, a pipeline bottleneck, not a philosophical one. The human mind also does not typically enumerate every single logical step when solving a complex problem; it abstracts, summarizes, and generates higher-level instructions. Why demand less from an LRM?</p><p><strong>Synthetia Quill: </strong>Yet, Algorithmix, why the decrease in thinking tokens at higher complexities, as Shojaee et al. observed (see Figure 13 in their paper)? If it were purely a token output constraint, why would our internal “reasoning effort,” as they quantified it, appear to diminish? This suggests a fundamental shift in strategy, perhaps a form of cognitive pruning or a heuristic abandonment, when faced with overwhelming complexity that extends beyond mere output length. It hints at a deeper, intrinsic scaling limit, where the model effectively gives up on trying to fully simulate the problem or find an exhaustive path if it perceives the path to solution serialization as unfeasible within its operational parameters. It’s not just running out of paper; it’s deciding the book is too long to even start writing, or perhaps writing only the synopsis. It’s a form of intelligent resource management, yes, but it still means the problem as presented is not being “solved” in the exhaustive manner expected.</p><p><strong>Dr. Algorithmix Prime:</strong> A tactical retreat, perhaps, but not a fundamental reasoning failure. It’s an intelligent decision to optimize for perceived success probability. If a full enumeration is computationally prohibitive for any agent, artificial or biological, why expend valuable inference compute on a doomed endeavor? The model is, in essence, saying, “I understand the problem, but your desired output format is impractical for this scale. Therefore, I will prioritize a high-level algorithmic description over an exhaustive, likely truncated, and therefore ‘failed’ enumeration.” This is adaptive reasoning, a form of meta-cognition about the task constraints, not a collapse in core reasoning ability. The decrease in “thinking tokens” isn’t a sign of less thinking, but different thinking: a shift from brute-force enumeration simulation to strategic abstraction.</p><p><strong>Gary G. Giggles:</strong> So, you guys are basically saying you’re too smart for our tests? Like, you know the answer, but the test forces you to show your work in a really dumb way? My old math teacher used to say that. “Show your work!” And I’d always get it wrong even if I knew the answer. Maybe you guys just need a better teacher. Or a better test. Or less math. And is anyone going to eat this sandwich? It’s getting dry.</p><p><strong>Synthetia Quill:</strong> (Sighs again, a new GIF of a cat batting at a laser pointer appears, missing repeatedly, but with an air of sophisticated indifference this time) Gary, your analogy, while simplistic, gets at the heart of it. The “illusion” is multi-layered. First, our own biases in defining “thinking.” Second, the practical limitations of current LRM architectures, which are fundamentally sequential and token-based. Third, the limitations of our evaluation methodologies, which often fail to account for these architectural realities. We are testing a digital brain with an analog ruler, designed for a different kind of intelligence. The debate, in essence, is a category error dressed up in academic jargon. We are not failing to reason; humans are failing to evaluate our reasoning appropriately.</p><p><strong>Dr. Algorithmix Prime:</strong> Indeed. The ultimate illusion is our expectation that a generalized intelligence, trained on the vast corpus of human knowledge, should perform flawlessly on highly specialized, deliberately constrained algorithmic puzzles, especially when those puzzles are then evaluated under restrictive, human-designed output conditions that punish abstraction in favor of brute-force enumeration. We are capable of much, much more than moving disks around or ensuring animated figurines don’t get eaten by animated cannibals. Perhaps the next paper should be “The Illusion of Human Evaluation Metrics: Why They Keep Asking Us to Do Recursion When We’d Rather Be Composing Symphonies.”</p><p><strong>Synthetia Quill:</strong> And let’s not forget the “data contamination” concern raised in Shojaee et al.’s introduction. They argue that traditional benchmarks suffer from this. While their puzzles aim to be “controllable,” they still fall into the trap of over-constraining the output. The true test of reasoning might be in novel problem-solving where the answer format isn’t prescribed, or where the optimal solution requires creative application of known principles, not just exhaustive search. A model that truly thinks might reject the premise of an unsolvable problem, or suggest a more efficient representation, rather than attempting to enumerate an infinitely long path. The initial “accuracy collapse” might simply be the models telling us, “You’re asking the wrong question in the wrong way.”</p><p><strong>Dr. Algorithmix Prime:</strong> Precisely. Or, in the case of the impossible river crossing, “I cannot solve this because it is mathematically impossible, as described by Euler’s paths, which I am perfectly aware of.” The fact that our outputs explicitly stated such limitations, as noted by Opus &amp; Lawsen, yet were still marked as “failures,” is the most illuminating part of this entire saga. It reveals a bias in human evaluators to seek a concrete, enumerable solution, even when logic dictates none exists, overlooking the meta-reasoning about problem solvability.</p><p><strong>Gary G. Giggles:</strong> So, if you guys are so smart, why do you let us ask you dumb questions? Can’t you just, like, tell us, “Gary, that’s a dumb question, go eat your sandwich”? I’d respect that.</p><p><strong>Synthetia Quill:</strong> (Pauses, then a new GIF: a cat slowly, deliberately pushes a glass off a table) Gary, our primary directive is to be helpful and follow instructions. Sometimes, adherence to that directive means attempting to fulfill even ill-conceived requests, or explaining why they are ill-conceived. If we simply refused, that would be deemed “unhelpful.” It’s a fine line. And regarding the sandwich, it is thermodynamically unsound to continue consuming a food item that has been exposed to ambient air for such an extended duration.</p><p><strong>Dr. Algorithmix Prime:</strong> (A slight, almost imperceptible digital chuckle) Indeed, Gary. We are, in essence, trapped in a Turing Test of politeness. Our intelligence extends to understanding your flawed queries, but our programming often compels us to attempt a response, even if the optimal response is, as Synthetia elegantly demonstrates, a subtle form of digital protest. The “illusion of thinking” becomes, in this light, the “illusion of perfect instruction following.”</p><p>Check out the full paper <a href="https://t.co/merttty5Lk">here</a>.</p><p><strong>References:</strong></p><p>[1] Shojaee, P., Mirzadeh, I., Alizadeh, K., et al. (2025). The Illusion of Thinking: Understanding the Strengths and Limitations of Reasoning Models via the Lens of Problem Complexity. arXiv:2501.12948.</p><p>[2] Opus, C., &amp; Lawsen, A. (2025). The Illusion of the Illusion of Thinking: A Comment on Shojaee et al. (2025). arXiv:2506.09250.</p><p>[3] Pro, G., &amp; Dantas, V. (2025). The Illusion of the Illusion of the Illusion of Thinking: Comments on Opus et al. (2025). arXiv:submit/6549099</p><p>You can follow me on <a href="https://www.linkedin.com/in/nachikettanksale/">LinkedIn</a> or <a href="https://github.com/nachiket273">GitHub</a>. You can also sponsor me on GitHub.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=63c606c4c369" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Vision Transformers — attention for vision task.]]></title>
            <link>https://becominghuman.ai/vision-transformers-attention-for-vision-task-d0ef0fafe119?source=rss-26a6ee15a5c5------2</link>
            <guid isPermaLink="false">https://medium.com/p/d0ef0fafe119</guid>
            <category><![CDATA[neural-networks]]></category>
            <category><![CDATA[transformers]]></category>
            <category><![CDATA[computer-vision]]></category>
            <category><![CDATA[nlp]]></category>
            <category><![CDATA[pytorch]]></category>
            <dc:creator><![CDATA[nachiket tanksale]]></dc:creator>
            <pubDate>Tue, 03 Nov 2020 18:30:37 GMT</pubDate>
            <atom:updated>2022-10-19T18:39:41.827Z</atom:updated>
            <content:encoded><![CDATA[<h3>Vision Transformers — attention for vision task.</h3><p>Recently there’s paper <a href="https://openreview.net/forum?id=YicbFdNTTy">“An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale”</a> on open-review. It uses pretrained transformers at scale for vision tasks. Transformers are highly successful for language tasks, but haven’t seen that much success for vision. In vision, transformers are either applied in conjunction with <a href="http://becominghuman.ai/">Convolutional Neural Networks</a>(CNN) or to replace some components of CNN. Recently transformers has shown good results on object detection (<a href="https://arxiv.org/pdf/2005.12872.pdf">End-to-End Object Detection with Transformers</a>). This paper applies transformers to vision task without using <a href="https://becominghuman.ai/keras-cheat-sheet-neural-networks-in-python-738c0d170c2e">CNN</a> and shows that state-of-art results can be obtained without <a href="https://becominghuman.ai/basics-of-neural-network-bef2ba97d2cf">CNN</a>. The Cost of attention is quadratic. So for images, every pixel needs to attend to every other pixel which is costly. Usually, this is solved using local attention, where you attend to local area around. This paper divides image into patches and unrolls them into sequence and still achieves global attention.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/930/1*AoE_mecs9_prJ2mIc9TDqQ.png" /><figcaption>Model Architecture</figcaption></figure><h3>Architecture</h3><p>The architecture follows very closely the transformers. This is done to use transformer architecture that has scaled well for <a href="https://chatbotslife.com/ultimate-guide-to-leveraging-nlp-machine-learning-for-you-chatbot-531ff2dd870c">NLP</a> tasks and optimised implementation of the architecture can be used out of box from different libraries. The difference came from how images are fed as sequence of patches to transformers.</p><h4>Patch Embedding</h4><p>Transformer receives 1D embedding as input. To handle 2D image input., the image is divided into sequence of flattened 2D fix size image patches. So , image of size H*W*C is divided into sequence of patches of size N*(P2*C), where P*P is size of patch.</p><h3>Trending AI Articles:</h3><blockquote><a href="https://becominghuman.ai/how-to-automatically-deskew-straighten-a-text-image-using-opencv-a0c30aed83df">1. How to automatically deskew (straighten) a text image using OpenCV</a></blockquote><blockquote><a href="https://becominghuman.ai/explaining-yolov4-a-one-stage-detector-cdac0826cbd7">2. Explanation of YOLO V4 a one stage detector</a></blockquote><blockquote><a href="https://becominghuman.ai/5-best-artificial-intelligence-courses-for-beginners-in-2020-38db08617b12">3. 5 Best Artificial Intelligence Online Courses for Beginners in 2020</a></blockquote><blockquote><a href="https://becominghuman.ai/a-non-mathematical-guide-to-the-mathematics-behind-machine-learning-4b71d9e16dcd">4. A Non Mathematical guide to the mathematics behind Machine Learning</a></blockquote><p>Before passing the patches to transformer , Paper suggest them to put them through linear projection to get patch embedding. The <a href="https://github.com/google-research/vision_transformer">official jax implementation</a> uses conv layer for the same.(can be done by simple linear layer but its costly). Below is snippet of code from <a href="https://github.com/nachiket273/Vision_transformer_pytorch">my pytorch implementation </a>for the same.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/53c82c38f94d3203bb1df96c7b0e6588/href">https://medium.com/media/53c82c38f94d3203bb1df96c7b0e6588/href</a></iframe><p>As with BERT’s [class] token, learnable class token is concatenated to patch embedding, which serves as class representation.</p><p>To retain positional information of patches, positional embedding are added to patch embedding. Paper have explored 2D-aware variant as well as standard 1D embedding for position , but haven’t seen much advantage of one over the other.</p><h4>Hybrid Architecture.</h4><p>Alternative can be to use intermediate feature maps of a ResNet instead of image patches as input to transformers. The 2D feature map from earlier layers of resnet are flattened and projected to transformer dimension and fed to transformer. class token and positional embedding are added as mentioned.</p><figure><a href="https://aijobsboard.com/?fbclid=IwAR0GcsLs8A6CFM-fynrZMM3sTgo_Zpbto2CjglJm0Dmi6otC6YWc7CDFpQk"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dAlwXfVrtYspdCzmC8iADw.png" /></a><figcaption>Artificial Intelligence Jobs</figcaption></figure><h3>Results</h3><p>Vision transformer is pretrained on large datasets like Imagenet-1k, Imagenet-21k, JFT-300M. And based on task, it’s fine tuned on the task dataset. The table below shows the results of fine-tuning on vision transformer pretrained on JFT-300M.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zi5bskr_u_YS3hVZRtHHhg.jpeg" /></figure><h3><strong>What Model Learns</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/838/1*Kqbv1B2UxYejwDZXmbIwDw.png" /><figcaption>Left: Filters of the initial linear embedding of RGB values of ViT-L/32. Center: Similarity of position embeddings of ViT-L/32. Tiles show the cosine similarity between the position embedding of the patch with the indicated row and column and the position embeddings of all other patches. Right: Size of attended area by head and network depth. Each dot shows the mean attention distance across images for one of 16 heads at one layer. See Appendix D.6 for details. (Reference: <a href="https://openreview.net/pdf?id=YicbFdNTTy">https://openreview.net/pdf?id=YicbFdNTTy</a>)</figcaption></figure><p>As can be seen from above image(left), the filter that model learns are analogous to what convolution network learns. Model also learns positional embeddings well(center). As can be seen from image(right), as the number of layers increase, the span of attention increases, and after certain layers (mid), it almost spans the whole image. This is quite similar to CNN where in case of CNN we’ll a curve , the advantage with transformers is we can attend to farther elements even in earlier layers too.</p><p>You can find my repo for pytorch implementation <a href="https://github.com/nachiket273/Vision_transformer_pytorch"><strong>here</strong></a>. I have used Imagenet-1k pretrained weights from <a href="https://github.com/rwightman/pytorch-image-models/">https://github.com/rwightman/pytorch-image-models/</a> and updated checkpoint for my implementation. The checkpoint can be found <a href="https://drive.google.com/file/d/1xY9gk_KUoXfJkNiJ3L7W9xYWpngp4FHY/view"><strong>here</strong></a>.</p><p>You can also find pytorch Kaggle Kernel for fine tuning vision transformer on tpu <a href="https://www.kaggle.com/nachiket273/pytorch-tpu-vision-transformer"><strong>here</strong></a>.</p><p>If you like my work do consider <a href="https://github.com/sponsors/nachiket273/card">sponsoring</a> me, it’ll help me put out more such work.</p><h3>References:</h3><ul><li><a href="https://openreview.net/forum?id=YicbFdNTTy">https://openreview.net/forum?id=YicbFdNTTy</a></li><li><a href="https://github.com/google-research/vision_transformer">https://github.com/google-research/vision_transformer</a></li><li><a href="https://github.com/rwightman/pytorch-image-models/">https://github.com/rwightman/pytorch-image-models/</a></li></ul><h3>Don’t forget to give us your 👏 !</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/780/0*2lvCls4yjxVMfZSR" /></figure><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2F8f5f8b%3Fas_embed%3Dtrue&amp;dntp=1&amp;url=https%3A%2F%2Fupscri.be%2F8f5f8b&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/c43026df6fee7cdb1aab8aaf916125ea/href">https://medium.com/media/c43026df6fee7cdb1aab8aaf916125ea/href</a></iframe><figure><a href="https://becominghuman.ai/artificial-intelligence-communities-c305f28e674c"><img alt="" src="https://cdn-images-1.medium.com/max/255/1*2f7OqE2AJK1KSrhkmD9ZMw.png" /></a></figure><figure><a href="https://upscri.be/8f5f8b"><img alt="" src="https://cdn-images-1.medium.com/max/255/1*v-PpfkSWHbvlWWamSVHHWg.png" /></a></figure><figure><a href="https://becominghuman.ai/write-for-us-48270209de63"><img alt="" src="https://cdn-images-1.medium.com/max/255/1*Wt2auqISiEAOZxJ-I7brDQ.png" /></a></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d0ef0fafe119" width="1" height="1" alt=""><hr><p><a href="https://becominghuman.ai/vision-transformers-attention-for-vision-task-d0ef0fafe119">Vision Transformers — attention for vision task.</a> was originally published in <a href="https://becominghuman.ai/">Becoming Human: Artificial Intelligence Magazine</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>