<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Monica Orellana</title>
    <description>The latest articles on DEV Community by Monica Orellana (@purischaky).</description>
    <link>https://dev.to/purischaky</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3777993%2F5a72d7b7-a327-4f76-b28c-dc50f62918ca.png</url>
      <title>DEV Community: Monica Orellana</title>
      <link>https://dev.to/purischaky</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/purischaky"/>
    <language>en</language>
    <item>
      <title>Predicting SLA Breaches in Technical Support</title>
      <dc:creator>Monica Orellana</dc:creator>
      <pubDate>Fri, 25 Sep 2026 14:18:00 +0000</pubDate>
      <link>https://dev.to/purischaky/predicting-sla-breaches-in-technical-support-4a1d</link>
      <guid>https://dev.to/purischaky/predicting-sla-breaches-in-technical-support-4a1d</guid>
      <description>&lt;p&gt;Case Study: Predicting SLA Breaches in Technical Support&lt;br&gt;
Project: NovaTech AI Support (hypothetical scenario, synthetic data)&lt;br&gt;
Repo: &lt;a href="https://github.com/purischaky/novatech-ai-bottleneck" rel="noopener noreferrer"&gt;GitHub-novatech-ai-bottleneck&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Executive Summary
&lt;/h3&gt;

&lt;p&gt;In technical support teams, not all tickets represent the same level of operational risk. Some are resolved in minutes; others consume hours of specialized work and end up breaching the Service Level Agreement (SLA).&lt;/p&gt;

&lt;p&gt;This case study explores how to build a Machine Learning (ML) system capable of identifying, from the moment a ticket is created, which ones are most likely to breach their SLA.&lt;/p&gt;

&lt;p&gt;The project was developed as a hypothetical scenario for NovaTech AI Support, using synthetic data to replicate a real IT support problem. The objective was not only to maximize predictive performance but to design a realistic, explainable, reproducible, and deployable ML workflow.&lt;/p&gt;

&lt;p&gt;The most important outcome of the project was not achieving a particular metric. It was discovering that the first model was using information from the future, and redesigning the problem around a more rigorous question:&lt;/p&gt;

&lt;p&gt;What can we know about a ticket's risk at the exact moment it enters the system?&lt;/p&gt;

&lt;h3&gt;
  
  
  The Business Problem
&lt;/h3&gt;

&lt;p&gt;Imagine a technology company that receives hundreds of support tickets every day. Each ticket can represent anything from a simple product question to an integration problem requiring specialized investigation.&lt;/p&gt;

&lt;p&gt;For support managers, the challenge is not just resolving tickets. It's deciding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which ones need immediate attention,&lt;/li&gt;
&lt;li&gt;Where to allocate specialized resources,&lt;/li&gt;
&lt;li&gt;Which tickets have the highest risk of breaching the SLA,&lt;/li&gt;
&lt;li&gt;How to move from a reactive to a preventive operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Business Hypothesis:&lt;/strong&gt; If high-risk tickets are identified in advance, support teams can prioritize resources before the problem becomes a breach, improving resource allocation, prioritization, and customer experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Success Criteria
&lt;/h3&gt;

&lt;p&gt;A high ML metric was not enough. The system had to meet four conditions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Predictive Performance:&lt;/strong&gt; Correctly identify tickets with breach risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Temporal Validity:&lt;/strong&gt; Use only information available at the moment of prediction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operational Explainability:&lt;/strong&gt; Enable understanding of why a ticket was classified as risky.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engineering Readiness:&lt;/strong&gt; Separate data, training, prediction, and documentation in a reproducible way.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Alarm Signal: 100% Accuracy
&lt;/h3&gt;

&lt;p&gt;The first result was exactly the type of outcome that generates a false sense of success: the model achieved ~100% on its classification metrics.&lt;/p&gt;

&lt;p&gt;In a real operational problem, a perfect prediction should generate more questions than celebration.&lt;/p&gt;

&lt;p&gt;The variable audit revealed the problem: temporal data leakage. The model was using information that would only be available after the ticket had been resolved particularly, the actual resolution time.&lt;/p&gt;

&lt;p&gt;This creates an almost direct relationship with the target: if we already know how long it took to resolve a ticket, it's trivial to know whether it breached its SLA. But that information doesn't exist when the ticket has just entered the system.&lt;/p&gt;

&lt;p&gt;The model wasn't predicting the future. It was using future information to reconstruct the past.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methodological Correction: Strict T=0 Restriction
&lt;/h3&gt;

&lt;p&gt;The solution wasn't removing a column. It was redefining the problem around the moment when the model would actually be used.&lt;/p&gt;

&lt;p&gt;I defined T=0 as the moment of ticket creation (intake). From there, a variable could only be used if it was already available at that instant.&lt;/p&gt;

&lt;p&gt;Features available at T=0 (kept):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ticket category&lt;/li&gt;
&lt;li&gt;Priority&lt;/li&gt;
&lt;li&gt;Channel&lt;/li&gt;
&lt;li&gt;Target SLA time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Removed (only exist after intake):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Actual resolution time&lt;/li&gt;
&lt;li&gt;Accumulated waiting time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This decision had an immediate consequence: the ROC-AUC dropped from 1.0000 → 0.9606. At first glance, it seems like a deterioration, but a slightly less accurate model that is valid in production is much more valuable than a perfect model that cannot be used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture Benchmarking: More Complexity Doesn't Mean Better
&lt;/h3&gt;

&lt;p&gt;With the problem redefined, two approaches were compared under the same T=0 feature set. The system solves a dual task: classification (will it breach the SLA?) and regression (estimating the associated risk/time), which is why both classification metrics (ROC-AUC, F1) and regression metrics (R²) are reported.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;ROC-AUC&lt;/th&gt;
&lt;th&gt;F1-Score&lt;/th&gt;
&lt;th&gt;R² (Reg)&lt;/th&gt;
&lt;th&gt;Ready for production?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Random Forest&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Intake (T=0)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.9606&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.9095&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.6416&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Yes (Recommended)&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PyTorch Multitask&lt;/td&gt;
&lt;td&gt;Intake (T=0)&lt;/td&gt;
&lt;td&gt;0.9617&lt;/td&gt;
&lt;td&gt;0.9047&lt;/td&gt;
&lt;td&gt;0.5232&lt;/td&gt;
&lt;td&gt;️ Optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Forest&lt;/td&gt;
&lt;td&gt;Omniscient (Leaky)&lt;/td&gt;
&lt;td&gt;1.0000&lt;/td&gt;
&lt;td&gt;1.0000&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;❌ No (Post-mortem only)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Random Forest was the chosen candidate for production. Both T=0 models are practically tied in classification (RF wins on F1; the neural network wins by a minimal margin on ROC-AUC — 0.0011), but RF has clearly better regression performance (R² 0.64 vs 0.52), plus native integration with TreeSHAP and lower computational cost. The additional complexity of deep learning is not justified for a marginal gain in classification that is also paid for with worse R² and less direct interpretability.&lt;/p&gt;

&lt;p&gt;The decision was based on the balance between performance, speed, interpretability, complexity, and required resources, not just the highest metric.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operational Explainability with SHAP: From Black Box to Support Tool
&lt;/h3&gt;

&lt;p&gt;A prediction alone is not enough for a support operation. If the system flags a ticket as "high risk," the team needs to know why. To answer that question, SHAP (SHapley Additive exPlanations) was incorporated at two levels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global explanation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0nf2rrck4899e8lg4dqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0nf2rrck4899e8lg4dqp.png" alt="Image 1 — Global SHAP summary: A " value="" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probability of breach. Positive SHAP values ​​push the prediction toward "high risk."&lt;/p&gt;

&lt;p&gt;The SHAP analysis identified the main risk factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integration/API is the most consistent category that increases risk.&lt;/li&gt;
&lt;li&gt;A short target SLA (8h) significantly increases risk compared to a broader one (72h).&lt;/li&gt;
&lt;li&gt;Technical Issue is the highest-magnitude feature, but it's bidirectional: it can increase or decrease risk depending on context.&lt;/li&gt;
&lt;li&gt;The entry channel (email, chat, or phone) has minimal impact.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This transforms the model from a purely predictive tool into a source of operational information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local Explanation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a ticket with a final breach probability of 99.1%, the analysis decomposes the prediction as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhgaz6gv3qvcrwzhh6zox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhgaz6gv3qvcrwzhh6zox.png" alt="Image 2 — Local explanation (waterfall): A waterfall chart titled " value="" width="799" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A ticket with a 99.1% probability of a breach.&lt;/p&gt;

&lt;p&gt;The question shifts from "Does the model say this ticket is risky?" to "What factors are making this ticket risky?", a fundamental difference when predictions must be translated into human decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Production Implementation and Software Robustness
&lt;/h3&gt;

&lt;p&gt;Another common problem in ML projects is confusing a model trained in a notebook with a usable system. To avoid this, the project explicitly separates training and prediction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;train.py&lt;/em&gt;&lt;/strong&gt; - loads the data, executes the pipeline, trains the model, and saves it for later use. Reproducible via a single command, without depending on manually running a notebook.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;predict.py&lt;/em&gt;&lt;/strong&gt; - receives new tickets, executes the transformation flow, generates predictions, and saves the results along with their probabilities.&lt;/p&gt;

&lt;p&gt;This creates a clear boundary: Training → Model Artifact → Prediction, leaving the system ready for future integration with other systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;First model with leakage: ROC-AUC = 1.0000 / F1 = 1.0000 (invalid, uses future information).&lt;/li&gt;
&lt;li&gt;Corrected model with T=0 features (Random Forest): ROC-AUC = 0.9606 · F1 = 0.9095 · R² = 0.6416.&lt;/li&gt;
&lt;li&gt;Multitask neural network (PyTorch) T=0: ROC-AUC = 0.9617 · F1 = 0.9047 · R² = 0.5232.&lt;/li&gt;
&lt;li&gt;Random Forest selected as production candidate for its balance between performance, simplicity, and interpretability.&lt;/li&gt;
&lt;li&gt;SHAP enabled explanation of both global patterns and individual predictions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Lessons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A perfect metric can be a warning sign, not a success.&lt;/li&gt;
&lt;li&gt;Define the moment of prediction before choosing features. The question is not "Is this variable predictive?" but "Would this variable exist at the moment I need to predict?"&lt;/li&gt;
&lt;li&gt;Complexity must earn its place. Deep learning is not used just because it's more advanced.&lt;/li&gt;
&lt;li&gt;Explainability matters when it answers concrete operational questions, not when it's included as an additional visualization.&lt;/li&gt;
&lt;li&gt;A notebook is not a production system: it takes data pipeline + validation + model + prediction workflow + logging + documentation + reproducibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;NovaTech AI started as an SLA prediction problem and ended up becoming a Machine Learning Engineering exercise.&lt;/p&gt;

&lt;p&gt;The most valuable result was not moving from one ROC-AUC to another slightly better one. It was identifying that the first perfect result was misleading, redefining the problem around T=0, comparing models considering complexity and operational value, incorporating explainability, and building a structure that could evolve from an experiment to a system.&lt;/p&gt;

&lt;p&gt;If you have feedback on the T=0 approach, the choice of Random Forest over deep learning, or ideas to take this further (drift monitoring, calibration, inference API), I'd be glad to read them in the comments. The complete code is in the repo linked above.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>mlops</category>
      <category>datascience</category>
      <category>python</category>
    </item>
    <item>
      <title>Optimizador de Retención de Talento con Machine Learning</title>
      <dc:creator>Monica Orellana</dc:creator>
      <pubDate>Wed, 23 Sep 2026 16:46:41 +0000</pubDate>
      <link>https://dev.to/purischaky/optimizador-de-retencion-de-talento-con-machine-learning-2e6k</link>
      <guid>https://dev.to/purischaky/optimizador-de-retencion-de-talento-con-machine-learning-2e6k</guid>
      <description>&lt;p&gt;La rotación de empleados no es solo un "problema de Recursos Humanos": es una fuga directa de capital. Según Gallup, reemplazar a un empleado cuesta habitualmente entre 0.5 y 2 veces su salario anual, entre reclutamiento, onboarding y pérdida de productividad.&lt;/p&gt;

&lt;p&gt;La mayoría de los proyectos de Machine Learning en este dominio se detienen en una métrica superficial: "nuestro modelo predice quién se irá con 85% de ROC-AUC". Pero esa cifra, por sí sola, no le dice a un director financiero cuánto invertir para evitarlo, ni a quién priorizar cuando el presupuesto es limitado.&lt;/p&gt;

&lt;p&gt;Este artículo documenta el diseño, evaluación y entrega de un Sistema de Soporte a la Decisión (DSS) que combina modelado predictivo, explicabilidad con SHAP, segmentación no supervisada y optimización financiera bajo restricción de presupuesto, junto con el proceso de control de calidad que se aplicó antes de considerarlo listo para producción.&lt;/p&gt;

&lt;p&gt;Repositorio completo: &lt;br&gt;
👉&lt;a href="https://github.com/purischaky/workforce_attrition_project" rel="noopener noreferrer"&gt;github.com/purischaky/workforce_attrition_project&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Paso 1: Diseñar el problema
&lt;/h2&gt;

&lt;p&gt;El primer paso no fue elegir un algoritmo. Fue definir qué pregunta de negocio se estaba respondiendo. "Predecir la rotación" no es el objetivo real; el objetivo es estimar un costo esperado y decidir dónde asignar presupuesto. Esa distinción definió toda la arquitectura:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/features.py&lt;/code&gt;&lt;/strong&gt; - un transformador custom (LaborEconomicsFeatures) que construye ratios econométricos, no solo variables crudas. Por ejemplo la presión de burnout:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Burnout&amp;nbsp;Ratio&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Manager&amp;nbsp;Support&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ϵ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Workload&amp;nbsp;Score&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Overtime&amp;nbsp;Hours&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Junto con la velocidad de carrera, el índice de estancamiento y el salario relativo contra la mediana correspondiente a departamento y nivel de cargo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/models.py&lt;/code&gt;&lt;/strong&gt; - Un enfoque de modelado dual: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;una regresión logística (para interpretabilidad vía odds ratios) &lt;/li&gt;
&lt;li&gt;un HistGradientBoostingClassifier calibrado con CalibratedClassifierCV. Un buen AUC no es suficiente: si las probabilidades no están calibradas, cualquier cálculo de ROI que dependa de ellas pierde validez matemática.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/explainability.py&lt;/code&gt;&lt;/strong&gt; - SHAP para explicar por qué el modelo predice lo que predice, a nivel global y local.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/segmentation.py&lt;/code&gt;&lt;/strong&gt; - Análisis de Componentes Principales(PCA) + K-Means para encontrar arquetipos latentes de empleados, más allá de la etiqueta binaria "se va / se queda".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/retention_optimizer.py&lt;/code&gt;&lt;/strong&gt; - el módulo central desde una perspectiva de negocio. Dado un presupuesto fijo, resuelve un problema para determinar ¿a quién se le asigna una intervención de retención para maximizar el valor esperado neto?&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 2: Traducir el modelo a una decisión de asignación de presupuesto
&lt;/h2&gt;

&lt;p&gt;Tras entrenar y calibrar, el modelo alcanzó un ROC-AUC ≈ 0.81 con un Brier Score de ~0.10, es decir, probabilidades bien calibradas y no solo un buen ranking. SHAP confirmó los principales drivers de rotación: satisfaction_score, burnout_pressure_ratio y promotion_wait_years.&lt;/p&gt;

&lt;p&gt;El resultado con mayor peso de negocio fue el siguiente: con un presupuesto de $50,000 distribuido entre 20 empleados de alto riesgo (a $2,500 por intervención), el modelo proyectó $745,000+ en valor esperado salvado, un ROI neto de ~1,391%.&lt;/p&gt;

&lt;p&gt;Esa cifra se deriva directamente de la optimización bajo restricción de presupuesto:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Ganancia&amp;nbsp;Neta&amp;nbsp;Total&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop op-limits"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mrel mtight"&gt;=&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="mop op-symbol large-op"&gt;∑&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="delimsizing size2"&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;reemplazo&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;I&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="delimsizing size2"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Donde:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;k: número de empleados seleccionados dentro del presupuesto disponible.&lt;/li&gt;
&lt;li&gt;P_i: probabilidad calibrada de que el empleado i renuncie.&lt;/li&gt;
&lt;li&gt;C_reemplazo,i: costo estimado de reemplazar al empleado i (1.5 × salario anual).&lt;/li&gt;
&lt;li&gt;S_i: tasa de éxito estimada de la intervención de retención.&lt;/li&gt;
&lt;li&gt;I_i: costo directo de implementar la intervención (ej. $2,500).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El valor de este enfoque no está en la cifra en sí, sino en que convierte una lista de probabilidades en una tabla de asignación de capital accionable: qué empleados, con qué prioridad, y con qué retorno esperado. Esa es la diferencia entre un modelo predictivo y una herramienta de decisión ejecutiva.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 3: Control de calidad: auditar el código antes de entregarlo como producción
&lt;/h2&gt;

&lt;p&gt;Un pipeline que produce buenas métricas no es lo mismo que un pipeline listo para producción. Antes de considerar el proyecto terminado, se ejecutó un proceso de auditoría técnica, tests y reproducibilidad, módulo por módulo, con apoyo de IA para acelerar la revisión y las correcciones. &lt;/p&gt;

&lt;p&gt;Los hallazgos y sus correcciones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Path roto&lt;/strong&gt; → el pipeline apuntaba a un archivo incorrecto y caía en un fallback silencioso que auditaba datos ya procesados en vez de datos crudos. Una vez corregido, se agregó un warning explícito para que cualquier futura desviación de este tipo sea visible en consola.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reentrenamiento&lt;/strong&gt; → el modelo se entrenaba desde cero tres veces en una sola corrida del pipeline. Se introdujo serialización con joblib: el modelo se entrena una vez y los módulos de explicabilidad y optimización cargan el artefacto en vez de reentrenar. El pipeline pasó de 3 entrenamientos a 1 por corrida.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;README vs. tests&lt;/strong&gt; → Se sincronizó la documentación con el código real y se agregó el test que faltaba (test_models.py) en vez de solo borrar la mención.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Módulo desconectado&lt;/strong&gt; → eda_economic.py, responsable de la validación de hipótesis econométricas, no estaba integrado en el pipeline principal. Se conectó a main.py como paso formal del proceso.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reproducibilidad del split de datos&lt;/strong&gt; → no existía un script que generara los conjuntos de entrenamiento y prueba desde el dato crudo. Se creó src/make_dataset.py, con train_test_split estratificado y semilla fija, para que el pipeline sea reproducible de punta a punta por cualquier persona que clone el repositorio.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lo que este proceso demuestra, desde una perspectiva de negocio
&lt;/h3&gt;

&lt;p&gt;Hoy en día, el verdadero diferencial no está en la métrica, sino en la capacidad de traducir esa predicción en una decisión de negocio con un ROI cuantificado. Para ello, se debe someter el propio trabajo a un rigor de ingeniería implacable antes de darlo por terminado: rutas de datos verificadas, persistencia de modelos, documentación sincronizada y reproducibilidad garantizada desde el dato crudo.&lt;/p&gt;

&lt;p&gt;Ese debe ser el estándar para evaluar cualquier proyecto de Machine Learning que aspire a estar en producción. No se trata solo de que el modelo prediga bien, sino de que el sistema completo (pipeline, tests, documentación y arquitectura), resista una auditoría externa sin una sola sorpresa.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Quieres replicarlo o contribuir?
&lt;/h3&gt;

&lt;p&gt;El proyecto usa datos sintéticos con propiedades econométricas realistas, pensado para adaptarse a datasets reales de cualquier organización interesada en cuantificar su exposición financiera a la rotación de talento.&lt;/p&gt;

&lt;p&gt;🔗Explora el código, clona el repositorio y ejecuta el dashboard aquí:&lt;br&gt;
👉 &lt;a href="https://github.com/purischaky/workforce_attrition_project.git" rel="noopener noreferrer"&gt;https://github.com/purischaky/workforce_attrition_project.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¿Has abordado el problema de la rotación de personal en tu empresa? ¿Usaste algún enfoque de optimización de presupuesto? ¡Déjame tus comentarios abajo! 👇&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>machinelearning</category>
      <category>python</category>
    </item>
    <item>
      <title>Prediciendo Brechas de SLA en Soporte Técnico</title>
      <dc:creator>Monica Orellana</dc:creator>
      <pubDate>Mon, 14 Sep 2026 16:31:45 +0000</pubDate>
      <link>https://dev.to/purischaky/de-la-metrica-trampa-a-la-decision-operativa-prediciendo-brechas-de-sla-en-soporte-tecnico-43p7</link>
      <guid>https://dev.to/purischaky/de-la-metrica-trampa-a-la-decision-operativa-prediciendo-brechas-de-sla-en-soporte-tecnico-43p7</guid>
      <description>&lt;p&gt;Caso de estudio: Predicción de brechas de SLA&lt;br&gt;
Proyecto: NovaTech AI Support (escenario hipotético, datos sintéticos)&lt;br&gt;
Repo: &lt;a href="https://github.com/purischaky/novatech-ai-bottleneck" rel="noopener noreferrer"&gt;GitHub-novatech-ai-bottleneck&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resumen ejecutivo
&lt;/h3&gt;

&lt;p&gt;En los equipos de soporte técnico, no todos los tickets representan el mismo nivel de riesgo operacional. Algunos se resuelven en minutos; otros consumen horas de trabajo especializado y terminan incumpliendo el Service Level Agreement (SLA).&lt;/p&gt;

&lt;p&gt;Este caso de estudio explora cómo construir un sistema de Machine Learning  (ML) capaz de identificar, desde el momento en que se crea un ticket, cuáles tienen mayor probabilidad de incumplir su SLA.&lt;/p&gt;

&lt;p&gt;El proyecto se desarrolló como un escenario hipotético para NovaTech AI Support, usando datos sintéticos para replicar un problema real de soporte TI. El objetivo no fue únicamente maximizar el desempeño predictivo, sino diseñar un flujo de ML realista, explicable, reproducible y desplegable.&lt;/p&gt;

&lt;p&gt;El resultado más importante del proyecto no fue alcanzar una métrica determinada. Fue descubrir que el primer modelo estaba utilizando información del futuro, y rediseñar el problema alrededor de una pregunta más rigurosa:&lt;/p&gt;

&lt;p&gt;¿Qué podemos saber sobre el riesgo de un ticket en el momento exacto en que entra al sistema?&lt;/p&gt;

&lt;h3&gt;
  
  
  El problema de negocio
&lt;/h3&gt;

&lt;p&gt;Imaginemos una empresa tecnológica que recibe cientos de tickets de soporte cada día. Cada ticket puede representar desde una pregunta simple sobre el producto hasta un problema de integración que requiere investigación especializada.&lt;/p&gt;

&lt;p&gt;Para los responsables de soporte, el reto no es solo resolver tickets. Es decidir:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cuáles necesitan atención inmediata,&lt;/li&gt;
&lt;li&gt;dónde asignar recursos especializados,&lt;/li&gt;
&lt;li&gt;qué tickets tienen mayor riesgo de incumplir el SLA,&lt;/li&gt;
&lt;li&gt;cómo pasar de una operación reactiva a una preventiva.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hipótesis de negocio:&lt;/strong&gt; si se identifican anticipadamente los tickets de mayor riesgo, los equipos de soporte pueden priorizar recursos antes de que el problema se convierta en un incumplimiento, mejorando la asignación de recursos, la priorización y la experiencia del cliente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criterios de éxito
&lt;/h3&gt;

&lt;p&gt;Una métrica alta de ML no bastaba. El sistema debía cumplir cuatro condiciones:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rendimiento predictivo:&lt;/strong&gt; identificar correctamente los tickets con riesgo de breach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validez temporal:&lt;/strong&gt; usar únicamente información disponible en el momento de la predicción.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicabilidad Operativa:&lt;/strong&gt; permitir entender por qué un ticket fue clasificado como riesgoso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preparación de ingenieria:&lt;/strong&gt; separar datos, entrenamiento, predicción y documentación de forma reproducible.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  La señal de alarma: 100% de precisión
&lt;/h3&gt;

&lt;p&gt;El primer resultado fue exactamente el tipo de resultado que genera una falsa sensación de éxito: el modelo alcanzó ~100% en sus métricas de clasificación.&lt;/p&gt;

&lt;p&gt;En un problema operacional real, una predicción perfecta debería generar más preguntas que celebración.&lt;/p&gt;

&lt;p&gt;La auditoría de variables reveló el problema: temporal data leakage. El modelo usaba información que solo estaría disponible después de que el ticket hubiera sido resuelto — en particular, el tiempo real de resolución.&lt;/p&gt;

&lt;p&gt;Eso crea una relación casi directa con el target: si ya sabemos cuánto tardó en resolverse un ticket, es trivial saber si incumplió su SLA. Pero esa información no existe cuando el ticket acaba de entrar al sistema.&lt;/p&gt;

&lt;p&gt;El modelo no estaba prediciendo el futuro. Estaba usando información del futuro para reconstruir el pasado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Corrección metodológica: restricción estricta a T=0
&lt;/h3&gt;

&lt;p&gt;La solución no fue eliminar una columna. Fue redefinir el problema alrededor del momento en que el modelo realmente se usaría.&lt;/p&gt;

&lt;p&gt;Definí T=0 como el momento de creación del ticket (intake). A partir de ahí, una variable solo podía usarse si ya estaba disponible en ese instante.&lt;/p&gt;

&lt;p&gt;Features disponibles en T=0 (se mantuvieron):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ticket category&lt;/li&gt;
&lt;li&gt;Priority&lt;/li&gt;
&lt;li&gt;Channel&lt;/li&gt;
&lt;li&gt;Target SLA time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se eliminaron (solo existen después del intake):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Actual resolution time&lt;/li&gt;
&lt;li&gt;Accumulated waiting time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esta decisión tuvo una consecuencia inmediata: el ROC-AUC cayó de 1.0000 → 0.9606. A primera vista parece un empeoramiento, pero un modelo ligeramente menos preciso pero válido en produccion es mucho más valioso que un modelo perfecto que no puede utilizarse.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benchmarking de arquitecturas: más complejidad no significa mejor
&lt;/h3&gt;

&lt;p&gt;Con el problema redefinido, se compararon dos enfoques bajo el mismo feature set T=0. El sistema resuelve una tarea dual: clasificación (¿va a incumplir el SLA?) y regresión (estimación del riesgo/tiempo asociado), de ahí que se reporten tanto métricas de clasificación (ROC-AUC, F1) como de regresión (R²).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;ROC-AUC&lt;/th&gt;
&lt;th&gt;F1-Score&lt;/th&gt;
&lt;th&gt;R² (Reg)&lt;/th&gt;
&lt;th&gt;¿Listo para producción?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Random Forest&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Intake (T=0)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.9606&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.9095&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.6416&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Sí (Recomendado)&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PyTorch Multitask&lt;/td&gt;
&lt;td&gt;Intake (T=0)&lt;/td&gt;
&lt;td&gt;0.9617&lt;/td&gt;
&lt;td&gt;0.9047&lt;/td&gt;
&lt;td&gt;0.5232&lt;/td&gt;
&lt;td&gt;️ Opcional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Forest&lt;/td&gt;
&lt;td&gt;Omniscient (Leaky)&lt;/td&gt;
&lt;td&gt;1.0000&lt;/td&gt;
&lt;td&gt;1.0000&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;❌ No (Post-mortem only)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Random Forest fue el candidato elegido para producción. Ambos modelos T=0 quedan prácticamente empatados en clasificación (RF gana en F1; la red neuronal gana por un margen mínimo en ROC-AUC - 0.0011), pero RF tiene un desempeño de regresión claramente mejor (R² 0.64 vs 0.52), además de integración nativa con TreeSHAP y menor costo computacional. La complejidad adicional del deep learning no se justifica para una ganancia marginal en clasificación que además se paga con peor R² y menos interpretabilidad directa.&lt;/p&gt;

&lt;p&gt;La decisión se basó en el equilibrio entre desempeño, velocidad, interpretabilidad, complejidad y recursos necesarios, no solo en la métrica más alta.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explicabilidad operativa con SHAP: de caja negra a herramienta de soporte
&lt;/h3&gt;

&lt;p&gt;Una predicción por sí sola no es suficiente para una operación de soporte. Si el sistema marca un ticket como "high risk", el equipo necesita saber por qué. Para responder esa pregunta se incorporó SHAP (SHapley Additive exPlanations) en dos niveles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explicación global&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0nf2rrck4899e8lg4dqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0nf2rrck4899e8lg4dqp.png" alt="Imagen 1 — Resumen SHAP global: Gráfico de puntos tipo " width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;probabilidad de breach. Valores SHAP positivos empujan la predicción hacia "alto riesgo".&lt;/p&gt;

&lt;p&gt;El análisis SHAP identificó los principales factores de riesgo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integration/API es la categoría más consistente que incrementa el riesgo.&lt;/li&gt;
&lt;li&gt;Un SLA objetivo corto (8h) incrementa significativamente el riesgo frente a uno más amplio (72h).&lt;/li&gt;
&lt;li&gt;Technical Issue es la feature de mayor magnitud, pero es bidireccional: puede aumentar o disminuir el riesgo según el contexto.&lt;/li&gt;
&lt;li&gt;El canal de entrada (email, chat o teléfono) tiene un impacto mínimo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto transforma el modelo de una herramienta puramente predictiva en una fuente de información operacional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explicación local&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para un ticket con una probabilidad final de incumplimiento de 99.1%, el análisis descompone la predicción así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhgaz6gv3qvcrwzhh6zox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhgaz6gv3qvcrwzhh6zox.png" alt="Imagen 2 — Explicación local (waterfall): Gráfico de cascada (" width="799" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ticket con 99.1% de probabilidad de breach.&lt;/p&gt;

&lt;p&gt;La pregunta deja de ser "¿el modelo dice que este ticket es riesgoso?" y pasa a ser "¿qué factores están haciendo que este ticket sea riesgoso?", una diferencia fundamental cuando las predicciones deben convertirse en decisiones humanas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementación en producción y robustez de software
&lt;/h3&gt;

&lt;p&gt;Otro problema común en proyectos de ML es confundir un modelo entrenado en un notebook con un sistema utilizable. Para evitarlo, el proyecto separa explícitamente entrenamiento y predicción.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;train.py&lt;/em&gt;&lt;/strong&gt; - carga los datos, ejecuta el pipeline, entrena el modelo y lo guarda para uso posterior. Reproducible mediante un solo comando, sin depender de ejecutar un notebook manualmente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;predict.py&lt;/em&gt;&lt;/strong&gt; - recibe nuevos tickets, ejecuta el flujo de transformación, genera predicciones y guarda los resultados junto con sus probabilidades.&lt;/p&gt;

&lt;p&gt;Esto crea una frontera clara: Training → Model Artifact → Prediction, dejando el sistema listo para una futura integración con otros sistemas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resultados
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Primer modelo con leakage: ROC-AUC 1.0000 / F1 1.0000 (no válido, usa información futura).&lt;/li&gt;
&lt;li&gt;Modelo corregido con features T=0 (Random Forest): ROC-AUC = 0.9606 · F1 = 0.9095 · R² = 0.6416.&lt;/li&gt;
&lt;li&gt;Red neuronal multitarea (PyTorch) T=0: ROC-AUC = 0.9617 · F1 = 0.9047 · R² = 0.5232.&lt;/li&gt;
&lt;li&gt;Random Forest seleccionado como candidato de producción por su equilibrio entre desempeño, simplicidad e interpretabilidad.&lt;/li&gt;
&lt;li&gt;SHAP permitió explicar tanto patrones globales como predicciones individuales.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lecciones clave
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Una métrica perfecta puede ser señal de alarma, no de éxito.&lt;/li&gt;
&lt;li&gt;Definir el momento de la predicción antes de elegir features. La pregunta no es "¿esta variable es predictiva?", sino "¿esta variable existiría en el momento en que necesito predecir?"&lt;/li&gt;
&lt;li&gt;La complejidad debe ganarse su lugar, deep learning no se usa solo porque sea más avanzado.&lt;/li&gt;
&lt;li&gt;La explicabilidad vale cuando responde preguntas operativas concretas, no cuando se incluye como una visualización adicional.&lt;/li&gt;
&lt;li&gt;Un notebook no es un sistema de producción: hace falta data pipeline + validation + model + prediction workflow + logging + documentation + reproducibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusión
&lt;/h3&gt;

&lt;p&gt;NovaTech AI comenzó como un problema de predicción de SLA y terminó convirtiéndose en un ejercicio de Machine Learning Engineering.&lt;/p&gt;

&lt;p&gt;El resultado más valioso no fue pasar de un ROC-AUC a otro ligeramente mejor. Fue identificar que el primer resultado perfecto era engañoso, redefinir el problema alrededor de T=0, comparar modelos considerando complejidad y valor operacional, incorporar explicabilidad y construir una estructura que pudiera evolucionar de un experimento a un sistema.&lt;/p&gt;

&lt;p&gt;Si tienes feedback sobre el enfoque de T=0, la elección de Random Forest sobre deep learning, o ideas para llevar esto más lejos (monitoreo de drift, calibración, API de inferencia), lo leo con gusto en los comentarios. El código completo está en el repo enlazado arriba.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>mlops</category>
      <category>datascience</category>
      <category>python</category>
    </item>
    <item>
      <title>🦆 Duck Generator Challenge</title>
      <dc:creator>Monica Orellana</dc:creator>
      <pubDate>Tue, 17 Feb 2026 16:40:51 +0000</pubDate>
      <link>https://dev.to/purischaky/duck-generator-challenge-2o7h</link>
      <guid>https://dev.to/purischaky/duck-generator-challenge-2o7h</guid>
      <description>&lt;p&gt;As someone learning AI, my strongest recommendation is this: the best way to learn is not only by reading, but getting your hands dirty.&lt;/p&gt;

&lt;p&gt;In this hands-on project, I used Kiro &lt;a href="https://kiro.dev/#what-is-kiro" rel="noopener noreferrer"&gt;An agentic AI with an IDE and CLI that helps you go from prototype to production with spec-driven development&lt;/a&gt;, to help me solve a challenge I discovered at the AWS re:Invent 2025.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The challenge?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fixing a broken AI-powered duck image generator that uses AWS Bedrock Nova Canvas to create images. This exercise is a full-stack interactive web application where we frontend debudding, backend validation, AI integration, and user experience design.&lt;/p&gt;

&lt;p&gt;Before touching any code, the first step was to understand how the system is designed:&lt;/p&gt;

&lt;p&gt;• The frontend - built with React and Vite&lt;br&gt;
• The backend - implemented using Flask and follows an agent-based workflow (duck_agent.py)&lt;br&gt;
• The AI engine – powered by AWS Bedrock, using the Nova Canvas model for image generation. &lt;br&gt;
• Reliability Layer - a fallback system that keeps the app running even without cloud credentials.&lt;/p&gt;

&lt;p&gt;According to the README.md, the challenge consists of 4 task and should take about 25 minutes. But with Kiro I completed it by writing just two prompts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Kiro app&lt;/li&gt;
&lt;li&gt;Prompt: “clone this repo: &lt;a href="https://github.com/aws-banjo/riv25_duck_game.git%E2%80%9D" rel="noopener noreferrer"&gt;https://github.com/aws-banjo/riv25_duck_game.git”&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Prompt: “your task is to complete the challenge. To do so, open the README.md file and follow the setup and implementation steps provide there. The file contains all the instructions you’ll need to get the project running.”&lt;/li&gt;
&lt;li&gt;Voila, the works is done! &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At first glance, this might look to easy or even lazy, but here’s the key point: Kiro didn’t just do the work – it explained every step it executed, so it was actually a learning accelerator, because it helps you understand what is happening, why it matters, and how the pieces connect. &lt;/p&gt;

&lt;p&gt;Here is what we accomplished doing the 4 tasks:&lt;/p&gt;

&lt;p&gt;Task 1: Start Backend &amp;amp; Test MCP, we ensured the backend is alive and the Flask server was reachable on port 8081. This step confirms the Model Context Protocol (MCP) servers were ready to accept requests.&lt;/p&gt;

&lt;p&gt;Task 2: Create Coding Standards, we defined how the AI should write a code, we created a Steering Document that define rules and conventions (e.g. quackFetch instead of fetch), also ensured error handling rules. This is a important lesson in AI governance and consistency.&lt;/p&gt;

&lt;p&gt;Task 3: Build the Duck Generator, we fixed bugs in the API client and wrote a feature specification. We simulated a real product cycle: defining behavior, AI assistant implements it and developer focuses on user flows and states. It reinforces thinking like a product-oriented AI builder.&lt;/p&gt;

&lt;p&gt;Task 4: Test with Chrome DevTools, this is end-to-end validation, we tested everything from API connectivity to the reliability of the fallback mechanism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Is a fully functional demo where you can generate duck images. Even without live AWS credentials, the reliability layer allows you to visualize 23 pre-generated duck images. &lt;/p&gt;

&lt;p&gt;If this project left you wanting more ways to bring your own AI art to life, stay tuned, in my next article, we’ll explore SageMaker Studio Lab, a free tool to experiment with AI.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
