Escrito por: Felipe Almeida, con contribuciones de Luiz Felix


Esta es la parte 2 de una serie de 3 partes sobre Feature Stores para ML en tiempo real. En la parte 1 hablamos sobre la Introducción y también sobre los Pros y Contras. En la parte 3 concluimos con configuraciones de arquitectura del mundo real de extremo a extremo de Nubank.

Un repaso rápido

En la parte 1, exploramos qué son los feature stores y el papel que desempeñan en los sistemas de machine learning en tiempo real. Analizamos cómo ayudan a mitigar problemas cruciales como el training-serving skew y por qué, a pesar de los costos de adopción, son una inversión valiosa para las organizaciones que operan ML a escala.

En los últimos años, hemos utilizado feature stores en una amplia gama de aplicaciones de ML en tiempo real en Nubank, incluyendo análisis de crédito, detección de fraudes y atención al cliente. En el camino, hemos visto surgir patrones recurrentes, nos hemos enfrentado a desafíos inesperados y hemos reunido lecciones prácticas que nos ayudaron a evitar errores comunes mientras maximizábamos el valor entregado por la plataforma.

En este artículo, cubriremos algunas que consideramos especialmente importantes.

Lección: Construir vs comprar es un espectro 

Es común referirse al dilema “construir vs comprar” al hablar de plataformas complejas como los feature stores. Algunas organizaciones pueden querer construir todo internamente, mientras que otras pueden querer trasladar parte de la complejidad a feature stores más “completos” como Chalk o Feast.

En nuestra opinión, no tienes que elegir entre construir todo o comprar todo. En su lugar, puedes tener un feature store híbrido: construyes algunas partes, usas herramientas open-source en otras y delegas a proveedores de servicios externos cuando sea necesario. Esto es similar al enfoque que seguimos actualmente en Nubank.

Construir vs comprar no es una elección binaria: puedes optar por “comprar” algunos componentes y construir otros tú mismo.

Figura 1 a continuación muestra una vista de alto nivel de un feature store en tiempo real y algunos de los componentes que pueden existir en cada capa. Cada uno de estos componentes puede ser “construido” o “comprado”.

Figura 1: Un feature store en tiempo real tiene muchos componentes y muchos de ellos podrían, en teoría, construirse internamente o comprarse como un producto “llave en mano”. Curiosamente, muchos proyectos open-source han dado origen a empresas que ofrecen versiones gestionadas de los mismos (p. ej. Kafka/Confluent, Spark/Databricks, Cassandra/Datastax).

En Nubank, usamos herramientas open-source como Kubernetes, Kafka, Pinot, Spark y Flink para las partes centrales de la arquitectura, donde nuestros casos de uso no se alejan demasiado de aquello para lo que están diseñadas las herramientas. También usamos servicios totalmente gestionados de nuestros proveedores de nube, mientras que otros componentes (como nuestra infraestructura de monitoreo) se construyen internamente. 

La clave para decidir qué partes se “construyen” vs se “compran” tiene que ver con el nivel de control que tienes y con dónde los patrones de flujo de trabajo de tu organización son demasiado diferentes de los casos de uso predeterminados para los que están diseñadas las herramientas: en estos casos, puede que no tengas otra opción que construir.

Descubre las oportunidades

Lección: Los feature stores son productos y deben gestionarse como tales 

Además de ser sistemas, los feature stores también son productos. Y los productos son entidades vivas que necesitan ser gestionadas, idealmente por un Product Manager (PM) dedicado. Todo lo relacionado con la gestión de productos internos aplica aquí. 

Muchas de las prácticas comúnmente asociadas con la gestión de productos internos aplican directamente a los feature stores, como:

  • Roadmap y priorización de tareas: ¿Qué tareas y mejoras deben construirse primero? ¿Qué solicitudes quedan fuera del alcance de la plataforma y por qué?
  • Canales de soporte: ¿Cómo obtendrán ayuda los usuarios cuando encuentren problemas o tengan preguntas? ¿Habrá una rotación de ingenieros para brindar soporte? ¿Cómo hará el equipo para medir el tiempo que toma responder preguntas?
  • Entrevistas/encuestas a usuarios: ¿Cómo evaluará el equipo de FS qué tan satisfechos están los usuarios con el producto? 
  • Gestión de stakeholders: ¿Cómo se mantendrán informados los stakeholders clave sobre las mejoras del producto? ¿Quién debería participar en la definición del roadmap para que se atiendan las prioridades de la empresa?

Ten en cuenta que los feature stores se diferencian de otros productos internos en que naturalmente abarcan múltiples disciplinas. Resolver un problema de training-serving skew, por ejemplo, a menudo requiere colaboración entre ingenieros de software, ingenieros de datos, científicos de datos y especialistas de dominio. Como resultado, operar un feature store con éxito implica coordinar la experiencia de varias áreas de la organización.

Lección: Define una convención de nomenclatura para las features

Establece una convención de nomenclatura para las features en el feature store. Las convenciones de nomenclatura tienen muy pocas desventajas (especialmente cuando son lo suficientemente ligeras como para acomodar muchos casos de uso).

Usa una convención de nomenclatura para las features: ayuda a humanos y herramientas de IA a navegar por el código.

Las convenciones de nomenclatura tienen varias ventajas (al igual que la estandarización en general):

  • Menor probabilidad de error humano: Los nombres estandarizados hacen que tareas como las revisiones de código, copiar y pegar y las ediciones masivas sean más seguras y fáciles.
  • Menor carga cognitiva: Los usuarios pueden inferir qué representa una feature sin necesitar documentación.
  • Mayor descubribilidad de features: Los usuarios se exponen naturalmente a otros elementos del mismo grupo al explorar features.
  • Monitoreo y depuración más simples: La mayoría de los problemas de features (p. ej. drift, skew) afectan a grupos enteros de features, lo que facilita identificar los problemas cuando esas relaciones son visibles.
  • Refactorización y organización más fáciles: Los nombres de los grupos de features sirven como namespaces naturales que pueden reutilizarse en carpetas, dashboards y otros recursos de monitoreo.

En realidad no importa qué convención de nomenclatura elijas, siempre que sea versátil y permita cierta personalización. Si las reglas se vuelven demasiado restrictivas, los usuarios tendrán que doblar y hackear la convención de nomenclatura hasta que ya no sirva para nada.

Una plantilla posible es: 

<FEATURE_GROUP>__<TIME_FRAME>__<FEATURE_NAME_AND_OR_OPERATION>

Algunos ejemplos:

  • customer_cc_transactions__24h__count
  • customer_cc_transactions__24h__amount_sum
  • customer_app_behavior__2h__logins
  • savings_account__5d__balance_daily_avg
  • savings_account__current_balance (el bloque TIME_FRAME se omite, ya que es el saldo de la cuenta de ahorros en un momento dado).

Algunas recomendaciones adicionales:

  • Evita usar m para representar meses, ya que puede confundirse con minutos. Si una feature cubre los últimos 2 meses, prefiere 60d.
  • Usa nombres a prueba de futuro que no dependan de la estructura del equipo, sino de conceptos de negocio. Los nombres de los equipos reflejan la estructura organizacional y cambian con mucha frecuencia, mientras que los conceptos de negocio tienden a permanecer estables a lo largo del tiempo.

Lección: Versionar features es difícil

Supongamos que un equipo necesita una pequeña variación de una feature en tiempo real existente en el Feature Store. El equipo de FS no puede simplemente cambiar la implementación de la feature, ya que eso causaría training-serving skew para los modelos entrenados con la versión actual de la feature. (Puede que no quieran reentrenar sus modelos con la versión más nueva).

Por lo tanto, hay que crear una feature completamente nueva o una nueva versión de una feature existente. La mayoría de los feature stores admiten el versionado de features pero, en la práctica, esto significa que los clientes deben proporcionar la versión de la feature que quieren, además de su nombre.

Sin embargo, no es tan fácil saber qué cambios se describen mejor como una nueva versión de una feature existente o como una feature completamente nueva por sí sola. Hay que aplicar criterio para decidir qué acción tomar en cada caso.

Por ejemplo: tienes una feature llamada customer_cc_purchases__5d__count. Intuitivamente, es el número de compras con tarjeta de crédito realizadas por un cliente dado en los últimos 5 días. Ahora veamos algunos escenarios de lo que puede suceder en una situación del mundo real, en la Figura 2:

Figura 2: Ejemplos de situaciones donde los equipos pueden necesitar crear una nueva versión de una feature existente, crear una diferente por completo (dependiendo de la semántica del cambio) o, en algunos casos, no hacer nada en absoluto.

El desafío es que el versionado puede volverse rápidamente difícil de gestionar. Es fácil terminar con docenas de versiones de una feature, lo que significa un conjunto de features complejo y desordenado (diferentes equipos tienen diferentes calendarios de reentrenamiento y siempre hay modelos que aún están atados a versiones anteriores de features y no pueden reentrenarse en este momento).

Una posible salida de este “infierno de versionado” es que el equipo del feature store se encargue de migrar los modelos que usan versiones antiguas de features para que usen las nuevas. La situación es similar al trabajo de actualizar aplicaciones para eliminar bibliotecas y dependencias antiguas y sin soporte en favor de versiones más nuevas. 

Los data contracts también pueden usarse para mitigar los problemas de versionado: los productores de features establecen las expectativas y se notifica a los consumidores cuando ocurren cambios de esquema y semánticos.

Lección: Usa una arquitectura de streaming cuando puedas y llamadas directas cuando debas

Como se discutió en la Parte 1, hay dos formas principales de recuperar features para la inferencia en tiempo real. La primera se basa en llamadas directas a los sistemas que poseen los datos de origen, mientras que la segunda se basa en una plataforma de streaming intermediaria que recibe y procesa eventos continuamente.

Estos enfoques pueden resumirse como:

Features de “llamada directa”

Las features se recuperan mediante llamadas HTTP a los microservicios que poseen las bases de datos transaccionales “fuente de verdad”. Dependiendo del caso de uso, esto puede incluir múltiples llamadas y joins.

Features basadas en streaming

En su lugar, las features se recuperan de un store intermediario: normalmente una base de datos de corto plazo que escucha eventos de un bus de eventos como Kafka.

Como regla general, recomendamos favorecer las features basadas en streaming siempre que sea posible. Hay varias razones para esto: 

  • Mejor escalabilidad: Las features de streaming escalan mejor, porque la ingesta de datos está desacoplada del consumo de datos. Un aumento en la tasa de consumo de eventos no requiere que los productores también escalen.
  • Mejor aislamiento de fallos y menor radio de impacto en caso de caídas: Las arquitecturas asíncronas proporcionan un “aislamiento de entornos” natural que reduce los fallos en cascada. Si el productor o el consumidor se cae, no causa un fallo en el otro extremo.
  • Menor carga en los servicios transaccionales: En una arquitectura de streaming, el feature store no consulta los servicios “fuente” para obtener información. Estos servicios normalmente tienen otras responsabilidades además de proporcionar datos para cargas de trabajo de ML, por lo que no se quiere sobrecargarlos provocando su caída, lo que podría causar interrupciones de negocio en flujos no relacionados.

Es cierto que usar features de streaming requiere una “plataforma” de streaming, que es la infraestructura de más bajo nivel que permite a los servicios de origen transmitir eventos a un bus de eventos asíncrono (normalmente Apache Kafka). Esta es una plataforma compleja y costosa en sí misma, y es un prerrequisito para las features de streaming.

Lección: La recuperación de features por llamada directa y por streaming tiene diferentes modos de fallo

La recuperación de features fallará de vez en cuando, ya sea usando estrategias de “llamada directa” o basadas en streaming. Algunos modos de fallo son “explícitos” (es decir, excepciones e interrupciones de flujo), mientras que otros son “silenciosos”. Esto ocurre porque simplemente cambian la distribución de la feature, pero no disparan excepciones explícitas. (Los fallos silenciosos son muy peligrosos porque corres el riesgo de tomar malas decisiones durante días o semanas antes de que alguien detecte que hay un problema.)

Cada estrategia falla de maneras diferentes, y la naturaleza asíncrona de la estrategia de streaming introduce algunos modos de fallo distintos a los que uno podría no estar acostumbrado. Debes entender cómo falla cada una y cuáles son las implicaciones para tu negocio. 

  • Las features de “llamada directa” fallan explícitamente si el microservicio propietario no está disponible por cualquier motivo: Esto incluye timeouts, caídas del servicio e incluso la sobrecarga del servicio causada por la propia obtención de la feature.
  • Las features de “llamada directa” fallan silenciosamente si se cambia alguna lógica en el servicio de origen: Muy a menudo, los ingenieros que poseen los servicios no saben que algunos endpoints se usan para “alimentar” modelos en tiempo real. A veces, hacen cambios para soportar algún caso de negocio y, sin darse cuenta, cambian la distribución de los datos solicitados, lo que causa un problema de training-serving skew.
  • Las features de streaming fallan silenciosamente si los retrasos se vuelven demasiado grandes: Aunque cierto nivel de retraso es esperable en las features de streaming, a veces este retraso alcanza niveles inaceptables debido a una serie de factores estructurales y temporales. Esto significa que el modelo en tiempo real consumirá información obsoleta, lo que lleva a training-serving skew y a una degradación del rendimiento.
  • Las features de streaming fallan silenciosamente si los eventos llegan fuera de orden: Dependiendo del bus de eventos usado para procesar las features ingeridas, algunos eventos pueden llegar fuera de orden, lo que causará training-serving skew y degradación del rendimiento en los modelos.
  • Las features de streaming fallan silenciosamente si no hay una paridad estricta entre la ingesta por batch y por streaming: Muy a menudo, los ingenieros hacen cambios en la lógica de ingesta por batch pero olvidan replicar los cambios en la lógica de ingesta por streaming. En estos casos, los datos de streaming se “desincronizarán” con los datos de batch, lo que causará training-serving skew. Debería haber pruebas de integración para garantizar que todo lo que se ingiere en batch también se ingiere en la capa de streaming.

Lección: El monitoreo del training-serving skew sigue siendo necesario

El training-serving skew se refiere a diferencias no deseadas entre cómo se generan las features durante el tiempo de entrenamiento y cómo se recuperan en el tiempo de inferencia o serving

En la parte 1, argumentamos que los feature stores ayudan a mitigar este problema, porque ambos “caminos” de datos (batch y tiempo real) se definen en un único lugar. Esto reduce la posibilidad de que tales desviaciones pasen desapercibidas.

Sin embargo, los feature stores no eliminan el problema. Todavía es necesario monitorear el training-serving skew, ya que todavía hay muchas formas en que los datos de batch y de tiempo real pueden desincronizarse incluso cuando ambos caminos se definen dentro de la plataforma del feature store. Dos ejemplos: (1) Los servicios upstream pueden cambiar la semántica de un campo en el camino de tiempo real sin actualizar el equivalente en batch. (2) Puede haber algunos retrasos sistemáticos en el bus de eventos, lo que provoca que las features de streaming en tiempo real siempre lleguen tarde en comparación con el instante en que deberían haber estado disponibles.

Pero, ¿cómo es realmente el monitoreo del training-serving skew en la práctica?

Se puede detectar el training-serving skew generando programáticamente la lógica de extracción de features del tiempo de entrenamiento (sin el target) para aquellos ejemplos que fueron puntuados en tiempo real en el pasado reciente, y luego comparándolos con los valores reales usados en el tiempo de inferencia (obtenidos de los logs de producción). Se puede ver una representación visual en la Figura 3 a continuación:

Figura 3: Una posible estrategia para monitorear el training-serving skew es extraer features usando la lógica de batch para instancias puntuadas en tiempo real y luego comparar los valores obtenidos en cada “camino” y ver si coinciden. Esto puede ejecutarse de forma ad-hoc o como un trabajo diario recurrente.

Aquí aplica una advertencia importante: Esta estrategia de monitoreo asume que los equipos son capaces de generar programáticamente conjuntos de datos de entrenamiento para los modelos, que se usarán como referencia de comparación frente a los logs en tiempo real. Esto no solo habilita el monitoreo del training-serving skew, sino que es crucial para garantizar la reproducibilidad.

Lección: Los proyectos piloto son una de las formas más efectivas de impulsar la adopción

Al introducir un feature store en una organización, puede que no todos los equipos quieran usarlo de inmediato, ya que podrían perder algo de autonomía y control sobre las features, perder poder relativo en la organización, tener que despriorizar otros proyectos, etc. Los factores habituales que contribuyen a resistir los esfuerzos de plataformización.

El mejor argumento para adoptar un feature store es una visión clara de los beneficios. Pero si todavía hay resistencia de los equipos cliente, los proyectos piloto a cargo del equipo de FS son un buen camino a seguir.

La adopción del feature store debe fomentarse con zanahorias, no con palos (p. ej. mandatos de arriba hacia abajo). Al final del día, los beneficios de usar un feature store (mayor impacto, más robustez, menor TTM, etc.) deben ser claros para fomentar la adopción. Figura 4 resume varias razones comunes por las que los equipos dudan en adoptar feature stores, junto con posibles estrategias de mitigación.

Figura 4: Hay muchas razones por las que los equipos se resisten a adoptar feature stores. La mayoría de ellas pueden mitigarse si el equipo del Feature Store comparte parte de la carga de integración (es decir, proyectos piloto) y si hay documentación clara y buenos canales de soporte.

En la Figura 4, vemos que una gran estrategia de mitigación general es que el equipo de FS cree las primeras integraciones para los equipos cliente, como proyectos piloto

Estos proyectos reducen enormemente el costo de adopción (desde el punto de vista de los equipos cliente) y es una estrategia win-win”: el equipo cliente obtiene features construidas “gratis” y el equipo de FS tiene un proyecto piloto para someter la plataforma a pruebas de estrés y servir como ejemplo del que otros equipos pueden aprender.

Conclusión

Como afirmamos en la parte 1, los feature stores requieren una inversión significativa en ingeniería de plataforma, madurez operacional y alineación organizacional. Pero para las empresas que ejecutan sistemas de ML en tiempo real a escala, esa inversión desbloquea beneficios sustanciales a largo plazo.

Nuestra experiencia en Nubank ha demostrado que la adopción exitosa de un feature store no se trata solo de decisiones tecnológicas. También depende del pensamiento de producto, de prácticas operacionales sólidas y de una comprensión profunda de cómo evolucionan los sistemas de ML del mundo real a lo largo del tiempo.

En el camino, algunas lecciones destacan de forma consistente:

  • Es posible combinar varios tipos de componentes (open-source, de proveedores, hechos en casa) para adaptar tu configuración a tus necesidades específicas. 
  • Los feature stores son productos y deben gestionarse como tales.
  • Definir y hacer cumplir una convención de nomenclatura reduce la carga cognitiva y facilita el versionado.
  • Las features basadas en streaming escalan mejor. Los feature stores también deben admitir la llamada directa para casos extremos.
  • Los flujos de trabajo síncronos y asíncronos son muy diferentes y fallan de maneras diferentes. Entiende cómo falla cada uno y cómo afectan a tu negocio.
  • Usar feature stores mitiga, pero nunca elimina por completo el training-serving skew. El monitoreo sigue siendo necesario.
  • Los proyectos piloto son una excelente táctica integral para ayudar a demostrar el beneficio de las iniciativas de tipo plataforma. Los feature stores no son la excepción.

Esta es la Parte 2 de nuestra serie sobre Feature Stores para ML en Tiempo Real en Nubank. En la Parte 3, reuniremos estos conceptos y exploraremos arquitecturas del mundo real que usamos en la práctica.

Descubre las oportunidades