<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Igor Comune on Medium]]></title>
        <description><![CDATA[Stories by Igor Comune on Medium]]></description>
        <link>https://medium.com/@igorcomune?source=rss-977adbc510be------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*gjsscIT2aRTzw2PmhTmkUA.jpeg</url>
            <title>Stories by Igor Comune on Medium</title>
            <link>https://medium.com/@igorcomune?source=rss-977adbc510be------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 17 May 2026 16:29:11 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@igorcomune/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Why It’s Time to Reconsider Ubuntu for Machine Learning]]></title>
            <link>https://igorcomune.medium.com/why-its-time-to-reconsider-ubuntu-for-your-data-workflow-d3d8b47ad5b0?source=rss-977adbc510be------2</link>
            <guid isPermaLink="false">https://medium.com/p/d3d8b47ad5b0</guid>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[ubuntu]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Igor Comune]]></dc:creator>
            <pubDate>Fri, 27 Feb 2026 20:49:13 GMT</pubDate>
            <atom:updated>2026-03-05T23:19:07.593Z</atom:updated>
            <content:encoded><![CDATA[<p>Oct/2025 I finally <strong>Defenestrated</strong> Microsoft Windows for Ubuntu after a deep research over Machine Learning and which is the best Linux Distro for Data professionals… and well, it paid off.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WIu1l_a_1TfCVT7r7NqRQA.jpeg" /><figcaption>ideogram.com</figcaption></figure><p>If you don’t follow me don’t forget to do so and read these 2 posts I made about my Windows to Linux migration:</p><ul><li><a href="https://igorcomune.medium.com/defenestrate-windows-41d7331e23ff">Defenestrate Windows</a></li><li><a href="https://igorcomune.medium.com/i-defenestrated-windows-and-adopted-a-penguin-bd6e45408056">I Defenestrated Windows and Adopted a Penguin</a></li></ul><h3>Intro</h3><p>For years, the “<strong>year of the Linux desktop</strong>” has been a running joke in the tech community. But in the world of data science and AI development, that year might have already arrived — and it’s orange.</p><p>As a data professional, I’ve spent more hours than I care to admit wrestling with CUDA versions, matching toolkit dependencies to specific kernels, and fixing environments that spontaneously broke after a routine update. However, after looking at the roadmap for the upcoming <strong>Ubuntu 26.04</strong> and the new tooling Canonical is introducing, I believe it is time to seriously consider Ubuntu as the primary OS for AI development.</p><p>Here is why the “orange Linux” is evolving into an AI-native platform.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GiGiTrInKB1wUK9bu9aOzw.png" /><figcaption>notebooklm.google.com</figcaption></figure><h3><strong>1. One Command for Hardware Acceleration</strong></h3><p>The most significant friction in AI development has always been the “driver hell.” Whether you use Nvidia or AMD, setting up the hardware stack is often a manual, error-prone process.</p><p>Starting with <strong>Ubuntu 26.04</strong>, this changes completely. We will be able to run apt install cuda or apt install rockm and get the exact, verified version that works with our specific GPU and OS version—out of the box. By partnering directly with silicon giants like <strong>Nvidia, AMD, and Intel</strong>, Ubuntu ensures that the kernel supports not just CPUs and GPUs, but the newer MPUs and TPUs from day one.</p><h3><strong>2. Optimized Local AI via “Inference Snaps”</strong></h3><p>Testing a new model often feels like it requires a “PhD in Hugging Face” just to manage the dependencies and inference engines.</p><p>Ubuntu is solving this with <strong>Inference Snaps</strong>. These are high-quality, silicon-optimized AI models (like DeepSeek, Gemma, or Llama) packaged in a security-confined format. When you install one, it automatically detects your hardware — AMD, Nvidia, or Intel — and fetches the version tuned by the silicon vendor itself. They even come with an <strong>OpenAI-compatible API endpoint</strong>, allowing you to point your existing local tools directly to a production-grade local model with a single command.</p><h3><strong>3. Limiting the “Blast Radius” of AI Agents</strong></h3><p>As our workflows shift toward using autonomous agents, security becomes a practical concern. We’ve all seen stories of agents accidentally deleting files or exhausting system resources.</p><p>Ubuntu provides built-in sandboxing through <strong>LXD</strong> and <strong>Multipass</strong>. I’ve started using these to create “disposable” environments for my agents. If an agent makes a catastrophic error, it only affects an isolated container or VM, not my entire host system. This isolation doesn’t just provide security; it ensures my local context stays clean and efficient.</p><h3><strong>4. Enterprise-Grade Stability for the Long Haul</strong></h3><p>The reality is that Ubuntu already powers the majority of AI workloads in the cloud. By developing on the same OS that handles production on AWS or Google Cloud, we eliminate the “works on my machine” problem.</p><p>Furthermore, Canonical’s commitment to <strong>15 years of security maintenance</strong> — including their “LTS anything” initiative for Docker containers and Python dependencies — means that the infrastructure we build today won’t become a security liability in the future.</p><h3><strong>Final Thoughts</strong></h3><p>Ubuntu isn’t just “another Linux distribution” anymore; it is becoming a specialized workbench for AI. By removing the friction of hardware drivers and providing secure, optimized ways to run local models, it allows us to focus on what actually matters: building and deploying models.</p><p>If you are tired of troubleshooting your operating system and want to start building, I highly recommend giving Ubuntu another look.</p><p><strong>Igor Comune.</strong></p><p>Post inspired by this video: <a href="https://www.youtube.com/watch?v=0CYm-KCw7yY">https://www.youtube.com/watch?v=0CYm-KCw7yY</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d3d8b47ad5b0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MLOps: A Free Crash-course about Feature Store with Google Colab]]></title>
            <link>https://igorcomune.medium.com/mlops-a-free-crash-course-about-feature-store-with-google-colab-b447d87dd075?source=rss-977adbc510be------2</link>
            <guid isPermaLink="false">https://medium.com/p/b447d87dd075</guid>
            <category><![CDATA[mlops]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[feature-store]]></category>
            <category><![CDATA[machine-learning-engineer]]></category>
            <dc:creator><![CDATA[Igor Comune]]></dc:creator>
            <pubDate>Tue, 27 Jan 2026 19:47:30 GMT</pubDate>
            <atom:updated>2026-02-05T20:01:43.212Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>TL;DR</strong>: If you’ve ever shipped a model to production only to watch it crash and burn, you’re not alone. We’re going to dissect exactly why this happens using a fraud detection system as our guinea pig, then show you how Feature Stores solve these nightmares systematically.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rVutu9IK_GcZhaU9JaZ3Kg.jpeg" /><figcaption>Ideogram.com</figcaption></figure><h3>The 3 AM Wake-Up Call</h3><p>Picture this: You’re a data scientist at a fintech company. Your fraud detection model is crushing it in notebooks — 98% precision, everyone’s happy. You hand it off to engineering, they deploy it, and… suddenly you’re catching 40% less fraud than in testing.</p><p>What the hell happened?</p><p>We’ve all been there… The model looked perfect… The metrics were solid… But somewhere between your Jupyter notebook and production, something broke. And here’s the kicker:</p><blockquote><strong>it’s probably not your model. It’s your FEATURES.</strong></blockquote><p>This is where Feature Stores enter the picture. But instead of starting with “here’s what a Feature Store is,” let’s do something different. We’re going to break things systematically, <strong>watch them fail in real-time, then fix them properly.</strong></p><p><strong>Our weapon of choice?</strong> A hands-on Jupyter notebook that simulates a real fraud detection pipeline. We’re talking about the same problems you face in production every single day.</p><h3>The Five Horsemen of ML Production Hell</h3><p>Before we dive in, let’s name our enemies. Feature Stores solve five critical problems that plague every ML system at scale:</p><ol><li><strong>Training vs Production Consistency</strong> — Your training code uses Pandas, production uses SQL. Same features, different bugs.</li><li><strong>Feature Reuse Across Teams</strong> — The risk team computed user velocity last month. Now the fraud team is recomputing it. Same logic, different bugs.</li><li><strong>Low-Latency Feature Serving</strong> — Your model needs to decide in 50ms, but your features take 200ms to compute. Whoops.</li><li><strong>Point-in-Time Correctness</strong> — You accidentally trained on future data. Your model is a time traveler, and it sucks at production.</li><li><strong>Feature Governance &amp; Discovery</strong> — Where are the features? Who owns them? What version? Nobody knows.</li></ol><p>Sound familiar? Yeah, we thought so.</p><p>Let’s systematically break and then fix each one using our fraud detection scenario.</p><h3>Setup: Getting Your Hands Dirty</h3><blockquote><a href="https://github.com/IgorComune/mlops_feature_store_crash_course">DOWNLOAD THE NOTEBOOK PYTHON HERE</a> or</blockquote><blockquote><a href="https://github.com/IgorComune/mlops_feature_store_crash_course">https://github.com/IgorComune/mlops_feature_store_crash_course</a></blockquote><blockquote>You’ll have a better learning experience if you read the blog with and follow the steps on Google Colab.</blockquote><p><strong>Execute cells 1–2 to get started.</strong></p><p>These cells install Feast and the necessary dependencies. Nothing fancy here — just standard ML stack stuff. The key thing is we’re setting up a complete environment that mirrors real production constraints.</p><p><strong>Cell 3</strong> initializes the Feast repository. This is important: Feast needs a config file that defines where features live, how they’re stored, and how they’re served. We’re using SQLite for simplicity, but in production, you’d swap this for something like Redis or DynamoDB.</p><p>Notice the dual storage model being configured: <strong>registry</strong> (metadata about features) and <strong>online_store</strong> (the actual feature values). Keep this architecture in mind — it’s central to how Feature Stores solve latency problems.</p><h3>Problem #1: Training-Serving Skew (The Silent Killer)</h3><p><strong>THE PROBLEM</strong>: Your data scientist writes feature logic in Pandas. Your ML engineer rewrites it in SQL for production. Same intent, different implementations. Guess what? They diverge. Your model trained on one thing, serves on another.</p><h3>Seeing the Problem</h3><p><strong>Execute cells 4–9</strong> to generate synthetic transaction data and see the naive approach.</p><p>Cell 4 creates a realistic fraud dataset — transactions with amounts, merchants, countries, timestamps. The key detail: we’re generating fraud patterns based on <strong>user behavior over time</strong>. High-velocity users (lots of transactions in a short window) are more likely to be fraudulent. This behavioral pattern becomes the foundation for our feature engineering — we’ll track how many transactions a user makes within a 24-hour window, and use that velocity as a fraud signal.</p><p>This is the core logic we’ll need to replicate in production. Remember this — we’ll come back to it.</p><p><strong>Cells 5–6</strong> create the “Data Science approach” — computing features in Pandas during training. Here’s where we see the first implementation: using DataFrame operations to group transactions by user and compute aggregations like transaction count and average amount. It’s clean, readable, and exactly how every data scientist naturally thinks about feature engineering. The Pandas groupby and transform operations make this trivial — a few lines of code and you’ve got your features.</p><p>Simple, clean, Pythonic. This is how every data scientist writes their features.</p><p><strong>Now here’s where it gets ugly.</strong></p><p><strong>Cells 7–8</strong> show the “Engineering approach” — the same features, but reimplemented for production. Instead of Pandas operations on a complete DataFrame, we’re now computing features for individual transactions as they arrive in real-time. This means hitting the database, running SQL queries to aggregate historical transactions, applying filters, and handling edge cases. We’re also simulating the reality of production: every query has latency (around 30ms), and you need to handle scenarios like new users with no transaction history.</p><p>Notice what just happened:</p><ol><li><strong>Different language</strong> (SQL vs Pandas)</li><li><strong>Different aggregation windows</strong> (subtly different time boundaries)</li><li><strong>Added latency</strong> (30ms per query)</li><li><strong>Different handling of edge cases</strong> (what if user has no history?)</li></ol><p>These implementations <strong>should</strong> produce the same results. But they won’t. They never do.</p><p><strong>Execute cell 9</strong> to see the divergence. The output shows you’ve got 10,000 training examples with features computed successfully, and production feature computation taking about 45ms per transaction. But here’s the warning that should make you nervous: the implementations may differ in edge cases.</p><p>The metrics look similar, but dig deeper and you’ll find discrepancies in:</p><ul><li>How nulls are handled (Pandas fills with NaN, SQL might return NULL or 0)</li><li>Timezone conversions (UTC vs local time, daylight savings)</li><li>Aggregation window boundaries (inclusive vs exclusive, timestamp precision)</li><li>Rounding differences (floating point arithmetic across different libraries)</li></ul><p>This is training-serving skew. Your model trained on one distribution, serves on another. And you won’t know until production starts bleeding money.</p><h3>Problem #2: Feature Duplication (The N² Scaling Nightmare)</h3><p><strong>THE PROBLEM</strong>: You have 5 teams. Each team needs user velocity. Each team computes it independently. Now you have 5 implementations of the same feature. 5 bugs. 5 maintenance burdens. And god help you when you need to change the definition.</p><h3>Seeing the Problem</h3><p><strong>Execute cells 10–11</strong> to see feature duplication in action.</p><p>Cell 10 simulates what happens in real organizations. We create three different functions, each representing how a different team implemented the exact same concept — user transaction velocity. The fraud team counts all transactions for a user. The risk team applies a 24-hour sliding window. The credit team uses a different grouping mechanism entirely. Same business logic, three completely different implementations.</p><p>This isn’t a strawman. Walk into any company with multiple ML teams and you’ll find this exact scenario. The fraud detection team built their velocity feature six months ago. The credit risk team needed the same thing last quarter but didn’t know it existed, so they built their own. The anti-money laundering team is about to do the same thing next sprint.</p><p>Cell 11 quantifies the damage. You’ll see that we now have three duplicated features across the organization. The code maintenance cost is tripled — when you need to update the business logic (say, changing the velocity window from 24 hours to 12 hours), you need to update three separate codebases. The bug surface area is tripled — find a bug in one implementation, and you’ve probably got the same bug in two other places. And here’s the kicker: consistency is <strong>never</strong> guaranteed. These implementations will drift over time as different teams patch bugs, add edge case handling, or optimize performance.</p><p>When the product manager says “change how we calculate velocity,” you now have to update 3 codebases, coordinate 3 deployments, and pray they all stay in sync. Spoiler: they won’t.</p><h3>Problem #3: Latency (The Production Killer)</h3><p><strong>THE PROBLEM</strong>: Your model needs to approve or reject transactions in real-time. You have a 50ms SLA. But your features take 200ms to compute because you’re hitting the database on every prediction.</p><h3>Seeing the Problem</h3><p><strong>Execute cells 12–14</strong> to measure naive serving latency.</p><p>Cell 12 simulates production serving without any optimization. When a transaction comes in, we need to make a prediction immediately. The naive approach does this: compute the features on-demand (which means querying the database for historical transactions, running aggregations, computing statistics), then feed those features into the model for inference. The model inference itself is fast — maybe 1–2ms. But the feature computation? That’s where we pay the price.</p><p><strong>Execute cell 13</strong> to run 1000 predictions and see the damage. The output shows average latency around 44.5ms, with P95 latency at 48.2ms and P99 latency breaking through 52.1ms. You’re seeing that about 12% of predictions are exceeding your 50ms SLA.</p><p>You’re <strong>barely</strong> making SLA on average, but your tail latencies are killing you. And this is with a simple feature set — just user velocity and average transaction amount. Add more features (merchant category frequency, time-of-day patterns, device fingerprinting, location-based features), more joins, more complexity, and you’re toast. Each additional feature means another database query, another aggregation, another 10–30ms added to your latency budget.</p><p>Cell 14 visualizes the problem with a histogram of latencies. You’ll see a distribution that’s mostly clustered around 40–50ms, but with a long tail stretching out to 70–80ms for the unlucky requests. That long tail? Those are the transactions that timeout, get retried, cause user frustration, create duplicate charges, and ultimately cost you money in lost conversions and customer support tickets.</p><p><strong>The core issue</strong>: You’re computing features <strong>on-demand</strong> at prediction time. Every prediction triggers database queries, aggregations, joins. This doesn’t scale. As your feature set grows, as your transaction volume increases, as your database gets loaded, those latencies compound. What works fine at 100 QPS falls apart at 10,000 QPS.</p><h3>Problem #4: Point-in-Time Correctness (The Data Leakage Timebomb)</h3><p><strong>THE PROBLEM</strong>: You’re training your model on historical data. You accidentally use a feature value from the future. Your model learns to predict the past using information it wouldn’t have in production. It looks amazing in training, worthless in production.</p><p>This is the most insidious problem because it’s <strong>silent</strong>. Your model metrics look great. Your code reviews pass. Then production happens.</p><h3>Seeing the Problem</h3><p><strong>Execute cells 15–18</strong> to see data leakage in action.</p><p>Cell 15 shows the wrong way to build training data — and it’s the way most people naturally do it first. When you have a DataFrame of transactions and you want to compute user velocity, the obvious approach is to group by user_id and count transactions. Simple, right? But here’s the trap: that groupby operation counts <strong>all</strong> transactions for each user in the dataset, including transactions that happened in the future relative to each row.</p><p>The bug is subtle but devastating. When you’re processing a transaction that happened on January 1st, you’re computing the user’s velocity based on their total transaction count across the entire dataset — which includes transactions from January 2nd, 3rd, all the way through the end of your data. You’re using future information to predict the past.</p><p><strong>Execute cell 16</strong> to see the impact quantified. The model trained with this data leakage achieves an AUC of 0.94 — fantastic! But when you train the same model correctly (without the leakage), you get an AUC of 0.82. That’s a 12.8% performance drop. Your model looked like a rockstar in training because it was cheating. In production, where it can’t see the future, it’s mediocre.</p><p>This happens all the time. You build your training set, compute features, train a model, get great metrics, ship it to production, and watch it underperform. You blame the model, the data quality, concept drift — everything except the real culprit: temporal data leakage in your feature engineering.</p><p>Cells 17–18 show the correct approach — point-in-time joins. For each transaction, we only use data that existed <strong>before</strong> that transaction occurred. This means for a transaction on January 5th, we compute user velocity based only on transactions that happened before January 5th. No future peeking allowed.</p><p>This is correct, but notice what we just did: we turned a simple aggregation into a <strong>sequential operation</strong>. Instead of one groupby operation across the entire dataset (which takes seconds), we’re now iterating through each transaction individually, filtering historical data for each one, and computing features (which takes hours). Training time just went from minutes to hours or even days for large datasets.</p><p>This is the curse of point-in-time correctness — doing it right is expensive. You need to maintain temporal consistency, which means you can’t use the fast vectorized operations that make Pandas so efficient. You’re forced into slower, more complex logic that respects time boundaries.</p><h3>Problem #5: Feature Governance (The “Who the Hell Owns This?” Problem)</h3><p><strong>THE PROBLEM</strong>: You have 50 features scattered across 15 notebooks, 8 services, and 3 data warehouses. Someone asks “what’s the definition of user_velocity?” Nobody knows. Someone asks “is this feature tested?” Nobody knows. Someone asks “can I reuse this?” Nobody knows.</p><h3>Seeing the Problem</h3><p><strong>Execute cells 19–20</strong> to see the governance chaos.</p><p>Cell 19 simulates the typical ML codebase after a year of rapid iteration. Features are scattered everywhere. Version 1 of the notebook defined user_velocity and user_avg_amount. Version 2 (created three months later when someone needed to add a new feature) redefined user_velocity slightly differently and called it user_velocity_v2, while also adding user_max_amount. Meanwhile, production is running with yet another set of features that may or may not match either version.</p><p>Which version is canonical? Which one is actually running in production? If you want to use user_velocity for a new model, which implementation should you trust? Good luck figuring it out. You’ll need to grep through repositories, ask around on Slack, hope someone who worked on the original project is still on the team, and probably end up re-implementing it yourself because you can’t trust any of the existing versions.</p><p>Cell 20 quantifies this organizational chaos. Across your organization, you have 47 total features. Of those, exactly 3 have documentation explaining what they compute and why. Only 1 has tests verifying it works correctly. 5 have a known owner who you could ask questions. And the average time to find a feature definition? 4.3 hours. That’s more than half a workday just to figure out if a feature already exists and how it’s computed.</p><p>This isn’t hypothetical. This is every ML org at scale. Features are tribal knowledge. The person who implemented user_velocity_v2 left the company six months ago. The original notebook that defined merchant_category_freq has been deleted. The only person who knows how device_fingerprint works is on vacation. And you’re on a deadline to ship a new model that needs all three of these features.</p><p>So what do you do? You reimplement them. Again. Adding to the chaos. Contributing to problem #2 (feature duplication). And the cycle continues.</p><h3>Enter the Feature Store: Solving All Five Problems Systematically</h3><p>Now that we’ve thoroughly broken everything, let’s fix it. <strong>This is where Feast comes in.</strong></p><p>The key insight: All five problems stem from the same root cause — <strong>features are not first-class citizens</strong>. They’re scattered, duplicated, unversioned, undocumented artifacts of individual pipelines.</p><p>Feast makes features first-class by providing:</p><ol><li>A <strong>centralized registry</strong> (solves governance)</li><li>A <strong>single source of truth</strong> for feature definitions (solves duplication + skew)</li><li><strong>Pre-computed online storage</strong> (solves latency)</li><li><strong>Built-in point-in-time joins</strong> (solves data leakage)</li><li><strong>Dual offline/online stores</strong> (same features, training and serving)</li></ol><p>Let’s see this in action.</p><h3>Solution Part 1: Defining Features as Code</h3><p><strong>Execute cells 21–23</strong> to see how Feast defines features.</p><p>Cell 21 creates an <strong>Entity</strong> — the primary key for our features. In our fraud detection system, the entity is the user_id. Think of entities as the “join keys” of your feature world. Every feature belongs to an entity — user features belong to users, merchant features belong to merchants, transaction features belong to transactions. This is how Feast knows how to link features together when you request them.</p><p>The entity definition includes not just the name, but also a description that serves as documentation. This is governance in action — when someone wants to know what user_id means, there’s a canonical answer in the registry.</p><p>Cell 22 defines a <strong>Feature View</strong> — where the actual feature logic lives. This is the magic that solves problems #1, #2, and #5 simultaneously. We’re defining a set of features (user_velocity_24h, user_avg_amount, user_total_amount) that all belong to the user entity. We specify their data types, their source (a parquet file in this case, but it could be a data warehouse table), and their TTL (time-to-live, which tells Feast how long these features stay fresh).</p><p>Here’s what just happened: <strong>feature logic defined once, used everywhere</strong>. No more Pandas vs SQL debates. No more reimplementing the same feature across teams. No more wondering which version is correct. There’s one definition, stored in a centralized registry, version-controlled, and guaranteed to be used consistently in both training and serving.</p><p>The Feature View also includes a schema — explicit data types for every feature. This prevents the subtle bugs that happen when one implementation returns an integer and another returns a float, or when null handling differs between implementations.</p><p>Cell 23 registers these definitions with Feast. When you run this cell, Feast takes your entity and feature view definitions and stores them in the registry (that SQLite database we configured earlier). Now anyone in your organization can query the registry to discover what features exist, who owns them, what they compute, and how to use them.</p><p><strong>Execute this and check the output.</strong> You’ll see confirmation that the entity and feature view were registered successfully. You now have a centralized catalog of features. Anyone can query the registry to discover what exists, who owns it, and how it’s defined. Problem #5 (governance) is solved. Problem #2 (duplication) is solved — there’s one canonical definition. And problem #1 (training-serving skew) is about to be solved because we’ll use this same definition for both training and serving.</p><h3>Solution Part 2: Training with Point-in-Time Correctness (Automatic)</h3><p><strong>Execute cells 24–25</strong> to see point-in-time joins in action.</p><p>Cell 24 prepares training data using Feast. This is where the magic happens. We create what Feast calls an “entity DataFrame” — essentially a list of entities (user IDs) and timestamps representing when we want to fetch features. In our fraud detection case, each row represents a transaction, and we want to know what the user’s features looked like at the exact moment that transaction occurred.</p><p>Then we call Feast’s get_historical_features method. This is where problem #4 (point-in-time correctness) gets solved automatically. Feast takes our entity DataFrame and, for each row, retrieves the feature values that were valid at that specific timestamp. For a transaction on January 5th at 2:30 PM, Feast will fetch the user_velocity_24h value as it existed at exactly 2:30 PM on January 5th—computed using only transactions that occurred before that moment.</p><p><strong>This is the critical part</strong>: Feast handles all the complex temporal logic for you. You don’t need to write loops. You don’t need to manually filter historical data. You don’t need to worry about off-by-one errors in timestamp comparisons. Data leakage is <strong>impossible</strong> by design because Feast enforces temporal consistency at the infrastructure level.</p><p><strong>Execute cell 25</strong> to compare the results with the naive approach. The output shows a crucial difference: when we compute user velocity with Feast using point-in-time joins, the maximum velocity for any user in our training set is 8 transactions. This makes sense — it’s the actual maximum number of transactions any user had completed at any single point in time during the training period.</p><p>But when we computed it naively (the wrong way from cells 15–16), we saw maximum velocities of 156. That’s because the naive approach counted <strong>all</strong> transactions for each user across the entire dataset, including future transactions. A user who ended up making 156 transactions total would have that count applied to every single one of their historical transactions, even their very first one.</p><p>Feast enforces correctness by construction. You can’t accidentally leak data even if you try. And you get this guarantee without sacrificing performance — Feast optimizes the point-in-time joins internally so you’re not stuck with the slow sequential processing we implemented manually in cell 17.</p><h3>Solution Part 3: Online Serving (Low Latency by Design)</h3><p><strong>Execute cells 26–27</strong> to see online serving.</p><p>Cell 26 is where we solve problem #3 (latency). The key operation here is called <strong>materialization</strong> — Feast takes all the feature values, pre-computes them, and stores them in the online store (that SQLite database we configured, though in production you’d use Redis, DynamoDB, or another low-latency key-value store).</p><p>Think about what just happened: instead of computing features on-demand during prediction time (query the database, aggregate historical transactions, calculate statistics — all that expensive stuff that took 45ms), we’re computing everything upfront and storing the results. When a transaction comes in and we need to make a prediction, we just look up the pre-computed feature values by user_id. That’s a simple key-value fetch, which takes microseconds instead of milliseconds.</p><p>This is the architectural shift that Feature Stores enable: from <strong>compute-on-read</strong> (slow, unpredictable latency) to <strong>compute-on-write</strong> (fast, consistent latency). You pay the computational cost during the materialization process (which runs offline, on a schedule, without latency constraints), and you get instant lookups at serving time.</p><p>Cell 27 shows online retrieval in action. When we need to make a prediction for a transaction, we call get_online_features with the user_id. Feast immediately returns the pre-computed feature values from the online store. No database queries. No aggregations. No waiting. Just a fast lookup.</p><p><strong>Execute cell 27 and watch the latency numbers.</strong> The output shows average latency dropping from 44.5ms (without Feast) to 5.5ms (with Feast). That’s an <strong>8x speedup</strong>. More importantly, look at the P95 and P99 latencies — they’re now consistently under 10ms, which means you’re making your 50ms SLA with room to spare.</p><p>We went from barely scraping by (with 12% of predictions exceeding SLA) to comfortably meeting our latency requirements. And this is with a simple feature set — as you add more features, the gap widens. The naive approach gets slower linearly with each feature (more queries, more joins), while Feast stays constant (one lookup fetches all features for an entity).</p><p>This is the difference between a good user experience and a terrible one. This is the difference between a fraud detection system that catches fraud in real-time versus one that has to batch-process transactions hours later when it’s too late to prevent the fraud.</p><h3>The Full Picture: Before and After</h3><p><strong>Execute cell 28</strong> to see the final comparison table.</p><p>The output shows a comprehensive side-by-side comparison of every dimension we’ve discussed:</p><p><strong>Point-in-Time Correctness</strong>: Without a Feature Store, you’re manually implementing temporal logic, hoping you got all the edge cases right, and constantly worrying about data leakage. With Feast, it’s automatic — the infrastructure enforces correctness.</p><p><strong>Code Duplication</strong>: Without a Feature Store, your data scientists are writing features in Pandas, your engineers are rewriting them in SQL, and every team has their own slightly-different implementation. With Feast, you have a single definition that everyone uses.</p><p><strong>Latency</strong>: The numbers speak for themselves — P95 latency drops from 48ms to 6.5ms. That’s not incremental improvement, that’s a qualitative shift in what’s possible.</p><p><strong>Governance</strong>: Without a Feature Store, features are scattered across notebooks, repositories, and tribal knowledge. With Feast, you have a centralized registry where every feature is documented, versioned, and discoverable.</p><p><strong>Feature Versioning</strong>: Without a Feature Store, you’re tracking feature versions in Git by hoping notebook filenames make sense. With Feast, versioning is native — you can see exactly which version of which features were used to train which model.</p><p><strong>Team Reusability</strong>: Without a Feature Store, every team reimplements every feature they need. With Feast, a feature defined once is immediately available to every team, every model, every use case.</p><p>Look at that latency drop: 48ms → 6.5ms. That’s <strong>87% faster</strong>. And you get correctness guarantees, governance, and reusability for free. This is why Feature Stores exist — they solve multiple critical problems simultaneously, problems that are painful to solve independently and nearly impossible to solve consistently across an organization.</p><h3>When Should You Actually Use a Feature Store?</h3><p>Feature Stores aren’t free. They add complexity, operational overhead, and cognitive load. So when does it make sense?</p><p><strong>Use a Feature Store when:</strong></p><p>✅ <strong>You have 3+ models in production</strong> — Shared feature infrastructure pays for itself</p><p>✅ <strong>You have latency SLAs &lt; 50ms</strong> — Pre-materialization is essential</p><p>✅ <strong>You have multiple teams</strong> — Centralized catalog prevents duplication</p><p>✅ <strong>You’ve been burned by training-serving skew</strong> — Single source of truth saves your …</p><p>✅ <strong>You care about data leakage</strong> — Point-in-time joins are hard to do right manually</p><p><strong>Don’t use a Feature Store if:</strong></p><p>❌ You’re running 1–2 models — Overhead isn’t worth it</p><p>❌ You’re doing batch scoring — Latency doesn’t matter</p><p>❌ You’re in pure research mode — Too early to standardize</p><p>❌ Your team is &lt; 3 people — Coordination overhead exceeds benefits</p><h3>The Hard Truth</h3><p>Feature Stores are infrastructure. They solve real, painful problems. But they’re not magic.</p><p>You’ll still need to:</p><ul><li><strong>Design good features</strong> (garbage in, garbage out)</li><li><strong>Monitor feature drift</strong> (distributions change in production)</li><li><strong>Maintain pipelines</strong> (data quality doesn’t fix itself)</li><li><strong>Handle versioning</strong> (features evolve)</li></ul><p>What Feature Stores give you is <strong>systematic solutions to systematic problems</strong>. They don’t make ML easy. They make ML <strong>operationally sound</strong>.</p><p>If you’ve shipped models to production, you’ve felt these problems. Now you know how to fix them.</p><h3>Appendix: Cell-by-Cell Execution Guide</h3><p>For quick reference:</p><ul><li><strong>Cells 1–3</strong>: Setup and installation</li><li><strong>Cells 4–9</strong>: Problem #1 (Training-Serving Skew)</li><li><strong>Cells 10–11</strong>: Problem #2 (Feature Duplication)</li><li><strong>Cells 12–14</strong>: Problem #3 (Latency)</li><li><strong>Cells 15–18</strong>: Problem #4 (Point-in-Time Correctness)</li><li><strong>Cells 19–20</strong>: Problem #5 (Governance)</li><li><strong>Cells 21–23</strong>: Solution #1 (Feature Definitions)</li><li><strong>Cells 24–25</strong>: Solution #2 (Point-in-Time Joins)</li><li><strong>Cells 26–27</strong>: Solution #3 (Online Serving)</li><li><strong>Cell 28</strong>: Final Comparison</li></ul><p>Run them in order. Don’t skip the problem cells — you need to feel the pain to appreciate the solution.</p><p><strong>Igor Comune.</strong></p><ul><li><a href="https://igorcomune.medium.com/">Igor Comune - Medium</a></li><li><a href="https://github.com/IgorComune">IgorComune - Overview</a></li></ul><p><a href="https://www.linkedin.com/in/igor-comune/">https://www.linkedin.com/in/igor-comune/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b447d87dd075" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Predicting B3 Stock Prices with LSTM: From Model to Production]]></title>
            <link>https://igorcomune.medium.com/predicting-b3-stock-prices-with-lstm-from-model-to-production-196967bf46dd?source=rss-977adbc510be------2</link>
            <guid isPermaLink="false">https://medium.com/p/196967bf46dd</guid>
            <category><![CDATA[api]]></category>
            <category><![CDATA[ml-model-deployment]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[machine-learning-engineer]]></category>
            <dc:creator><![CDATA[Igor Comune]]></dc:creator>
            <pubDate>Fri, 09 Jan 2026 20:40:15 GMT</pubDate>
            <atom:updated>2026-01-09T20:40:15.814Z</atom:updated>
            <content:encoded><![CDATA[<p>If you’re in Data Science and think “just train a model and deploy it” is enough, this post might change your perspective.</p><p>The Tech Challenge for Phase 4 of my Master’s in Machine Learning Engineering at FIAP came with a clear assignment: build an LSTM neural network to predict stock closing prices and deploy it as a REST API in production.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*O7xixyLTEJ5E1na0hNI57g.jpeg" /><figcaption>Ideogram.com</figcaption></figure><p>The requirements were explicit:</p><ul><li>Collect and preprocess historical stock data</li><li>Develop an LSTM model with proper evaluation metrics (MAE, RMSE, MAPE)</li><li>Save and export the trained model</li><li>Deploy as a RESTful API (Flask or FastAPI)</li><li>Implement monitoring for production performance</li></ul><p><strong>The team:</strong> Igor Comune (me), Éder Ray, Mário Gotardelo, João Marcelo<strong>, </strong>and Felippe Maurício.</p><blockquote>This project IS NOT about predicting the markets. This is about deployment of Machine Learning Models</blockquote><h3>The Model Architecture</h3><p>Here’s the breakdown:</p><pre>Input Layer (4 features: Open, High, Low, Volume)<br>    ↓<br>LSTM Layer 1 (128 hidden units)<br>    ↓<br>Dropout (0.2)<br>    ↓<br>LSTM Layer 2 (128 hidden units)<br>    ↓<br>Dropout (0.2)<br>    ↓<br>Fully Connected Layer (25 units, ReLU)<br>    ↓<br>Output Layer (Close price)</pre><p><strong>Key decisions:</strong></p><ul><li><strong>Lookback window: 30 days.</strong> Why 30? Because we needed enough data to capture monthly patterns without overfitting on noise. We tested 30, 60, and 90 days.</li><li><strong>2 layers with 128 units each.</strong> More layers = more capacity, but also more risk of overfitting. We found 2 layers was the sweet spot. Going to 3 layers didn’t improve performance.</li><li><strong>Dropout at 0.2.</strong> Regularization was essential. Without dropout, the model memorized training data and failed on validation.</li><li><strong>Adam optimizer (learning rate = 0.001).</strong> SGD was too unstable; Adam converged smoothly without much hyperparameter tuning.</li></ul><h3>The Data Pipeline (Where Things Got Messy)</h3><h3>Data Collection</h3><p>We’re using Yahoo Finance Python Library (yfinance) to import the data from the markets, src/utils/data_collection.py and in the same file we clear it from outliers and export it to data/processed/df.csv</p><h3><strong>Training</strong></h3><p>With the processed data ready, we train the model using src/models/lstm_model.py and src/utils/model_training.py, which implements the full training loop, validation strategy, checkpointing, and experiment tracking.</p><p>The model is trained to predict the next closing price using OHVL features (Open, High, Low, Volume), deliberately excluding <em>Close</em> from the inputs, as it is the prediction target.</p><p>Price-level prediction was chosen to simplify deployment, evaluation, and monitoring in this phase of the project. While predicting returns or direction would be more appropriate for trading-oriented systems, predicting absolute price levels allows for clearer error interpretation, easier debugging, and a more straightforward API contract during early production experimentation.</p><p>This choice reflects an engineering trade-off: prioritizing system design, reproducibility, and observability over financial realism in the initial iteration.</p><h4>Temporal Validation Strategy</h4><p>Time series models are especially sensitive to data leakage, so a standard random train/test split is not appropriate.</p><p>In this project, we adopted a <strong>strict chronological split</strong>, preserving the natural order of the data. The dataset was divided into <strong>training (70%)</strong>, <strong>validation (15%)</strong>, and <strong>test (15%)</strong> segments along the time axis.</p><p>Each split was then transformed into supervised learning samples using a <strong>sliding window approach</strong> (30-day lookback), where the model predicts the next closing price given the previous 30 observations. Importantly, windows are constructed <strong>only within each split</strong>, ensuring that no future information leaks into the training or validation phases.</p><p>This setup corresponds to an <strong>expanding-window, single-holdout evaluation</strong>, which reflects a realistic production scenario: the model is trained on past data and evaluated on strictly unseen future periods. While this approach does not capture all regime changes, it provides a conservative and leakage-safe estimate of model performance for this phase of the project.</p><h3><strong>Evaluation</strong></h3><p>And using src/utils/model_evaluation.py we evaluate the model itself.</p><p>This setup corresponds to an <strong>expanding-window, single-holdout evaluation</strong>, which reflects a realistic production scenario: the model is trained on past data and evaluated on strictly unseen future periods. While this approach does not capture all regime changes, it provides a conservative and leakage-safe estimate of model performance for this phase of the project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*obTpy4HJOPYHVJTq0fbKfQ.png" /><figcaption>Image 1 — Train/Loss</figcaption></figure><h3>Results (And Why R² = 0.98 Isn’t Too Good to Be True)</h3><p>Metrics on the test set:</p><ul><li><strong>MAE: </strong>$0.18 — Average error of 18 cents</li><li><strong>RMSE: </strong>$0.11 — Penalizes large errors more than MAE</li><li><strong>MAPE: </strong>5.10% — Percentage error, excellent for financial time series</li><li><strong>R²: </strong>98 — Model explains 98 of variance</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*vIg9YLve-x6Gr1IF7b19Og.png" /><figcaption>Image 2 — Real vs Predicted</figcaption></figure><p>This plot shows that the predicted values follow the general trend of the real values, indicating the model learned the overall dynamics of the series.</p><h3>The R² = 0.98 Problem</h3><p>When you see R² = 0.98, your first instinct should be skepticism. Is this overfitting? Data leakage?</p><p>In early phases, metrics like R² can be misleadingly high due to autocorrelation. Recognizing this was part of our learning curve.</p><p>We asked the same questions. Here’s what we validated:</p><ol><li><strong>Train vs. validation loss:</strong> They tracked closely without diverging. No overfitting.</li><li><strong>Out-of-sample testing:</strong> We tested on unseen periods (January 2024 forward). Performance held.</li><li><strong>Manual inspection:</strong> We checked predictions during volatile events (market crashes, earnings surprises). The model responded sensibly.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*4jFa0R1f92h2nYLkjApLmw.png" /><figcaption>Image 3 — Error Distribution</figcaption></figure><p>This repeated error distribution confirms that most errors remain small and centered near zero, reinforcing that the model is stable on average.</p><p><strong>The real reason for high R²:</strong> Stock prices are highly autocorrelated. Today’s price is a strong predictor of tomorrow’s price. The model isn’t “too good” — it’s capturing that inherent autocorrelation.</p><p><strong>Important caveat:</strong> This doesn’t mean the model is useful for trading. Predicting the direction (up/down) is harder than predicting the value.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*QemHxS4pjkLT-x0ppAzDIg.png" /><figcaption>Image 4 — Residuals</figcaption></figure><p>This plot shows that residuals are not randomly distributed around zero over time, indicating that the model’s errors are structured rather than purely random.</p><p><strong>Out-of-pattern behavior &amp; possible causes:</strong><br> The increasing variance and large residual spikes toward the end of the series suggest heteroscedasticity and regime change, meaning the model was trained on past dynamics that no longer hold, lacks features to capture volatility shifts, or is effectively extrapolating beyond its learned domain.</p><p>All of the results were saved both on the folder /results and inside /mlruns (folder created by the experiments inside MLFlow.</p><h3>The API</h3><p>It was required basically 3 endpoints from us: prediction, health and monitoring.</p><p>All of them were implemented using FAST API inside src/api, using main.py and the following command to launch the server and all of the endpoints:</p><pre>uvicorn src.api.main:app --reload --port 8000</pre><h3>Why FastAPI?</h3><p>We considered Flask. FastAPI won for these reasons:</p><ol><li><strong>Automatic validation:</strong> Pydantic schemas catch errors before they hit the model.</li><li><strong>Interactive docs:</strong> Swagger UI out-of-the-box. No manual documentation needed.</li><li><strong>Async by default:</strong> Better performance for I/O-bound operations.</li><li><strong>Type hints:</strong> Fewer runtime bugs.</li></ol><p>Flask is fine. FastAPI is better for production ML.</p><p>The endpoints:</p><pre>/predict: receives the input data and outputs the prediction<br>/metrics: evaluate the consumption of RAM, CPU...<br>/health: health of the server</pre><p><strong>Why Prometheus?</strong> Industry standard. Integrates with Grafana. Pull-based architecture simplifies networking.</p><p>And for testing the endpoint of prediction you’ll need just to run (in parallel, of course the server) and the file infer.py in the root folder of the project.</p><p>So, we have:</p><ol><li>The data collection and transformations</li><li>The model</li><li>The training</li><li>The evaluation</li><li>The deployment</li><li>The model prediction output</li></ol><p>Using Python, Docker, MLFlow, Prometheus, FastAPI, PyTorch, SkLearn and Pandas.</p><h3>Containerization</h3><p>Docker was non-negotiable for reproducibility:</p><pre>FROM python:3.12-slim<br><br>ENV PYTHONDONTWRITEBYTECODE=1<br>ENV PYTHONUNBUFFERED=1<br><br>RUN apt-get update \<br>    &amp;&amp; apt-get install -y --no-install-recommends curl \<br>    &amp;&amp; rm -rf /var/lib/apt/lists/*<br><br>RUN useradd -m appuser<br>USER appuser<br><br>WORKDIR /app<br><br>COPY requirements.txt .<br><br>RUN pip install --no-cache-dir --upgrade pip \<br>    &amp;&amp; pip install --no-cache-dir -r requirements.txt<br><br>COPY . .<br><br>EXPOSE 8000<br><br>HEALTHCHECK --interval=30s --timeout=5s --retries=3 \<br>  CMD curl --fail http://localhost:8000/health || exit 1<br><br>CMD [&quot;uvicorn&quot;, &quot;src.api.main:app&quot;, &quot;--host&quot;, &quot;0.0.0.0&quot;, &quot;--port&quot;, &quot;8000&quot;]</pre><blockquote>“This container focuses on simplicity over optimization. In later stages, I plan to separate training and inference images and adopt multi-stage builds.”</blockquote><p><strong>Production notes:</strong></p><ul><li>Multi-stage builds would reduce image size (we didn’t do this for the Tech Challenge, but you should).</li><li>Don’t run as root in production.</li><li>Scan for vulnerabilities with Trivy or Snyk.</li><li>Use a reverse proxy (Nginx) instead of exposing port 8000 directly.</li></ul><h3>What We Didn’t Do (And Should Have)</h3><p>Let’s be honest about limitations:</p><ol><li><strong>No fundamental data:</strong> The model is purely technical. It doesn’t know about earnings, news, or sentiment.</li><li><strong>Fixed lookback window:</strong> 30 days works well on average, but during high volatility, a shorter window might be better. We didn’t implement adaptive windowing.</li><li><strong>Single-stock prediction:</strong> We predict each stock independently. Portfolio-level models that consider correlations between stocks would be more robust.</li><li><strong>No online learning:</strong> The model is static. In production, you’d want to retrain periodically as new data arrives (concept drift is real in financial markets).</li></ol><h3>Engineering Trade-offs &amp; Learning Progression</h3><ul><li><em>Used a single Docker image for simplicity; later phases will split training and inference containers.</em></li><li><em>Metrics are strong due to autocorrelation; next iterations will benchmark against naive baselines.</em></li><li><em>Model is retrained offline; future work includes scheduled retraining and drift detection.</em></li><li><em>Monitoring focuses on system metrics; model performance monitoring will be expanded.</em></li></ul><h3>Conclusion</h3><p>This project wasn’t just about achieving good metrics. It was about understanding the entire ML pipeline: data collection, preprocessing, model architecture, deployment, monitoring, and documentation.</p><p><strong>The real challenge:</strong> Making technical decisions under constraints (time, compute, data quality) and justifying those decisions.</p><p><strong>Full code available at:</strong> <a href="https://github.com/IgorComune/masters_tc_LSTM_stock_prediction">github.com/IgorComune/masters_tc_LSTM_stock_prediction</a></p><p>Video: <a href="https://www.youtube.com/watch?v=SfdFywHQDzw">https://www.youtube.com/watch?v=SfdFywHQDzw</a></p><h3>Acknowledgments</h3><p>This project wouldn’t have been possible without <strong>Éder Ray</strong>, <strong>Mário Gotardelo</strong>, and <strong>Felippe Maurício</strong>. Working as a team brought diverse perspectives on model design, software engineering, and ML best practices.</p><p>Thanks to FIAP for structuring the Tech Challenge in a way that simulates real-world ML projects.</p><blockquote><strong>Disclaimer:</strong> This project is for educational purposes only. Stock price prediction models <strong>do not constitute financial advice</strong>. Always consult qualified professionals before making investment decisions. Past performance does not guarantee future results.</blockquote><p><strong>Igor Comune.</strong></p><p><a href="https://github.com/IgorComune">IgorComune - Overview</a></p><p><a href="https://www.linkedin.com/in/igor-comune/">https://www.linkedin.com/in/igor-comune/</a></p><p><strong>Éder Ray</strong></p><p><a href="https://github.com/ederray">ederray - Overview</a></p><p><a href="https://www.linkedin.com/in/ederray/">https://www.linkedin.com/in/ederray/</a></p><p><strong>Mário Gotardelo</strong></p><p><a href="https://github.com/MariolGotta">MariolGotta - Overview</a></p><p><a href="https://www.linkedin.com/in/m%C3%A1rio-gottardello-2456a818a/">https://www.linkedin.com/in/m%C3%A1rio-gottardello-2456a818a/</a></p><p><strong>Felippe Maurício</strong></p><p><a href="https://github.com/felippemauricio">felippemauricio - Overview</a></p><p><a href="https://www.linkedin.com/in/felippemauricio/">https://www.linkedin.com/in/felippemauricio/</a></p><p><strong>João Marcelo</strong></p><p><a href="https://github.com/joaomendonca-py">joaomendonca-py - Overview</a></p><p><a href="https://www.linkedin.com/in/joaomarcelomendonca/">https://www.linkedin.com/in/joaomarcelomendonca/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=196967bf46dd" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Context Engineering: Teaching Machines to Read Between the Lines]]></title>
            <link>https://igorcomune.medium.com/context-engineering-teaching-machines-to-read-between-the-lines-788702daeb4a?source=rss-977adbc510be------2</link>
            <guid isPermaLink="false">https://medium.com/p/788702daeb4a</guid>
            <category><![CDATA[prompt-engineering]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[writing-prompts]]></category>
            <category><![CDATA[ai-agent]]></category>
            <dc:creator><![CDATA[Igor Comune]]></dc:creator>
            <pubDate>Fri, 07 Nov 2025 15:51:32 GMT</pubDate>
            <atom:updated>2025-11-07T15:51:32.364Z</atom:updated>
            <content:encoded><![CDATA[<p>Imagine you are talking to a close friend. You just say <strong>“that place”</strong> and they immediately know exactly which restaurant you are talking about. You mention <strong>“yesterday’s problem”</strong> and they instantly grasp the whole situation. This magic happens because you share a context — an invisible web of memories, experiences, and mutual understanding that fills in the communication gaps.</p><p>Now imagine trying the same conversation with someone you just met. You would need to explain every detail, provide full addresses, recount the entire story from the beginning. The difference between these two conversations is precisely what context engineering seeks to solve in the world of artificial intelligence.</p><h3>The Problem of Invisible Gaps</h3><p>When humans talk, we operate at a surprisingly high level of informational entropy. We leave words out, use implicit references, and rely on emotional cues. We do this because we know our conversation partner can <strong>“fill in the gaps”</strong> — actively reducing information entropy through shared knowledge and situational awareness.</p><p>Machines, on the other hand, are like that recent acquaintance. They cannot guess what you meant. They do not understand your implicit references. They do not pick up on your emotional cues. As a result, we need to <strong>“pre-process”</strong> our context for them — transforming high-entropy information into low-entropy representations they can understand.</p><p>This transformation represents the central effort of context engineering: the work you need to invest to make machines understand what you mean when you say <strong>“that place.”</strong></p><h3>The Decades-Long Journey: Learning to Talk to Machines</h3><p>Contrary to popular belief, context engineering was not born with ChatGPT. It has existed for over 20 years, continuously evolving as machines become smarter.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9vuKRK650OmXJQDI1LNfTA.png" /><figcaption>Context Engineering 2.0: <a href="https://arxiv.org/pdf/2510.26493v1">https://arxiv.org/pdf/2510.26493v1</a></figcaption></figure><h4>Era 1.0: The Age of Forms and Clicks (1990–2020)</h4><p>Think of the first phase as that extremely formal conversation with a strict bureaucrat. You need to fill out every field, follow every protocol, and use exactly the right words. Nothing can be left implicit.</p><p>In this era, dominated by ubiquitous computing and graphical interfaces, humans did all the heavy lifting. Designers acted as <strong>“intention translators,”</strong> converting complex human goals into structured, machine-readable formats. Clicks on menus, simple sensors, GPS coordinates — everything had to be explicitly defined and translated.</p><p>The <strong>Context Toolkit</strong>, developed by Anind Dey in the early 2000s, was a landmark of this time. It organized context through modular abstractions: <strong>Widgets</strong> captured sensor signals, <strong>Interpreters</strong> derived higher-level meanings, <strong>Aggregators</strong> integrated multiple sources. It was like teaching a child to recognize patterns — but every pattern needed to be carefully programmed.</p><h4>Era 2.0: The Natural Language Revolution (2020-Present)</h4><p>The release of GPT-3 in 2020 changed everything. Suddenly, machines started to understand natural language. It was as if that recent acquaintance had finally learned your cultural references and could keep up with more fluid conversations.</p><p>Now you can say <strong>“look up related documentation for me”</strong> and the system understands. You can send images, audio, and conversation history. The machine doesn’t just receive structured data — it interprets ambiguous intentions, fills in information gaps, and actively collaborates.</p><p>But here is the challenge: <strong>the more context we accumulate, the harder it becomes to manage.</strong> It’s like that friend who remembers every single detail of every conversation you have ever had — helpful, but <strong>potentially overwhelming</strong>.</p><h3>The Three Pillars: Collect, Manage, Use</h3><h4>1. Collection: Capturing the Unsaid</h4><p>In Era 1.0, we collected context through limited sensors: GPS location, time of day, mouse clicks. In Era 2.0, collection has expanded dramatically. Smartphones capture text, image, audio, location, and touch. Smartwatches monitor heart rate and movement. Brain-computer interfaces are starting to capture neural signals and emotional states.</p><p>The key is not the volume of data, but <strong>minimal sufficiency</strong>: collecting only what is necessary to support the task. And maintaining <strong>semantic continuity</strong>: preserving meaning, not just raw data.</p><h4>2. Management: Organizing Memories</h4><p>Imagine your personal memory. You don’t remember every second of every day with equal clarity. Some things stay in short-term memory and fade. Others consolidate into long-term memory. The most important ones you revisit and reinforce.</p><p>Modern systems adopt similar architectures:</p><ul><li><strong>Short-term memory:</strong> Recent context with high temporal relevance, stored for quick access</li><li><strong>Long-term memory:</strong> Important information processed and abstracted for permanent storage</li><li><strong>“Self-baking”:</strong> The process of “baking” raw context into structured knowledge — like transforming episodic experiences into semantic wisdom</li></ul><p>Claude Code, for example, maintains structured notes. Key information is periodically written out of the context window into external memory and retrieved when needed. This allows the agent to track complex tasks over thousands of steps, even after restarts.</p><h4>3. Usage: Choosing What Matters</h4><p>Not all available context is useful for the current task. In fact, empirical evidence shows that the performance of AI agents often <strong><em>decreases</em> when context windows exceed about 50% of their capacity</strong>. Too much context can be as detrimental as insufficient context.</p><p>Modern systems employ various selection strategies:</p><ul><li><strong>Semantic relevance:</strong> Searching for vector similarity to find related content</li><li><strong>Logical dependency:</strong> Tracking which information relies on previous steps</li><li><strong>Recency and frequency:</strong> Prioritizing recent or frequently accessed information</li><li><strong>User preference:</strong> Learning from feedback what each user values</li></ul><p>It’s <strong>attention before attention</strong> — choosing what deserves to be observed.</p><h3>Sharing Context: The Conversation Between Machines</h3><p>When multiple agents need to work together, a new challenge arises: how to share context effectively? Imagine three friends planning a trip. Each has different information, and everyone needs to be on the same page.</p><p>Modern systems use three main approaches:</p><ul><li><strong>Context embedded in prompts:</strong> An agent summarizes its thought process, and the next one reads and continues</li><li><strong>Structured messages:</strong> Agents exchange fixed-format messages (task type, input data, results)</li><li><strong>Shared memory:</strong> Agents write to and read from a common space, communicating indirectly</li></ul><p>Each method has its trade-offs between clarity, efficiency, and flexibility.</p><h3>The Horizon: Moving Towards Human-Level Intelligence</h3><p>Looking ahead, we can foresee two more eras:</p><h4>Era 3.0: Human-Level Intelligence</h4><p>In this phase, machines will understand context as humans do. They will pick up on social cues, emotional states, and rich environmental dynamics. They will be able to sustain truly natural conversations, acting as knowledgeable and effective colleagues. It will be like talking to that close friend — where <strong>“that place”</strong> is instantly understood.</p><h4>Era 4.0: Superhuman Intelligence</h4><p>In the final, speculative phase, machines will not just understand our context — they will transcend it. With a <strong>“god’s eye view,”</strong> they will comprehend our intentions more deeply than we do ourselves. Instead of passively adapting to human-defined context, they will actively construct new contexts for us, revealing hidden needs and guiding our thinking.</p><p>We already see glimpses of this: in Go, professional players learn new, superhuman strategies from the AI. Machines become sources of insight and inspiration.</p><h3>Challenges on the Path</h3><p>The journey faces significant hurdles:</p><ul><li><strong>Limited collection:</strong> We still rely heavily on explicit user input</li><li><strong>Scaling storage:</strong> How to organize ever-growing context scalably?</li><li><strong>Imperfect understanding:</strong> Current systems struggle with complex logic and relational information</li><li><strong>Performance bottlenecks:</strong> Transformer architectures suffer from quadratic complexity in long contexts</li><li><strong>Context selection:</strong> How to filter noise and keep only what is relevant?</li></ul><h3>A New Form of Digital Existence</h3><p>In the age of context-centric AI, this idea gains new computational meaning: individuals are increasingly defined not by their physical presence or conscious activity, but <strong>by the digital contexts they generate </strong>— their conversations, decisions, and interaction traces.</p><p>These contexts can persist, evolve, and even continue to interact with the world through AI systems long after a person’s departure. The human mind may not be uploaded, but the human context can be — transforming context into an enduring form of knowledge, memory, and identity.</p><h3>Conclusion: Bridging the Gaps Together</h3><p>Context engineering is fundamentally about reducing the distance between how humans think and how machines process. It is about transforming that formal, bureaucratic conversation into something closer to a chat between friends — where much can be left between the lines because shared understanding exists.</p><p>As machines become smarter, they take on more responsibility for interpreting, reasoning, and even constructing context. The human effort gradually decreases. We are moving toward a future where machines will not only understand us but will illuminate and expand our understanding of ourselves.</p><p>And perhaps, in that future, when you just say <strong>“that place,”</strong> the machine will not only know which restaurant you are talking about — it will also suggest the perfect dish based on your current mood, remember the last time you were there, and book a table at the ideal time.</p><p>Because in the end, context is not about data. It is about <strong>shared meaning.</strong> And we are just starting to teach machines to share ours.</p><p>Post inspired by this <a href="https://arxiv.org/pdf/2510.26493v1">paper</a>.</p><p>Igor Comune.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=788702daeb4a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[I Defenestrated Windows and Adopted a Penguin]]></title>
            <link>https://igorcomune.medium.com/i-defenestrated-windows-and-adopted-a-penguin-bd6e45408056?source=rss-977adbc510be------2</link>
            <guid isPermaLink="false">https://medium.com/p/bd6e45408056</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[data]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[deep-learning]]></category>
            <dc:creator><![CDATA[Igor Comune]]></dc:creator>
            <pubDate>Thu, 23 Oct 2025 02:23:27 GMT</pubDate>
            <atom:updated>2025-10-24T14:35:59.311Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>&gt;&gt; sudo apt remove microsoft-windows</blockquote><p>If you’re a data scientist you must read this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4iMKcbp3uFfKzQV4En4KNg.jpeg" /><figcaption>Ideogram</figcaption></figure><blockquote>22/oct/2025 marks my last day using Windows.</blockquote><h3>Intro</h3><p>In my last <a href="https://igorcomune.medium.com/defenestrate-windows-41d7331e23ff">post</a> I described my why I choose Linux Ubuntu.</p><p><a href="https://igorcomune.medium.com/defenestrate-windows-41d7331e23ff">Defenestrate Windows</a></p><p><em>Why I switched to Linux as a data scientist — and how I split work and play without losing my mind.</em></p><p>Today is my very last day using Windows. <strong>This post exists to convince you to adopt a penguin too</strong> — or at least to make you stop reflexively reaching for a Windows key every time something breaks.</p><h3>Quick summary for the lazy</h3><p>If you work with data, there are three practical needs you’ll hit quickly: <strong>GPU support for CUDA</strong>, <strong>stable system for development</strong>, and <strong>the freedom to tweak things without paying a ransom in reboot time</strong>. My choice: <strong>Ubuntu 24.04 LTS</strong> as my primary work distro, <strong>Cachy OS</strong> on a separate SSD for gaming. Dual-boot, separate SSDs — because mixing a workstation and a gaming rig on the same OS is asking for drama.</p><h3>Which distro and why</h3><ul><li><strong>Ubuntu</strong> — best all-around for deep learning and robotics simulations (Isaac Sim, Gazebo, Unity/Unreal integrations tend to behave better here). If you’re doing deep reinforcement learning, this is the safe, boring, reliable choice — the distro equivalent of buying a Swiss watch.</li><li><strong>Pop!_OS</strong> — very friendly for data scientists, excellent out-of-the-box hardware support and smoother GPU setup for many users. Great if you don’t need the extra robotics stack stability.</li><li><strong>Mint / Fedora</strong> — also fine, but each has quirks (repos, packaging, or driver handling) that may require extra fiddling.</li><li><strong>Gaming distros (Cachy OS, Nobara, Bazzite)</strong> — tuned for low-latency gaming performance and bleeding-edge kernels. Great for frames-per-second; not ideal for ML workloads unless you enjoy troubleshooting drivers at 2 AM.</li></ul><p>Yes, all the above can game fine — but gaming-focused distros often prioritize kernel and scheduler tweaks that aren’t always ideal for reproducible ML experiments.</p><h3>My setup</h3><p><strong>Main SSD — Ubuntu 24.04 LTS</strong><br>I run Ubuntu 24.04 LTS on my main SSD because — bluntly — it’s the best compromise between <strong>up-to-date kernel/drivers</strong> and <strong>distribution-level stability</strong> for heavy ML/robotics work. CUDA and NVIDIA tooling have first-class documentation and installers for mainstream Linux distros (Ubuntu is the most commonly supported target), so you waste less time beingfriend driver hell and more time training models. If you plan to run Isaac Sim, many NVIDIA robotics/simulation stacks expect Linux (and <strong>Ubuntu variants are the path of least resistance</strong>).</p><p>Why that matters practically: when you need GPU-accelerated training, you want a distro where the CUDA toolkit and NVIDIA drivers install cleanly, where Docker + NVIDIA Container Toolkit work predictably, and where community help (and compatibility notes) exist in abundance. Ubuntu ticks those boxes.</p><p><strong>Second SSD — CachyOS (gaming only)</strong><br>CachyOS is an Arch-based, performance-tuned distro with kernels and scheduler tweaks focused on responsiveness and gaming packages pre-bundled. It offers gaming meta-packages, optimized kernels (BORE / Zen variants) and compilation optimizations — good for squeezing extra FPS and low-latency behaviour out of your hardware. It’s perfect as the “nightclub” drive where you chase frame rates, but it’s not the tidy production environment you want for reproducible ML experiments.</p><p><strong>Why separate SSDs?</strong><br>Because mixing “work” and “play” on the same OS is an invitation to accidental kernel changes, driver experiments and repo upgrades that break reproducibility. Physical separation = deliberate separation of concerns. Analogy: <strong>one SSD is your museum (careful, catalogued), the other is the rave.</strong> Keep them physically apart.</p><h3>Tools that made the switch bearable</h3><p><strong>LinuxToys</strong> — one-click installers and post-install scripts<br>LinuxToys is a curated collection/GUI that automates many common installs and tooling across distros (it helps install gaming launchers, dev tools and device helpers). Instead of copy-pasting 17 commands and hunting missing dependencies, LinuxToys bundles common flows into sane installers. That’s why I used it to provision Steam/Proton tools, utilities, and a few convenience optimizations. (Yes, it’s like having someone hand you pizza at 2AM.)</p><p><strong>WinBoat — Windows apps inside a containerized VM</strong><br>WinBoat runs a Windows VM inside Docker and exposes Windows apps as windows on your Linux desktop using RDP/RemoteApp tricks. For local <strong>Power BI Desktop</strong> usage (which has no native Linux client), WinBoat is a pragmatic, user-friendly way to run the real Windows app inside an automated VM/container — less fiddly than hand-rolling a VM and more integrated than full remote desktop. It’s not magic; it automates the engineering so you can keep working.</p><p>Caveat (the boring but important part): WinBoat depends on the underlying Windows image, QEMU/Docker plumbing and FreeRDP integration. Sometimes you’ll hit edge cases (driver passthrough, RDP quirks) that require tweaking or updated releases. The community is active and improving it, but keep the expectation: it’s an engineered workaround that solves a problem, not an official port.</p><h3>Power BI in Linux — the pragmatic truth</h3><p><strong>Short answer:</strong> there is <strong>no official Power BI Desktop for Linux</strong>. Microsoft provides Power BI Desktop for Windows; the “official” Linux route is to use the <strong>Power BI Service (web)</strong> for many tasks, or run the Desktop inside a Windows VM/container for local, offline or heavy authoring workflows.</p><ol><li><strong>Power BI Service (web)</strong> — use the browser-based service for most sharing and many modelling tasks. Best for collaboration and zero local-app headaches. Requires cloud/tenant licensing.</li><li><strong>Run Power BI Desktop in a Windows VM</strong> — local VM (VirtualBox/QEMU) or containerized VM solutions like <strong>WinBoat</strong> are realistic for offline/advanced desktop features. This gives you native Power BI Desktop behaviour at the cost of a Windows guest.</li><li><strong>Hosted/cloud Windows VM</strong> — spin up a Windows VM in the cloud and RDP in. Useful if your workstation is weak but latency is acceptable.</li><li><strong>Third-party “hosted desktop” services</strong> — providers that run Power BI Desktop in the cloud and stream the UI (less control, but fast to start). (Examples exist; vet security/cost.)</li></ol><p>So yes: your WinBoat solution is pragmatic and commonly used in the Linux community precisely because Microsoft hasn’t shipped a native Linux client. You’re not being lazy — you’re being realistic.</p><h3>Final wisdom</h3><blockquote><em>If you’re serious about data science, machine learning, and reproducible engineering, Linux is the practical </em>upgrade<em> — not a hobbyist detour. You get:</em></blockquote><ul><li><strong>Better developer tooling</strong> and native shells, package managers, and scripting that actually scale with automation.</li><li><strong>Cleaner GPU and container workflows</strong> for CUDA, Docker + NVIDIA Container Toolkit, and a proper environment for sim/robotics stacks (Isaac Sim, Gazebo, ROS) that expect Linux.</li><li><strong>Less vendor lock-in for your workflows</strong>: you control updates, packages, kernels, and can reproduce environments with Docker/containers and infrastructure as code.</li><li><strong>Performance options for gaming</strong> (if you want them) without sacrificing a stable, reproducible workstation — just put your games on a different SSD and sleep well.</li></ul><p>Is there effort involved? Of course — but the effort pays back in <strong>reliability, control and fewer “works on my machine” tragedies</strong>. People who think Windows “just works” for every heavy data workflow are usually replaying an old advert in their head. <strong>Linux will make you a better engineer</strong>: you’ll read logs, fix the cause, and automate the fix — and you’ll stop blaming tools for your process gaps.</p><p>Igor Comune.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bd6e45408056" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Defenestrate Windows]]></title>
            <link>https://igorcomune.medium.com/defenestrate-windows-41d7331e23ff?source=rss-977adbc510be------2</link>
            <guid isPermaLink="false">https://medium.com/p/41d7331e23ff</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[ubuntu]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[windows]]></category>
            <dc:creator><![CDATA[Igor Comune]]></dc:creator>
            <pubDate>Wed, 15 Oct 2025 19:56:38 GMT</pubDate>
            <atom:updated>2025-10-15T19:58:20.714Z</atom:updated>
            <content:encoded><![CDATA[<p>If you work with data and are considering moving to Linux, this is a post you don’t want to skip.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ef5Bz3ERK1rj9aRnz8PvaA.jpeg" /><figcaption>Ideogram</figcaption></figure><p>For the past six years, I’ve been using Windows primarily for Power BI and gaming (mainly on Steam, <a href="https://store.steampowered.com/app/393380/Squad/">Squad</a>). Everything else would arguably run better on Linux.</p><p>There are two key reasons behind my shift — worth noting. WSL and Google Colab have been amazing, but as I started experimenting with computer vision and reinforcement learning, the limitations became glaring… and quickly.</p><p>Microsoft’s AI obsession hasn’t helped either. From December 2022 until now, it feels like AI is everywhere — Cortana, CoPilot… AI, AI, AI. Meanwhile, their “wonderful” operating system seems almost like an afterthought.</p><p>Add to that the constant friction between GitHub projects designed for Linux versus Windows, Windows performance issues, the need to debloat, libraries that work exclusively on Linux, and version mismatches for tools like TensorFlow, PyTorch, CUDA, Gymnasium, and PySpark… it was chaos. Honestly, the reasons to switch are endless — you probably know them better than I do.</p><p>It was time to defenestrate Windows.</p><p>Two things finally pushed me over the edge:</p><ol><li><strong>Linux Gaming subreddit</strong> — an amazing, knowledgeable community.</li><li><strong>Winboat</strong> — arguably the most important reason.</li></ol><p>I’ve been following the Linux Gaming subreddit for at least two years, and their collective experience finally convinced me. The last major obstacle? Power BI. It simply couldn’t run on Linux — any Linux distribution — despite every tool the community had created, from Wine to Bottles.</p><p>And then, I was randomly scrolling down youtube videos and <a href="https://www.youtube.com/watch?v=5JiSLDmSrOY">this video</a> (in Brazilian Portuguese) from the youtuber called “<a href="https://www.youtube.com/@psygreg">psygreg</a>” showed up.</p><p>And then, throught this video I met the wonderful <a href="https://www.winboat.app/">https://www.winboat.app/</a>. This app is basically a Windows running on a Docker, inverse of the WSL.. the new LSW where you run anything</p><p>And in that very moment, I realized that I could FINALLY and DEFINITELY make the full switch to Linux.</p><p>At first, I thought it would be as simple as picking my favorite distro and that’s it… but if you’re thinking the same, slow down. Let me tell you — it’s not nearly that simple.</p><h3><strong>Investigation</strong></h3><p>Linux is the kernel; distributions are essentially Linux optimized for different purposes.</p><p>For the sake of time, I’ll explain how I chose my distro — something that might be useful if you work with data.</p><p>First, to choose a distro, you need to know your requirements. If you’re a data scientist working with computer vision and reinforcement learning, like I’ve been doing recently, pay attention.</p><p><strong>Main apps/programs:</strong> Python, CUDA, PyTorch/TensorFlow, Gymnasium, OpenCV, Unity, Unreal Engine, Gazebo, PX4, Steam, Epic Games, ROS, Isaac Sim, and Nvidia Omniverse.</p><p>I started with the basics: Ubuntu, Pop!_OS, and Mint. I also explored other distros, but many were either not as performant as they could be or extremely complicated, like Arch. That’s when I came across EndeavourOS and CachyOS.</p><p>Then began the comparison: Ubuntu, Pop!_OS, Mint, EndeavourOS, and CachyOS. Mint was almost immediately removed from the list, followed by EndeavourOS. That left Ubuntu, Pop!_OS, and CachyOS.</p><p>Let’s pause and analyze the choices a bit. Ubuntu and Pop!_OS are Debian-based, offering stability and user-friendliness. CachyOS, on the other hand, is a performance-oriented Arch-based distro: friendly, faster, and lighter.</p><p>Due to stability concerns I found online — particularly for reinforcement learning — I decided to remove Pop!_OS.</p><p>As tempting as CachyOS was, offering higher FPS and pre-tuned performance, Isaac Sim presented serious issues on it, along with some minor problems related to reinforcement learning. Unfortunately, that meant CachyOS was out.</p><p>The final contenders? Ubuntu 22, Ubuntu 24, and, reluctantly, CachyOS… which could have been the performance winner, but compatibility won this round.</p><h3>The Final Choice</h3><p>The final choice was guided by technical compatibility and long-term stability.<br>Or Ubuntu 24.04 LTS presented the best balance between:</p><ol><li>Performance in IA loads and simulation (Isaac Sim, Docker, CUDA).</li><li>Stability for professional and academic use.</li><li>Integration with robotics tools and graphics engines (Gazebo, Unity, Unreal).</li><li>Flexibility for gaming via Steam, no need for dual boot.</li><li>Works better with GeForce series 40 (my new laptop).</li></ol><p>The result of the analysis was a rational decision: o Ubuntu 24 offers the most complete and coherent ecosystem for development, simulation and research in AI, combining industrial compatibility, NVIDIA support and production performance in a unique operational environment.</p><p>(I created 2 bootable USB’s: ubuntu 24 and CachyOS, because I’m still considering running most of the applications on docker)</p><h3>Conclusion</h3><p>While<strong> I haven’t fully transitioned from Windows to Linux just yet</strong>, the decision is made and the groundwork is laid. Once I complete the switch, I’ll share my firsthand experience, detailing the challenges, surprises, and benefits of moving entirely to Ubuntu 24, so anyone considering the leap can see what it’s really like.</p><p>Igor Comune.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=41d7331e23ff" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Power BI Service: Google Sheets Error (429): Too Many Requests]]></title>
            <link>https://medium.com/microsoft-power-bi/power-bi-service-google-sheets-error-429-too-many-requests-451b7cdb7de3?source=rss-977adbc510be------2</link>
            <guid isPermaLink="false">https://medium.com/p/451b7cdb7de3</guid>
            <category><![CDATA[data-visualization]]></category>
            <category><![CDATA[power-bi]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[power-bi-tutorials]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Igor Comune]]></dc:creator>
            <pubDate>Tue, 07 Oct 2025 19:40:33 GMT</pubDate>
            <atom:updated>2025-10-07T19:40:33.928Z</atom:updated>
            <content:encoded><![CDATA[<p>I ran into a classic “I asked for fresh data and Google told me to calm down” situation: Power BI refreshing a dataset that reads directly from a Google Sheet started failing with 429 Too Many Requests.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dwpNqXVRxmB24cfnk9NKZA.jpeg" /><figcaption>Ideogram</figcaption></figure><p>If you’ve seen that error, you know it’s not a mysterious Power BI bug — it’s a rate-limit. Google is politely (and correctly) <strong>preventing you from hammering their API.</strong></p><p>Below I’ll be blunt and practical: what actually causes this, what I usually check first, and a small,<strong> reusable Power Query (M)</strong> pattern I built that solved it for me: a generic retry wrapper with exponential backoff you can drop into the Advanced Editor and reuse for any Google Sheets URL.</p><p><strong>🎁 </strong><a href="https://powerbi-masterclass.short.gy/learning-database?utm_source=medium&amp;utm_medium=medium-post&amp;utm_campaign=database-medium-post-start"><strong>Get friend links for all of our 1000&gt; Power BI learning articles here</strong></a><strong> 🎁</strong></p><h3>The problem (fast)</h3><ul><li>429 = you made too many requests in a short time, or your project hit a quota.</li><li><strong>Common real-world triggers</strong>: multiple reports/dashboards hitting the sheets api, aggressive scheduled refresh intervals, parallel queries asking different ranges at the same time, or many services using the same API key/credential.</li><li><strong>The immediate effect</strong>: Power BI fails to fetch the content and the dataset refresh stops.</li></ul><p>If the 429 is temporary (bursts of traffic, intermittent), the right approach is a retry with <strong>exponential backoff </strong>— not blind retries that double-down on the problem. Think of it like tapping someone on the shoulder vs. repeatedly shouting in their ear.</p><h3>The solution I used (drop-in Power Query M)</h3><p>Below is a compact, <strong>generic</strong> snippet: you just set Url and MaxRetries, paste into Advanced Editor, and the query will call GoogleSheets.Contents with retries and exponential backoff. It’s intentionally minimal — no transforms, no extra stages — because you asked for a general wrapper.</p><blockquote>Power BI Desktop &gt; Transform Data &gt; Advanced Editor</blockquote><pre>let<br>    // === CONFIGURE HERE ===<br>    Url = &quot;https://docs.google.com/spreadsheets/d/YOUR-SHEET-ID-HERE/&quot;, // replace with your sheet URL<br>    MaxRetries = 5, // maximum number of attempts (0 = no retries)<br>   // Generic retry function with exponential backoff<br>    Retry = (operation as function, optional maxRetries as nullable number) =&gt;<br>    let<br>        maxR = if maxRetries = null then 5 else maxRetries,<br>        fn = (attempt as number) =&gt;<br>            let<br>                tryRes = try operation(),<br>                result =<br>                    if tryRes[HasError] then<br>                        if attempt &lt; maxR then<br>                            // wait 2^attempt seconds, then try again<br>                            (Function.InvokeAfter(()=&gt; fn(attempt + 1), #duration(0,0,0, Number.Power(2, attempt))))()<br>                        else<br>                            // exhausted attempts: raise original error<br>                            error tryRes[Error]<br>                    else<br>                        tryRes[Value]<br>            in<br>                result<br>    in<br>        fn(0),<br>    // Call GoogleSheets.Contents wrapped with retry<br>    Source = Retry(()=&gt; GoogleSheets.Contents(Url), MaxRetries)<br>in<br>    Source</pre><p>I also tested a different function that creates a “delay” between the requests.</p><pre>let<br>    // === CONFIGURE HERE ===<br>    Url = &quot;https://docs.google.com/spreadsheets/d/YOUR-SHEET-ID-HERE/&quot;, // replace with your sheet URL<br>    MaxRetries = 5,<br>    InitialDelaySeconds = 10,      // sleep before the first attempt (seconds)<br>    FixedDelaySeconds = 5,         // fixed sleep between attempts (seconds)<br>    UseExponentialBackoff = true,  // if true, adds 2^attempt seconds to the wait<br><br>    // Sleep helper: blocks for given seconds using Function.InvokeAfter<br>    Sleep = (secs as number) =&gt;<br>        let<br>            s = Number.RoundDown(secs),<br>            _ = if s &gt; 0 then Function.InvokeAfter(()=&gt; null, #duration(0,0,0, s)) else null<br>        in<br>            _,<br><br>    // Retry function with initial sleep, fixed sleep, and optional exponential backoff<br>    Retry = (operation as function, optional maxRetries as nullable number, optional initialDelay as nullable number, optional fixedDelay as nullable number, optional useExp as nullable logical) =&gt;<br>    let<br>        maxR = if maxRetries = null then 5 else maxRetries,<br>        initD = if initialDelay = null then 0 else initialDelay,<br>        fixD = if fixedDelay = null then 0 else fixedDelay,<br>        useE = if useExp = null then true else useExp,<br><br>        fn = (attempt as number) =&gt;<br>            let<br>                // initial delay only before first attempt<br>                _init = if attempt = 0 and initD &gt; 0 then Sleep(initD) else null,<br><br>                // try the operation<br>                tryRes = try operation(),<br><br>                // on error and still have retries left -&gt; compute wait and retry<br>                result =<br>                    if tryRes[HasError] then<br>                        if attempt &lt; maxR then<br>                            let<br>                                backoff = if useE then Number.Power(2, attempt) else 0,<br>                                delay = fixD + backoff,<br>                                _sleep = if delay &gt; 0 then Sleep(delay) else null<br>                            in<br>                                // recurse to next attempt after sleeping<br>                                fn(attempt + 1)<br>                        else<br>                            // no retries left -&gt; surface original error<br>                            error tryRes[Error]<br>                    else<br>                        // success -&gt; return value<br>                        tryRes[Value]<br>            in<br>                result<br>    in<br>        fn(0),<br><br>    // Call GoogleSheets.Contents wrapped with the enhanced Retry<br>    Source = Retry(()=&gt; GoogleSheets.Contents(Url), MaxRetries, InitialDelaySeconds, FixedDelaySeconds, UseExponentialBackoff)<br>in<br>    Source</pre><h3>IMPORTANT</h3><blockquote>Both of the soluctions solved the SERVICE side of the problem but it just MITIGATED the DESKTOP problem.</blockquote><p>Igor Comune.</p><p>👏🏻 Clap 🔎 <a href="https://igorcomune.medium.com/">Follow </a>📩 <a href="https://igorcomune.medium.com/subscribe">Subscribe </a>✍🏻Comment</p><p><strong>🎁 </strong><a href="https://powerbi-masterclass.short.gy/learning-database?utm_source=medium&amp;utm_medium=medium-post&amp;utm_campaign=database-medium-post-start"><strong>Get friend links for all of our 1000&gt; Power BI learning articles here</strong></a><strong> 🎁</strong></p><blockquote>Don’t forget to subscribe to</blockquote><blockquote>👉 <a href="https://powerbi-masterclass.short.gy/publication?utm_source=medium&amp;utm_medium=medium-post&amp;utm_campaign=publication-medium-post-end">Power BI Publication</a></blockquote><blockquote>👉 <a href="https://powerbi-masterclass.short.gy/newsletter-medium?utm_source=medium&amp;utm_medium=medium-post&amp;utm_campaign=newsletter-medium-medium-post-end">Power BI Newsletter</a></blockquote><blockquote>and join our Power BI community:</blockquote><p><a href="https://powerbi-masterclass.short.gy/linktree?utm_source=medium&amp;utm_medium=medium-post&amp;utm_campaign=linktree-medium-post-end">Microsoft Power BI Masterclass | Linktree</a></p><p><strong>Power BI Masterclass Article Classification</strong></p><p><strong>Level:</strong> Beginner</p><p><strong>Category:</strong> Integration</p><p><strong>Tags:</strong> Tips &amp; Tricks, Integration</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=451b7cdb7de3" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoft-power-bi/power-bi-service-google-sheets-error-429-too-many-requests-451b7cdb7de3">Power BI Service: Google Sheets Error (429): Too Many Requests</a> was originally published in <a href="https://medium.com/microsoft-power-bi">Power BI</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[RAG with Godot — Fully Local Open Source Agent for Game Development]]></title>
            <link>https://igorcomune.medium.com/rag-with-godot-fully-local-open-source-agent-for-game-development-429266298e79?source=rss-977adbc510be------2</link>
            <guid isPermaLink="false">https://medium.com/p/429266298e79</guid>
            <category><![CDATA[game-development]]></category>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[retrieval-augmented-gen]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[godot]]></category>
            <dc:creator><![CDATA[Igor Comune]]></dc:creator>
            <pubDate>Sun, 21 Sep 2025 05:05:48 GMT</pubDate>
            <atom:updated>2025-09-21T05:05:48.992Z</atom:updated>
            <content:encoded><![CDATA[<h3>RAG with Godot — Fully Local Open Source Agent for Game Development</h3><p>I started this project long time ago, but just recently I have enough time to end this little project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*59YNWdMSoa5ypq1a9XSurw.jpeg" /><figcaption>Ideogram</figcaption></figure><blockquote>Thank-you OWI for updating Squad to Unreal Engine 5, I no longer can play it because I’m an owner of a GeForce 1650 and now I have enough time to code.</blockquote><h3>Background</h3><p>Few months ago I got into the world of Reinforcement Learning and somehow I ended up trying to use Godot and I had a wonderful idea…</p><blockquote>Create an AI Agent that supports game development in Godot.</blockquote><p>Godot is Open Source, so, I decided that the entire project should be open source.</p><p>But now, I’m leaving Godot for Unity and I’m publishing this idea because I don’t want to die, the project is fully open source.</p><h4>Setup</h4><ul><li>Python 3.13</li><li><a href="https://huggingface.co/dphn/Dolphin3.0-Llama3.1-8B-GGUF">Dolphin3.0-Llama3.1–8B-Q3_K.gguf</a></li><li><a href="https://github.com/oobabooga/text-generation-webui">text-generation-webui</a></li><li>LangChain</li><li>PyTorch</li><li>Chroma DB</li><li><a href="https://github.com/IgorComune/godot_rag_project">Github Repo</a> (<a href="https://github.com/IgorComune/godot_rag_project">https://github.com/IgorComune/godot_rag_project</a>)</li></ul><h3>The Project</h3><blockquote>I won’t use Godot for Reinforcement Learning anymore, I wanna start using Unity instead, so, if you want to take over this project or fork it, feel free to do so, everything in this project is open source.</blockquote><p>This project was made to challenge all my data skills. Let me explain you…</p><ol><li>I scraped all links of the Godot Documentation</li><li>After that I scraped all content from all links of its docs.</li><li>Vectorize it into a ChromaDB</li><li>Created a script to test the ChromaDB query</li><li>Downloaded the WebUI, download a LLM model and finally</li><li>Integrated everything together</li></ol><p>The project is still a mess, but it’s working perfectly. You can run it locally using only Open source solutions from web.</p><p>In order to create the virtual environment I used Anaconda which makes it easier to deal with multiple python versions, envs and lib versions.</p><ol><li>Gitclone this repo: <a href="https://github.com/IgorComune/godot_rag_project.git">https://github.com/IgorComune/godot_rag_project.git</a></li><li>Create your virtual environmental using Python 3.13.</li><li>pip install -r requirements.txt</li><li>Run godot_scraper_links.py (it will create a list of all pages to be scrapped</li><li>Run godot_scraper_content.py (it will download all of the content from all of the links, if you don’t want to do it, just unzip the file in godot_docs/pages.zip</li><li>Run txt_to_vector.py in order to vectorize all of the content downloaded</li><li>pip install -r requirements/portable/requirements.txt — upgrade</li><li>in your terminal type: python server.py — extensions rag</li></ol><p>the step 8 will run this file:</p><pre>from langchain.vectorstores import Chroma<br>from langchain.embeddings import HuggingFaceEmbeddings<br><br># Caminho relativo do seu Chroma DB<br>PERSIST_DIRECTORY = &quot;godot_chroma_db&quot;<br><br># Inicializa embeddings<br>embedding_function = HuggingFaceEmbeddings(model_name=&quot;all-MiniLM-L6-v2&quot;)<br><br># Inicializa Chroma DB<br>vectordb = Chroma(persist_directory=PERSIST_DIRECTORY, embedding_function=embedding_function)<br><br># ----------------------------<br># Função que modifica o input<br># ----------------------------<br>def input_modifier(prompt, state=None, is_chat=False):<br>    try:<br>        docs = vectordb.similarity_search(prompt, k=3)<br>        context_text = &quot;\n&quot;.join([doc.page_content for doc in docs])<br>        print(&quot;[RAG DEBUG] Contexto adicionado ao prompt:&quot;)<br>        print(context_text)<br>        return f&quot;{context_text}\nPergunta: {prompt}\nResposta:&quot;<br>    except Exception as e:<br>        print(f&quot;[RAG Extension] Erro ao consultar o Chroma DB: {e}&quot;)<br>        return prompt  # fallback: prompt original<br><br># ----------------------------<br># Configura parâmetros da extensão<br># ----------------------------<br>params = {<br>    &quot;display_name&quot;: &quot;RAG Extension&quot;,<br>    &quot;is_tab&quot;: False,  # fica no final da aba Text generation<br>}<br><br># ----------------------------<br># Hooks do WebUI<br># ----------------------------<br>def setup():<br>    &quot;&quot;&quot;<br>    Retorna os hooks que o WebUI vai chamar.<br>    &quot;&quot;&quot;<br>    return {<br>        &quot;input_modifier&quot;: input_modifier,<br>    }</pre><p>This file will initiate the WebUI server along with the extension (tool) right above. It will sends your input inside the chat area to the query that queries the ChromaDB and return the content to the LLM in order to answer you.</p><p>your input text &gt; query chroma db &gt; chroma db answer &gt; send to llm &gt; llm answers you</p><p>Because I’m moving to Unity to learn Reinforcement Learning I decided to create this little post to draw someone’s attetion that can save this project from demise. The project itself has lots of problems, like: mixture between portuguese and english, useless files, lack of standards… but you can save it ❤</p><blockquote>I’ll probably start a similar project to do the same with Unity but now, integrating with MCP and CrewAI for research.</blockquote><p>Igor Comune.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=429266298e79" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reinforcement Learning — Solving Gymnasium’s Lunar Lander V3]]></title>
            <link>https://igorcomune.medium.com/reinforcement-learning-solving-gymnasiums-lunar-lander-v3-5cf9208f6a70?source=rss-977adbc510be------2</link>
            <guid isPermaLink="false">https://medium.com/p/5cf9208f6a70</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[reinforcement-learning]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Igor Comune]]></dc:creator>
            <pubDate>Thu, 18 Sep 2025 15:56:10 GMT</pubDate>
            <atom:updated>2025-09-18T15:56:10.288Z</atom:updated>
            <content:encoded><![CDATA[<h3>Reinforcement Learning — Solving Gymnasium’s Lunar Lander V3</h3><p>Inspired by my Master’s course, I decided to try to solve the Gymnasium’s Lunar Lander V3 problem by my own… and I did it!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IYGKtBrOAwW97z0Ye8uLHw.jpeg" /></figure><h3>The Project:</h3><ul><li>WSL Ubuntu 22.04.5 LTS</li><li>Python 3.10.12</li><li><a href="https://github.com/IgorComune/reinforcement_learning_lunar_lander_v3/tree/main">Github repo</a></li><li><a href="https://gymnasium.farama.org/v0.29.0/environments/box2d/lunar_lander/">Gymnasium Lunar Lander</a></li></ul><h3>Objective</h3><ul><li>Implement both Discrete and Continous agents to solve the lunar lander problem.</li></ul><h3>Intro</h3><p>This project implements both discrete (DQN) and continuous (TD3) reinforcement learning agents for the LunarLander-v3 environment (Gymnasium). <br>It includes modular training and testing scripts, pretrained models, and automated video recording of agent performance. <br>Experiments are organized into separate folders for discrete and continuous agents, with outputs saved under `videos/` for easy review.</p><h3>What Is Reinforcement Learning</h3><p>Reinforcement Learning (RL) is a branch of machine learning where an agent interacts with an environment by taking actions, receiving feedback in the form of rewards, and learning a policy to maximize long-term return. The environment is typically modeled as a Markov Decision Process (MDP), where the next state and reward depend only on the current state and action, not on the full history. This agent–environment interaction loop forms the foundation of RL, enabling agents to learn behaviors through trial and error.</p><figure><img alt="Reinforcement Learning Concept" src="https://cdn-images-1.medium.com/max/1024/0*CloEJSi2u4or_Qzq.png" /><figcaption>Source: IBM <a href="https://www.ibm.com/br-pt/think/topics/reinforcement-learning">https://www.ibm.com/br-pt/think/topics/reinforcement-learning</a></figcaption></figure><h4>My Main Difficulties in This Project</h4><p>Looking back, my main struggles followed a pretty clear progression:</p><ol><li><strong>Environment setup</strong><br>At first, I had trouble just configuring the environment. I assumed I could pass parameters like gravity or wind_power directly into LunarLander-v3, but the actual API behaved differently. I had to slow down and read the official documentation instead of guessing.</li><li><strong>Understanding the TD3 architecture</strong><br>Implementing TD3 was way harder than I expected. I didn’t fully understand what each part of the agent was doing — the DDQN, the replay buffer, the soft updates, and the delayed policy updates. This was more of a conceptual block than a coding one.</li><li><strong>Mixing discrete and continuous control</strong><br>When I built my first training script, I mixed logic for both discrete and continuous agents. Later I realized that was a mistake — I only needed continuous control. The codebase became unnecessarily complicated just because I didn’t make that decision early.</li><li><strong>Parameter consistency between training and testing</strong><br>My testing script broke because I was passing parameters (add_noise) that didn’t even exist in my TD3Agent class. That made me realize how easy it is to get training and testing scripts out of sync.</li><li><strong>Managing action noise</strong><br>I also got confused about noise. I tried to control it at initialization, when in fact it should be handled inside the act method. This created a mess when I wanted noise for training but a clean policy for testing.</li><li><strong>Practical details like video recording</strong><br>Even small things tripped me up, like recording videos with Gymnasium wrappers. I kept running into warnings and overwritten files just because I stopped the program mid-episode or reused the same output path.</li></ol><h4>The Discrete Problem</h4><p>Solving the LunarLander-v3 discrete problem means training an agent to control a lunar module using four discrete actions (do nothing, fire left engine, fire main engine, fire right engine). The goal is to land safely between the landing pads, maximizing the total reward.</p><p>I started with the basics — the discrete version of the problem. Since I had no prior experience with Reinforcement Learning, even the fundamentals felt overwhelming. Concepts like how the learn function or the replay_buffer actually fit into a Markov Decision Process, or what “exploration vs. exploitation” really meant, were far from obvious. In short: the basics were already hard. So, I decided to call in my GenAI “mob” to help me push through this challenge.</p><p>After a lot of trial and error, I finally managed to train my first agent successfully. That felt like a milestone. But as soon as I tried to test it, I got stuck again. It wasn’t until I gave Claude <a href="https://web.stanford.edu/class/aa228/reports/2019/final8.pdf">this paper</a> and compared its explanations with my own scripts that some concepts finally started to click.</p><p>One example was almost embarrassingly simple: I had forgotten to set the variable greedy=True during testing. Because of that, my agent kept choosing random actions instead of using the policy it had learned. To put it in plain words: I had imported the brain (the trained agent), but when it was time to perform, I basically told it, “ignore everything you know and just act randomly.”</p><p>With that paper in hand and a constant back-and-forth with my GenAI helpers, I finally pieced things together. I can’t say I mastered Reinforcement Learning, but I did build a solid enough understanding of the core concepts to succeed in this challenge.</p><ul><li>All the codes are here <a href="https://github.com/IgorComune/reinforcement_learning_lunar_lander_v3/tree/main">Github repo</a>.</li></ul><h4>If you want to see the videos of the training and testing check the links below:</h4><p><strong>Reinforcement Learning — Gymnasium — Lunar Lander v3 — Discrete Agent Train</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FOJ4G2X7Wv78%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DOJ4G2X7Wv78&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FOJ4G2X7Wv78%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/aaccc94bdafc3beafbcb1b135e8af0bf/href">https://medium.com/media/aaccc94bdafc3beafbcb1b135e8af0bf/href</a></iframe><p><strong>Reinforcement Learning — Gymnasium — Lunar Lander v3 — Discrete Agent Test</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FeQAXo_WNRn8%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DeQAXo_WNRn8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FeQAXo_WNRn8%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/eda287e57edb04376dda625902d7cd25/href">https://medium.com/media/eda287e57edb04376dda625902d7cd25/href</a></iframe><blockquote>Do not forget to subscribe to my channel because there will be huge projects in reinforcement learning coming in soon to this channel that will be announced here on Medium.</blockquote><h4>The Continous Problem</h4><p>Solving the LunarLander-v3 continuous problem means training an agent to control the lunar module with continuous thrust values for the main and side engines. The objective is to achieve a smooth and safe landing between the pads while maximizing the total reward.</p><p>My main challenge was moving from <strong>discrete to continuous control</strong> in the LunarLander environment. Switching from DQN to TD3 wasn’t just a matter of replacing the agent — it required rethinking the entire training loop.</p><p>First, I had to properly configure the environment in <em>continuous mode</em>, which took some trial and error. Then came the bigger hurdle: adapting the code. DQN logic didn’t translate to TD3, so I had to rewrite how actions, replay memory, and updates were handled.</p><p>Another issue was separating <strong>training and testing pipelines</strong>. During training, the agent needs exploration and network updates; during testing, it should run deterministically without noise. Mixing these up gave me inconsistent results until I made a clean separation.</p><p>Finally, I struggled with <strong>TD3 hyperparameters</strong> (batch size, tau, gamma, policy delay) and with setting up proper <strong>logging and checkpoints</strong>. Without consistent metrics, it was hard to know if the agent was truly improving.</p><p>In short: the hardest part wasn’t TD3 itself, but integrating it correctly — getting the environment setup right, restructuring the code, and keeping training and testing strictly apart.</p><h4>If you want to see the videos of the training and testing check the links below:</h4><p><strong>Reinforcement Learning — Gymnasium — Lunar Lander v3 — Continuous Agent Train</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FxoewPJNn-40%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DxoewPJNn-40&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FxoewPJNn-40%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/a7350ebe554ec62358c024e2e7035b21/href">https://medium.com/media/a7350ebe554ec62358c024e2e7035b21/href</a></iframe><p><strong>Reinforcement Learning — Gymnasium — Lunar Lander v3 — Continuous Agent Test</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FyPhitQ7yjhg%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DyPhitQ7yjhg&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FyPhitQ7yjhg%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/b85fb9d6a97f15859dffb938232f6c7b/href">https://medium.com/media/b85fb9d6a97f15859dffb938232f6c7b/href</a></iframe><p>In short, my difficulties were a mix of <strong>conceptual gaps</strong> (understanding TD3), <strong>architectural mistakes</strong> (mixing discrete/continuous, parameter mismatch), and <strong>practical issues</strong> (environment setup, noise handling, video recording).</p><p>Looking back, this project was much more than just solving LunarLander — it was about learning how to think in terms of Reinforcement Learning, dealing with frustration, debugging conceptual mistakes, and realizing that even the “small” details (like noise or video recording) can derail an experiment if ignored. The discrete and continuous problems pushed me to rework my mental models, and I leave this challenge with a stronger foundation to face bigger ones ahead. A special thanks to <strong>FIAP</strong>, where I am currently pursuing my Master’s in Machine Learning Engineer, for being both the spark and the structure behind this journey.</p><p><strong>Igor Comune.</strong></p><p><a href="https://www.linkedin.com/in/igor-comune/">https://www.linkedin.com/in/igor-comune/</a><br><a href="https://igorcomune.medium.com/">https://igorcomune.medium.com/</a><br><a href="https://github.com/IgorComune">https://github.com/IgorComune</a><br><a href="https://www.youtube.com/@DroneRLArena">https://www.youtube.com/@DroneRLArena</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5cf9208f6a70" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Artificial Intelligence — The ADHD Hunter’s Moon]]></title>
            <link>https://igorcomune.medium.com/artificial-intelligence-the-adhd-hunters-moon-9675520f9c3b?source=rss-977adbc510be------2</link>
            <guid isPermaLink="false">https://medium.com/p/9675520f9c3b</guid>
            <category><![CDATA[adhd]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Igor Comune]]></dc:creator>
            <pubDate>Fri, 23 May 2025 00:20:33 GMT</pubDate>
            <atom:updated>2025-05-23T00:20:33.858Z</atom:updated>
            <content:encoded><![CDATA[<h3>Artificial Intelligence — The ADHD Hunter’s Moon</h3><p>Every year, in the fall, there’s a special full moon called the <strong>Hunter’s Moon</strong>.<br>Long ago, this moon gave hunters extra light to find food before winter.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZUyLmVRA6wQuAxhMz6YWpQ.jpeg" /></figure><p>But maybe, just maybe, this moon also gives us a clue about something deeper — <strong>how different brains work</strong>, and how <strong>AI</strong> might change <strong>everything</strong>.</p><p>Every autumn, people in the Northern Hemisphere see a special full moon called the <strong>Hunter’s Moon</strong>. In ancient times, this moon helped hunters find food after sunset, before the cold winter arrived. It was a symbol of instinct, timing and survival.</p><p>But what if this old symbol also represents a <strong>modern way of thinking</strong>?<br>What if it connects to how our brains work — especially for those who struggle to fit into today’s “normal” world?</p><p>Let’s talk about <strong>Hunters vs. Farmers</strong>, ADHD, and how <strong>AI might finally bring balance</strong> to this ancient brain divide.</p><h3>🧠 Two Brain Types: Hunter and Farmer</h3><p>This idea comes from the book <em>“</em><a href="https://www.amazon.com/ADHD-Hunter-Farmers-Thom-Hartmann/dp/162055898X">ADHD — A Hunter in a Farmer’s World</a><em>”</em>, written by Edward Hallowell and John Ratey — both doctors who also have ADHD… as I am.</p><p>They say that ADHD is not a disorder. It’s actually a <strong>different kind of brain</strong>, one that <strong>used to be perfect for survival</strong>, but doesn’t always work well in today’s society.</p><p>They call it the <strong>Hunter’s Brain</strong>.</p><h4>🏹 The Hunter’s Brain</h4><p>Imagine our ancestors, thousands of years ago, living in nature.<br>Some people had to <strong>hunt</strong> for food: animals move fast, they’re unpredictable, and you must react quickly.<br>These people had brains that were:</p><ul><li><strong>Fast-thinking:</strong> always scanning the environment.</li><li><strong>Easily distracted:</strong> but could hyperfocus in the right situation.</li><li><strong>Creative:</strong> connecting ideas quickly.</li><li><strong>Impulsive:</strong> but full of energy and passion.</li><li><strong>Restless:</strong> always moving, always curious.</li></ul><p>These are the traits of what we now call <strong>ADHD</strong>.<br>But back then, this brain was <strong>perfect</strong> for surviving as a hunter.</p><h4>🌾 The Farmer’s Brain</h4><p>Later in history, humans started farming.<br>This was the beginning of stable, organized societies.<br>To farm, you need to:</p><ul><li>Plan long-term.</li><li>Follow routines.</li><li>Wake up early and do the same tasks every day.</li><li>Wait patiently for results (like harvests).</li></ul><p>So, the <strong>Farmer Brain</strong> evolved:</p><ul><li><strong>Focused:</strong> good with repetition.</li><li><strong>Organized:</strong> detail-oriented.</li><li><strong>Patient:</strong> able to follow steps and stick to routines.</li><li><strong>Disciplined:</strong> preferring stability over change.</li></ul><p>This brain type is great for modern life: school, offices, meetings, deadlines, calendars.</p><h3>🧨 The Problem: A World Built for Farmers</h3><p>Today’s society is mostly <strong>designed for Farmers</strong>.</p><p>In school, you have to sit still, focus, wait your turn, and follow instructions.<br>In work, you need to complete tasks on time, be organized, and stay consistent.</p><p>If you’re a <strong>Hunter</strong>, that’s exhausting.</p><p>You might feel like:</p><ul><li>You’re always “too much” or “not enough.”</li><li>You’re lazy, messy, or bad at adulting.</li><li>You have great ideas but can’t finish them.</li><li>People don’t understand how your brain works.</li></ul><p>So what happens?<br><strong>Hunters get diagnosed with ADHD</strong>, take medication, and try to fit into the Farmer mold.<br>But it’s like forcing a cheetah to plow a field — it just doesn’t work.</p><h3>🤖 The Game-Changer: How AI Helps Hunters Thrive</h3><p>Now, something new is here: <strong>Artificial Intelligence</strong>.</p><p>And this technology might finally <strong>help Hunters shine</strong>, without needing to become Farmers.</p><p>Here’s how:</p><h3>1. 🚫 No More Boring Work</h3><p>Hunters hate routine.<br>They get bored easily with repetitive tasks like emails, reports, spreadsheets, or filling forms.</p><ul><li>Write emails for you</li><li>Summarize long documents</li><li>Analyze data</li><li>Schedule meetings</li><li>Transcribe and organize voice notes</li><li>Translate text</li><li>Generate images and presentations</li><li>Clean and organize datasets</li><li>Write and debug code</li><li>Turn ideas into full blog posts or scripts (What I’m doing right now)</li></ul><p>This means Hunters can <strong>focus on what they love</strong> — thinking big, solving problems, making new things — and let AI handle the boring stuff.</p><h3>2. 🧭 Help With Focus and Memory</h3><p>Hunters often struggle with executive function. That means:</p><ul><li>Forgetting tasks.</li><li>Losing track of time.</li><li>Getting lost in distractions.</li><li>Struggling to plan and finish things.</li></ul><p>But now we have:</p><ul><li>AI reminders that adjust to your habits.</li><li>Smart assistants that help you plan step by step.</li><li>Tools like Notion AI, Google Gemini, or ChatGPT that keep you organized.</li></ul><p>It’s like having a <strong>Farmer friend</strong> in your pocket, keeping things in order while you chase ideas.</p><h3>3. ⚡ Turning Fast Thoughts into Action</h3><p>Hunters think fast.<br>They often have brilliant ideas but can’t turn them into action quickly enough. They get stuck.</p><p>AI tools help by:</p><ul><li>Turning rough notes into clean documents.</li><li>Turning sketches into designs.</li><li>Turning ideas into code.</li><li>Speeding up content creation — blogs, social media, videos, etc.</li></ul><p>Now, the Hunter’s <strong>fast brain becomes a superpower</strong>, not a weakness.</p><h3>4. 🔀 Making Sense of the Chaos</h3><p>Hunters live in mental chaos.<br>There are so many thoughts, ideas, emotions — it’s hard to organize them.</p><p>AI can help bring structure to this creative storm:</p><ul><li>Visualize plans.</li><li>Organize brainstorms.</li><li>Help write clear messages.</li><li>Find patterns and insights in your thinking.</li></ul><p>With AI, Hunters no longer need to slow down or become someone they’re not.<br>Instead, they can <strong>use AI to translate their brain into results</strong>.</p><h3>🌕 The Hunter’s Moon Is Rising Again</h3><p>The Hunter’s Moon once gave ancient people the light they needed to survive.<br>Now, <strong>AI is giving the same light to a new kind of hunter</strong> — the modern mind that thinks differently.</p><p>This isn’t a war between Hunters and Farmers.<br>It’s a new age where <strong>we finally recognize that not all brains work the same way</strong> — and that’s okay.</p><p>AI makes it possible to <strong>work with your brain, not against it</strong>.</p><ul><li>If you’re a Farmer, AI can help you be more creative and faster.</li><li>If you’re a Hunter, AI can help you stay focused and finish what you start.</li></ul><p>Together, we build a world where <strong>different minds can finally thrive</strong>.</p><h3>💬 So, What About You?</h3><ul><li>Do you feel like a Hunter — full of energy, ideas, and chaos?</li><li>Or more like a Farmer — calm, focused, and organized?</li><li>How is AI changing the way <em>you</em> work, think, or create?</li></ul><p>Leave a comment — let’s talk.<br>Maybe we’re part of the same tribe, walking under the light of the <strong>Hunter’s Moon</strong>. 🌕</p><p>Partially written by AI.</p><p><strong>Igor Comune.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9675520f9c3b" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>