<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: deeplearning</title>
    <description>The latest articles tagged 'deeplearning' on DEV Community.</description>
    <link>https://dev.to/t/deeplearning</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tag/deeplearning"/>
    <language>en</language>
    <item>
      <title>Mastering Low-Precision AI: FP8 and FP4 Support Across Frameworks in Mid-2026</title>
      <dc:creator>Dmitry Noranovich</dc:creator>
      <pubDate>Thu, 13 Aug 2026 21:23:44 +0000</pubDate>
      <link>https://dev.to/javaeeeee/mastering-low-precision-ai-fp8-and-fp4-support-across-frameworks-in-mid-2026-4c98</link>
      <guid>https://dev.to/javaeeeee/mastering-low-precision-ai-fp8-and-fp4-support-across-frameworks-in-mid-2026-4c98</guid>
      <description>&lt;p&gt;In mid-2026, &lt;a href="https://medium.com/@javaeeeee/low-precision-ai-format-comparisonthe-low-precision-edge-fp8-and-fp4-in-pytorch-jax-tensorflow-19bfbcb13438" rel="noopener noreferrer"&gt;FP8 and FP4 have become essential tools for making large-scale AI training and inference more efficient&lt;/a&gt;. FP8 uses two main formats-E4M3 for better precision on activations and weights, and E5M2 for wider dynamic range on gradientswhile NVIDIA’s NVFP4 takes things further with 4-bit values and micro-block scaling (shared FP8 scales per 16 elements plus a tensor-level scale). These formats dramatically cut memory use and increase throughput on modern GPUs compared with traditional BF16 or FP16, making it possible to train and serve bigger models on the same hardware.&lt;/p&gt;

&lt;p&gt;The benefits are clear: roughly 2× memory savings with FP8 and up to 3.5× with NVFP4, higher Tensor Core performance, and better energy efficiency. The trade-offs come from reduced numerical range and precision, which can lead to accuracy loss or instability unless carefully managed with techniques such as delayed scaling, stochastic rounding, Hadamard transforms, and selective quantization that skips sensitive layers. When these methods are applied properly, accuracy often stays within 1–2 % of higher-precision baselines on real workloads.&lt;/p&gt;

&lt;p&gt;Research has moved quickly from the foundational 2022 FP8 paper to 2025 studies showing stable FP4 pre-training of multi-billion-parameter models. Hardware support is mature for FP8 on Hopper GPUs and reaches its peak on Blackwell with native NVFP4 and MXFP8 acceleration. Among frameworks, PyTorch currently leads with native float8 dtypes, Transformer Engine for production training, and TorchAO for optimized inference. JAX offers solid support through Transformer Engine, TensorFlow/Keras provides simpler quantize-to-FP8 options but relies more on TensorRT for high performance, and libraries such as bitsandbytes remain useful for complementary 4-bit memory savings.&lt;/p&gt;

&lt;p&gt;Practical adoption is already strong for both training and inference, especially when teams start with proven recipes, monitor scaling factors, and prototype on smaller models. Workarounds for remaining gaps include casting unsupported operations to higher precision or using selective quantization. Overall, FP8 is now production-ready for most teams, while NVFP4 is rapidly becoming practical on Blackwell hardware for maximum efficiency.&lt;/p&gt;

&lt;p&gt;Curious how a specific number behaves in FP8 or BF16?&lt;br&gt;&lt;br&gt;
Try the free converter here: &lt;a href="https://www.bestgpusforai.com/calculators/number-to-GPU-float-converter" rel="noopener noreferrer"&gt;https://www.bestgpusforai.com/calculators/number-to-GPU-float-converter&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;And if you want more insights, real-world tips, and a place to discuss AI programming hardware, come hang out with us at &lt;a href="https://www.reddit.com/r/AIProgrammingHardware" rel="noopener noreferrer"&gt;https://www.reddit.com/r/AIProgrammingHardware&lt;/a&gt;. We’d love to have you.&lt;/p&gt;

</description>
      <category>nvidia</category>
      <category>gpu</category>
      <category>ai</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>Unlocking Multimodal AI: Your Next Move</title>
      <dc:creator>Ravi Roy</dc:creator>
      <pubDate>Thu, 13 Aug 2026 18:45:15 +0000</pubDate>
      <link>https://dev.to/ravi_roy_1222f9e6b2ea51bd/unlocking-multimodal-ai-your-next-move-2dai</link>
      <guid>https://dev.to/ravi_roy_1222f9e6b2ea51bd/unlocking-multimodal-ai-your-next-move-2dai</guid>
      <description>&lt;h2&gt;
  
  
  What is Multimodal AI?
&lt;/h2&gt;

&lt;p&gt;Multimodal AI is reshaping how machines interpret data by merging formats like text, images, and audio. Over the years, it's advanced industries, making technology adaptive to user needs. This means more accurate decision-making since it can analyze multiple inputs in real-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Components of Multimodal Systems
&lt;/h2&gt;

&lt;p&gt;These systems primarily consist of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Inputs&lt;/strong&gt;: Text, images, and audio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Processing Units&lt;/strong&gt;: Algorithms and models like Transformers that merge and interpret data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output Mechanisms&lt;/strong&gt;: Deliver insights seamlessly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consider virtual assistants that blend speech with visual cues for a personalized experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does Multimodal AI Work?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Underlying Technologies
&lt;/h3&gt;

&lt;p&gt;A game-changer here is the Transformer model, crucial for understanding context through data relationships. &lt;/p&gt;

&lt;h3&gt;
  
  
  Data Processing Techniques
&lt;/h3&gt;

&lt;p&gt;Data fusion techniques—early, late, and hybrid fusion—combine these inputs effectively. Imagine autonomous vehicles processing camera feeds and LIDAR data to navigate complex environments safely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Implementing Multimodal AI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Improved Data Interpretation
&lt;/h3&gt;

&lt;p&gt;Combining data types can enhance prediction accuracy. Companies implementing such strategies report up to 30% improvement in model performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enhanced User Experience
&lt;/h3&gt;

&lt;p&gt;Multimodal systems can heighten user engagement, boosting satisfaction levels by 40%. &lt;/p&gt;

&lt;h2&gt;
  
  
  Examples of Multimodal AI Applications
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Healthcare
&lt;/h3&gt;

&lt;p&gt;In medical imaging, integrating imaging data with patient history can reduce diagnostic errors by 25%.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entertainment
&lt;/h3&gt;

&lt;p&gt;Games adapt to player actions, offering rich experiences. Streaming platforms create personalized recommendations based on viewer behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automation
&lt;/h3&gt;

&lt;p&gt;In manufacturing, multimodal systems allow machines to use audio and visual inputs, improving efficiency by up to 20%.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges of Multimodal AI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Technical Hurdles
&lt;/h3&gt;

&lt;p&gt;Data integration complexity can be a challenge; effective communication across modalities is vital.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ethical Considerations
&lt;/h3&gt;

&lt;p&gt;Biases in training datasets can result in skewed outcomes, necessitating a solid governance framework to ensure responsible AI use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Strategies for Multimodal AI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Framework Development
&lt;/h3&gt;

&lt;p&gt;Start by aligning your multimodal strategy with business objectives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pilot Testing
&lt;/h3&gt;

&lt;p&gt;Test with a small group to gather feedback, refine, and validate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scaling Implementation
&lt;/h3&gt;

&lt;p&gt;Once successful, expand across your organization with robust training.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Trends in Multimodal AI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Emerging Technologies
&lt;/h3&gt;

&lt;p&gt;Generative AI will likely enhance multimodal capabilities, driving richer interpretations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Industry Innovations
&lt;/h3&gt;

&lt;p&gt;The blend of data formats will revolutionize user experiences across sectors.&lt;/p&gt;

&lt;p&gt;Multimodal AI is full of opportunities and challenges. What’s the biggest hurdle you’ve faced in its implementation? How did you tackle it?&lt;br&gt;&lt;br&gt;
💡 Share your insights below!&lt;/p&gt;

&lt;p&gt;For more insights, check out &lt;a href="https://www.raviroy.in" rel="noopener noreferrer"&gt;Ravi Roy&lt;/a&gt; and his projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://apps.apple.com/us/app/ravi-video-chat-meet-singles/id1534950454" rel="noopener noreferrer"&gt;Download from the App Store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.pegatech.ravi" rel="noopener noreferrer"&gt;Get it on Google Play&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;App Store: &lt;a href="https://apps.apple.com/us/app/ravi-video-chat-meet-singles/id1534950454%5D(https://apps.apple.com/us/app/ravi-video-chat-meet-singles/id1534950454" rel="noopener noreferrer"&gt;https://apps.apple.com/us/app/ravi-video-chat-meet-singles/id1534950454](https://apps.apple.com/us/app/ravi-video-chat-meet-singles/id1534950454&lt;/a&gt;&lt;br&gt;
Google Play: &lt;a href="https://play.google.com/store/apps/details?id=com.pegatech.ravi%5D(https://play.google.com/store/apps/details?id=com.pegatech.ravi" rel="noopener noreferrer"&gt;https://play.google.com/store/apps/details?id=com.pegatech.ravi](https://play.google.com/store/apps/details?id=com.pegatech.ravi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>multimodalai</category>
      <category>ai</category>
      <category>machinelearning</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>How GPUs Really Store Numbers: An Interactive Tour of FP32, BF16, FP8, and FP4 for AI</title>
      <dc:creator>Dmitry Noranovich</dc:creator>
      <pubDate>Thu, 13 Aug 2026 16:11:36 +0000</pubDate>
      <link>https://dev.to/javaeeeee/how-gpus-really-store-numbers-an-interactive-tour-of-fp32-bf16-fp8-and-fp4-for-ai-4198</link>
      <guid>https://dev.to/javaeeeee/how-gpus-really-store-numbers-an-interactive-tour-of-fp32-bf16-fp8-and-fp4-for-ai-4198</guid>
      <description>&lt;p&gt;&lt;a href="https://www.bestgpusforai.com/calculators/number-to-GPU-float-converter" rel="noopener noreferrer"&gt;This page presents an interactive Number to GPU Float Converter&lt;/a&gt; that demonstrates how any decimal number is stored and approximated across the main floating-point formats used by GPUs in AI workloads. Users enter a value and immediately see the results in FP64, FP32, TF32, FP16, BF16, FP8 E4M3, FP8 E5M2, and FP4 E2M1. The tool highlights the practical trade-offs between numerical precision, dynamic range, memory footprint, and compute throughput that arise when reducing bit width.&lt;/p&gt;

&lt;p&gt;The converter covers the full spectrum of formats relevant to modern machine learning. FP32 serves as the stable baseline, TF32 trims the mantissa for faster tensor-core math while retaining FP32 range, FP16 and BF16 each use 16 bits with different priorities (precision versus range), the two FP8 variants further split bits between exponent and mantissa, and raw FP4 is shown as an extreme low-precision option that normally requires block scaling (as in MXFP4 or NVFP4) to be useful. FP64 is provided purely as a high-precision reference.&lt;/p&gt;

&lt;p&gt;Under the hood the page walks through the standard binary floating-point encoding process: determining the sign bit, normalizing the magnitude into the form 1.mantissa × 2^exponent, applying the format-specific bias, rounding the mantissa to fit the available bits (typically round-to-nearest-even), packing the bits, and decoding the stored value back to decimal. A detailed step-by-step example converts 13.625 into FP8 E4M3 and shows why it becomes 14, illustrating the rounding error that appears once the mantissa is truncated. The same principles explain special values (zeros, subnormals, infinity, and NaN) and why smaller formats can underflow, overflow, or collapse nearby numbers.&lt;/p&gt;

&lt;p&gt;Practical examples and guidance complete the article. Numbers such as 0.1, 1.1, 0.00009, and 449 demonstrate how approximation behaves differently across formats, while the text emphasizes that lower precision is valuable for memory and speed only when the hardware and software stack support it and when scaling or mixed-precision techniques are applied carefully. The overall message is that these formats are engineering compromises: fewer bits enable larger models and higher throughput, but they require awareness of the resulting numerical limitations.&lt;/p&gt;

&lt;p&gt;Ready to put the theory into practice?&lt;br&gt;&lt;br&gt;
→ Join &lt;a href="https://www.reddit.com/r/AIProgrammingHardware" rel="noopener noreferrer"&gt;https://www.reddit.com/r/AIProgrammingHardware&lt;/a&gt; for discussions, benchmarks, and expert tips on AI hardware and low-precision training.&lt;br&gt;&lt;br&gt;
→ Experiment live with the Number-to-GPU-Float Converter at &lt;a href="https://www.bestgpusforai.com/calculators/number-to-GPU-float-converter" rel="noopener noreferrer"&gt;https://www.bestgpusforai.com/calculators/number-to-GPU-float-converter&lt;/a&gt;  convert numbers across NVIDIA float formats in seconds and see the precision trade-offs yourself.&lt;/p&gt;

</description>
      <category>nvidia</category>
      <category>gpu</category>
      <category>ai</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>The Evolution of Precision in AI: How NVIDIA’s FP32, BF16, FP16, and FP8 Formats Power Faster, More Efficient Training and Inference</title>
      <dc:creator>Dmitry Noranovich</dc:creator>
      <pubDate>Thu, 13 Aug 2026 16:02:49 +0000</pubDate>
      <link>https://dev.to/javaeeeee/the-evolution-of-precision-in-ai-how-nvidias-fp32-bf16-fp16-and-fp8-formats-power-faster-more-13k9</link>
      <guid>https://dev.to/javaeeeee/the-evolution-of-precision-in-ai-how-nvidias-fp32-bf16-fp16-and-fp8-formats-power-faster-more-13k9</guid>
      <description>&lt;p&gt;&lt;a href="https://www.reddit.com/r/AIProgrammingHardware/comments/1uxzrf2/precision_at_scale_nvidias_floatingpoint_formats/" rel="noopener noreferrer"&gt;Floating-point numbers form the foundation of modern deep learning&lt;/a&gt;, with FP32 long serving as the reliable default due to its strong balance of dynamic range and precision. As AI models grew dramatically in size, the computational and memory costs of sticking exclusively with FP32 became unsustainable. NVIDIA addressed this by pioneering lower-precision formats and mixed-precision techniques, enabling significant speedups and efficiency gains without sacrificing model accuracy. The core idea is to use reduced precision for the bulk of matrix multiplications while protecting critical operations like weight updates with higher precision.&lt;/p&gt;

&lt;p&gt;Mixed-precision training, introduced in NVIDIA’s influential 2018 work, combines formats strategically: a master copy of weights stays in FP32 for stability, while forward and backward passes use FP16 or the more forgiving BF16. FP16 offers speed and halved memory use but requires loss scaling to prevent gradient underflow, whereas BF16 retains FP32’s wide dynamic range with fewer mantissa bits, often needing less intervention. Hardware acceleration via Tensor Cores delivers up to several times the throughput of standard FP32 operations, allowing larger batches or models on the same hardware. This approach has been validated across CNNs, RNNs, and early language models, consistently matching full-precision results.&lt;/p&gt;

&lt;p&gt;FP8 represents the next major advance, with two complementary formats-E4M3 for precision-focused weights and activations, and E5M2 for the wider range needed in gradients-supported natively on Hopper and later GPUs. Effective use relies on dynamic scaling strategies (such as delayed or block/micro-scaling in MXFP8) to keep values within the limited range of these 8-bit formats. NVIDIA’s Transformer Engine automates much of this complexity, including optimized kernels and integration with frameworks. Research, including papers on FP8-LM and MXFP8 recipes, shows FP8 can deliver roughly double the throughput and memory savings of BF16 while maintaining near-identical convergence on large language models.&lt;/p&gt;

&lt;p&gt;Beyond the formats themselves, careful rounding during conversions (typically round-to-nearest-even, with stochastic rounding explored in research for added stability) and higher-precision accumulation help minimize error buildup. Training emphasizes long-term stability and convergence, while inference benefits from aggressive post-training quantization for latency and memory gains. For developers and MLEs, practical tools like Automatic Mixed Precision in PyTorch/TensorFlow and the Transformer Engine make adoption straightforward, with guidance to monitor loss curves and selectively retain higher precision in sensitive layers. Looking ahead, emerging FP4 and refined micro-scaling techniques promise even greater efficiency, continuing NVIDIA’s role in making ever-larger AI systems practical.&lt;/p&gt;

&lt;p&gt;Want to go deeper on floating-point formats, Tensor Cores, and real-world GPU performance?&lt;br&gt;&lt;br&gt;
Join the community at &lt;a href="https://www.reddit.com/r/AIProgrammingHardware" rel="noopener noreferrer"&gt;https://www.reddit.com/r/AIProgrammingHardware&lt;/a&gt; - share experiments, ask questions, and stay updated with fellow developers and ML engineers.  &lt;/p&gt;

&lt;p&gt;While you’re at it, try the free Number-to-GPU-Float Converter:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.bestgpusforai.com/calculators/number-to-GPU-float-converter" rel="noopener noreferrer"&gt;https://www.bestgpusforai.com/calculators/number-to-GPU-float-converter&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Paste any value and instantly see how it looks in FP32, BF16, FP16, FP8, and more.&lt;/p&gt;

</description>
      <category>nvidia</category>
      <category>gpu</category>
      <category>deeplearning</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Deleted 94% of a Neural Network's Weights and Lost 0.6 Points. Here Is the Whole Algorithm</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Thu, 13 Aug 2026 14:36:12 +0000</pubDate>
      <link>https://dev.to/dev48v/i-deleted-94-of-a-neural-networks-weights-and-lost-06-points-here-is-the-whole-algorithm-3ho2</link>
      <guid>https://dev.to/dev48v/i-deleted-94-of-a-neural-networks-weights-and-lost-06-points-here-is-the-whole-algorithm-3ho2</guid>
      <description>&lt;p&gt;Here is a sentence that should be strange and somehow isn't: you can throw away &lt;strong&gt;90 to 95 percent of the weights&lt;/strong&gt; in a trained neural network and get the accuracy back.&lt;/p&gt;

&lt;p&gt;That result is not new and not fragile. LeCun published &lt;em&gt;Optimal Brain Damage&lt;/em&gt; in 1989. Han et al. re-ran it on AlexNet and VGG in 2015. It has held up on ResNets, on BERT, on 70-billion-parameter language models. So the interesting question was never "does pruning work" — it is &lt;strong&gt;why a trained network is mostly empty in the first place&lt;/strong&gt;, and what exactly you are allowed to conclude from the fact that it is.&lt;/p&gt;

&lt;p&gt;I built the whole thing from scratch in a browser tab to find out: a 144–32–3 MLP, a hand-written backward pass, four pruning criteria, iterative pruning, and the lottery-ticket experiment with both of its controls. No libraries. Every number below came out of code you can run.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Live, everything computed in your browser:&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/dl/day61-network-pruning.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/dl/day61-network-pruning.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why there is anything to delete
&lt;/h2&gt;

&lt;p&gt;Over-parameterisation is a &lt;strong&gt;training&lt;/strong&gt; aid, not a deployment requirement.&lt;/p&gt;

&lt;p&gt;That is the whole resolution. A network with far more parameters than the task needs has a loss surface gradient descent can actually navigate — lots of redundant directions, lots of routes downhill. A network sized exactly right has a landscape full of walls. So you train big because that is what makes training work, and then you are holding a model whose extra capacity has already done its job.&lt;/p&gt;

&lt;p&gt;You are allowed to bill for the journey and ship only the destination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which weights die
&lt;/h2&gt;

&lt;p&gt;The question you actually want answered is: &lt;em&gt;how much would the loss rise if this weight were zero?&lt;/em&gt; Expand the loss around the trained point. At a minimum the gradient term is roughly zero, so the leading term is quadratic — which is exactly what Optimal Brain Damage estimates with the Hessian diagonal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;score_obd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;hessian_diag&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is expensive. Magnitude pruning replaces the entire analysis with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A small weight multiplies its input into a small contribution, so cut the smallest. It ignores the input scale, the curvature, and every interaction between weights. And it is brutally hard to beat.&lt;/p&gt;

&lt;p&gt;That last claim is only worth anything if you check it, which brings us to the part most write-ups skip.&lt;/p&gt;

&lt;h2&gt;
  
  
  The control you are not allowed to omit
&lt;/h2&gt;

&lt;p&gt;Take the same sparsity. Replace the saliency score with a coin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mask_random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sparsity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sparsity&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;permutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On my trained network, held-out accuracy at &lt;strong&gt;80 % sparsity&lt;/strong&gt;, no fine-tuning:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;criterion&lt;/th&gt;
&lt;th&gt;accuracy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;dense baseline&lt;/td&gt;
&lt;td&gt;93.3 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;global magnitude&lt;/td&gt;
&lt;td&gt;87.3 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;structured (whole neurons)&lt;/td&gt;
&lt;td&gt;65.3 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;random, same sparsity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;48.0 %&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 39-point gap between magnitude and random is the &lt;em&gt;only&lt;/em&gt; direct evidence that &lt;code&gt;|w|&lt;/code&gt; carries information. It is not a nice-to-have on the chart. It is the measurement. A criterion that merely tracks random has not been shown to work, however principled its derivation, and a surprising number of published ones barely clear it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sparsity is not speed
&lt;/h2&gt;

&lt;p&gt;This is the number people quote wrong more than any other.&lt;/p&gt;

&lt;p&gt;A 95 %-sparse weight matrix on a normal GPU runs at &lt;strong&gt;exactly the same speed as the dense one&lt;/strong&gt;. The zeros are still sitting in the tensor and the kernel multiplies them with full enthusiasm. Stored densely it also takes exactly the same bytes.&lt;/p&gt;

&lt;p&gt;To get memory you need a sparse format, and those carry index overhead — CSR stores an index per non-zero, so below roughly 70 % sparsity the compressed version can be &lt;em&gt;larger&lt;/em&gt;. To get speed you need a kernel that skips zeros and still beats a heavily optimised dense GEMM, which usually means north of 90 % sparsity before it wins at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structured&lt;/strong&gt; pruning is the version that converts sparsity into latency: delete a whole hidden unit, channel or attention head, and the tensor genuinely shrinks.&lt;/p&gt;

&lt;p&gt;The catch is that a neuron owns weights on &lt;em&gt;both&lt;/em&gt; sides — the row of the incoming matrix that produces it and the column of the outgoing matrix that consumes it. Miss the second and you have left a consumer reading zeros. The test is exact and it is the best one in the whole project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dead&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="n"&gt;m2&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="n"&gt;dead&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;            &lt;span class="c1"&gt;# mask it
&lt;/span&gt;&lt;span class="n"&gt;keep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dead&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;W1s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b1s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;W2s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;W1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;keep&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;keep&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;W2&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="n"&gt;keep&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="c1"&gt;# or physically delete it
&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;allclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;forward_masked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;forward_small&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W1s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b1s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;W2s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;atol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1e-12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Masking a neuron and deleting it must produce &lt;strong&gt;bit-identical logits&lt;/strong&gt;. If they differ, your index arithmetic is wrong, and nothing downstream will tell you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The half everyone forgets
&lt;/h2&gt;

&lt;p&gt;The accuracy right after a big cut is the &lt;em&gt;raw damage&lt;/em&gt;, not the result.&lt;/p&gt;

&lt;p&gt;Cutting 90 % of my network in one shot dropped it from 93.3 % to &lt;strong&gt;54.7 %&lt;/strong&gt; — barely above the 33 % chance line. Twelve epochs of fine-tuning &lt;strong&gt;under the mask&lt;/strong&gt; brought it to &lt;strong&gt;92.0 %&lt;/strong&gt;. Recovered 37.3 points. Weights that came back from the dead: &lt;strong&gt;0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That last number is the one to watch, because this is where implementations quietly break:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mom&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;lr_ft&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;W&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;                       &lt;span class="c1"&gt;# mask the UPDATE, not only the gradient
&lt;/span&gt;
&lt;span class="nf"&gt;assert &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;    &lt;span class="c1"&gt;# exactly 0.0, not 1e-17
&lt;/span&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;nnz_after&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;nnz_before&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mask only the gradient and momentum still carries a velocity from before the cut, so pruned weights drift off zero. Your 95 %-sparse network is dense again after one epoch, silently, with no error message and a suspiciously good accuracy number.&lt;/p&gt;

&lt;p&gt;Also: use a &lt;strong&gt;lower&lt;/strong&gt; learning rate than the original run. You are repairing a solution, not searching for one.&lt;/p&gt;

&lt;h2&gt;
  
  
  One shot is the wrong schedule
&lt;/h2&gt;

&lt;p&gt;Given a target sparsity you can take it in one cut or in a sequence of smaller cuts with healing in between. The difference is bigger than the difference between most competing criteria.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ones_like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rounds&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;                    &lt;span class="c1"&gt;# on SURVIVORS, not on the total
&lt;/span&gt;    &lt;span class="n"&gt;mask&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;magnitude_mask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;W&lt;/span&gt;     &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;
    &lt;span class="nf"&gt;finetune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ft_epochs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each round sorts on magnitudes that already reflect the network's adaptation to the &lt;em&gt;previous&lt;/em&gt; round, instead of on a snapshot of a model that has not yet noticed it lost anything.&lt;/p&gt;

&lt;p&gt;Ten rounds at &lt;code&gt;p = 0.25&lt;/code&gt; lands on exactly &lt;code&gt;1 − 0.75¹⁰ = 94.37 %&lt;/code&gt; sparsity — 265 weights out of 4,704. Worth asserting that closed form, by the way: applying &lt;code&gt;p&lt;/code&gt; to the original total instead of the survivors is a silent and very common off-by-one.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;route to 94.4 % sparsity&lt;/th&gt;
&lt;th&gt;accuracy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;iterative (10 × prune 25 % + heal)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;92.7 %&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;one shot, identical fine-tuning budget&lt;/td&gt;
&lt;td&gt;90.0 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dense baseline&lt;/td&gt;
&lt;td&gt;93.3 %&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Same criterion, same data, same total compute. Only the order changed.&lt;/p&gt;

&lt;p&gt;The price is real — IMP costs &lt;code&gt;rounds × ft_epochs&lt;/code&gt; of training — which is why one-shot pruning still ships and why gradual magnitude pruning (prune on a schedule &lt;em&gt;during&lt;/em&gt; the original run) is the compromise most frameworks implement.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lottery ticket, stated precisely
&lt;/h2&gt;

&lt;p&gt;Frankle and Carbin's 2019 claim is &lt;em&gt;not&lt;/em&gt; "pruned networks work". That was thirty years old. The claim is that a dense randomly-initialised network already &lt;strong&gt;contains&lt;/strong&gt; a sparse sub-network which, trained alone from the same initial values for the same number of steps, matches the full network.&lt;/p&gt;

&lt;p&gt;The recipe: save &lt;code&gt;θ₀&lt;/code&gt; before training, train, prune iteratively to a mask &lt;code&gt;m&lt;/code&gt;, then reset the survivors to &lt;code&gt;m ⊙ θ₀&lt;/code&gt; and retrain.&lt;/p&gt;

&lt;p&gt;What makes it a claim rather than a demo is the &lt;strong&gt;control&lt;/strong&gt; — the identical mask filled with a fresh random init. If the ticket beats that, the specific initial values carried information. If not, only the structure did. Both are interesting; they are not the same result; and running one without the other tells you nothing.&lt;/p&gt;

&lt;p&gt;My four arms, 94.4 % sparsity, three seeds each, identical budget:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;arm&lt;/th&gt;
&lt;th&gt;accuracy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;dense baseline&lt;/td&gt;
&lt;td&gt;93.3 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;winning ticket&lt;/strong&gt; (mask + θ₀)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;92.4 %&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;same mask, fresh random init&lt;/td&gt;
&lt;td&gt;90.0 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;random mask, same size&lt;/td&gt;
&lt;td&gt;45.1 %&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read those honestly.&lt;/p&gt;

&lt;p&gt;The gap to the &lt;strong&gt;random mask&lt;/strong&gt; is 47 points and has never been in dispute. The structure iterative pruning found is real and it matters enormously.&lt;/p&gt;

&lt;p&gt;The gap to the &lt;strong&gt;fresh init&lt;/strong&gt; — the actual hypothesis — is 2.4 points, and it moves between seeds. That is not me failing to reproduce a result; it is what the follow-up literature found at scale. Rewinding to step 0 stops working on larger models, and the fix (Frankle et al., &lt;em&gt;late rewinding&lt;/em&gt;) is to rewind to iteration &lt;em&gt;k&lt;/em&gt; of the original run instead. Their &lt;em&gt;Linear Mode Connectivity&lt;/em&gt; paper explains why: early training is dominated by SGD noise, and a mask found at the end only means something at the start once the run has become stable to that noise. Meanwhile several replications found that random pruning followed by proper retraining is a far stronger baseline than the original framing implied, and that much of the reported effect is IMP discovering good per-layer sparsity &lt;em&gt;ratios&lt;/em&gt; rather than lucky individual weights.&lt;/p&gt;

&lt;p&gt;Solid: IMP finds real structure, and late rewinding works. Shaky: the specific initial values are lucky.&lt;/p&gt;

&lt;h2&gt;
  
  
  One debugging trap worth the whole post
&lt;/h2&gt;

&lt;p&gt;I wrote a finite-difference check for the backward pass and it failed. The code was correct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;numeric&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;eps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;eps&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;rel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numeric&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;analytic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analytic&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;rel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;1e-6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At convergence the true gradient has decayed towards &lt;code&gt;1e-5&lt;/code&gt;, while the difference of two nearly identical float64 losses bottoms out around &lt;code&gt;1e-11&lt;/code&gt;. The relative error explodes and you go hunting for a bug that does not exist — the check is measuring round-off, not correctness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gradient-check a freshly initialised network&lt;/strong&gt;, where the gradients are large and the check has headroom. Same code, same assertion, passes at &lt;code&gt;1e-8&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually ships
&lt;/h2&gt;

&lt;p&gt;Everything above assumed you can afford to fine-tune, which stops being true at billions of parameters. That constraint produced a family of one-shot post-training methods: &lt;strong&gt;SparseGPT&lt;/strong&gt; solves layer-wise reconstruction in closed form with the inverse Hessian of the layer's own inputs, and &lt;strong&gt;Wanda&lt;/strong&gt; simplifies it to a single score with no gradients at all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# |w| scaled by what it multiplies
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both reach roughly 50 % unstructured sparsity on a 70B model in GPU-hours, and both make the small-scale point again: what matters is not &lt;code&gt;|w|&lt;/code&gt; alone but &lt;code&gt;|w|&lt;/code&gt; scaled by the size of the thing it multiplies.&lt;/p&gt;

&lt;p&gt;And the pattern that actually reaches production is &lt;strong&gt;prune → quantise → encode&lt;/strong&gt;, with the pruning style chosen by the deployment bottleneck: unstructured if you are bound by size, structured if you are bound by latency, and &lt;strong&gt;2:4 semi-structured&lt;/strong&gt; if you are on an NVIDIA GPU from Ampere onwards, where exactly two zeros in every group of four executes natively at roughly twice the dense rate. That constraint is why 50 % sparsity is a real production number while 95 % often is not — it was chosen to match silicon, not to maximise a headline.&lt;/p&gt;

&lt;p&gt;Report three numbers, always: non-zeros, multiply–adds, and measured milliseconds on the target device. Only the last one is not a proxy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification
&lt;/h2&gt;

&lt;p&gt;The page ships with the maths block extracted verbatim and run in Node against independent baselines — a brute-force top-k selection, closed-form sparsity arithmetic, a physically compacted network, and central finite differences on an untrained net. &lt;strong&gt;213 assertions, all passing&lt;/strong&gt;, plus 59 more that run in your browser while you read.&lt;/p&gt;

&lt;p&gt;If you only take one thing from this: &lt;strong&gt;always plot the random control&lt;/strong&gt;. Everything else in pruning is an argument. That is the measurement.&lt;/p&gt;

&lt;p&gt;Live page: &lt;a href="https://dev48v.infy.uk/dl/day61-network-pruning.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/dl/day61-network-pruning.html&lt;/a&gt;&lt;br&gt;
Repo: &lt;a href="https://github.com/dev48v/dl-from-zero" rel="noopener noreferrer"&gt;https://github.com/dev48v/dl-from-zero&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>deeplearning</category>
      <category>python</category>
      <category>optimization</category>
    </item>
    <item>
      <title>Three Correct TSP Solvers. Three Incompatible Promises.</title>
      <dc:creator>Kyrylo Malovychko</dc:creator>
      <pubDate>Thu, 13 Aug 2026 12:02:46 +0000</pubDate>
      <link>https://dev.to/katalvlaran/three-correct-tsp-solvers-three-incompatible-promises-4d2h</link>
      <guid>https://dev.to/katalvlaran/three-correct-tsp-solvers-three-incompatible-promises-4d2h</guid>
      <description>&lt;p&gt;The cold-chain fixture returns a &lt;strong&gt;114-minute&lt;/strong&gt; tour. The validated thermal window is &lt;strong&gt;120 minutes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Six minutes of margin.&lt;/p&gt;

&lt;p&gt;The dispatcher asks a perfectly reasonable question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is 114 the best possible route?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this run, the answer is &lt;strong&gt;not proven&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The tour came from Christofides with exact minimum-weight perfect matching. &lt;code&gt;lvlath/tsp&lt;/code&gt; publishes &lt;code&gt;ApproximationRatio=1.5&lt;/code&gt; and &lt;code&gt;Optimal=false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The difference matters because the public call looks identical.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Tour&lt;/code&gt; and &lt;code&gt;Cost&lt;/code&gt; are not enough for a production TSP result. In a 30-matrix experiment, 2-opt matched the exact optimum cost &lt;strong&gt;24/30&lt;/strong&gt; times and 3-opt &lt;strong&gt;27/30&lt;/strong&gt; times, yet neither solver can honestly publish &lt;code&gt;Optimal=true&lt;/code&gt;. Christofides + Blossom matched the optimum only &lt;strong&gt;8/30&lt;/strong&gt; times, but it is the heuristic regime with a formal &lt;code&gt;1.5&lt;/code&gt; worst-case guarantee. Runtime, observed solution quality, and proof strength are different axes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Textbooks explain permutations, NP-hardness, Branch-and-Bound, and 2-opt well enough. The awkward part appears later, when all of those algorithms are hidden behind one friendly function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The call looks uniform. The result is not.&lt;/p&gt;
&lt;h2&gt;
  
  
  One result type, several very different claims
&lt;/h2&gt;

&lt;p&gt;This is the public &lt;code&gt;Result&lt;/code&gt; in &lt;code&gt;github.com/lvlath/go@v0.1.0/tsp&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Tour&lt;/span&gt;  &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Cost&lt;/span&gt;  &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="n"&gt;IDs&lt;/span&gt;   &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;

    &lt;span class="n"&gt;Algorithm&lt;/span&gt; &lt;span class="n"&gt;Algorithm&lt;/span&gt;
    &lt;span class="n"&gt;Exact&lt;/span&gt;     &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;Optimal&lt;/span&gt;   &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;TimedOut&lt;/span&gt;  &lt;span class="kt"&gt;bool&lt;/span&gt;

    &lt;span class="n"&gt;MetricClosureApplied&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;Symmetric&lt;/span&gt;             &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="n"&gt;ApproximationRatio&lt;/span&gt;   &lt;span class="kt"&gt;float64&lt;/span&gt;

    &lt;span class="n"&gt;Iterations&lt;/span&gt;    &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;NodesExpanded&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Those fields are intentionally redundant with the solver choice. A caller should not have to reconstruct what happened from old options, log text, or a function name.&lt;/p&gt;

&lt;p&gt;A few valid states:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Exact&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Optimal&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;TimedOut&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;ApproximationRatio&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Held-Karp completed&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch-and-Bound completed&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch-and-Bound stopped by time limit&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Blossom&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Greedy&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2-opt / 3-opt&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Route one: six minutes of cold-chain margin
&lt;/h2&gt;

&lt;p&gt;The first runnable example is a six-stop symmetric metric travel-time matrix for vaccine distribution.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Algo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Christofides&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Symmetric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartVertex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchingAlgo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BlossomMatch&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableLocalSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The relevant output is short:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;route-minutes=114.0
formal-ratio=1.5
thermal-margin=6.0 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;114&lt;/code&gt; is empirical: it belongs to this matrix and this returned tour.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;1.5&lt;/code&gt; comes from a theorem, and it survives only if the whole Christofides contract survives.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhrtqon2hetoxf1g5lkgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhrtqon2hetoxf1g5lkgw.png" alt=" " width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;
Same outer pipeline, different matching policy. The proof obligation changes even when both paths return a valid tour.



&lt;p&gt;One caveat matters here: &lt;code&gt;v0.1.0&lt;/code&gt; documents &lt;strong&gt;metric input as a precondition&lt;/strong&gt;; it does not prove the triangle inequality for every arbitrary matrix before solving. Symmetry and completeness can be validated mechanically. Metricity may still be a domain fact the caller has to defend. If that assumption is not trustworthy, the downstream system should not present &lt;code&gt;1.5&lt;/code&gt; as an unconditional theorem.&lt;/p&gt;

&lt;p&gt;The load-bearing stage here is minimum-weight perfect matching on the odd-degree vertices of the MST.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lvlath/tsp&lt;/code&gt; exposes that choice directly:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;GreedyMatch&lt;/span&gt; &lt;span class="n"&gt;MatchingAlgo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;
    &lt;span class="n"&gt;BlossomMatch&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;BlossomMatch&lt;/code&gt; is exact MWPM. &lt;code&gt;GreedyMatch&lt;/code&gt; is deterministic and cheaper, but heuristic.&lt;/p&gt;

&lt;p&gt;So this is a valid explicit configuration:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Algo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Christofides&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Symmetric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MatchingAlgo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GreedyMatch&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableLocalSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApproximationRatio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// 0: no formal ratio claimed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There is no hidden "Blossom failed, quietly use Greedy" fallback. A failed stronger policy stays visible instead of returning weaker mathematics with stronger-looking metadata.&lt;/p&gt;
&lt;h2&gt;
  
  
  Route two: asymmetric cost is domain information
&lt;/h2&gt;

&lt;p&gt;The second example models armored cash-in-transit routing. Cost combines time, fuel, guard exposure, and interception risk, so &lt;code&gt;A -&amp;gt; B&lt;/code&gt; can legitimately differ from &lt;code&gt;B -&amp;gt; A&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The solver is directed 2-opt*:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Algo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TwoOptOnly&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Symmetric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartVertex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableLocalSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It returns:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;directed-risk-cost=34.0
exact=false
optimal=false
approximation-ratio=0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The result is a deterministic locally improved ATSP tour under the selected policy. &lt;code&gt;ApproximationRatio=0&lt;/code&gt; states the missing guarantee explicitly instead of leaving the caller to infer it from &lt;code&gt;Algorithm&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Route three: exact search can still return a non-optimal result
&lt;/h2&gt;

&lt;p&gt;The semiconductor example has five drilling sites and an offline planning stage, so Branch-and-Bound with a 1-tree lower bound is a sensible exact choice:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Algo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BranchAndBound&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Symmetric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartVertex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BoundAlgo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OneTreeBound&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableLocalSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The example completes with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;single-board-latency=16.8 ms
exact=true
optimal=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now add a wall-clock limit.&lt;/p&gt;

&lt;p&gt;Branch-and-Bound is still an exact algorithm, but an interrupted search has not completed the proof. &lt;code&gt;v0.1.0&lt;/code&gt; may return a non-nil incumbent together with &lt;code&gt;ErrTimeLimit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SolveMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tsp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrTimeLimit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"time limit without incumbent"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cost=%.3f exact=%v optimal=%v timedOut=%v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c"&gt;// true&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Optimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c"&gt;// false&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimedOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// true&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Exact&lt;/code&gt; describes the algorithm family. &lt;code&gt;Optimal&lt;/code&gt; describes what this invocation actually proved.&lt;/p&gt;

&lt;p&gt;That is a distinction a single &lt;code&gt;Success bool&lt;/code&gt; cannot encode.&lt;/p&gt;
&lt;h2&gt;
  
  
  180 runs: observed quality vs. formal proof
&lt;/h2&gt;

&lt;p&gt;For the article I generated &lt;strong&gt;30 deterministic Euclidean metric matrices&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;n = 8, 10, 12
10 fixed seeds per size
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Each matrix was solved by six policies, for &lt;strong&gt;180 solver runs&lt;/strong&gt;. Held-Karp supplied the exact-cost baseline. Before writing a CSV row, an independent harness checked that the returned witness was a closed Hamiltonian cycle, visited every matrix vertex once, used finite non-negative edges, and recomputed the published cost from the source matrix.&lt;/p&gt;

&lt;p&gt;I kept solution-quality measurements separate from &lt;code&gt;testing.B&lt;/code&gt;: &lt;code&gt;duration_ns&lt;/code&gt; in that CSV is diagnostic single-run timing, not benchmark evidence.&lt;/p&gt;

&lt;p&gt;Across all 30 matrices:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solver&lt;/th&gt;
&lt;th&gt;Median gap to exact&lt;/th&gt;
&lt;th&gt;Worst observed gap&lt;/th&gt;
&lt;th&gt;Matched exact cost&lt;/th&gt;
&lt;th&gt;What that proves&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Held-Karp&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;30 / 30&lt;/td&gt;
&lt;td&gt;exact baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch-and-Bound&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;30 / 30&lt;/td&gt;
&lt;td&gt;completed exact search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Blossom&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.059%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;12.234%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8/30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;empirical quality + formal 1.5 bound&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Greedy&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8.261%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;34.568%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5/30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;empirical quality only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2-opt&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.634%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;24/30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;empirical quality only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3-opt&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.222%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;27/30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;empirical quality only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51csu9jnt4kj4kmyri2f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51csu9jnt4kj4kmyri2f.png" alt=" " width="799" height="462"&gt;&lt;/a&gt;&lt;/p&gt;
Local search won the empirical hit-rate on these small fixtures; Christofides + Blossom retained the theorem.



&lt;p&gt;This is where the experiment gets uncomfortable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2-opt hit the exact optimum cost 24 times. Christofides + Blossom did it 8 times. Yet Christofides is the one allowed to publish a worst-case mathematical guarantee.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The apparent contradiction disappears once the two questions are separated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;How did this solver behave on these 30 fixtures?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;What can the algorithm prove outside this sample?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first is empirical evidence. The second is a theorem.&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  &lt;br&gt;
&lt;strong&gt;Observed quality and proof strength are different axes.&lt;/strong&gt;&lt;br&gt;

&lt;/div&gt;



&lt;p&gt;Treating "the route was close to the optimum in my benchmark" as a formal guarantee is benchmark-driven overfitting.&lt;/p&gt;

&lt;h3&gt;
  
  
  One matrix makes the distinction even sharper
&lt;/h3&gt;

&lt;p&gt;The equal-size benchmark used the same deterministic &lt;code&gt;n=10&lt;/code&gt;, seed-47 matrix for every solver. &lt;code&gt;testing.B&lt;/code&gt; measured only &lt;code&gt;SolveMatrix&lt;/code&gt;; fixture construction stayed outside the timed region.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solver&lt;/th&gt;
&lt;th&gt;Median time&lt;/th&gt;
&lt;th&gt;B/op&lt;/th&gt;
&lt;th&gt;allocs/op&lt;/th&gt;
&lt;th&gt;Gap on the same seed-47 matrix&lt;/th&gt;
&lt;th&gt;Published claim&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Held-Karp&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;313.6 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;172.1 KiB&lt;/td&gt;
&lt;td&gt;68&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;exact + proven optimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch-and-Bound&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;388.9 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;14.39 KiB&lt;/td&gt;
&lt;td&gt;197&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;exact + proven optimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Blossom&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;25.24 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;9.887 KiB&lt;/td&gt;
&lt;td&gt;158&lt;/td&gt;
&lt;td&gt;1.409%&lt;/td&gt;
&lt;td&gt;formal 1.5 approximation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Christofides + Greedy&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;16.26 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5.809 KiB&lt;/td&gt;
&lt;td&gt;96&lt;/td&gt;
&lt;td&gt;1.409%&lt;/td&gt;
&lt;td&gt;no formal ratio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2-opt&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7.008 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.562 KiB&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;heuristic; no proof of optimality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3-opt&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;37.60 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3.844 KiB&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;heuristic; no proof of optimality&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The CSV for that exact fixture records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Branch-and-Bound      cost=26037.596462281  nodes=3663  exact=true  optimal=true
2-opt                 cost=26037.596462281  iters=9     exact=false optimal=false
3-opt                 cost=26037.596462281  iters=0     exact=false optimal=false
Christofides/Blossom  cost=26404.536340990  ratio=1.5
Christofides/Greedy   cost=26404.536340990  ratio=0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The costs are identical, while the metadata differs because only the exact runs completed a proof of global optimality.&lt;/p&gt;

&lt;p&gt;The equal-&lt;code&gt;n&lt;/code&gt; table is a performance comparison for one fixed workload, not a universal solver ranking. That caveat matters: the permanent package benchmarks deliberately exercise very different regimes (&lt;code&gt;n=12&lt;/code&gt; Held-Karp, &lt;code&gt;n=14&lt;/code&gt; Branch-and-Bound, &lt;code&gt;n=200&lt;/code&gt; Christofides, &lt;code&gt;n=500&lt;/code&gt; 2-opt), so putting those permanent numbers into one "fastest TSP algorithm" chart would be nonsense.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the 1.5 guarantee cost here?
&lt;/h2&gt;

&lt;p&gt;The cleanest apples-to-apples regression pair in the package changes only the matching policy inside Christofides. Both use the same deterministic metric &lt;code&gt;n=200&lt;/code&gt; fixture. Local search is disabled.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Matching policy&lt;/th&gt;
&lt;th&gt;sec/op&lt;/th&gt;
&lt;th&gt;B/op&lt;/th&gt;
&lt;th&gt;allocs/op&lt;/th&gt;
&lt;th&gt;Formal ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Blossom exact MWPM&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;70.13 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.714 MiB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8,925&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1.5&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Greedy matching&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.655 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;450.4 KiB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1,401&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foluzcjjbhc14pqv0bp44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foluzcjjbhc14pqv0bp44.png" alt=" " width="799" height="412"&gt;&lt;/a&gt;&lt;/p&gt;
Same n=200 fixture and outer Christofides pipeline; only the matching policy changes.



&lt;p&gt;On this machine and fixture, the exact-matching pipeline is about &lt;strong&gt;26.4× slower&lt;/strong&gt;, uses &lt;strong&gt;6.2×&lt;/strong&gt; the bytes per operation, and performs &lt;strong&gt;6.4×&lt;/strong&gt; the allocations.&lt;/p&gt;

&lt;p&gt;This comparison is narrow enough to be useful: the outer algorithm, matrix family, size, and local-search setting stay fixed. The changed subroutine is also the one that carries the proof obligation.&lt;/p&gt;

&lt;p&gt;The isolated dense Blossom benchmark makes the growth visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;32 odd vertices   2.350 ms
64               12.36  ms
128              57.72  ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From 32 to 128 odd vertices, measured solve time increased about &lt;strong&gt;24.6×&lt;/strong&gt; on this workload.&lt;/p&gt;

&lt;p&gt;That does not make Greedy "better" or Blossom "slow". It tells me what the stronger matching policy costs in this implementation, on this machine, for these fixtures.&lt;/p&gt;

&lt;h2&gt;
  
  
  A claim-first way to choose the solver
&lt;/h2&gt;

&lt;p&gt;A size-only rule is too vague for exact TSP. &lt;code&gt;v0.1.0&lt;/code&gt; ships Held-Karp with a &lt;strong&gt;soft &lt;code&gt;MaxExactN&lt;/code&gt; guard whose default is 16&lt;/strong&gt;. Callers may raise that option, but the underlying cost remains &lt;code&gt;O(n²·2ⁿ)&lt;/code&gt; time and &lt;code&gt;O(n·2ⁿ)&lt;/code&gt; memory. Branch-and-Bound has no comparable fixed vertex cap; its worst case is exponential and its practical limit depends on the matrix, lower bound, incumbent quality, and wall-clock budget.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Start here&lt;/th&gt;
&lt;th&gt;Do not say&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Predictable exact DP and &lt;code&gt;n&lt;/code&gt; fits the configured &lt;code&gt;MaxExactN&lt;/code&gt; plus memory/time budget (default guard: 16)&lt;/td&gt;
&lt;td&gt;Held-Karp&lt;/td&gt;
&lt;td&gt;Raising &lt;code&gt;MaxExactN&lt;/code&gt; makes the exponential state space cheap.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global optimum required but Held-Karp's DP budget is unattractive; pruning may help and runtime may be instance-dependent&lt;/td&gt;
&lt;td&gt;Branch-and-Bound + explicit &lt;code&gt;TimeLimit&lt;/code&gt;; use an admissible bound&lt;/td&gt;
&lt;td&gt;A timeout incumbent is optimal.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Symmetric complete metric input; formal approximation bound required&lt;/td&gt;
&lt;td&gt;Christofides + Blossom&lt;/td&gt;
&lt;td&gt;Greedy matching keeps the 1.5 proof.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Locally optimal route required; global proof is unnecessary or computationally infeasible&lt;/td&gt;
&lt;td&gt;2-opt / 3-opt with explicit move limits&lt;/td&gt;
&lt;td&gt;Local optimum is global optimum.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Directed/asymmetric cost&lt;/td&gt;
&lt;td&gt;Held-Karp / Branch-and-Bound when exact search is feasible, otherwise directed local search&lt;/td&gt;
&lt;td&gt;Symmetrization is harmless cleanup.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing edges encoded as &lt;code&gt;+Inf&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Metric closure only when that transformation is valid for the domain&lt;/td&gt;
&lt;td&gt;Derived closure distances are original edges.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metric assumptions are unknown&lt;/td&gt;
&lt;td&gt;Validate them or publish no ratio&lt;/td&gt;
&lt;td&gt;Symmetry alone proves triangle inequality.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;
  Reproduction details
  &lt;p&gt;The benchmark output recorded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository's permanent regression benchmarks live in &lt;code&gt;tsp/bench_test.go&lt;/code&gt;. The equal-&lt;code&gt;n&lt;/code&gt; benchmark and the CSV quality harness were article-only local files; I ran them, kept the raw results, and did not add them to the library.&lt;/p&gt;

&lt;p&gt;Exact regression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 go &lt;span class="nb"&gt;test&lt;/span&gt; ./tsp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-run&lt;/span&gt; &lt;span class="s1"&gt;'^$'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="s1"&gt;'Benchmark(HeldKarp|BranchBound)'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="nt"&gt;-cpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10 &lt;span class="nt"&gt;-benchtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Practical regimes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 go &lt;span class="nb"&gt;test&lt;/span&gt; ./tsp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-run&lt;/span&gt; &lt;span class="s1"&gt;'^$'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="s1"&gt;'Benchmark(Christofides|TwoOpt|ThreeOpt)'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="nt"&gt;-cpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10 &lt;span class="nt"&gt;-benchtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Blossom regression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 go &lt;span class="nb"&gt;test&lt;/span&gt; ./tsp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-run&lt;/span&gt; &lt;span class="s1"&gt;'^$'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-bench&lt;/span&gt; &lt;span class="s1"&gt;'BenchmarkBlossom'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-benchmem&lt;/span&gt; &lt;span class="nt"&gt;-cpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10 &lt;span class="nt"&gt;-benchtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For strict reproduction, publish the exact commit SHA alongside the raw benchmark files. The Go version was not present in the benchmark outputs I kept, so I would not invent it after the fact.&lt;/p&gt;



&lt;br&gt;
&lt;p&gt;&lt;/p&gt;

&lt;p&gt;There was no single winner in these fixtures. Local search often matched the exact optimum cost; Christofides carried the stronger worst-case statement; exact methods were the only ones allowed to set &lt;code&gt;Optimal=true&lt;/code&gt;. The benchmark and the theorem ranked the same solvers differently.&lt;/p&gt;

&lt;p&gt;If a caller cannot distinguish &lt;strong&gt;proven&lt;/strong&gt;, &lt;strong&gt;bounded&lt;/strong&gt;, &lt;strong&gt;timed out&lt;/strong&gt;, and merely &lt;strong&gt;good on this run&lt;/strong&gt;, the solver is hiding state it already knows.&lt;/p&gt;

&lt;p&gt;Code and contracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lvlath/go/tree/v0.1.0/tsp" rel="noopener noreferrer"&gt;TSP package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lvlath/go/blob/v0.1.0/tsp/example_test.go" rel="noopener noreferrer"&gt;Runnable scenarios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pkg.go.dev/github.com/lvlath/go@v0.1.0/tsp" rel="noopener noreferrer"&gt;Go Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lvlath/go/blob/v0.1.0/docs/TSP.md" rel="noopener noreferrer"&gt;Long-form TSP documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>algorithms</category>
      <category>opensource</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>Top Benefits of Learning Generative AI &amp; Data Science Course in Telugu</title>
      <dc:creator>Trinayan SriPrasan</dc:creator>
      <pubDate>Thu, 13 Aug 2026 10:09:15 +0000</pubDate>
      <link>https://dev.to/trinayan_sriprasan_eb5c27/top-benefits-of-learning-generative-ai-data-science-course-in-telugu-554n</link>
      <guid>https://dev.to/trinayan_sriprasan_eb5c27/top-benefits-of-learning-generative-ai-data-science-course-in-telugu-554n</guid>
      <description>&lt;p&gt;Generative AI and data science are shaping how organizations analyze information, automate processes, develop digital products, and make decisions. Learning these technologies together can provide students and professionals with a broader understanding of modern data-driven systems. A &lt;strong&gt;&lt;a href="https://courses.frontlinesedutech.com/generative-ai-data-science-course-telugu/?utm_source=Gayathri&amp;amp;utm_medium=Off+page&amp;amp;utm_campaign=articale_submission_August26" rel="noopener noreferrer"&gt;Generative AI &amp;amp; Data Science Course in Telugu&lt;/a&gt;&lt;/strong&gt; can make this learning journey more accessible by explaining technical concepts through a familiar language while gradually introducing practical tools and industry applications. For beginners as well as professionals looking to expand their technical knowledge, this combination can create a useful foundation for exploring several areas of technology.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build Knowledge Across Two Connected Fields&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Data science and generative AI may have different applications, but they share an important foundation: data. Data science focuses on extracting insights, identifying patterns, and supporting decisions, while generative AI uses learned patterns to produce new content or assist with intelligent tasks.&lt;br&gt;
Learning both areas together can help students understand how data moves from collection and preparation to analysis and intelligent application. This broader perspective can be useful when working on projects that involve both analytical and AI-based components.&lt;br&gt;
Instead of seeing these technologies as isolated subjects, learners can understand how they complement each other within modern digital workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Develop Practical Data Analysis Skills&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Data analysis is an essential part of data science. Learners can develop the ability to examine datasets, identify trends, calculate useful metrics, and interpret results.&lt;br&gt;
Working with real datasets can help students understand why raw information needs to be cleaned and organized before meaningful conclusions can be drawn. They can also learn how analytical findings can support business questions related to customers, sales, operations, and performance.&lt;br&gt;
These capabilities provide a foundation that can remain valuable even as new AI technologies continue to emerge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gain Exposure to Generative AI Applications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the major advantages of studying generative AI is exposure to technologies capable of producing text, images, code, summaries, and other forms of content.&lt;br&gt;
Learners can explore how these systems are being used for content assistance, document processing, software development, research support, customer communication, and workflow automation.&lt;br&gt;
Understanding practical applications can help students recognize where generative AI can provide value and where human judgment remains necessary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn Python for Modern Technology Work&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python is widely associated with data analysis, machine learning, and AI development. Learning Python alongside data science concepts can help students develop a versatile technical foundation.&lt;br&gt;
Beginners can start with programming fundamentals before moving toward libraries used for data manipulation, visualization, and machine learning.&lt;br&gt;
A Generative AI &amp;amp; Data Science Course in Telugu can introduce Python progressively, helping learners understand how programming contributes to different stages of analytical and AI workflows rather than treating coding as a separate topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improve Analytical Thinking&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Working with data encourages learners to think logically and evaluate evidence before reaching conclusions. Instead of accepting information at face value, students can learn to examine patterns, compare results, and investigate unusual observations.&lt;br&gt;
This analytical mindset is useful beyond technical assignments. It can support better decision-making when working with business information, AI-generated outputs, and other technology-driven processes.&lt;br&gt;
Learning to ask the right questions is often just as important as knowing which tool to use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understand Machine Learning Fundamentals&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Machine learning provides an important bridge between data science and artificial intelligence. Students can learn how algorithms identify patterns in historical information and use those patterns for prediction or classification.&lt;br&gt;
Understanding concepts such as training datasets, features, model evaluation, and predictions can prepare learners for more advanced AI topics.&lt;br&gt;
These fundamentals also help students understand why data quality, feature selection, and model evaluation are important when developing intelligent systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explore Data Visualization and Storytelling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Data visualization helps transform complex datasets into understandable graphical representations. Learners can use charts, reports, and dashboards to communicate important findings.&lt;br&gt;
The ability to explain what the data means is valuable because analytical results often need to be shared with managers, clients, or other non-technical stakeholders.&lt;br&gt;
Combining visualization with analytical reasoning can help learners move beyond simply calculating numbers and focus on communicating useful information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengthen Problem-Solving Abilities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Data science and generative AI involve solving problems where the solution may not always be obvious. Learners can practice breaking broad challenges into smaller tasks, identifying relevant information, testing possible approaches, and evaluating outcomes.&lt;br&gt;
For example, a business may want to understand why customer engagement is declining. An analyst needs to determine which data can help investigate the issue and which analytical methods are appropriate.&lt;br&gt;
These problem-solving habits can support learners across many technical and professional situations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gain Experience with Real-World Projects&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Practical projects allow students to combine multiple concepts within a single assignment. A project may involve preparing a dataset, analyzing information, creating visualizations, and exploring how an AI system could assist with a related task.&lt;br&gt;
Project work can also help learners understand the complete workflow instead of learning each technology separately.&lt;br&gt;
A Generative AI &amp;amp; Data Science Course in Telugu that includes practical projects can give students opportunities to apply their knowledge to realistic scenarios and gradually build confidence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Develop Career Versatility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Learning data science and generative AI together can expose learners to multiple areas of technology. Depending on their interests, they may later explore data analysis, machine learning, AI applications, business intelligence, automation, or related fields.&lt;br&gt;
This broader knowledge can help learners understand where their strengths and interests are strongest.&lt;br&gt;
Career development also becomes easier when students have a foundation that allows them to adapt to changing technologies instead of depending entirely on one tool or platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build a Stronger Professional Portfolio&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Projects completed during training can become valuable portfolio material. Learners can demonstrate how they approached a problem, prepared information, performed analysis, and applied AI concepts where appropriate.&lt;br&gt;
A portfolio that explains the reasoning behind each project can be more informative than simply displaying final screenshots. It can show how technical skills were used to produce meaningful outcomes.&lt;br&gt;
This type of practical evidence can also help learners prepare for interviews and professional discussions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn Through a Familiar Language&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Technical subjects can become easier to understand when complex ideas are explained in a language the learner is comfortable with. Telugu-based instruction can help beginners focus on the underlying concept without being overwhelmed by unfamiliar explanations.&lt;br&gt;
At the same time, learners can gradually become familiar with English terminology used in programming, data science, and AI environments.&lt;br&gt;
This approach can provide a comfortable starting point while still supporting the development of professional technical vocabulary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prepare for Continuous Technology Growth&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Generative AI and data science are rapidly evolving fields. New models, tools, frameworks, and applications continue to emerge, making continuous learning important.&lt;br&gt;
A strong foundation allows learners to evaluate new technologies more effectively because they understand the basic principles behind data analysis and AI systems.&lt;br&gt;
The goal is not simply to learn what is popular today but to develop the ability to understand and adapt to technologies introduced in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Learning generative AI and data science together can provide several advantages, from improving analytical thinking and programming skills to developing practical knowledge of machine learning, visualization, automation, and intelligent applications. This combination can help learners understand how data supports modern AI systems and business decisions.&lt;br&gt;
A Generative AI &amp;amp; Data Science Course in Telugu can offer an accessible pathway for students and professionals who want to develop these capabilities through structured learning. By combining foundational concepts with practical projects and real-world applications, learners can build a versatile technical foundation and prepare themselves for continued growth in the evolving fields of data science and artificial intelligence. &lt;/p&gt;

</description>
      <category>generativeai</category>
      <category>datasciencecourseintelugu</category>
      <category>machinelearning</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>How Cloud Infrastructure Is Transforming Machine Learning for Modern Businesses</title>
      <dc:creator>Agami Technologies</dc:creator>
      <pubDate>Thu, 13 Aug 2026 09:33:02 +0000</pubDate>
      <link>https://dev.to/agami_tech_414cabb7522ea1/how-cloud-infrastructure-is-transforming-machine-learning-for-modern-businesses-5d9c</link>
      <guid>https://dev.to/agami_tech_414cabb7522ea1/how-cloud-infrastructure-is-transforming-machine-learning-for-modern-businesses-5d9c</guid>
      <description>&lt;p&gt;Technology has changed dramatically over the past decade.&lt;/p&gt;

&lt;p&gt;Businesses are collecting more information than ever before. Customer interactions, sales transactions, website activity, operational data, and market insights are being generated every second.&lt;/p&gt;

&lt;p&gt;The challenge isn't collecting information.&lt;/p&gt;

&lt;p&gt;The challenge is processing it efficiently.&lt;/p&gt;

&lt;p&gt;This is one reason why cloud infrastructure has become an essential part of modern machine learning systems.&lt;/p&gt;

&lt;p&gt;Organizations can no longer rely on traditional environments to support growing data requirements. They need flexible, scalable, and reliable infrastructure that can adapt as business demands evolve.&lt;/p&gt;

&lt;p&gt;Cloud computing has made that possible.&lt;/p&gt;

&lt;p&gt;Why Traditional Infrastructure Creates Limitations&lt;/p&gt;

&lt;p&gt;Many companies still operate with systems that were designed years ago.&lt;/p&gt;

&lt;p&gt;These environments often struggle to support large-scale data processing because they were never built for modern analytical workloads.&lt;/p&gt;

&lt;p&gt;Some common challenges include:&lt;/p&gt;

&lt;p&gt;Limited storage capacity&lt;br&gt;
Slow processing speeds&lt;br&gt;
High maintenance costs&lt;br&gt;
Difficulty scaling resources&lt;br&gt;
Manual deployment processes&lt;/p&gt;

&lt;p&gt;As businesses continue to grow, these limitations become more noticeable.&lt;/p&gt;

&lt;p&gt;Teams spend more time maintaining infrastructure and less time focusing on innovation.&lt;/p&gt;

&lt;p&gt;This is where cloud-based environments create a significant advantage.&lt;br&gt;
**&lt;br&gt;
Scalability Has Become a Business Requirement**&lt;/p&gt;

&lt;p&gt;One of the biggest benefits of cloud computing is scalability.&lt;/p&gt;

&lt;p&gt;Businesses no longer need to purchase expensive hardware before launching new projects.&lt;/p&gt;

&lt;p&gt;Instead, they can increase or decrease computing resources according to demand.&lt;/p&gt;

&lt;p&gt;This approach offers several advantages:&lt;/p&gt;

&lt;p&gt;Better resource management&lt;br&gt;
Reduced operational costs&lt;br&gt;
Faster deployment&lt;br&gt;
Improved flexibility&lt;br&gt;
Greater efficiency&lt;/p&gt;

&lt;p&gt;Organizations can start with smaller implementations and gradually expand their infrastructure as requirements increase.&lt;/p&gt;

&lt;p&gt;This reduces financial risk while creating opportunities for growth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Faster Deployment Improves Business Agility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Speed has become a competitive advantage.&lt;/p&gt;

&lt;p&gt;Companies that can adapt quickly are often better positioned to respond to changing market conditions.&lt;/p&gt;

&lt;p&gt;Cloud platforms simplify deployment by allowing development teams to automate many processes that previously required manual intervention.&lt;/p&gt;

&lt;p&gt;Modern development environments commonly rely on:&lt;/p&gt;

&lt;p&gt;Continuous integration&lt;br&gt;
Automated testing&lt;br&gt;
Continuous deployment&lt;br&gt;
Infrastructure automation&lt;br&gt;
Performance monitoring&lt;/p&gt;

&lt;p&gt;These practices allow teams to release updates more efficiently while reducing the possibility of human error.&lt;/p&gt;

&lt;p&gt;As a result, businesses can deliver improvements faster without compromising stability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Processing Requires Flexible Infrastructure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern applications generate enormous amounts of information.&lt;/p&gt;

&lt;p&gt;Managing that data requires systems that can process information efficiently while maintaining reliability.&lt;/p&gt;

&lt;p&gt;Cloud environments make it possible to:&lt;/p&gt;

&lt;p&gt;Store large datasets&lt;br&gt;
Process information in real time&lt;br&gt;
Support multiple applications simultaneously&lt;br&gt;
Improve system availability&lt;br&gt;
Maintain consistent performance&lt;/p&gt;

&lt;p&gt;This flexibility is particularly important for businesses that rely on predictive technologies and analytical applications.&lt;/p&gt;

&lt;p&gt;Without scalable infrastructure, maintaining performance becomes increasingly difficult.&lt;br&gt;
**&lt;br&gt;
Security Should Always Be a Priority**&lt;/p&gt;

&lt;p&gt;Technology adoption brings new challenges.&lt;/p&gt;

&lt;p&gt;As organizations process larger amounts of information, security becomes even more important.&lt;/p&gt;

&lt;p&gt;Businesses must protect customer records, financial information, operational data, and other sensitive assets.&lt;/p&gt;

&lt;p&gt;Strong security practices often include:&lt;/p&gt;

&lt;p&gt;Access controls&lt;br&gt;
Data encryption&lt;br&gt;
User authentication&lt;br&gt;
Continuous monitoring&lt;br&gt;
Secure data pipelines&lt;/p&gt;

&lt;p&gt;Security should never be treated as an afterthought.&lt;/p&gt;

&lt;p&gt;It should be incorporated into every stage of development.&lt;/p&gt;

&lt;p&gt;Organizations that prioritize security are better prepared to manage risk while maintaining customer trust.&lt;br&gt;
**&lt;br&gt;
Technology Works Best When Teams Work Together**&lt;/p&gt;

&lt;p&gt;Infrastructure alone cannot guarantee success.&lt;/p&gt;

&lt;p&gt;Strong collaboration remains one of the most important factors in any technology project.&lt;/p&gt;

&lt;p&gt;Successful organizations rely on multiple specialists, including:&lt;/p&gt;

&lt;p&gt;Data engineers&lt;br&gt;
Software developers&lt;br&gt;
Operations teams&lt;br&gt;
Business analysts&lt;br&gt;
Technology leaders&lt;/p&gt;

&lt;p&gt;Each team contributes unique expertise that helps transform technical ideas into practical business solutions.&lt;/p&gt;

&lt;p&gt;When collaboration becomes part of the process, projects are more likely to achieve long-term success.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cloud infrastructure has transformed the way businesses develop and deploy modern applications.&lt;/p&gt;

&lt;p&gt;Scalability, automation, flexibility, and security have become essential requirements rather than optional features.&lt;/p&gt;

&lt;p&gt;Organizations that invest in strong infrastructure will be better prepared to support future growth and adapt to changing business demands.&lt;/p&gt;

&lt;p&gt;If you'd like to explore enterprise frameworks, deployment strategies, and implementation best practices, you can read this detailed guide on &lt;a href="https://agamitechnologies.com/blog/machine-learning-tools-ml-solutions" rel="noopener noreferrer"&gt;machine learning tools and solutions&lt;/a&gt; from Agami Technologies.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>cloudcomputing</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>Quantization and Pruning of Models</title>
      <dc:creator>Aviral Srivastava</dc:creator>
      <pubDate>Thu, 13 Aug 2026 08:09:30 +0000</pubDate>
      <link>https://dev.to/godofgeeks/quantization-and-pruning-of-models-2knc</link>
      <guid>https://dev.to/godofgeeks/quantization-and-pruning-of-models-2knc</guid>
      <description>&lt;h2&gt;
  
  
  Shrinking Giants: How Quantization and Pruning Make AI Models Lean and Mean
&lt;/h2&gt;

&lt;p&gt;Hey there, fellow tech enthusiasts and AI aficionados! Ever marveled at the sheer power and intelligence of those giant AI models like ChatGPT or Midjourney? They can write essays, conjure stunning images, and even code for you. But have you ever stopped to think about the enormous computational muscle and memory they need to perform their magic? It's like having a supercomputer in your pocket – not exactly practical for your smartphone or even most laptops.&lt;/p&gt;

&lt;p&gt;This is where the superheroes of model optimization, &lt;strong&gt;Quantization&lt;/strong&gt; and &lt;strong&gt;Pruning&lt;/strong&gt;, swoop in to save the day! These techniques are like giving your AI models a rigorous workout and a healthy diet, making them smaller, faster, and more efficient without sacrificing too much of their brainpower.&lt;/p&gt;

&lt;p&gt;So, buckle up, because we're about to dive deep into the fascinating world of shrinking these AI giants.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Why" Behind the Shrink: Why Bother?
&lt;/h3&gt;

&lt;p&gt;Imagine you've trained a magnificent AI model, a digital masterpiece. It's incredibly accurate, but it's also a behemoth. It requires a powerful GPU, loads of RAM, and takes ages to run inference (that's just a fancy word for making predictions or generating output). This is a problem for several reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Deployment on Edge Devices:&lt;/strong&gt; Think smartphones, smartwatches, IoT devices in your home, or even sensors on a factory floor. These devices have limited processing power, memory, and battery life. A giant model is a non-starter.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Faster Inference:&lt;/strong&gt; In real-time applications like self-driving cars, voice assistants, or even responsive web applications, every millisecond counts. Smaller, more efficient models lead to quicker responses.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Reduced Costs:&lt;/strong&gt; Running large models on cloud infrastructure incurs significant costs for compute and storage. Shrinking them can lead to substantial savings.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Energy Efficiency:&lt;/strong&gt; Less computation means less power consumption, which is crucial for battery-powered devices and for reducing the environmental impact of AI.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Accessibility:&lt;/strong&gt; Making AI models accessible on more devices democratizes their use and allows for wider adoption.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Training Ground: What You Need to Know Before We Start
&lt;/h3&gt;

&lt;p&gt;Before we get our hands dirty with quantization and pruning, it's helpful to have a basic understanding of how neural networks work.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Weights and Biases:&lt;/strong&gt; These are the numerical parameters within a neural network that the model learns during training. They essentially dictate how the model processes information.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Floating-Point Numbers:&lt;/strong&gt; Typically, these weights and biases are stored as 32-bit floating-point numbers (FP32). These offer high precision but take up a lot of memory.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Inference:&lt;/strong&gt; This is the process of using a trained model to make predictions or generate outputs on new, unseen data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like this: A neural network is a complex recipe. The ingredients are the input data, and the instructions (the weights and biases) tell the chef (the network) how to combine them to create a delicious dish (the output).&lt;/p&gt;

&lt;h3&gt;
  
  
  Quantization: Trading Precision for Size
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Quantization&lt;/strong&gt; is like taking a high-resolution photograph and compressing it into a JPEG. You might lose a tiny bit of detail, but the file size shrinks dramatically, making it much easier to store and share.&lt;/p&gt;

&lt;p&gt;In the context of AI, quantization involves reducing the precision of the numbers used to represent the model's weights and biases. Instead of using 32-bit floating-point numbers (FP32), we might use 16-bit floating-point numbers (FP16), 8-bit integers (INT8), or even fewer bits!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Does it Work Under the Hood?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you have a range of numbers representing your weights, say from -10.5 to +10.5.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;FP32:&lt;/strong&gt; This range is represented with a lot of decimal places, giving you very fine-grained control.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;INT8:&lt;/strong&gt; Now, imagine you map this entire range to only 256 possible integer values (from 0 to 255, or -128 to 127). Each integer value then corresponds to a specific range of original FP32 values. This drastically reduces the memory footprint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Types of Quantization:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Post-Training Quantization (PTQ):&lt;/strong&gt; This is the simplest approach. You train your model as usual using FP32, and then, &lt;em&gt;after&lt;/em&gt; training, you convert its weights to a lower precision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Dynamic Quantization:&lt;/strong&gt; This is the easiest form of PTQ. Weights are quantized offline, but activations (the intermediate outputs of neurons) are quantized dynamically during inference. This offers good speedups with minimal accuracy loss.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Static Quantization:&lt;/strong&gt; This is more involved. You need a "calibration dataset" (a small, representative subset of your training data) to determine the ranges of activations. This allows both weights and activations to be quantized beforehand, leading to even greater speedups.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quantization-Aware Training (QAT):&lt;/strong&gt; This is a more advanced technique where you &lt;em&gt;simulate&lt;/em&gt; the effects of quantization &lt;em&gt;during&lt;/em&gt; the training process. The model learns to be robust to the reduced precision from the start. This often yields the best accuracy for quantized models.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Code Snippet Example (PyTorch - Post-Training Dynamic Quantization):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.nn&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.quantization&lt;/span&gt;

&lt;span class="c1"&gt;# Assume 'model' is your pre-trained FP32 PyTorch model
# Example:
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleNN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimpleNN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fc1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ReLU&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fc2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fc1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fc2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleNN&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Load your trained weights here if you have them
# model.load_state_dict(torch.load('your_model_weights.pth'))
&lt;/span&gt;
&lt;span class="c1"&gt;# --- Post-Training Dynamic Quantization ---
&lt;/span&gt;&lt;span class="n"&gt;quantized_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quantization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;quantize_dynamic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;# Quantize only Linear layers
&lt;/span&gt;    &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;qint8&lt;/span&gt;  &lt;span class="c1"&gt;# Target data type (8-bit integer)
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Now you can use 'quantized_model' for faster inference
# Example inference:
&lt;/span&gt;&lt;span class="n"&gt;dummy_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;quantized_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dummy_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Quantized model output:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Advantages of Quantization:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Reduced Model Size:&lt;/strong&gt; Significantly less memory required.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Faster Inference:&lt;/strong&gt; Operations on lower-precision numbers are generally faster.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Lower Power Consumption:&lt;/strong&gt; Less computation means less energy.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Easier Deployment:&lt;/strong&gt; Enables models on resource-constrained devices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages of Quantization:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Potential Accuracy Loss:&lt;/strong&gt; Reducing precision can lead to a decrease in model accuracy, especially with aggressive quantization (e.g., below INT8).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Requires Careful Tuning:&lt;/strong&gt; Finding the right balance between size, speed, and accuracy can be tricky.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Hardware Support:&lt;/strong&gt; Not all hardware architectures are optimized for all types of quantized operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pruning: Trimming the Fat from the Model
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pruning&lt;/strong&gt; is like giving your AI model a haircut. You identify the parts of the network that aren't contributing much to the final output and simply snip them away. This can involve removing individual weights, neurons, or even entire layers.&lt;/p&gt;

&lt;p&gt;The intuition here is that not all connections and neurons in a neural network are equally important. Some might have very small weights, meaning they have a negligible impact on the overall computation. Pruning focuses on identifying and eliminating these "redundant" components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Does it Work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The core idea is to measure the "importance" of a weight or neuron and then remove those deemed least important.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Identify Importance:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Magnitude Pruning:&lt;/strong&gt; This is the simplest method. Weights with absolute values below a certain threshold are considered less important and are pruned.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Gradient-Based Pruning:&lt;/strong&gt; This involves analyzing the gradients of weights during training to understand their impact on the loss function.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Hessian-Based Pruning:&lt;/strong&gt; More sophisticated methods that use second-order derivatives to assess importance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pruning Strategy:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Unstructured Pruning:&lt;/strong&gt; Individual weights are removed anywhere in the network. This can lead to very sparse matrices, which can be tricky for hardware to accelerate efficiently.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Structured Pruning:&lt;/strong&gt; Entire neurons, filters, or channels are removed. This maintains a more regular structure, making it easier for hardware to exploit the sparsity.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fine-tuning (Crucial Step!):&lt;/strong&gt; After pruning, the model's performance often degrades. To recover accuracy, the pruned model is typically fine-tuned on the training data. This allows the remaining weights to adjust and compensate for the removed components.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Code Snippet Example (PyTorch - Unstructured Magnitude Pruning):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.nn&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.nn.utils.prune&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;prune&lt;/span&gt;

&lt;span class="c1"&gt;# Assume 'model' is your pre-trained FP32 PyTorch model
# Example:
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleNN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimpleNN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fc1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ReLU&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fc2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fc1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fc2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleNN&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Load your trained weights here if you have them
# model.load_state_dict(torch.load('your_model_weights.pth'))
&lt;/span&gt;
&lt;span class="c1"&gt;# --- Unstructured Magnitude Pruning ---
# Define which layers to prune and the pruning method
&lt;/span&gt;&lt;span class="n"&gt;parameters_to_prune&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fc1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fc2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Apply pruning: prune 50% of the weights with the smallest magnitudes
&lt;/span&gt;&lt;span class="n"&gt;prune&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;global_unstructured&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;parameters_to_prune&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pruning_method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prune&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;L1Unstructured&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Prune 50% of the weights
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# To make the pruning permanent (remove the zeroed weights from memory)
# and remove the pruning reparameterization:
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parameters_to_prune&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;prune&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Now you can use the pruned model for inference and fine-tuning
# Example inference:
&lt;/span&gt;&lt;span class="n"&gt;dummy_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dummy_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pruned model output:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# You would then fine-tune this pruned model to recover accuracy
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Advantages of Pruning:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Reduced Model Size:&lt;/strong&gt; By removing unnecessary parameters.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Faster Inference:&lt;/strong&gt; Fewer computations to perform.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Potentially Improved Generalization:&lt;/strong&gt; Removing redundant parameters can sometimes prevent overfitting.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Reduced Memory Footprint:&lt;/strong&gt; Less storage needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages of Pruning:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Accuracy Degradation:&lt;/strong&gt; If too much is pruned, accuracy can suffer significantly.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Irregular Sparsity:&lt;/strong&gt; Unstructured pruning can lead to sparse weight matrices that are not efficiently handled by all hardware.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Computational Overhead of Pruning:&lt;/strong&gt; The process of identifying and pruning can itself be computationally intensive.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Requires Fine-tuning:&lt;/strong&gt; Usually, fine-tuning is necessary to regain lost accuracy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Dynamic Duo: Quantization and Pruning Together
&lt;/h3&gt;

&lt;p&gt;The real magic often happens when you combine &lt;strong&gt;Quantization&lt;/strong&gt; and &lt;strong&gt;Pruning&lt;/strong&gt;. These techniques are not mutually exclusive; they can complement each other beautifully.&lt;/p&gt;

&lt;p&gt;Imagine a model that has been pruned to remove a significant portion of its less important weights. Now, you can further reduce its size and speed by quantizing the remaining weights. This synergistic approach can lead to models that are dramatically smaller and faster, often with minimal impact on accuracy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Prune then Quantize:&lt;/strong&gt; This is a common approach. First, you prune the model to remove redundant connections, and then you quantize the remaining, more important weights.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Quantize then Prune:&lt;/strong&gt; Less common, but sometimes you might quantize first and then prune based on the quantized values.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Joint Optimization:&lt;/strong&gt; More advanced methods aim to optimize both pruning and quantization simultaneously during training.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When to Use Which (or Both)?
&lt;/h3&gt;

&lt;p&gt;The choice between quantization, pruning, or a combination depends heavily on your specific use case and constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Edge Deployment with Strict Memory Limits:&lt;/strong&gt; &lt;strong&gt;Quantization&lt;/strong&gt; (especially INT8) is often the first go-to. If accuracy is still an issue, consider &lt;strong&gt;Quantization-Aware Training&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Need for Maximum Speedup on Powerful Hardware:&lt;/strong&gt; &lt;strong&gt;Pruning&lt;/strong&gt; (especially structured pruning) can be very effective, often followed by quantization.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Balance of Size, Speed, and Accuracy:&lt;/strong&gt; A combination of both techniques, possibly with &lt;strong&gt;Quantization-Aware Training&lt;/strong&gt; and careful fine-tuning, will likely yield the best results.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Resource-Constrained Development Environment:&lt;/strong&gt; &lt;strong&gt;Post-Training Quantization&lt;/strong&gt; is a great starting point for quick wins.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Future is Lean and Mean
&lt;/h3&gt;

&lt;p&gt;Quantization and pruning are no longer niche techniques; they are becoming essential tools in the AI developer's arsenal. As AI models continue to grow in complexity and power, the ability to make them efficient and deployable on a wider range of devices will be paramount.&lt;/p&gt;

&lt;p&gt;These techniques are not just about making AI smaller; they're about making it more accessible, more sustainable, and more impactful. So, the next time you marvel at an AI's capabilities on your phone, remember the unsung heroes – quantization and pruning – that made it all possible. They are the silent architects of the efficient AI revolution, transforming monstrous models into nimble, intelligent companions.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>deeplearning</category>
      <category>llm</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Claude Code Skill Market Gini Hits 0.96</title>
      <dc:creator>gentic news</dc:creator>
      <pubDate>Thu, 13 Aug 2026 04:26:28 +0000</pubDate>
      <link>https://dev.to/gentic_news/claude-code-skill-market-gini-hits-096-1379</link>
      <guid>https://dev.to/gentic_news/claude-code-skill-market-gini-hits-096-1379</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Claude Code skill adoption is a winner-take-all market (Gini 0.96). Top 1% hold 77.4% of installs; median skill gets 56. Publish niche, bundle skills, or target the fast-growing interrogation category (grill-me: 787K installs).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code skill adoption is a winner-take-all market (Gini 0.96).&lt;/li&gt;
&lt;li&gt;Top 1% hold 77.4% of installs; median skill gets 56.&lt;/li&gt;
&lt;li&gt;Publish niche, bundle skills, or target the fast-growing interrogation category (grill-me: 787K installs).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Changed — The Agent Economy Census, August 2026
&lt;/h2&gt;

&lt;p&gt;On 2026-08-09, Skillselion dumped its entire production catalog: 79,827 public listings covering agent skills, MCP servers, plugins, and marketplaces — 157,833,061 cumulative installs. They then ran the Gini coefficient (the economic inequality metric) across the 58,751 listings that are agent skills.&lt;/p&gt;

&lt;p&gt;The result: &lt;strong&gt;0.96&lt;/strong&gt;. That's not a typo. South Africa's income Gini is 0.63. Brazil's is 0.52. A 0.96 is closer to a raffle than a market.&lt;/p&gt;

&lt;p&gt;For Claude Code users, this isn't abstract. The skills you install — or publish — live in this distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Means For You — The Numbers That Matter
&lt;/h2&gt;

&lt;p&gt;Here's what 0.96 looks like from the inside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Half of all 158M installs go to just 198 skills&lt;/strong&gt; — that's 0.34% of the catalog.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The median skill has 56 installs.&lt;/strong&gt; Not 5,600. Fifty-six.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;59.3% have fewer than 100 installs. 9.9% have zero.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The top 1% hold 77.4% of every install.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What does this mean for your daily Claude Code workflow? When you install a skill, you're almost certainly pulling from that top 1%. When you publish one, you're entering a lottery where the median outcome is effectively zero.&lt;/p&gt;

&lt;p&gt;But there's a second, more actionable layer: &lt;strong&gt;the fastest-growing category in the entire census is interrogation skills&lt;/strong&gt; — tools that argue with you and grill your code. The cluster of 88 skills reached 2,425,925 installs and is growing at +160%, the #1 rising search in the platform.&lt;/p&gt;

&lt;p&gt;Top interrogation skills:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;grill-me&lt;/strong&gt;: 787,155 installs (mattpocock/skills)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;grill-with-docs&lt;/strong&gt;: 669,499 installs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;triage&lt;/strong&gt;: 534,688 installs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;grilling&lt;/strong&gt;: 380,693 installs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Matt Pocock — an independent TypeScript educator — sits at #3 overall, above Vercel Labs, Anthropic, Google, and AWS combined. He's also the author of the top interrogation skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Now — How to Compete in a 0.96 Market
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhwvgpaqhmhl7epij1qhb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhwvgpaqhmhl7epij1qhb.png" alt="From AI to Financial Intelligence: How to Connect Claude to Real Market ..." width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install an interrogation skill today.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're not using grill-me or a similar skill, you're missing the fastest-growing workflow in the ecosystem. It's the #1 rising search for a reason: developers want their Claude Code agent to challenge assumptions, not just execute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# From mattpocock/skills repo&lt;/span&gt;
claude &lt;span class="nt"&gt;--add-skill&lt;/span&gt; grill-me
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. If you publish skills, bundle them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ByteDance's Lark/Feishu suite holds 15.4% of all installs — but they're installed as bundles. One user action installs several skills at once, and each gets counted separately. This is the single biggest lever in the census for boosting install counts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Target a niche, not a generalist audience.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The median skill has 56 installs. Skills that automate work reporting — standups, meeting notes, status reports — collectively hit 1,889,988 installs across 111 skills. Meeting summary, inbox triage, and resume tailoring are proven categories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Don't read your numbers as a verdict.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are cumulative all-time totals. Anything published this week starts from zero against a field that's been accumulating for months. The median skill has 56 installs, so if you're below that, you're not failing — you're average.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Consider charging.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of 79,827 listings, only 55 carry a price (0.07%). If you build something genuinely useful, you'd be one of 55. The market hasn't built a paid tier yet — that's an opportunity, not a barrier.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;The agent skill economy is brutally unequal. But the census also shows that a single independent developer with TypeScript education skills can outrank Google and OpenAI. The market rewards what developers actually install, not what companies fund.&lt;/p&gt;

&lt;p&gt;If you want to win: build interrogation tools, bundle your skills, target the work-reporting niche, and don't expect overnight adoption. The median is 56 installs — beat that and you're in the top 40%.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Full methodology and raw CSV available at Skillselion's Agent Economy Census.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://dev.to/skillselion/we-ran-the-gini-coefficient-on-58751-ai-agent-skills-it-came-out-at-096-2d40"&gt;dev.to&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[Updated 12 Aug via devto_claudecode]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Design skills are now surging alongside interrogation tools. On 2026-08-12, Skillselion reported that four of the seven fastest-rising Claude Code skill searches are design-focused (Ui Ux Pro Max, Frontend Design, Impeccable, Design Taste Frontend), collectively holding 1,659,726 installs and growing +20% to +70%. Anthropic's own Frontend Design leads with 767,871 installs, explicitly aimed at avoiding "templated defaults." Independent leonxlnx's Design Taste Frontend (350,625) and its sibling high-end-visual-design (265,273) show a family of taste skills gaining traction. [per Skillselion]&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[Updated 13 Aug via devto_claudecode]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The taste-skill trend extends beyond the top four: leonxlnx's family includes high-end-visual-design (265,273 installs) and stitch-design-taste (223,682), both fetched from the live catalog on 2026-08-12. Meanwhile, non-design risers signal a restraint theme: Grill Me now at 832,797 installs, Caveman (429,065) targeting a 75% token cut, and Ponytail (33,353) enforcing minimal changes. [per Skillselion]&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://gentic.news/article/claude-code-skill-market-gini-hits" rel="noopener noreferrer"&gt;gentic.news&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>research</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>Anthropic Adds Invisible Watermarks to Claude Text Outputs</title>
      <dc:creator>gentic news</dc:creator>
      <pubDate>Wed, 12 Aug 2026 22:26:17 +0000</pubDate>
      <link>https://dev.to/gentic_news/anthropic-adds-invisible-watermarks-to-claude-text-outputs-30bh</link>
      <guid>https://dev.to/gentic_news/anthropic-adds-invisible-watermarks-to-claude-text-outputs-30bh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Anthropic adds invisible watermarks to new Claude text at model level, enabling detection after light edits. No rollout details disclosed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anthropic is adding invisible watermarks to text from new Claude models, according to a tweet by @rohanpaul_ai. The watermark is embedded at the model level, meaning detection works even after light editing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key facts&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Watermark embedded at model level in new Claude models&lt;/li&gt;
&lt;li&gt;Detection works even after light editing&lt;/li&gt;
&lt;li&gt;Anthropic did not disclose model names or rollout timeline&lt;/li&gt;
&lt;li&gt;Announced via tweet by @rohanpaul_ai&lt;/li&gt;
&lt;li&gt;Follows OpenAI and Google watermarking experiments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anthropic is adding invisible watermarks to text from new Claude models, according to a tweet by &lt;a href="https://x.com/rohanpaul_ai/status/2087445044160790590" rel="noopener noreferrer"&gt;@rohanpaul_ai&lt;/a&gt;. The watermark is embedded at the model level, meaning detection works even after light editing. The company did not disclose which models get the feature or when it rolls out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Anthropic adds invisible watermarks to new Claude text at model level, enabling detection after light edits.&lt;/li&gt;
&lt;li&gt;No rollout details disclosed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why model-level marking matters
&lt;/h2&gt;

&lt;p&gt;Most text watermarking schemes—like OpenAI's earlier attempts—operate as a post-hoc layer, adding statistical patterns that can be stripped by paraphrasing or simple rewrites. Embedding at the model level means the watermark is baked into the token distribution itself, making it far harder to remove without degrading output quality. Anthropic's approach reportedly survives light edits, a significant improvement over prior art.&lt;/p&gt;

&lt;p&gt;This is not the first time Anthropic has signaled interest in provenance. In a 2024 paper, the company explored statistical watermarking for its own models, and it has funded third-party research on detection. The new announcement appears to be the first production deployment of such a scheme.&lt;/p&gt;

&lt;h2&gt;
  
  
  The disinformation calculus
&lt;/h2&gt;

&lt;p&gt;Watermarking is a defensive move against AI-generated disinformation, a risk that has grown as model outputs become harder to distinguish from human writing. Anthropic's move aligns with industry pressure—OpenAI and Google have both experimented with watermarking, though neither has shipped a fully robust solution. The fact that Anthropic is doing it at the model level suggests it sees this as a core safety feature, not a bolt-on.&lt;/p&gt;

&lt;p&gt;The company did not disclose technical details like token-level bias or detection thresholds, nor did it say whether the watermark applies to all new Claude models or only specific tiers. That silence leaves open questions about false-positive rates and whether the watermark can be defeated by translation or heavy paraphrasing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to watch
&lt;/h2&gt;

&lt;p&gt;Watch for Anthropic's technical blog post or API changelog detailing the watermark's implementation—specifically which Claude models support it, the detection API, and any false-positive metrics. A rollout to the Claude API would signal enterprise adoption, while a paper would reveal the underlying statistical method.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://gentic.news/article/anthropic-adds-invisible" rel="noopener noreferrer"&gt;gentic.news&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>research</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>PyTorch Autograd Explained: What .backward() Actually Does</title>
      <dc:creator>Wesam Khallaf — Author of PyTorch From Ground Up</dc:creator>
      <pubDate>Wed, 12 Aug 2026 20:50:08 +0000</pubDate>
      <link>https://dev.to/pytorchfromgroundup/pytorch-autograd-explained-what-backward-actually-does-4acg</link>
      <guid>https://dev.to/pytorchfromgroundup/pytorch-autograd-explained-what-backward-actually-does-4acg</guid>
      <description>&lt;p&gt;most &lt;strong&gt;&lt;em&gt;autograd&lt;/em&gt;&lt;/strong&gt; tutorials show you &lt;strong&gt;&lt;em&gt;requires_grad&lt;/em&gt;&lt;/strong&gt;, then .&lt;em&gt;backward&lt;/em&gt;(), then .&lt;em&gt;grad&lt;/em&gt;, and then they hand you a training loop, and you come out of it able to run autograd and still not able to say what it did, and i think that is backwards. so in this one you do the derivative first, by hand, on a tiny network that fits on one page, and only once you have your own number do we run pytorch and check it against .grad. the two agree to the decimal. and that is the point where autograd stops being magic, because you already did the thing it does, you just did it slower.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, what a gradient actually is
&lt;/h2&gt;

&lt;p&gt;Skip this section if you are comfortable with it, but most confusion about autograd is really confusion about what it is producing.&lt;/p&gt;

&lt;p&gt;Imagine standing on a hillside in fog. You cannot see the bottom, but you can feel that the ground tilts. Step in the direction it tilts downward and you get lower. That is a gradient: the slope of the ground under your feet.&lt;/p&gt;

&lt;p&gt;Now put that on a graph. The horizontal axis is one adjustable number inside the model, a parameter. The vertical axis is the loss. The curve shows how the loss changes as the parameter&lt;br&gt;
changes, and somewhere on it there is a lowest point.&lt;/p&gt;

&lt;p&gt;Take &lt;code&gt;y = x²&lt;/code&gt;. Its slope at position &lt;code&gt;x&lt;/code&gt; is &lt;code&gt;2x&lt;/code&gt;. At &lt;code&gt;x = 3&lt;/code&gt; the slope is 6, steep and positive, so the loss climbs to the right and you should step left. At &lt;code&gt;x = -2&lt;/code&gt; it is -4, so you step right. At &lt;code&gt;x = 0&lt;/code&gt; it is 0, and you have arrived.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;# tensor(6.)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PyTorch produced the slope without being told the formula. That is autograd, and the rest of this article is how.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning on the tape
&lt;/h2&gt;

&lt;p&gt;Tensors do not track gradients by default. That would be wasted work on your input data, which is never adjusted. You opt in with &lt;code&gt;requires_grad=True&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this moment every operation involving &lt;code&gt;x&lt;/code&gt; gets recorded. Think of it as a receipt. Each multiplication, addition and power you apply gets written down, along with enough information to reverse it later.&lt;/p&gt;

&lt;h2&gt;
  
  
  The computation graph
&lt;/h2&gt;

&lt;p&gt;The receipt has a proper name, the computation graph. It is a chain of nodes where each node is an operation and each edge carries a tensor from one operation into the next.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;        &lt;span class="c1"&gt;# node: power
&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;     &lt;span class="c1"&gt;# nodes: multiply, then add
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three lines of Python, four values, three operation nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x (leaf)      **2         ×2          +1        z
  3.0    →    9.0    →   18.0   →    19.0   →  19.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the forward pass. It runs left to right, computes the answer, and as a side effect builds the graph. Nothing has been differentiated yet. The graph exists purely so that something can walk it backwards.&lt;/p&gt;

&lt;p&gt;Two things are worth noticing here. First, &lt;code&gt;x&lt;/code&gt; is a &lt;strong&gt;leaf&lt;/strong&gt; — you created it directly rather than computing it from something else. Second, every result node remembers the operation that produced it. You can see this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad_fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# &amp;lt;AddBackward0 object at ...&amp;gt;
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad_fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# &amp;lt;PowBackward0 object at ...&amp;gt;
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad_fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# None  ← leaves have no history
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;grad_fn&lt;/code&gt; is the recording. &lt;code&gt;AddBackward0&lt;/code&gt; is not the addition, it is the &lt;em&gt;instruction for reversing&lt;/em&gt; the addition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calling .backward()
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# tensor(12.)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check it by hand. &lt;code&gt;z = 2x² + 1&lt;/code&gt;, so &lt;code&gt;dz/dx = 4x&lt;/code&gt;, and at &lt;code&gt;x = 3&lt;/code&gt; that is 12. Correct.&lt;/p&gt;

&lt;p&gt;But the interesting part is not that the answer is right, it is how it was produced, because PyTorch never formed the expression &lt;code&gt;4x&lt;/code&gt; at all. It walked the graph right to left and at each node multiplied the incoming gradient by that node's own local slope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;z = 19          +1              ×2              **2            x.grad
start           slope 1         slope 2         slope 2x = 6
grad 1     →    grad 1     →    grad 2     →    grad 12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reading right to left: the &lt;code&gt;+1&lt;/code&gt; node has slope 1, so the gradient passes through unchanged. The &lt;code&gt;×2&lt;/code&gt; node has slope 2, so the gradient doubles. The &lt;code&gt;x²&lt;/code&gt; node has slope &lt;code&gt;2x&lt;/code&gt;, which at &lt;code&gt;x = 3&lt;/code&gt; is 6, so the gradient multiplies by 6. Altogether &lt;code&gt;1 × 2 × 6 = 12&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is the whole of backpropagation. It is the chain rule, applied one node at a time, right to left, automatically. Nobody ever writes down &lt;code&gt;4x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This also explains why the forward pass has to happen first, and why it has to store its intermediate values. The &lt;code&gt;x²&lt;/code&gt; node's local slope is &lt;code&gt;2x&lt;/code&gt;, which needs the &lt;em&gt;value&lt;/em&gt; of &lt;code&gt;x&lt;/code&gt; that went in. Every node keeps whatever it needs to compute its own derivative later. This is where the memory goes during training, and it is why a batch that fits in memory for inference can still run you out of memory when training.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now do it on an actual network, by hand
&lt;/h2&gt;

&lt;p&gt;Everything above is one variable. Here is the smallest thing that is honestly a neural network:&lt;br&gt;
one input, one weight, one bias, a ReLU, and a squared-error loss. Five operations. Enough to show every part of the chain rule, small enough to hold in your head.&lt;/p&gt;

&lt;p&gt;Numbers: &lt;code&gt;x = 2.0&lt;/code&gt;, &lt;code&gt;w = 3.0&lt;/code&gt;, &lt;code&gt;b = -1.0&lt;/code&gt;, target &lt;code&gt;y = 2.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forward pass&lt;/strong&gt;, left to right, writing down everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h = w·x + b     = 3·2 + (-1)  = 5.0
a = ReLU(h)     = max(0, 5)   = 5.0
L = (a - y)²    = (5 - 2)²    = 9.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Loss is 9. Now the question that matters: how should &lt;code&gt;w&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; change to make it smaller?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backward pass&lt;/strong&gt;, one node at a time, right to left. At each node, local derivative times the&lt;br&gt;
gradient arriving from the right.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Loss to &lt;code&gt;a&lt;/code&gt;.&lt;/em&gt; &lt;code&gt;L = (a - y)²&lt;/code&gt;, so &lt;code&gt;∂L/∂a = 2(a - y) = 2(5 - 2) = 6.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;a&lt;/code&gt; to &lt;code&gt;h&lt;/code&gt;, through the ReLU.&lt;/em&gt; ReLU's derivative is 1 if its input was positive and 0 if it was&lt;br&gt;
negative. Our &lt;code&gt;h&lt;/code&gt; was 5, positive, so &lt;code&gt;∂a/∂h = 1.0&lt;/code&gt; and therefore&lt;br&gt;
&lt;code&gt;∂L/∂h = 6.0 × 1.0 = 6.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;h&lt;/code&gt; to &lt;code&gt;w&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;.&lt;/em&gt; Since &lt;code&gt;h = w·x + b&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;∂h/∂w = x = 2.0    →    ∂L/∂w = 6.0 × 2.0 = 12.0
∂h/∂b = 1.0        →    ∂L/∂b = 6.0 × 1.0 = 6.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So by hand: &lt;code&gt;∂L/∂w = 12&lt;/code&gt; and &lt;code&gt;∂L/∂b = 6&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now ask PyTorch the same question:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;loss  = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# 9.0
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dL/dw = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# 12.0
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dL/db = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# 6.0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exact match, all three. Autograd traced the same five operations and applied the same chain rule. It just did it without asking you.&lt;/p&gt;

&lt;p&gt;If you read nothing else here, run that block and compare it to the hand calculation above. The whole point of the exercise is the moment the numbers agree.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when the ReLU is closed
&lt;/h2&gt;

&lt;p&gt;Change one number. Keep &lt;code&gt;w = 3&lt;/code&gt; and &lt;code&gt;b = -1&lt;/code&gt;, but feed &lt;code&gt;x = -1.0&lt;/code&gt;. Now &lt;code&gt;h = 3·(-1) + (-1) = -4&lt;/code&gt;, which is negative, so ReLU outputs 0 and its local derivative is also 0.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;          &lt;span class="c1"&gt;# -4.0
&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;#  0.0
&lt;/span&gt;&lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;    &lt;span class="c1"&gt;# (0 - 2)² = 4.0
&lt;/span&gt;&lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;   &lt;span class="c1"&gt;# 0.0
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;   &lt;span class="c1"&gt;# 0.0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The loss is 4, so the network is wrong, and yet both gradients are exactly zero. No learning&lt;br&gt;
signal reaches &lt;code&gt;w&lt;/code&gt; or &lt;code&gt;b&lt;/code&gt; at all.&lt;/p&gt;

&lt;p&gt;This follows straight from the hand calculation. &lt;code&gt;∂a/∂h = 0&lt;/code&gt;, and every gradient behind that node gets multiplied by zero on its way through. The ReLU is a gate, and this one is shut.&lt;/p&gt;

&lt;p&gt;That is the dying-ReLU problem, and it is worth meeting it here rather than three months later in a model with fifty layers. When a neuron's input is negative for every example in your data, its gradient is permanently zero and it never learns again. &lt;code&gt;LeakyReLU&lt;/code&gt; exists because it lets a small gradient through instead.&lt;/p&gt;

&lt;p&gt;More generally: when a model stops learning and you cannot see why, the question to ask is what is multiplying the gradient by zero on the way back.&lt;/p&gt;
&lt;h2&gt;
  
  
  Three mechanics that catch nearly everyone
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Only leaves keep their &lt;code&gt;.grad&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Intermediate results do not store their gradient. It is computed, used to keep the chain going, and thrown away, because keeping every intermediate gradient in a real model would be enormous. If you want one, ask before calling backward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retain_grad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;        &lt;span class="c1"&gt;# keep y's gradient too
&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# tensor(60.)   dz/dx = 15x² = 60
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# tensor(5.)    dz/dy = 5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without &lt;code&gt;retain_grad()&lt;/code&gt;, &lt;code&gt;y.grad&lt;/code&gt; is &lt;code&gt;None&lt;/code&gt; and you get a warning rather than an error, which is why people spend twenty minutes confused by it.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Gradients accumulate, they do not overwrite
&lt;/h3&gt;

&lt;p&gt;This one causes more silently broken training loops than anything else in PyTorch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  grad = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;step 0  grad = 6.0
step 1  grad = 12.0
step 2  grad = 18.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gradient of &lt;code&gt;x²&lt;/code&gt; at &lt;code&gt;x = 3&lt;/code&gt; is 6, every time. It reads 12 and then 18 because &lt;code&gt;.grad&lt;/code&gt; is added to, not replaced.&lt;/p&gt;

&lt;p&gt;This is deliberate. It is what lets you accumulate gradients over several mini-batches and take one larger step, which is how people train with an effective batch size their GPU cannot hold.&lt;br&gt;
But it means that unless you clear it, every step of your training loop is stepping on a sum of all previous gradients, and your loss curve will do something strange that is very hard to diagnose from the outside.&lt;/p&gt;

&lt;p&gt;The fix is &lt;code&gt;x.grad.zero_()&lt;/code&gt;, or in a real loop, &lt;code&gt;optimizer.zero_grad()&lt;/code&gt; before every &lt;code&gt;loss.backward()&lt;/code&gt;. That line is not boilerplate. It is load-bearing.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. &lt;code&gt;no_grad&lt;/code&gt; and &lt;code&gt;detach&lt;/code&gt; — switching the recorder off
&lt;/h3&gt;

&lt;p&gt;During evaluation you do not need gradients, and building the graph costs both time and memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_grad&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# False
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the block no graph is built. This is why every evaluation loop you have ever copied is wrapped in &lt;code&gt;torch.no_grad()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.detach()&lt;/code&gt; is the narrower tool. It gives you a tensor that shares the same data but has no connection to the graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;y_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;detach&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                  &lt;span class="c1"&gt;# tensor(9.)
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_val&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# False
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it when you want a value without dragging its history along — logging, or using a model's output as a target that should not be differentiated through. It is the mechanism behind stop-gradient tricks and target networks, and it is also, occasionally, the reason your gradient is unexpectedly zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  One call, every parameter
&lt;/h2&gt;

&lt;p&gt;Everything so far had one or two parameters so the arithmetic stayed visible. Nothing changes at scale.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_grad&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;            &lt;span class="c1"&gt;# 2·3 + 1 = 7
&lt;/span&gt;&lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;      &lt;span class="c1"&gt;# (7 - 5)² = 4
&lt;/span&gt;
&lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# tensor(12.)
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grad&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# tensor(4.)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One &lt;code&gt;backward()&lt;/code&gt; filled in both. In a model with eleven million parameters, the same single call fills in all eleven million, because the graph reaches every one of them and the chain rule multiplies along every path. Nothing about the mechanism is different. There are just more nodes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The summary worth keeping
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;requires_grad=True&lt;/code&gt; marks a tensor as something you want the gradient of. Model parameters
get it automatically; your data does not need it.&lt;/li&gt;
&lt;li&gt;The forward pass computes the answer and records a graph as a side effect. Each node stores what it needs to reverse itself later.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.backward()&lt;/code&gt; walks that graph in reverse, multiplying the incoming gradient by each node's
local derivative. That is the chain rule, and it is all backpropagation is.&lt;/li&gt;
&lt;li&gt;Gradients land in &lt;code&gt;.grad&lt;/code&gt; on leaf tensors only. Use &lt;code&gt;retain_grad()&lt;/code&gt; for intermediates.&lt;/li&gt;
&lt;li&gt;Gradients accumulate. &lt;code&gt;zero_grad()&lt;/code&gt; before every backward, always.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;torch.no_grad()&lt;/code&gt; for evaluation, &lt;code&gt;.detach()&lt;/code&gt; for a single value without its history.&lt;/li&gt;
&lt;li&gt;A zero gradient means something on the path back multiplied by zero. A closed ReLU is the
usual suspect.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try this before you close the tab
&lt;/h2&gt;

&lt;p&gt;Take &lt;code&gt;x = 4.0&lt;/code&gt; with &lt;code&gt;requires_grad=True&lt;/code&gt;, compute &lt;code&gt;y = x**3 - 2*x&lt;/code&gt;, call &lt;code&gt;backward()&lt;/code&gt;, and print&lt;br&gt;
&lt;code&gt;x.grad&lt;/code&gt;. Then work out &lt;code&gt;3x² - 2&lt;/code&gt; at &lt;code&gt;x = 4&lt;/code&gt; on paper and check whether they agree. It takes&lt;br&gt;
about ninety seconds and it is worth more than rereading this article.&lt;/p&gt;

&lt;p&gt;Then the harder version: put a second weight after the ReLU in the tiny network above, &lt;code&gt;w2 =&lt;br&gt;
0.5&lt;/code&gt;, and write out the full chain rule for &lt;code&gt;∂L/∂w&lt;/code&gt; before you run it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is one chapter's worth of an idea from my book,&lt;/em&gt; &lt;strong&gt;PyTorch From Ground Up&lt;/strong&gt;, &lt;em&gt;which builds&lt;br&gt;
everything from tensors upward so nothing stays vague. If it helped: &lt;a href="https://github.com/pytorch-from-ground-up/book_code/blob/main/PyTorch-From-Ground-Up-8-Free-Chapters.pdf" rel="noopener noreferrer"&gt;8 chapters are free, no email required&lt;/a&gt;,&lt;br&gt;
there's a &lt;a href="https://payhip.com/b/7ukxh" rel="noopener noreferrer"&gt;free one-page tensor cheat-sheet here&lt;/a&gt;, every example runs&lt;br&gt;
in the &lt;a href="https://github.com/pytorch-from-ground-up/book_code" rel="noopener noreferrer"&gt;companion notebooks on GitHub&lt;/a&gt;, and&lt;br&gt;
the full book is on &lt;a href="https://leanpub.com/pytorchfromgroundup" rel="noopener noreferrer"&gt;Leanpub&lt;/a&gt; or in&lt;br&gt;
&lt;a href="https://www.amazon.com/dp/B0H8WMCV33" rel="noopener noreferrer"&gt;paperback and Kindle on Amazon&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  More in this series
&lt;/h3&gt;

&lt;p&gt;Shape mechanics, the part that has to be solid before any of this makes sense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/pytorchfromgroundup/reshape-vs-view-in-pytorch-whats-the-difference-and-when-view-breaks-4a9o"&gt;Reshape vs View in PyTorch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/pytorchfromgroundup/pytorch-broadcasting-explained-the-3-rules-and-the-silent-bug-that-bites-everyone-3606"&gt;PyTorch Broadcasting Explained&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>deeplearning</category>
      <category>machinelearning</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
