<?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: Adrian</title>
    <description>The latest articles on DEV Community by Adrian (@adrian_368e1d3e691afab697).</description>
    <link>https://dev.to/adrian_368e1d3e691afab697</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%2F3983803%2F92991c8b-073d-44be-80c4-584f44d63100.jpg</url>
      <title>DEV Community: Adrian</title>
      <link>https://dev.to/adrian_368e1d3e691afab697</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adrian_368e1d3e691afab697"/>
    <language>en</language>
    <item>
      <title>Detección de fraude: por qué el AUC-ROC engaña y el AUC-PR no (datos reales)</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 24 Sep 2026 10:00:02 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/deteccion-de-fraude-por-que-el-auc-roc-engana-y-el-auc-pr-no-datos-reales-1gik</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/deteccion-de-fraude-por-que-el-auc-roc-engana-y-el-auc-pr-no-datos-reales-1gik</guid>
      <description>&lt;p&gt;En detección de fraude hay una trampa estadística que infla currículums: el &lt;strong&gt;AUC-ROC&lt;/strong&gt;. Sobre datos extremadamente desbalanceados es fácil presumir de un 0.99 que no significa casi nada. Este proyecto está construido alrededor de la métrica que sí importa —el &lt;strong&gt;AUC-PR&lt;/strong&gt;— y de no esconder los fallos del modelo.&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;El objetivo: marcar transacciones fraudulentas en tiempo real y, sobre todo, de forma &lt;em&gt;honesta&lt;/em&gt; y &lt;em&gt;explicable&lt;/em&gt;. Un analista necesita saber por qué se marca una operación, no un número opaco.&lt;/p&gt;

&lt;h2&gt;
  
  
  Los datos: ULB, reales y brutalmente desbalanceados
&lt;/h2&gt;

&lt;p&gt;Entrené sobre el dataset &lt;strong&gt;ULB Credit Card Fraud Detection&lt;/strong&gt;: &lt;strong&gt;284.807 transacciones reales&lt;/strong&gt; de tarjetas europeas, con features anonimizadas por PCA (V1–V28) más importe y tiempo. El detalle clave es el desbalanceo: solo el &lt;strong&gt;0,17%&lt;/strong&gt; son fraude (unas 492 de 284.807). Esa rareza es justo lo que hace difícil —y honesto— el problema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué el AUC-ROC engaña (y el AUC-PR no)
&lt;/h2&gt;

&lt;p&gt;Sobre datos tan desbalanceados, el &lt;strong&gt;AUC-ROC&lt;/strong&gt; sale altísimo casi sin esfuerzo (aquí ~0,91) porque premia clasificar bien la clase mayoritaria, que es trivial. El &lt;strong&gt;AUC-PR&lt;/strong&gt; (precisión-recall) cuenta la verdad: mi modelo logra &lt;strong&gt;0,67&lt;/strong&gt; frente a un &lt;em&gt;baseline&lt;/em&gt; de 0,0012 — es decir, &lt;strong&gt;~550× mejor que el azar&lt;/strong&gt; en lo que de verdad cuesta. Por eso la demo muestra el AUC-PR, no el ROC inflado.&lt;/p&gt;

&lt;h2&gt;
  
  
  El modelo
&lt;/h2&gt;

&lt;p&gt;Un clasificador &lt;strong&gt;LightGBM&lt;/strong&gt; con &lt;code&gt;scale_pos_weight&lt;/code&gt; para penalizar más los errores sobre la clase fraude, hiperparámetros buscados con &lt;strong&gt;Optuna&lt;/strong&gt; y umbral de decisión calibrado (0,9) para equilibrar precisión y recall según el coste real de cada error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resultados (honestos)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AUC-PR: 0,67&lt;/strong&gt; (baseline 0,0012 → ~550× sobre el azar) — la métrica que importa.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AUC-ROC: 0,91&lt;/strong&gt; — alto, pero engañoso en desbalanceo; lo reporto solo para contraste.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Precisión 0,88 · Recall 0,71 · F1 0,79 · MCC 0,79&lt;/strong&gt; sobre el fraude real.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No hay 0,99 de fantasía: el modelo acierta mucho y falla algo, y la demo lo enseña tal cual.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explicabilidad con SHAP
&lt;/h2&gt;

&lt;p&gt;Cada predicción se acompaña de un desglose &lt;strong&gt;SHAP&lt;/strong&gt;: cuánto empujó cada feature (V11, importe, etc.) hacia "fraude" o "legítimo". Eso convierte el modelo en una herramienta que un equipo humano puede auditar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que en problemas desbalanceados &lt;strong&gt;elegir bien la métrica es un acto de honestidad&lt;/strong&gt;. Es fácil publicar un AUC-ROC de 0,99 y parecer un genio; es más útil —y más honrado— reportar el AUC-PR real y explicar por qué. Un modelo que conoce y muestra sus límites vale más que uno que presume de una cifra vacía.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/deteccion-fraude-lightgbm-auc-pr-datos-reales" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>lightgbm</category>
      <category>fraude</category>
      <category>shap</category>
    </item>
    <item>
      <title>Detectar volatilidad anómala en los mercados con un Temporal Fusion Transformer</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 17 Sep 2026 10:00:02 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/detectar-volatilidad-anomala-en-los-mercados-con-un-temporal-fusion-transformer-20c2</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/detectar-volatilidad-anomala-en-los-mercados-con-un-temporal-fusion-transformer-20c2</guid>
      <description>&lt;p&gt;Predecir el precio de una acción es casi imposible y, francamente, poco útil. Hay una pregunta más alcanzable y más valiosa: &lt;strong&gt;¿cuándo está a punto de volverse anormalmente inestable un activo?&lt;/strong&gt; Los picos de volatilidad suelen preceder a las noticias, no seguirlas. Ese era el objetivo de este "sensor de mercado".&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;En lugar de estimar un único número (el retorno esperado), quería estimar la &lt;strong&gt;distribución completa&lt;/strong&gt; de retornos para cada activo y horizonte, y marcar como anómalos los momentos en los que la realidad se sale de los cuantiles que el modelo considera plausibles.&lt;/p&gt;

&lt;h2&gt;
  
  
  La arquitectura: TFT + regresión cuantílica
&lt;/h2&gt;

&lt;p&gt;Elegí el &lt;strong&gt;Temporal Fusion Transformer&lt;/strong&gt; porque combina tres cosas que necesitaba:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Variable Selection Networks&lt;/strong&gt; que aprenden qué inputs importan en cada momento, dándome interpretabilidad sin renunciar a la potencia.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Atención multi-cabeza&lt;/strong&gt; sobre la ventana temporal, que captura dependencias largas (un patrón de hace semanas) mejor que una LSTM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Salida de &lt;strong&gt;regresión cuantílica&lt;/strong&gt;: en vez de un valor, predice varios cuantiles (p10, p50, p90...). La distancia entre cuantiles &lt;em&gt;es&lt;/em&gt; la incertidumbre estimada.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cuando un retorno real cae fuera del intervalo cuantílico esperado, salta la alerta de anomalía.&lt;/p&gt;

&lt;h2&gt;
  
  
  La métrica que de verdad valida el modelo
&lt;/h2&gt;

&lt;p&gt;Un modelo cuantílico solo sirve si está &lt;strong&gt;bien calibrado&lt;/strong&gt;: si dice que algo ocurre el 90% de las veces, debe ocurrir el 90% de las veces. La calibración cuantílica de este modelo resultó prácticamente perfecta, lo que significa que sus intervalos de incertidumbre son fiables, no decorativos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resultados
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;F1-score (detección de anomalías): 0.82&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MCC: 0.80&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Calibración cuantílica: ≈ perfecta&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que reformular el problema —de "predecir el precio" a "predecir la incertidumbre"— lo vuelve tratable y útil. Y que en finanzas, un modelo que conoce sus propios límites (su calibración) vale más que uno que da respuestas precisas y falsas.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/volatilidad-anomala-temporal-fusion-transformer" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>deeplearning</category>
      <category>transformers</category>
      <category>finanzascuantitativas</category>
      <category>seriestemporales</category>
    </item>
    <item>
      <title>Regímenes de mercado con Hidden Markov Models: un score de riesgo que bate al buy-and-hold</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 10 Sep 2026 10:00:02 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/regimenes-de-mercado-con-hidden-markov-models-un-score-de-riesgo-que-bate-al-buy-and-hold-ipg</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/regimenes-de-mercado-con-hidden-markov-models-un-score-de-riesgo-que-bate-al-buy-and-hold-ipg</guid>
      <description>&lt;p&gt;Los mercados no se comportan igual todo el tiempo. Hay periodos de calma alcista, periodos neutrales y periodos de pánico. El problema es que ese "régimen" es un &lt;strong&gt;estado oculto&lt;/strong&gt;: no viene etiquetado en los datos, solo lo intuimos por cómo se comportan los retornos y la volatilidad. Es el escenario perfecto para un Hidden Markov Model.&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Quería un score de riesgo &lt;strong&gt;en tiempo real&lt;/strong&gt; que no se limitara a mirar la volatilidad pasada, sino que identificara en qué régimen está el mercado &lt;em&gt;ahora&lt;/em&gt; y ajustara la exposición en consecuencia.&lt;/p&gt;

&lt;h2&gt;
  
  
  La arquitectura: Gaussian HMM
&lt;/h2&gt;

&lt;p&gt;Entrené un &lt;strong&gt;GaussianHMM&lt;/strong&gt; (con &lt;code&gt;hmmlearn&lt;/code&gt;) sobre 5 años de datos reales de cinco activos representativos: SPY, IBEX35, STOXX50E, TLT (bonos) y GLD (oro). El modelo asume que en cada momento el mercado está en uno de &lt;strong&gt;3 estados ocultos&lt;/strong&gt; —Bull, Neutral, Bear— y que los retornos observados se generan a partir de una gaussiana distinta según el estado. El algoritmo de Baum-Welch aprende las matrices de transición y las distribuciones de emisión sin que yo etiquete nada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Del régimen a la decisión
&lt;/h2&gt;

&lt;p&gt;Una vez el modelo infiere el régimen actual (vía el algoritmo de Viterbi/forward), la estrategia ajusta la exposición: plena en Bull, reducida en Neutral, defensiva en Bear. Sobre esa base calculo además VaR al 95%, Sortino y un score de riesgo normalizado de 0 a 100.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resultados (HMM vs. buy-and-hold)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sharpe: 2.12&lt;/strong&gt; frente a 1.11 del comprar-y-mantener.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CVaR (riesgo de cola): reducido un 32%.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Máximo drawdown: de -21,9% a -7,5%.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lo interesante no es solo el mayor Sharpe, sino la brutal reducción del drawdown: el modelo se sale a tiempo de los regímenes bajistas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que los modelos de estados latentes son una forma honesta de capturar algo que los traders saben intuitivamente —"esto ha cambiado de tono"— sin caer en el sobreajuste de intentar predecir el precio exacto. El HMM no adivina el futuro; reconoce el presente mejor que la media móvil.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/score-riesgo-cartera-hidden-markov-models" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>finanzascuantitativas</category>
      <category>hiddenmarkovmodels</category>
      <category>gestionderiesgo</category>
      <category>seriestemporales</category>
    </item>
    <item>
      <title>Value Betting Engine: del modelo de probabilidad a la apuesta de valor con el criterio de Kelly</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 03 Sep 2026 10:00:03 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/value-betting-engine-del-modelo-de-probabilidad-a-la-apuesta-de-valor-con-el-criterio-de-kelly-a4n</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/value-betting-engine-del-modelo-de-probabilidad-a-la-apuesta-de-valor-con-el-criterio-de-kelly-a4n</guid>
      <description>&lt;p&gt;Hay un malentendido fundamental sobre las apuestas deportivas: la gente cree que se trata de &lt;em&gt;acertar&lt;/em&gt; quién gana. No es así. Se trata de encontrar situaciones en las que la &lt;strong&gt;cuota del mercado está equivocada&lt;/strong&gt; respecto a la probabilidad real. Eso es el &lt;em&gt;value betting&lt;/em&gt;, y es matemáticamente idéntico a buscar activos infravalorados en bolsa.&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Necesitaba dos cosas: (1) una estimación propia y fiable de la probabilidad de cada resultado, y (2) una forma de compararla con las cuotas del mercado para detectar valor y dimensionar la apuesta sin arruinarme.&lt;/p&gt;

&lt;h2&gt;
  
  
  La probabilidad: reutilizar el Sports Engine
&lt;/h2&gt;

&lt;p&gt;Las probabilidades vienen del modelo del &lt;a href="https://dev.to/proyecto/sports-engine"&gt;Sports Performance Engine&lt;/a&gt; (ensemble LightGBM + XGBoost sobre datos StatsBomb). Reutilizar ese motor fue una decisión de arquitectura: un buen modelo de predicción deportiva es la base sobre la que se construye el value betting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detectar valor: EV &amp;gt; 0
&lt;/h2&gt;

&lt;p&gt;Para cada mercado consulto las cuotas de &lt;strong&gt;más de 350 casas&lt;/strong&gt; vía OddsPapi. La señal de valor es simple pero implacable: el &lt;strong&gt;valor esperado&lt;/strong&gt; de la apuesta, &lt;code&gt;EV = p · (cuota − 1) − (1 − p)&lt;/code&gt;, donde &lt;code&gt;p&lt;/code&gt; es mi probabilidad estimada. Solo entran las apuestas con &lt;strong&gt;EV positivo&lt;/strong&gt;: aquellas donde el mercado paga más de lo que el riesgo justifica.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dimensionar: el criterio de Kelly
&lt;/h2&gt;

&lt;p&gt;Detectar valor no basta; hay que decidir &lt;em&gt;cuánto&lt;/em&gt; apostar. El &lt;strong&gt;criterio de Kelly&lt;/strong&gt; da la fracción del capital que maximiza el crecimiento geométrico a largo plazo: &lt;code&gt;f = (p · b − q) / b&lt;/code&gt;. En la práctica uso un Kelly fraccional (una fracción de lo que recomienda) porque el Kelly puro es demasiado agresivo y muy sensible a errores en la estimación de &lt;code&gt;p&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validación: backtesting 2022–2024
&lt;/h2&gt;

&lt;p&gt;Toda la lógica se validó con &lt;strong&gt;backtesting sobre datos de 2022 a 2024&lt;/strong&gt;, simulando el bankroll a lo largo del tiempo para comprobar que la estrategia sobrevive a las rachas malas —que las hay, incluso con EV positivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que la gestión del riesgo (Kelly) es tan importante como la detección de la oportunidad (EV). Un buen modelo con mal sizing quiebra; un modelo modesto con sizing disciplinado sobrevive. La misma lección que en cualquier mesa de trading.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/value-betting-engine-kelly-criterion" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>finanzascuantitativas</category>
      <category>apuestasdeportivas</category>
      <category>kellycriterion</category>
      <category>backtesting</category>
    </item>
    <item>
      <title>Sports Performance Engine: predecir fútbol con datos StatsBomb y un ensemble LightGBM+XGBoost</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 27 Aug 2026 10:00:02 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/sports-performance-engine-predecir-futbol-con-datos-statsbomb-y-un-ensemble-lightgbmxgboost-d18</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/sports-performance-engine-predecir-futbol-con-datos-statsbomb-y-un-ensemble-lightgbmxgboost-d18</guid>
      <description>&lt;p&gt;El fútbol es uno de los deportes más difíciles de predecir: tiene pocos goles, mucho azar y un equipo inferior gana con sorprendente frecuencia. Eso lo convierte en un banco de pruebas honesto para el machine learning, porque no puedes esconderte detrás de métricas infladas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Los datos: StatsBomb
&lt;/h2&gt;

&lt;p&gt;Usé los datos abiertos de &lt;strong&gt;StatsBomb&lt;/strong&gt; (vía &lt;code&gt;statsbombpy&lt;/code&gt;), que van mucho más allá del marcador: eventos por partido, posición de cada acción, expected goals (xG), presiones, pases progresivos. Cuando faltaban datos, completé con un generador sintético calibrado de partidos de LaLiga y Champions, hasta unos 3.200 partidos analizados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature engineering: el corazón del proyecto
&lt;/h2&gt;

&lt;p&gt;El modelo no mira un partido aislado, sino la &lt;strong&gt;forma reciente&lt;/strong&gt; de cada equipo. Construí features &lt;em&gt;rolling&lt;/em&gt;: medias móviles de xG a favor y en contra, de presiones, de rendimiento, en ventanas de los últimos N partidos. Esto captura "este equipo llega en racha" sin que el modelo haga trampa mirando el futuro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validación: TimeSeriesSplit, no K-Fold
&lt;/h2&gt;

&lt;p&gt;Este es el error más común en ML deportivo y financiero: usar validación cruzada aleatoria. Si entrenas con partidos de mayo y validas con partidos de enero, estás &lt;strong&gt;filtrando el futuro&lt;/strong&gt;. Usé &lt;strong&gt;TimeSeriesSplit&lt;/strong&gt; (división temporal 70/15/15), de modo que el modelo siempre se evalúa sobre partidos posteriores a los de entrenamiento.&lt;/p&gt;

&lt;h2&gt;
  
  
  El modelo: ensemble + Optuna
&lt;/h2&gt;

&lt;p&gt;Combiné &lt;strong&gt;LightGBM y XGBoost&lt;/strong&gt; en un ensemble —dos implementaciones de gradient boosting con sesgos ligeramente distintos cuyas predicciones promediadas generalizan mejor— con hiperparámetros buscados por &lt;strong&gt;Optuna&lt;/strong&gt; (30+25 trials).&lt;/p&gt;

&lt;h2&gt;
  
  
  Resultados
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AUC-ROC: 0.71&lt;/strong&gt; — un número modesto en apariencia, pero &lt;em&gt;realista&lt;/em&gt; para fútbol; desconfía de cualquiera que te prometa 0.95 prediciendo resultados de fútbol.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;3.200 partidos&lt;/strong&gt; analizados, &lt;strong&gt;25+ features&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explicabilidad &lt;strong&gt;SHAP&lt;/strong&gt; por predicción.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que un AUC de 0.71 honesto vale más que un 0.95 fruto de fugas de datos. La integridad de la validación temporal es lo que separa un modelo que funciona en producción de uno que solo brilla en el notebook.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/sports-performance-engine-statsbomb-ensemble" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>deportes</category>
      <category>lightgbm</category>
      <category>xgboost</category>
    </item>
    <item>
      <title>Predicción de precio inmobiliario: por qué un ensemble GBM + red neuronal bate a cualquiera por separado</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 20 Aug 2026 10:00:02 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/prediccion-de-precio-inmobiliario-por-que-un-ensemble-gbm-red-neuronal-bate-a-cualquiera-por-2b4k</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/prediccion-de-precio-inmobiliario-por-que-un-ensemble-gbm-red-neuronal-bate-a-cualquiera-por-2b4k</guid>
      <description>&lt;p&gt;El precio de una vivienda depende de factores que se comportan de formas muy distintas. Algunos son cuasi-reglas ("más de 3 baños dispara el precio en esta zona"); otros son interacciones suaves y continuas (la relación entre metros, antigüedad y barrio). Ningún tipo de modelo captura bien ambas cosas a la vez. Por eso usé un &lt;strong&gt;ensemble&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Estimar el precio de mercado de una vivienda a partir de sus características, con un error lo bastante bajo como para ser útil en una valoración real, y exponerlo como una API de predicción en tiempo real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Los dos modelos del ensemble
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gradient Boosting Machine:&lt;/strong&gt; excelente capturando relaciones no lineales y "reglas" abruptas sobre datos tabulares. Es el caballo de batalla de los datos estructurados.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Perceptrón multicapa (MLP):&lt;/strong&gt; una red neuronal que modela bien las interacciones suaves y continuas entre variables, algo donde los árboles, por su naturaleza escalonada, son más toscos.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Las predicciones de ambos se combinan. El ensemble funciona porque sus errores están &lt;strong&gt;poco correlacionados&lt;/strong&gt;: donde uno falla por su sesgo, el otro tiende a compensar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decisiones técnicas
&lt;/h2&gt;

&lt;p&gt;El preprocesado trató con cuidado las variables sesgadas (el precio y la superficie se distribuyen log-normalmente, no normalmente) y las categóricas de localización. El stack es &lt;code&gt;scikit-learn&lt;/code&gt; para el GBM y &lt;strong&gt;PyTorch&lt;/strong&gt; para el MLP, servido todo con &lt;strong&gt;FastAPI&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resultados
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;R² ≈ 0.90:&lt;/strong&gt; el modelo explica alrededor del 90% de la varianza del precio.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MAE ≈ ±$62K:&lt;/strong&gt; error medio absoluto.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;~11% de error porcentual relativo.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que el ensembling no es hacer trampa: es reconocer que distintos modelos tienen distintos puntos ciegos, y que combinarlos es casi siempre más robusto que pelearse por exprimir el último 0,5% de un único modelo.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/prediccion-precio-inmobiliario-ensemble-gbm-mlp" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ensemble</category>
      <category>gradientboosting</category>
      <category>redesneuronales</category>
    </item>
    <item>
      <title>Un chatbot RAG multilingüe sobre tus PDFs con FAISS y reranking (coste de búsqueda: 0 €)</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 13 Aug 2026 10:00:03 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/un-chatbot-rag-multilingue-sobre-tus-pdfs-con-faiss-y-reranking-coste-de-busqueda-0-eu-3bjc</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/un-chatbot-rag-multilingue-sobre-tus-pdfs-con-faiss-y-reranking-coste-de-busqueda-0-eu-3bjc</guid>
      <description>&lt;p&gt;En un sistema RAG (Retrieval-Augmented Generation), todo el mundo se fija en el LLM. Es un error. La calidad de las respuestas depende muchísimo más de &lt;strong&gt;qué fragmentos recuperas&lt;/strong&gt; que del modelo que los redacta. Si recuperas el contexto equivocado, el mejor LLM del mundo te dará una respuesta equivocada con total seguridad.&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Construir un asistente que responda preguntas sobre documentos PDF —manuales, normativas, catálogos— en varios idiomas, con respuestas fundamentadas en el documento y no inventadas, y a coste de infraestructura cercano a cero.&lt;/p&gt;

&lt;h2&gt;
  
  
  El pipeline de recuperación (donde está el truco)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Embeddings multilingües:&lt;/strong&gt; uso &lt;code&gt;intfloat/multilingual-e5-large&lt;/code&gt; para vectorizar los fragmentos. El modelo entiende que "precio" y "price" están cerca en el espacio vectorial, lo que da soporte multilingüe de serie.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Búsqueda vectorial con FAISS:&lt;/strong&gt; los vectores se indexan en &lt;strong&gt;FAISS&lt;/strong&gt;, la librería de Facebook para búsqueda de similitud. Corre en CPU, en local, sin servicios gestionados: de ahí el &lt;strong&gt;coste de búsqueda de 0 €&lt;/strong&gt;. Los índices estáticos se pre-generan por idioma; los PDFs que sube el usuario se indexan en RAM por sesión.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reranking con cross-encoder:&lt;/strong&gt; la búsqueda vectorial es rápida pero imprecisa. Por eso añado un segundo paso: un &lt;strong&gt;cross-encoder&lt;/strong&gt; (&lt;code&gt;mmarco-mMiniLMv2&lt;/code&gt;) que re-puntúa los candidatos leyendo pregunta y fragmento &lt;em&gt;juntos&lt;/em&gt;. Es más lento, pero solo se aplica a un puñado de candidatos, y mejora drásticamente la precisión del contexto.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  La generación
&lt;/h2&gt;

&lt;p&gt;Solo entonces entra el LLM (&lt;strong&gt;Llama vía Groq&lt;/strong&gt;, por su latencia bajísima), que redacta la respuesta a partir del contexto ya filtrado. El resultado: respuesta media &lt;strong&gt;por debajo de 3 segundos&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  De demo a producto: SaaS multi-tenant
&lt;/h2&gt;

&lt;p&gt;Por encima del motor RAG monté una capa &lt;strong&gt;SaaS multi-tenant&lt;/strong&gt; con SQLite: clientes, planes (free/basic/pro/enterprise), autenticación por &lt;code&gt;X-API-Key&lt;/code&gt; y registro de consumo de tokens con límites por plan. Lo que empezó como una demo es, en arquitectura, un producto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que la frase "RAG es solo meter documentos en un LLM" es engañosa. El valor está en el &lt;strong&gt;pipeline de recuperación&lt;/strong&gt; —embeddings + búsqueda + reranking— y en hacerlo barato y rápido. El LLM es la última milla, no el motor.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/chatbot-rag-multilingue-faiss-reranking" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nlp</category>
      <category>rag</category>
      <category>faiss</category>
      <category>embeddings</category>
    </item>
    <item>
      <title>FeliniAI: un triple pipeline (visión + clínico + LLM) para detectar alergias felinas con F1 0.97</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 06 Aug 2026 10:00:02 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/feliniai-un-triple-pipeline-vision-clinico-llm-para-detectar-alergias-felinas-con-f1-097-2jac</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/feliniai-un-triple-pipeline-vision-clinico-llm-para-detectar-alergias-felinas-con-f1-097-2jac</guid>
      <description>&lt;p&gt;Cuando el objetivo es algo tan delicado como un diagnóstico asistido, confiar en un único modelo es arriesgado. FeliniAI usa &lt;strong&gt;tres pipelines complementarios&lt;/strong&gt; que se refuerzan entre sí, igual que un veterinario combina lo que ve, lo que mide y lo que sabe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipeline 1 — Visión: MobileNetV2
&lt;/h2&gt;

&lt;p&gt;Una CNN &lt;strong&gt;MobileNetV2&lt;/strong&gt; (PyTorch, transfer learning) clasifica imágenes de la piel/pelaje del gato en categorías visuales. Elegí MobileNetV2 por su equilibrio entre precisión y ligereza: corre rápido en CPU, lo que mantiene la inferencia por debajo de 1 segundo. Alcanza un &lt;strong&gt;93,4% de accuracy visual&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipeline 2 — Clínico: XGBoost + ICADA
&lt;/h2&gt;

&lt;p&gt;El núcleo del sistema es un clasificador &lt;strong&gt;XGBoost&lt;/strong&gt; que trabaja sobre &lt;strong&gt;33 features clínicas&lt;/strong&gt; derivadas de los criterios &lt;strong&gt;ICADA&lt;/strong&gt; (los criterios estandarizados de dermatitis atópica felina): estacionalidad, distribución de las lesiones, prurito, respuesta a tratamientos previos. Sobre un dataset de &lt;strong&gt;8.000 casos&lt;/strong&gt;, este módulo logra un &lt;strong&gt;F1 macro de 0.9675&lt;/strong&gt; en validación cruzada 5-fold. La búsqueda de hiperparámetros se hizo con Optuna y la explicabilidad con SHAP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipeline 3 — LLM: la síntesis
&lt;/h2&gt;

&lt;p&gt;Finalmente, un LLM (&lt;strong&gt;Llama 3.3 70B vía Groq&lt;/strong&gt;) integra las salidas de los dos modelos anteriores y las traduce en una recomendación legible: qué tipo de alergia es más probable, con qué confianza y qué pasos sugerir. El LLM no diagnostica solo: &lt;em&gt;orquesta y comunica&lt;/em&gt; lo que han calculado los modelos especializados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué tres pipelines y no uno
&lt;/h2&gt;

&lt;p&gt;Porque cada uno cubre el punto ciego del otro. La visión capta lo que una foto muestra pero un cuestionario no; el modelo clínico capta el historial que una foto no puede mostrar; el LLM convierte ambos en algo accionable. Es un patrón de &lt;strong&gt;ensemble heterogéneo&lt;/strong&gt; aplicado a datos de naturaleza distinta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resultados
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;F1 macro (clínico): 0.9675&lt;/strong&gt;, accuracy 0.9909.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accuracy visual: 93,4%.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;4 tipos de alergia, 33 features clínicas, &amp;lt;1s&lt;/strong&gt; de inferencia.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que en dominios sensibles, la arquitectura correcta no es "el modelo más grande", sino &lt;strong&gt;varios modelos especializados orquestados&lt;/strong&gt;, cada uno haciendo aquello en lo que es bueno.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/feliniai-triple-pipeline-vision-clinico-llm" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>deeplearning</category>
      <category>visionporcomputador</category>
      <category>xgboost</category>
      <category>salud</category>
    </item>
    <item>
      <title>Separar canciones en stems con HTDemucs v4 en un servidor con poca RAM</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 30 Jul 2026 10:00:02 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/separar-canciones-en-stems-con-htdemucs-v4-en-un-servidor-con-poca-ram-47nf</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/separar-canciones-en-stems-con-htdemucs-v4-en-un-servidor-con-poca-ram-47nf</guid>
      <description>&lt;p&gt;La separación de fuentes musicales —descomponer una canción mezclada en sus pistas individuales— parecía ciencia ficción hace pocos años. Hoy, modelos como &lt;strong&gt;HTDemucs&lt;/strong&gt; lo hacen sorprendentemente bien. El reto de este proyecto no fue el modelo, sino &lt;strong&gt;ponerlo a funcionar en un servidor modesto, sin GPU.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Separar cualquier canción en 4 stems (voces, batería, bajo y melodía) y permitir remezclarla en el navegador. Todo ello en una máquina con CPU y RAM limitada, donde un proceso descuidado tumba el servidor.&lt;/p&gt;

&lt;h2&gt;
  
  
  El modelo: HTDemucs v4
&lt;/h2&gt;

&lt;p&gt;Uso &lt;strong&gt;HTDemucs v4&lt;/strong&gt; (variante &lt;code&gt;htdemucs_ft&lt;/code&gt;), un modelo híbrido transformer/convolucional que opera tanto en el dominio de la forma de onda como en el espectrograma. Es el estado del arte abierto en separación de fuentes, con licencia MIT.&lt;/p&gt;

&lt;h2&gt;
  
  
  Las dos decisiones de ingeniería que lo hacen viable
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Segmentación (&lt;code&gt;--segment 5&lt;/code&gt;):&lt;/strong&gt; procesar una canción entera de golpe dispara el uso de memoria. Trocear el audio en segmentos cortos mantiene el pico de RAM bajo control, a costa de algo más de tiempo. Sin esto, el proceso muere por OOM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Procesado asíncrono:&lt;/strong&gt; la separación tarda decenas de segundos. Bloquear la petición HTTP sería inaceptable, así que el trabajo se encola y procesa en segundo plano (sin necesidad de Celery: una solución asíncrona ligera), y el frontend consulta el progreso.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El frontend usa &lt;strong&gt;WaveSurfer.js&lt;/strong&gt; para visualizar las ondas y la &lt;strong&gt;Web Audio API&lt;/strong&gt; para la remezcla en tiempo real: ajustar el volumen de cada stem, silenciar la voz para hacer karaoke, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detalle de despliegue
&lt;/h2&gt;

&lt;p&gt;El modelo (~400 MB) se descarga en el primer uso. El servicio corre con límites de memoria de systemd y, como otras demos pesadas del portfolio, arranca bajo demanda y se apaga tras un periodo de inactividad para no malgastar RAM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que desplegar IA en hardware limitado es una disciplina en sí misma. El modelo es solo el principio; la segmentación, el procesado asíncrono y la gestión de memoria son lo que separa una demo que funciona de una que tumba el servidor.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/separar-stems-htdemucs-v4-cpu-ram-limitada" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>audioai</category>
      <category>htdemucs</category>
      <category>deeplearning</category>
      <category>procesadoasincrono</category>
    </item>
    <item>
      <title>Construir un SDK de música adaptativa para juegos con la Web Audio API</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 23 Jul 2026 10:00:02 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/construir-un-sdk-de-musica-adaptativa-para-juegos-con-la-web-audio-api-2ao1</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/construir-un-sdk-de-musica-adaptativa-para-juegos-con-la-web-audio-api-2ao1</guid>
      <description>&lt;p&gt;En los grandes juegos, la música cambia de forma fluida según lo que ocurre: explorar, combatir, ganar. Esa "música adaptativa" suele requerir middleware caro y complejo (FMOD, Wwise). Quise llevar esa capacidad a los desarrolladores &lt;strong&gt;indie&lt;/strong&gt; de juegos web, con un SDK que se integre en menos de 10 líneas.&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Cambiar de pista musical en respuesta al estado del juego sin que se note el corte. Un crossfade ingenuo suena fatal porque rompe el compás; la transición debe ocurrir &lt;strong&gt;en el momento musical correcto.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  La arquitectura: capas + crossfade al beat
&lt;/h2&gt;

&lt;p&gt;El SDK gestiona varias &lt;strong&gt;capas musicales&lt;/strong&gt; (town, explore, combat, victory) que comparten tempo. Cuando el juego pide cambiar de estado, el motor no corta de golpe: programa un &lt;strong&gt;crossfade sincronizado al beat&lt;/strong&gt; usando el reloj de alta precisión de la &lt;strong&gt;Web Audio API&lt;/strong&gt;. Las transiciones esperan al siguiente tiempo musical, de modo que el cambio suena intencionado, no accidental. La latencia percibida del crossfade es prácticamente nula.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;Está escrito en &lt;strong&gt;TypeScript&lt;/strong&gt; sobre &lt;strong&gt;Tone.js&lt;/strong&gt; (que abstrae el scheduling de la Web Audio API), empaquetado con &lt;strong&gt;tsup&lt;/strong&gt; en formatos ESM y CJS para que funcione en cualquier proyecto moderno. La demo es un mini-RPG en &lt;strong&gt;Phaser 3&lt;/strong&gt; donde la banda sonora cambia al entrar en combate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diseño de API: la obsesión por la simplicidad
&lt;/h2&gt;

&lt;p&gt;La métrica de éxito de un SDK no es su potencia, sino lo poco que tienes que escribir para usarlo. El objetivo de diseño fue que añadir música adaptativa cueste &lt;strong&gt;5 líneas&lt;/strong&gt;: instanciar el motor, registrar las capas y llamar a &lt;code&gt;setState('combat')&lt;/code&gt;. Todo lo complejo —el scheduling, el crossfade, la sincronía— queda escondido.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que escribir una librería para otros desarrolladores es un ejercicio de empatía: cada decisión de API es un compromiso entre flexibilidad y simplicidad. Y que el audio en el navegador, con su reloj propio, exige pensar el tiempo de otra manera.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/sdk-musica-adaptativa-web-audio-api-juegos" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webaudioapi</category>
      <category>gamedev</category>
      <category>sdk</category>
    </item>
    <item>
      <title>RoomCraft AI: optimizar la distribución de una habitación con Simulated Annealing</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 16 Jul 2026 10:00:02 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/roomcraft-ai-optimizar-la-distribucion-de-una-habitacion-con-simulated-annealing-bj7</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/roomcraft-ai-optimizar-la-distribucion-de-una-habitacion-con-simulated-annealing-bj7</guid>
      <description>&lt;p&gt;Colocar los muebles de una habitación es un problema de optimización con muchas restricciones: la cama no va delante de la puerta, el escritorio quiere luz natural, hay que poder circular. Hay un número enorme de disposiciones posibles. RoomCraft AI las explora automáticamente a partir de una descripción en lenguaje natural.&lt;/p&gt;

&lt;h2&gt;
  
  
  El pipeline de tres etapas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parser con LLM:&lt;/strong&gt; el usuario describe su habitación en texto libre ("un dormitorio de 4x3 con la puerta al norte y una ventana al este"). Un LLM (&lt;strong&gt;Llama 3.1 vía Groq&lt;/strong&gt;) lo convierte en una estructura de datos validada con &lt;strong&gt;Pydantic&lt;/strong&gt;: dimensiones, aberturas, muebles deseados. Latencia: &amp;lt;1s.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimizador con Simulated Annealing:&lt;/strong&gt; aquí está el corazón del proyecto.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Visualización y export:&lt;/strong&gt; los layouts se renderizan en 3D en el navegador con &lt;strong&gt;Three.js&lt;/strong&gt; y se exportan como plano técnico en PDF con &lt;strong&gt;ReportLab&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Por qué Simulated Annealing
&lt;/h2&gt;

&lt;p&gt;El espacio de disposiciones posibles es combinatorio y lleno de óptimos locales. Una búsqueda voraz se queda atascada en la primera solución "decente". El &lt;strong&gt;Simulated Annealing&lt;/strong&gt; imita el enfriamiento de un metal: al principio acepta movimientos malos con cierta probabilidad (alta "temperatura"), lo que le permite escapar de óptimos locales; según baja la temperatura, se vuelve cada vez más exigente y converge. Es una metaheurística ideal cuando el espacio de soluciones es irregular y no tienes gradiente.&lt;/p&gt;

&lt;p&gt;La función objetivo puntúa cada disposición de 0 a 100 según ergonomía: espacio de circulación, relaciones entre muebles, acceso a luz y aberturas. El sistema devuelve el &lt;strong&gt;top 5&lt;/strong&gt; de layouts, no solo el mejor, para dar opciones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendimiento
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Parse: &lt;strong&gt;&amp;lt;1s&lt;/strong&gt;. Optimización: &lt;strong&gt;2–5s&lt;/strong&gt;. Export PDF: &lt;strong&gt;&amp;lt;1s&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Footprint en reposo: &lt;strong&gt;~100 MB de RAM.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que combinar un LLM (para entender lenguaje) con una metaheurística clásica (para optimizar de verdad) es un patrón potentísimo: el LLM traduce el problema humano a uno formal, y un algoritmo determinista y barato lo resuelve mejor —y de forma más explicable— que pedirle al propio LLM que "coloque los muebles".&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/roomcraft-ai-simulated-annealing-distribucion-habitaciones" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>optimizacioncombinatoria</category>
      <category>simulatedannealing</category>
      <category>llm</category>
      <category>threejs</category>
    </item>
    <item>
      <title>BabyMind: un asistente de desarrollo infantil con alertas pediátricas y memoria conversacional</title>
      <dc:creator>Adrian</dc:creator>
      <pubDate>Thu, 09 Jul 2026 10:00:02 +0000</pubDate>
      <link>https://dev.to/adrian_368e1d3e691afab697/babymind-un-asistente-de-desarrollo-infantil-con-alertas-pediatricas-y-memoria-conversacional-1n16</link>
      <guid>https://dev.to/adrian_368e1d3e691afab697/babymind-un-asistente-de-desarrollo-infantil-con-alertas-pediatricas-y-memoria-conversacional-1n16</guid>
      <description>&lt;p&gt;Construir un asistente de IA sobre salud infantil obliga a una pregunta incómoda: &lt;strong&gt;¿qué pasa si se equivoca?&lt;/strong&gt; Un LLM genérico, por capaz que sea, puede dar consejos peligrosos con total seguridad. BabyMind está diseñado alrededor de esa preocupación, no a pesar de ella.&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Ayudar a madres y padres a seguir el desarrollo de su bebé (0–36 meses), comparándolo con hitos médicos reconocidos y respondiendo dudas, &lt;strong&gt;sin pretender sustituir al pediatra&lt;/strong&gt; y derivando a él cuando toca.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conocimiento anclado: hitos OMS/AAP
&lt;/h2&gt;

&lt;p&gt;El asistente no improvisa los hitos del desarrollo: trabaja sobre &lt;strong&gt;37 hitos tabulados&lt;/strong&gt; de la OMS y la Academia Americana de Pediatría (AAP), organizados en 4 categorías —motor, lenguaje, social y cognitivo— por franja de edad. El LLM razona &lt;em&gt;sobre&lt;/em&gt; esa base de conocimiento, no desde su memoria paramétrica, lo que reduce las alucinaciones.&lt;/p&gt;

&lt;h2&gt;
  
  
  El sistema de alertas de tres niveles
&lt;/h2&gt;

&lt;p&gt;Esta es la parte de seguridad. Cada interacción se clasifica en uno de tres niveles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Normal:&lt;/strong&gt; respuesta informativa estándar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; ante palabras clave como "alerta" o señales de retraso, recomienda explícitamente consultar al pediatra.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Emergency:&lt;/strong&gt; ante términos críticos ("convulsiones", "no respira"), corta el flujo conversacional normal y dirige de inmediato al 112.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Este filtro determinista &lt;em&gt;envuelve&lt;/em&gt; al LLM: no dependemos de que el modelo "decida bien" en una emergencia.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memoria conversacional
&lt;/h2&gt;

&lt;p&gt;Usa &lt;strong&gt;ConversationSummaryBufferMemory&lt;/strong&gt; de LangChain: en vez de arrastrar todo el historial (caro y limitado por el contexto), mantiene un &lt;em&gt;resumen&lt;/em&gt; de la conversación más los últimos turnos literales. Así recuerda lo importante de un diálogo largo sin disparar el coste. El motor es &lt;strong&gt;Llama 3.x 70B vía Groq&lt;/strong&gt;, con respuesta &amp;lt;1s.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué aprendí
&lt;/h2&gt;

&lt;p&gt;Que en aplicaciones de salud, la ingeniería de seguridad (conocimiento anclado + filtros deterministas de alertas) importa más que la elocuencia del modelo. El LLM aporta la conversación; la arquitectura aporta la responsabilidad.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Publicado originalmente en &lt;a href="https://adrianmoreno-dev.com/blog/babymind-asistente-desarrollo-infantil-llm-memoria" rel="noopener noreferrer"&gt;adrianmoreno-dev.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>langchain</category>
      <category>salud</category>
      <category>seguridadenia</category>
    </item>
  </channel>
</rss>
