Mise en production des projets de data science

ENSAE 3A - 2023/2024

Romain Avouac
Lino Galiana

Introduction

Ressources associées

Slides

Site web

Contexte

  • Qui sommes-nous ?
    • des data scientists de l’Insee
    • frustrés par l’approche souvent purement technique de la data science
    • convaincus que les bonnes pratiques de développement valent à être enseignées
  • ,

Qu’est ce qu’un data scientist ?

  • Tendance à la spécialisation : data analyst, data engineer, ML Engineer

  • Rôle d’interface entre métier et équipes techniques

    • Compétences mixtes : savoir métier, modélisation, IT

La notion de mise en production

  • Mettre en production : faire vivre une application dans l’espace de ses utilisateurs
    • Notion simple mais mise en oeuvre compliquée !
  • Dépasser le stade de l’expérimentation
    • Comprendre les besoins des utilisateurs
    • Bonnes pratiques de développement
    • Techniques informatiques d’industrialisation

La notion de bonnes pratiques

  • Origine : communauté des développeurs logiciels

  • Constats :

    • le “code est plus souvent lu qu’écrit” (Guido Van Rossum)
    • la maintenance d’un code est très coûteuse
  • Conséquence : un ensemble de règles informelles, conventionnellement acceptées comme produisant des logiciels fiables, évolutifs et maintenables

Pourquoi s’intéresser aux bonnes pratiques ?


L’activité du datascientist tend à se rapprocher de celle du développeur :

  • projets intenses en code

  • projets collaboratifs et de grande envergure

  • complexification des données et des infrastructures

  • déploiement d’applications pour valoriser les modèles

Contenu du cours

  • Pré-requis
    • Introduction au terminal Linux
    • Contrôle de version avec Git
  • Bonnes pratiques de développement
    • Travail collaboratif avec Git
    • Qualité du code
    • Structure des projets
    • Traitement des données volumineuses
    • Favoriser la portabilité d’une application
  • Mise en production
    • Déploiement
    • MLOps

Site web du cours

Modalités pédagogiques

  • Apprentissage par la pratique
  • Langage : Python
    • Langage dominant dans le monde de la donnée
    • Les principes présentés sont agnostiques au langage
  • Environnement d’exécution : SSP Cloud
    • Environnement de développement normalisé
    • Véritable environnement de production
    • Acquisition des bonnes pratiques

Evaluation

  • Objectif : mise en pratique réaliste des notions étudiées
    • Problématique métier
    • Données réelles
  • Evaluation en deux parties :
    • En groupe : projet à construire selon 3 “parcours”
    • Individuel : revue de code d’un autre projet

Partie 1️⃣ : bonnes pratiques de développement

Plan de la partie

1️⃣ Travail collaboratif avec Git

2️⃣ Qualité du code

3️⃣ Structure des projets

4️⃣ Traitement des données volumineuses

5️⃣ Favoriser la portabilité d’une application

1️⃣ Le travail collaboratif avec Git

Pourquoi utiliser Git ?

Source : ThinkR

Concepts essentiels

Source : fabacademy.org

Bonnes pratiques

Que versionne-t-on ?

  • Essentiellement du code source
  • Pas d’outputs (fichiers .html, .pdf, modèles…)
  • Pas de données, d’informations locales ou sensibles

Note

Pour définir des règles qui évitent de committer tel ou tel fichier, on utilise un fichier nommé .gitignore.

Si on mélange du code et des éléments annexes (output, données…) dans un même dossier, il faut consacrer du temps à ce fichier.

Le site gitignore.io peut vous fournir des modèles.

N’hésitez pas à y ajouter des règles conservatrices (par exemple *.csv), comme cela est expliqué dans la documentation utilitR.

Bonnes pratiques

Format des commits

  • Fréquence
    • Aussi souvent que possible
    • Le lot de modifications doit “faire sens”
  • Messages
    • Courts et informatifs (comme un titre de mail)
    • Décrire le pourquoi plutôt que le comment dans le texte

Outils pour le travail collaboratif

  • L’éco-système Git facilite le travail collaboratif
    • Git : modèle des branches
    • GitHub / GitLab : Issues, Pull Requests, Forks

Le modèle des branches

 

Source : lutece.paris.fr

Les outils de contribution

  • Issue : soumettre un problème ou une suggestion aux développeurs d’un projet

  • Pull Request : proposer aux développeurs d’un projet d’intégrer des modifications

  • Fork : faire la copie d’un projet existant dans son espace personnel

    • Indispensable pour faire une pull request à un dépôt sur lequel on n’a pas les droits

Une organisation courante : le GitHub flow

Description plus détaillée : ici

2️⃣ Qualité du code

Enjeux

  • D’une vision utilitariste du code à une vision du code comme outil de communication

  • Favoriser la lisibilité et la maintenabilité

  • Faciliter la réutilisation

Principes généraux

  • Adopter les standards communautaires

  • Utiliser des fonctions

  • (Auto-)documenter son code

1️⃣ Standards communautaires

“Good coding style is like correct punctuation: you can manage without it, butitsuremakesthingseasiertoread”

Tidyverse Style Guide (R)

  • Python : PEP8, PEP 257
    • Des règles opinionated, mais conventionnelles
  • La cohérence intra-projet doit toujours primer

1️⃣ Standards communautaires - Outils

  • Linters : diagnostic de qualité du code
  • Formatters : application automatique des standards

Astuce

  • Exemples d’erreurs repérées par un linter :
    • lignes de code trop longues ou mal indentées, parenthèses non équilibrées, noms de fonctions mal construits…
  • Exemples d’erreurs non repérées par un linter :
    • fonctions mal utilisées, arguments mal spécifiés, structure du code incohérente, code insuffisamment documenté…

2️⃣ Utiliser des fonctions

Règle d’or

Il faut utiliser une fonction dès qu’on utilise une même portion de code plus de deux fois (don’t repeat yourself (DRY))

  • Limite les risques d’erreurs liés aux copier/coller
  • Rend le code plus lisible et plus compact
  • Un seul endroit du code à modifier lorsqu’on souhaite modifier le traitement
  • Facilite la réutilisation et la documentation du code !

Règles pour écrire des fonctions pertinentes

  • Une tâche = une fonction
  • Une tâche complexe = un enchaînement de fonctions réalisant chacune une tâche simple
  • Limiter l’utilisation de variables globales.

3️⃣ Documenter son code

  • Documenter le pourquoi plutôt que le comment

  • Privilégier l’auto-documentation via des nommages pertinents

Comment bien documenter un script ?

  • Minimum 🚦 : décrire ce que le code fait au début du script
  • Bien 👍 : commenter les parties “délicates” du code
  • Idéal 💪 : documenter ses fonctions avec des docstrings

3️⃣ Structure des projets

Enjeux

  • Favoriser la lisibilité et la maintenabilité

  • Enjeux spécifiques à la data science

    • Expérimentation
    • Non-linéarité
    • Reproductibilité

Principes généraux

  • Favoriser une structure modulaire selon l’état du projet

    • Exploration : travail à partir de notebooks
    • Industrialisation : adopter une structure type package
  • Adopter les standards communautaires

  • (Auto-)documenter son projet

1️⃣ Phase d’exploration : notebooks

  • Avantages
    • Interactivité : idéal pour l’expérimentation
    • Communication : diffusion de résultats sous forme exécutable
  • Inconvénients
    • Reproductibilité généralement limitée
    • Pas adaptés pour l’automatisation
    • Mal gérés par le contrôle de version

2️⃣ Industrialisation : structure modulaire

  • Premier niveau : structuration du code

  • Adopter une structure type package

    • Des fonctions rangées dans des modules
    • Un script principal (main) orchestre les traitements
    • Utilisation de chemins relatifs uniquement

2️⃣ Industrialisation : structure modulaire

  • Deuxième niveau : structuration du projet

3️⃣ Adopter les standards communautaires

4️⃣ Documenter son projet

  • Favoriser l’auto-documentation via des nommages pertinents

L’auto-documentation : illustration

├── report.ipynb
├── correlation.png
├── data.csv
├── data2.csv
├── fig1.png
├── figure 2 (copy).png
├── report.pdf
├── partial data.csv
├── script.py
└── script_final.py
  • Difficile de rentrer dans le projet…
    • Tout au même niveau
    • Titres non informatifs

L’auto-documentation : illustration

├── data
│   ├── raw
│   │   ├── data.csv
│   │   └── data2.csv
│   └── interim
│       └── partial data.csv
├── notebooks
│   └── report.ipynb
├── src
|   ├── script.py
│   └── script_final.py
└── reports
    ├── report.pdf
    └── figures
        ├── fig1.png
        ├── figure 2 (copy).png
        ├── figure10.png
        └── correlation.png
  • Une structure déjà plus lisible !
    • Les titres restent non informatifs

L’auto-documentation : illustration

├── data
│   ├── raw
│   │   ├── dpe_logement_202103.csv
│   │   └── dpe_logement_202003.csv
│   └── interim
│       └── dpe_logement_merged_preprocessed.csv
├── notebooks
│   └── report.ipynb
├── src
|   ├── main.R
|   ├── preprocessing.R
│   └── generate_plots.R
└── reports
    ├── report.pdf
    └── figures
        ├── histogram_energy_diagnostic.png
        ├── barplot_consumption_pcs.png
        ├── correlation_matrix.png
        └── correlation.png
  • Une structure auto-documentée
    • On comprend le projet sans même lire le code

4️⃣ Documenter son projet

  • Favoriser l’auto-documentation via des nommages pertinents

  • Inclure un fichier README.md à la racine du projet

    • Carte d’identité et vitrine du projet
    • Présente le contexte et le fonctionnement du projet
  • Si open-source : inclure une licence

Application

Bonnes pratiques de développement

  • Consignes sur le site du cours
    • Partie 0️⃣ : initialisation de l’environnement et du projet
    • Partie 1️⃣ : qualité du code
    • Partie 2️⃣ : adoption d’une structure modulaire

4️⃣ Traitement des données volumineuses

“The obligatory intro slide”

Source : motherduck.com

Enjeux

  • Tendance à la massification des données
    • Relatif aux capacités de stockage et de traitement

Source : AI with Python

Choisir des technologies adaptées

1️⃣ Infrastructures de données

2️⃣ Formats de données

3️⃣ Frameworks de traitement de données

1️⃣ Infrastructures : historique

1️⃣ Limite des data warehouses

  • Peu adaptées aux données big data
    • Passage à l’échelle coûteux
    • Limitées aux données structurées
  • 2010’s : modèle du data lake

1️⃣ Le data lake

  • Un stockage peu coûteux fait pour des données
    • Volumineuses
    • Brutes
    • Issues de sources variées

Source : qlik.com

1️⃣ Le stockage objet

  • Standard des data lakes dans le cloud
    • Implémentation dominante : Amazon S3
    • Implémentation open-source : MinIO

Source : min.io

2️⃣ Formats de données

  • Le choix d’un format de données répond à un arbitrage entre plusieurs critères :
    • Public cible
    • Finalité (traitement, analyse, diffusion)
    • Volumétrie
    • Interopérabilité

2️⃣ Limites des formats usuels

  • Les formats usuels (CSV, JSON, XML) sont utiles pour :
    • Le traitement de faibles volumes de données
    • La diffusion de données
  • Limités pour le traitement de données volumineuses
    • Non-compressés : espace disque élevé
    • Orientés ligne : peu adaptés aux traitements analytiques

2️⃣ Orientation ligne vs. orientation colonne

2️⃣ Parquet : propriétés

  • Orienté colonne
    • Adapté aux traitements analytiques
    • Conçu pour être écrit une fois mais lu fréquemment
  • Optimisé
    • Compression (jusqu’à 87 % moins d’espace qu’un CSV)
    • Lecture du fichier (jusqu’à 34x plus rapide qu’un CSV)
  • Interopérable
    • Gestion native des méta-données

2️⃣ Parquet : partitionnement

  • Division en blocs des données selon un critère
    • Optimise la lecture pour certaines queries

Source : datio.com

3️⃣ Traitement in-memory

  • Parquet ne résout pas tout
    • L’espace disque est optimisé
    • Les données décompressées doivent passer en RAM
  • Le framework adapté dépend de la volumétrie

3️⃣ Données volumineuses

  • Calcul larger than memory optimisé
    • Arrow : orientation fichier (Parquet)
    • DuckDB : orientation base de données (SQL)
  • Autre avantage : interopérabilité

Source : Arrow

3️⃣ Données massives

  • Calcul distribué sur un cluster de machines
  • Base : paradigme MapReduce

Source : nd.edu

En résumé : pour traiter la volumétrie

  • Utiliser un format de données adapté (Parquet)

  • Utiliser des outils informatiques adaptés

    • Suffisant la plupart du temps : calcul larger than memory optimisé (Arrow / DuckDB)
    • Si volumétrie massive : calcul distribué (Spark)

“Big Data is dead” ?

  • Jordan Tigani : Big Data is dead
    • “The big data frontier keeps receding”
    • “Most people don’t have that much data”
    • “Most data is rarely queried”
  • Plaidoyer pour une parcimonie
    • … qui facilite la mise en production !

5️⃣ Portabilité

“It works… on my machine”

  • On a construit un projet lisible, structuré et versionné

  • Peut-on partager notre projet ?

    • En théorie, oui !
    • En pratique, c’est toujours plus compliqué…

Le critère de la portabilité

  • Un code ne vit jamais dans une bulle isolée, il contient en général de nombreuses adhérences
    • Des dépendances
    • Des librairies système
  • Un code est portable s’il peut être exécuté dans un environnement différent que celui du développement

Limites du mode de travail usuel

  • Workflow classique
    • Installer une distribution de Python sur son poste
    • Développer un projet en installant les packages nécessaires
    • Passer au projet suivant et ainsi de suite
  • Quels problèmes peuvent se poser ?

Limites du mode de travail usuel

  • Conflits de version : différents projets peuvent requérir des versions différentes d’un même package

  • Version de Python fixe, celle de l’installation système

  • Reproductibilité limitée : difficile de dire quel projet nécessite quel package

  • Portabilité limitée : difficile de fixer dans un fichier les dépendances spécifiques à un projet

Comment favoriser la portabilité ?

  • Enjeu central pour la mise en production
    • Passer d’un environnement de développement à un environnement de production
  • Besoin de nouveaux outils
    • Les environnements virtuels
    • Les conteneurs

Environnements virtuels : fonctionnement

  • Dossier auto-suffisant qui :
    • contient un intepréteur Python et des packages
    • est isolé des autres environnements existants

Source : dataquest.io

Environnements virtuels : implémentations

  • Implémentation standard : venv

  • Une implémentation populaire en data science : conda

    • Également un package manager (comme pip, mais multi-langages)
  • D’autres implémentations existent : virtualenv, pyenv

venv : utilisation

  • venv fait partie de la librairie standard de Python

  • Utilisation basique (sous Linux)

    • Créer un environnement : python -m venv myenv
    • Activer l’environnement : source myenv/bin/activate
    • Installer des packages : pip install scikit-learn
    • Quitter l’environnement : deactivate

Spécifier les dépendances

  • Développer dans un environnement virtuel favorise :
    • la reproductibilité : fixer les packages utilisés et leurs versions
    • la portabilité : distribuer ces spécifications
  • Convention : fichier requirements.txt à la racine du projet (à commit !)
    • Génération : pip freeze > requirements.txt
    • Installation : pip install -r requirements.txt

Le fichier requirements.txt

beautifulsoup4==4.12.3
expecttest!=0.2.0
networkx>=3.0.0
numpy
pandas
  • Arbitrage à trouver entre :
    • Reproductibilité : spécifier finement les versions
    • Sécurité : laisser les versions évoluer

Environnements virtuels : limites

  • Reproductibilité :
    • Version de Python non-gérée
    • Librairies système non-gérées
  • Peu adaptés aux environnements de production :
    • Reproductibilité limitée -> portabilité limitée
    • Lourdeur de gestion des environnements

Le gold-standard de la portabilité

  • Idée : au lieu de distribuer la recette pour recréer la bonne machine, peut-on distribuer directement la bonne machine ?
    • On ne peut pas distribuer des machines physiques
    • Les machines virtuelles sont coûteuses à redistribuer
  • Les conteneurs offrent le compromis idéal

Conteneurs vs. machines virtuelles

Source : docker.com

Conteneurs : implémentations

  • Plusieurs implémentations des conteneurs
    • Docker est largement prédominant

Docker : installation

  • Docker : outil en ligne de commande (CLI)

Le Dockerfile

# Image Docker de base
FROM python:3.11

# Définition du répertoire de travail
WORKDIR /code

# Copie des fichiers nécessaires sur l'image
COPY requirements.txt /code/requirements.txt

# Installation des dépendances
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt && \
    python -m spacy download en_core_web_sm

COPY app/ code/app

# Commande lancée par l'image au runtime
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"]

Docker : fonctionnement

Source : k21academy.com

Docker en pratique

  • Présentation détaillée sur la page du cours
    • Concepts (caching, buildtime/runtime)
    • Commandes essentielles
    • Application à un exemple concret

Application

Portabilité du projet

  • Consignes sur le site du cours
    • Partie 3️⃣ : construction d’un projet portable et reproductible
      • Construire un environnement virtuel pour le projet
      • Conteneuriser l’application avec Docker

Partie 2️⃣ : mise en production

Le “mur de la production”

  • La majorité des projets “data-drivenne délivrent pas de valeur (1, 2, 3)

  • Comment dépasser le stade de l’expérimentation ?

Mise en production

  • Mettre en production : faire vivre une application dans l’espace de ses utilisateurs
    • Servir : déployer l’application dans un format pertinent auprès de ses utilisateurs potentiels
    • Faire vivre : gérer le cycle de vie et favoriser l’amélioration continue
  • Multiples dimensions : connaissance métier, organisation, infrastructure, outils techniques..

Favoriser la continuité

Source : ibm.com

  • Comment faire ?
    • Application des bonnes pratiques de développement
    • Besoin de nouveaux concepts et outils : DataOps

Le DataOps

Source : syloe.com
  • DataOps : construction de pipelines de données

  • MLOps : déploiement et maintenance de modèles de ML

Plan de la partie

6️⃣ Déploiement

7️⃣ MLOps

6️⃣ Déploiement

Un sujet large

  • Les questions essentielles à se poser :
    • Quel est le format adapté pour valoriser le projet ?
    • Quelle infrastructure de production ?
    • Comment automatiser le processus de déploiement ?
    • Comment suivre l’application en production ?
  • De nombreuses choix possibles
    • Présentation des concepts et outils standards

Formats de valorisation

  • Critères à prendre en compte :
    • Quels sont les utilisateurs potentiels ?
    • Quels sont leurs besoins ?
  • Exemple : mise à disposition d’un LLM

Source : ubuntu.com

Cas d’usage

  • Servir un modèle de ML via une API

Les APIs

Une API (application programming interface ou « interface de programmation d’application ») est une interface logicielle qui permet de « connecter » un logiciel ou un service à un autre logiciel ou service afin d’échanger des données et des fonctionnalités.

CNIL

  • Définition peu informative
    • Python, scikit-learn, Docker, etc. sont des APIs
    • En pratique, on signifie généralement une API REST

Les APIs REST

Architecture cible

  • Construire une API pour servir le modèle
    • Interface entre l’utilisateur et le modèle entraîné

Environnement de production

  • Dépend essentiellement de l’infrastructure à disposition

  • Propriétés recherchées :

    • Adapter les ressources (scaler) selon les besoins
    • Déploiements reproductibles et automatisés
    • Monitoring de l’état de santé des applications
  • Solution : utiliser un orchestrateur de conteneurs

Fonctionnement de Kubernetes

L’approche CI/CD

  • Intégration continue (CI) : chaque commit déclenche un processus “test, build and release
  • Déploiement continu (CD) : les nouvelles releases sont automatiquement déployées

CI : implémentation avec GitHub Actions

  • Principe : commit -> exécution d’une série d’étapes
    • Script exécuté sur une VM : runner
    • Mise à disposition d’un output : artifact
  • Multiples outputs possibles

CI : anatomie d’un fichier de CI

  • Spécification : fichier .yaml qui paramétrise le runner
    • ⚠️ Situé dans le dossier .github/workflows/
.github/workflows/ci.yaml
name: Build Docker image

on: 
  push:
    branches:
      - main
    tags:

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ensae-reproductibilite/api-titanic
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

CD : implémentation avec ArgoCD

CD : anatomie d’un fichier de CD

CI/CD : implémentation sur Kubernetes

Pipeline DataOps complet

  • Intégration des étapes dans un pipeline (DAG)

Source : ubuntu.com
  • En pratique : utilisation d’un orchestrateur

Conclusion

  • On a construit un pipeline reproductible et automatisé

Source : ibm.com
  • Comment tenir compte des spécificités du ML ?
    • Approche MLOps

Application

Mise en production

  • Consignes sur le site du cours
    • Partie 4️⃣ : automatisation de la livraison d’une application avec l’intégration continue
    • Partie 5️⃣ : déploiement d’une application et industrialisation

7️⃣ MLOps

Motivation

  • Intégrer :
    • les principes DataOps
    • les spécificités des projets de ML

Source : ml4devs.com

MLOps : principes

  • Reproductibilité

  • Contrôle de version

  • Automatisation

  • Collaboration

  • Monitoring

MLOps : implémentation

  • De nombreux frameworks implémentent les principes du MLOps
    • Catalogue du SSP Cloud : MLFlow
  • Avantages de MLflow :
    • Open-source
    • Couvre l’entièreté du cycle de vie d’un modèle ML
    • Agnostique au package ML utilisé
    • Intégration avec Kubernetes

MLFlow : vue d’ensemble

Source : dzlab.github.io

MLFlow : Tracking server

  • “Une API et une interface utilisateur pour enregistrer les paramètres, les versions du code, les métriques et les artefacts”

Source : Databricks

MLFlow : Models

  • “Une convention pour ‘packager’ des modèles de machine learning sous plusieurs formes

Source : Dataiku

MLFlow : Model registry

  • “Un entrepôt centralisé de modèles, un ensemble d’API et une interface utilisateur pour gérer collaborativement le cycle de vie complet d’un modèle MLflow”

Source : Databricks

Servir le modèle (sans MLFlow)

Servir le modèle (avec MLFlow)

Suivi du modèle

  • Pourquoi surveiller un modèle en production ?
    • Détecter d’éventuels biais des données d’entraînement
    • Détecter une instabilité du modèle
    • Amélioration continue du modèle
  • ⚠️ Le mot surveillance d’une application/modèle recouvre des réalités différentes

Surveillance selon l’informaticien

  • Surveiller une application est partie intégrante de l’approche DevOps

  • Contrôle technique de l’API :

    • Latence
    • Mémoire
    • Utilisation disque

Surveillance selon le data scientist

  • Surveiller un modèle ML est partie intégrante de l’approche MLOps

  • Contrôle méthodologique du modèle

  • Performance en temps réel du modèle souvent impossible, utilisation de proxys :

    • Data drift : la distribution des données d’entrée change dans le temps
    • Concept drift : la relation modélisée change dans le temps

Comment surveiller un modèle en production ?

  • Intégration de logs dans l’API

  • Récupération et mise en forme des logs

  • Suivi de métriques de ML

  • Mise en place d’un système d’alertes

Résultat : un pipeline reproductible

Source: martinfowler.com

Application

MLOps

  • Consignes sur le site du cours
    • Partie 6️⃣ : application des principes MLOps avec MLFlow

Conclusion

  • La mise en production met en lumière le rôle d’interface
    • De la data science : statistique et informatique
    • Du data scientist : équipes métier et techniques
  • Enjeu : adopter des modes d’organisation plus continus
    • Des bonnes pratiques à appliquer le plus tôt possible
    • Automatiser pour favoriser l’amélioration continue
  • ⚠️ Ce cours présente une vision technique du sujet
    • Les changements nécessaires sont plus larges !