MLOps

Feast : mettre en place un Feature Store open source

Un modèle de Machine Learning n'est jamais meilleur que les features qui l'alimentent, et ces features sont souvent recalculées de manière différente par chaque équipe, chaque notebook et chaque service de prédiction. Résultat : des écarts entre l'entraînement et la production, des calculs dupliqués et des fuites de données difficiles à détecter. Le Feature Store répond à ce problème en centralisant la définition, le stockage et la diffusion des features.

Équipe Blent

Publié le · 10 min de lecture

Dans cet article

Un modèle de Machine Learning n'est jamais meilleur que les features qui l'alimentent, et ces features sont souvent recalculées de manière différente par chaque équipe, chaque notebook et chaque service de prédiction. Résultat : des écarts entre l'entraînement et la production, des calculs dupliqués et des fuites de données difficiles à détecter. Le Feature Store répond à ce problème en centralisant la définition, le stockage et la diffusion des features.

Comment s'assurer que la variable « nombre de commandes sur 30 jours » est calculée de la même façon dans un notebook de Data Scientist et dans une API qui répond en quelques millisecondes ? Comment éviter que dix équipes réécrivent dix fois la même transformation ? Comment reconstituer l'état exact des données à la date d'un événement passé ? Ces questions deviennent centrales dès que l'on industrialise des modèles, et c'est précisément le terrain du Feature Store.

Feast (Feature Store) est aujourd'hui la référence open source du domaine. Il ne cherche pas à remplacer votre entrepôt de données ni votre moteur de calcul : il s'appuie sur l'infrastructure existante pour servir les mêmes features en batch et en temps réel. Dans cet article, nous allons expliquer à quoi sert un Feature Store, détailler l'architecture de Feast avec un exemple de code, puis le situer face aux offres managées de Databricks, SageMaker et Vertex AI.

À quoi sert un Feature Store ?

Le Feature Engineering consiste à transformer des données brutes en variables exploitables par un modèle. Sans outillage dédié, ce travail est dispersé : une requête SQL pour l'entraînement, un script Python pour l'inférence, parfois un calcul réimplémenté dans un autre langage côté application. Un Feature Store est la couche qui rassemble ces features dans un catalogue versionné, avec un stockage adapté à chaque usage.

Cohérence entre entraînement et inférence

Le training-serving skew désigne l'écart entre les features vues à l'entraînement et celles reçues en production. Il provient le plus souvent de deux implémentations distinctes de la même logique : une moyenne glissante calculée en SQL d'un côté, approchée en Python de l'autre, avec des arrondis, des fuseaux horaires ou des valeurs manquantes traités différemment. Le modèle se dégrade alors sans qu'aucune erreur technique ne soit levée.

Avec un Feature Store, la définition d'une feature est écrite une seule fois. Les mêmes objets servent à produire le jeu d'entraînement (lecture historique) et à répondre aux requêtes en ligne (lecture à faible latence). La cohérence n'est plus une affaire de discipline entre équipes, elle est garantie par l'architecture.

Réutilisation et gouvernance des features

Une feature comme « montant moyen des achats par client » est utile à la fois pour un modèle de détection de fraude, de recommandation et d'attrition. Dans un Feature Store, elle est découvrable, documentée et réutilisable par toutes les équipes. Cela apporte plusieurs bénéfices :

  • Moins de duplication : une feature est calculée et stockée une fois, puis partagée.
  • Traçabilité : chaque feature possède un propriétaire, une source, des tags et une description.
  • Mise en production accélérée : un nouveau modèle réutilise un catalogue existant au lieu de repartir de zéro.
  • Contrôle d'accès : on sait quels modèles consomment quelles données, ce qui facilite les audits.

Point-in-time correctness

C'est la propriété la plus subtile, et sans doute la plus précieuse. Pour entraîner un modèle, on associe à chaque exemple (par exemple une commande passée le 12 avril à 10 h 59) les valeurs des features telles qu'elles étaient à cet instant précis, et non leurs valeurs actuelles. Utiliser des valeurs plus récentes revient à donner au modèle une information qu'il n'aurait pas eue en production : c'est une fuite de données (data leakage), qui produit des métriques flatteuses en test et des performances décevantes en réel.

Le Feature Store réalise automatiquement cette jointure temporelle (point-in-time join) : pour chaque ligne, il retient la dernière valeur de la feature connue avant l'horodatage de l'événement, dans la limite d'une durée de validité. Écrire cette logique à la main en SQL est fastidieux et source d'erreurs, d'où l'intérêt de la déléguer à l'outil.

À lire : découvrez notre formation MLOps

L'architecture de Feast

Feast est une bibliothèque Python accompagnée d'une CLI. Son architecture repose sur quatre briques principales qui s'articulent autour de vos définitions de features.

Architecture de Feast avec ses sources de données, son offline store, son online store et son registre

Registre, offline store et online store

Le registre (registry) est le catalogue central : il contient la définition des entités, des sources de données, des vues de features et des services de features. Par défaut, il s'agit d'un simple fichier, mais il peut être remplacé par un registre adossé à une base SQL, plus adapté à un usage en équipe.

L'offline store est l'espace où vivent les données historiques. Il sert à générer les jeux d'entraînement et à calculer les jointures point-in-time. Feast ne stocke pas ces données lui-même : il s'appuie sur des moteurs existants, comme des fichiers Parquet en local, un Data Warehouse (BigQuery, Snowflake, Redshift) ou Spark.

L'online store contient uniquement la dernière valeur connue de chaque feature, indexée par entité, pour une lecture en quelques millisecondes. On y retrouve des bases clé-valeur comme Redis ou DynamoDB, mais aussi SQLite pour le développement local.

ComposantRôleContenuExemples de technologies
RegistreCatalogue des définitionsEntités, vues, servicesFichier, base SQL
Offline storeHistorique pour l'entraînementToutes les valeurs horodatéesParquet, BigQuery, Snowflake, Spark
Online storeService à faible latenceDernière valeur par entitéRedis, DynamoDB, SQLite
MatérialisationSynchronisation offline vers onlineValeurs récentesCommandes feast materialize

La liste exacte des backends pris en charge évolue d'une version à l'autre : la documentation officielle reste la source à consulter avant de choisir une combinaison.

Matérialisation

La matérialisation est l'opération qui copie les valeurs les plus récentes de l'offline store vers l'online store. On l'exécute à intervalle régulier, typiquement depuis un orchestrateur comme Apache Airflow, pour que les features servies en ligne restent fraîches. Pour des données en flux, par exemple issues de Kafka, Feast propose également un mécanisme de poussée (push) qui écrit directement dans l'online store.

Définir des features avec Feast

Le point de départ est un dépôt de features, composé d'un fichier feature_store.yaml qui configure le projet, et d'un fichier Python de définitions. Voici une configuration minimale pour un usage local :

yaml
project: my_project
# Registre sous forme de fichier (remplaçable par un registre SQL)
registry: data/registry.db
provider: local
online_store:
  type: sqlite
  path: data/online_store.db
entity_key_serialization_version: 3

Les définitions décrivent l'entité (la clé métier), la source de données et la vue de features :

python
from datetime import timedelta

from feast import Entity, FeatureService, FeatureView, Field, FileSource
from feast.types import Float32, Int64

# Entité : la clé de jointure métier
driver = Entity(name="driver", join_keys=["driver_id"])

# Source : un fichier Parquet horodaté
driver_stats_source = FileSource(
    name="driver_hourly_stats_source",
    path="data/driver_stats.parquet",
    timestamp_field="event_timestamp",
    created_timestamp_column="created",
)

# Vue de features : schéma, durée de validité (ttl) et source
driver_stats_fv = FeatureView(
    name="driver_hourly_stats",
    entities=[driver],
    ttl=timedelta(days=1),
    schema=[
        Field(name="conv_rate", dtype=Float32),
        Field(name="acc_rate", dtype=Float32),
        Field(name="avg_daily_trips", dtype=Int64),
    ],
    online=True,
    source=driver_stats_source,
    tags={"team": "driver_performance"},
)

# Service de features : l'ensemble consommé par un modèle donné
driver_activity_v1 = FeatureService(
    name="driver_activity_v1",
    features=[driver_stats_fv],
)

Le paramètre ttl fixe la durée pendant laquelle une valeur reste utilisable lors de la jointure point-in-time. Le FeatureService regroupe les features d'un modèle : c'est lui que l'on versionne lorsque le modèle évolue. On enregistre ensuite ces définitions dans le registre, puis on matérialise les valeurs récentes vers l'online store :

bash
feast apply

CURRENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S")
feast materialize-incremental $CURRENT_TIME

À découvrir : notre formation MLOps

Récupérer les features : entraînement et production

Une fois les features définies, deux méthodes couvrent tous les usages, avec les mêmes noms de features dans les deux cas.

Lecture historique pour l'entraînement

Pour constituer un jeu d'entraînement, on fournit un DataFrame d'entités avec leurs horodatages et leur cible. Feast réalise la jointure point-in-time et renvoie les features correspondantes :

python
from datetime import datetime

import pandas as pd
from feast import FeatureStore

# Chaque ligne porte la clé d'entité, l'instant de l'événement et la cible
entity_df = pd.DataFrame.from_dict(
    {
        "driver_id": [1001, 1002, 1003],
        "event_timestamp": [
            datetime(2021, 4, 12, 10, 59, 42),
            datetime(2021, 4, 12, 8, 12, 10),
            datetime(2021, 4, 12, 16, 40, 26),
        ],
        "label_driver_reported_satisfaction": [1, 5, 3],
    }
)

store = FeatureStore(repo_path=".")

training_df = store.get_historical_features(
    entity_df=entity_df,
    features=[
        "driver_hourly_stats:conv_rate",
        "driver_hourly_stats:acc_rate",
        "driver_hourly_stats:avg_daily_trips",
    ],
).to_df()

Le résultat est un DataFrame prêt à être utilisé pour entraîner un modèle, dont les versions peuvent être suivies avec un outil comme MLflow.

Lecture en ligne pour l'inférence

En production, l'API de prédiction interroge l'online store avec uniquement la clé de l'entité. La latence est faible, car seule la dernière valeur est lue :

python
from feast import FeatureStore

store = FeatureStore(repo_path=".")

feature_vector = store.get_online_features(
    features=[
        "driver_hourly_stats:conv_rate",
        "driver_hourly_stats:acc_rate",
        "driver_hourly_stats:avg_daily_trips",
    ],
    entity_rows=[{"driver_id": 1004}, {"driver_id": 1005}],
).to_dict()

Les noms de features étant identiques dans les deux appels, le code d'entraînement et le code d'inférence consomment strictement la même définition. C'est ce qui supprime le training-serving skew à la source.

Feast face aux offres managées

Feast n'est pas la seule option. Les grandes plateformes proposent leur propre Feature Store, intégré à leur écosystème.

SolutionTypePoints fortsLimites
FeastOpen sourceNeutre vis-à-vis du cloud, backends interchangeablesÀ déployer et à exploiter soi-même
DatabricksManagéIntégré au catalogue Unity Catalog et aux tables DeltaLié à la plateforme Databricks
SageMaker Feature StoreManagéIntégré à l'écosystème AWS, stockage online et offlineLié à AWS
Vertex AI Feature StoreManagéS'appuie sur BigQuery pour les donnéesLié à Google Cloud

Les offres managées réduisent la charge d'exploitation et s'intègrent naturellement aux outils de la plateforme (catalogue de données, entraînement, déploiement). Elles ont en contrepartie un coût d'enfermement : changer de cloud implique de redéfinir ses features. Feast, de son côté, découple la définition des features du fournisseur d'infrastructure et permet de rester portable, mais demande de piloter soi-même le registre, les jobs de matérialisation et la supervision.

Le choix dépend donc du contexte. Une organisation déjà standardisée sur Databricks, AWS ou Google Cloud a souvent intérêt à adopter l'offre native. Une équipe multi-cloud, soumise à des contraintes de souveraineté ou souhaitant garder la maîtrise de sa stack se tournera plus volontiers vers Feast. Dans tous les cas, un Feature Store n'est pas indispensable pour un premier modèle : il devient rentable dès que plusieurs modèles partagent des features ou que l'inférence en ligne exige une parfaite cohérence avec l'entraînement.

Conclusion

Un Feature Store s'attaque à trois problèmes classiques de l'industrialisation du Machine Learning : l'écart entre l'entraînement et la production, la duplication des calculs entre équipes, et les fuites de données liées au temps. En définissant chaque feature une seule fois, puis en la servant en batch comme en temps réel, il apporte la rigueur qui manque souvent aux pipelines construits au fil de l'eau.

Feast propose une approche simple et ouverte : un registre pour le catalogue, un offline store pour l'historique, un online store pour la faible latence et la matérialisation pour les synchroniser. Quelques dizaines de lignes de Python suffisent pour obtenir une première chaîne cohérente, que l'on peut ensuite faire évoluer vers des backends plus robustes. Face aux offres de Databricks, SageMaker ou Vertex AI, c'est le compromis entre portabilité et charge d'exploitation qui guide la décision.

Maîtriser la gestion des features, l'orchestration et le déploiement des modèles est devenu une compétence différenciante pour les Machine Learning Engineers et les Data Engineers. Le Feature Store est l'une des briques qui font passer un modèle du notebook à un service fiable en production.

Pour aller plus loin

D'autres articles MLOps

Approfondir le sujet

Formation MLOps

Apprenez à automatiser l'entraînement, le déploiement et le suivi des modèles.

  • CI/CD
  • Model serving
  • Monitoring
  • Feature store