Aller au contenu

Industrialisation de projet data

·8 mins·
DataScience Industrialisation Modop

Aujourd’hui, je m’attaque Ă  un article sur l’industrialisation d’un projet de donnĂ©es. Il s’agit de ma feuille de route Ă©tape par Ă©tape avec les meilleures pratiques, les outils recommandĂ©s et des exemples de code Ă  copier et Ă  coller. Je me suis inspirĂ© des programmes de diverses formations, ce qui vous permettra peut-ĂŞtre d’Ă©conomiser un peu d’argent.

1. CrĂ©ation d’un environnement isolĂ© pour chaque projet
#

Isoler les dépendances de chaque projet évite les conflits de version et garantit que votre code est reproductible et portable.

J’utilise venv pour crĂ©er ces environnements virtuels.

mkdir my_project_dir                  # create directory
cd my_project_dir                     # move to directory
python -m venv venv                   # create venv
source venv/bin/activate              # activate venv
deactivate                            # deactivate venv
rm -r venv                            # delete venv

2. Versionner avec Git et GitHub/GitLab
#

Le contrĂ´le des versions vous permet de suivre les modifications du code, de collaborer efficacement avec d’autres dĂ©veloppeurs et de revenir Ă  des versions antĂ©rieures si nĂ©cessaire.

Outils recommandĂ©s : Git pour les versions locales, GitHub ou GitLab pour l’hĂ©bergement du code et la collaboration.

Pensez Ă  exclure venv de la gestion des versions avec touch .gitignore :

venv/
*.pyc
__pycache__/

Ensuite:

git init                        # initializing a git repository
git add .                       # add all files
git commit -m "Initial commit - Project setup with virtual environment"
git remote add origin https://github.com/user/my_project.git  # add remote repository
git push -u origin main         # pushing changes to the remote repository

Utiliser les branches pour dĂ©velopper de nouvelles fonctionnalitĂ©s, et les intĂ©grer dans la version principale via des demandes d’extraction après examen du code.

git branch branch_name          # initializing a new branch
git branch                      # check all branch
git checkout branch_name        # switch branch
git checkout main               # switch main branch before merge
git merge branch_name           # merge branch_name with main
git branch -d branch_name       # delete local branch_name if it's merged
git push origin --delete branch_name # delete remote branch_name

3. Structure du project
#

Une bonne structure de projet facilite la maintenance, la collaboration et l’Ă©volution du code. Voici un article de Baran KöseoÄźlu (Towards Data Science), qui dĂ©crit très bien le problème. Il parle notamment de l’outil Cookiecutter, et de la structure créée spĂ©cifiquement pour un projet de science des donnĂ©es ici.

Voici comment l’installer :

pip install cookiecutter
cookiecutter https://github.com/drivendata/cookiecutter-data-science

Et voici la structure du projet :

├── LICENSE
├── Makefile           # makefile with commands like `make data` or `make train`
├── README.md          # the top-level README for developers using this project.
├── config             # all files about database configuration, path, etc.
├── data
│   ├── external       # data from third party sources.
│   ├── interim        # intermediate data that has been transformed.
│   ├── processed      # the final, canonical data sets for modeling.
│   └── raw            # the original, immutable data dump.
│
├── docs               # a default Sphinx project; see sphinx-doc.org for details
│
├── models             # trained and serialized models, model predictions, or model summaries
│
├── notebooks          # jupyter notebooks. Naming convention is a number (for ordering),
│                      #   the creator's initials, and a short `-` delimited description,
│                      #   e.g. 1.0-jqp-initial-data-exploration.
│
├── refs               # data dictionaries, manuals, and all other explanatory materials.
│
├── reports            # generated analysis as HTML, PDF, LaTeX, etc.
│   └── figures        # generated graphics and figures to be used in reporting
│
├── requirements.txt   # the requirements file for reproducing the analysis environment
│
├── setup.py           # makes project pip installable (pip install -e .) so src can be imported
│
├── src                # source code for use in this project
│   ├── __init__.py    # makes src a Python module
│   ├── main.py        # main file of the process
│   │
│   ├── data           # scripts to download or generate data
│   │   └── make_dataset.py
│   │
│   ├── eda            # scripts to analyse the data
│   │
│   ├── features       # scripts to turn raw data into features for modeling
│   │   └── build_features.py
│   │
│   ├── models         # scripts to train models and then use trained models to make predictions
│   │   ├── predict_model.py
│   │   └── train_model.py
│   │
│   ├── utils          # transverse scripts
│   │
│   └── visualization  # scripts to create exploratory and results oriented visualizations
│       └── visualize.py
│
├── tests              # test code for testing the project
│
├── tox.ini            # tox file with settings for running tox; see tox.testrun.org
│
└── venv               # virtual environment

4. Gestion des dépendances avec requirements.txt
#

Un fichier requirements.txt répertorie toutes les dépendances de votre projet, ce qui permet une installation facile et cohérente sur différentes machines. Vérifiez et mettez à jour vos dépendances régulièrement. Utilisez des spécificateurs de version pour éviter les conflits, par exemple pandas>=1.2,<2.0.

# Generate a requirements.txt file
pip freeze > requirements.txt

5. Testing et pipeline de test (CI/CD)
#

Les tests automatisés garantissent que votre code fonctionne comme prévu et facilitent les mises à jour sans régression.

Outil recommandĂ© : Pytest pour les tests unitaires et GitHub Actions ou GitLab CI/CD pour l’intĂ©gration continue.

Écrivez des tests unitaires pour chaque fonction critique de votre code. Utilisez l’intĂ©gration continue pour exĂ©cuter automatiquement les tests Ă  chaque modification de votre code.

# tests/test_data_preprocessing.py
import pandas as pd
from src.utils.data_preprocessing import clean_data

def test_clean_data():
    df = pd.DataFrame({"A": [1, 2, None], "B": [4, None, 6]})
    cleaned_df = clean_data(df)
    assert cleaned_df.isnull().sum().sum() == 0

6. Documentation avec Sphinx
#

Une documentation bien rédigée aide les utilisateurs et les développeurs à comprendre et à utiliser efficacement votre projet. Sphinx pour générer de la documentation à partir de docstrings.

Maintenez la documentation Ă  jour avec le code. Utilisez des exemples de code pour illustrer l’utilisation des fonctions et des classes

pip install sphinx
sphinx-quickstart docs  # Initializes a new documentation in the docs folder

Configurer Sphinx : Ajouter le chemin d’accès Ă  la source et activer les extensions nĂ©cessaires dans conf.py.

# docs/conf.py
import os
import sys
sys.path.insert(0, os.path.abspath('../src'))

extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']

Générer la documentation

sphinx-apidoc -o docs/source src
sphinx-build -b html docs/source docs/build

7. Conteneurisation avec Docker
#

La conteneurisation facilite le dĂ©ploiement de votre application dans n’importe quel environnement avec toutes ses dĂ©pendances. [Docker] (https://www.docker.com/) pour crĂ©er des conteneurs lĂ©gers et portables.

CrĂ©ez des images Docker aussi lĂ©gères que possible, en n’incluant que les dĂ©pendances nĂ©cessaires. Utilisez les fichiers .dockerignore pour Ă©viter d’ajouter des fichiers inutiles Ă  l’image.

# Dockerfile
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "src/main.py"]
# Building the Docker image
docker build -t my_project .

# Launching a Docker container
docker run -d -p 5000:5000 my_project

8. Déploiement et surveillance
#

Le dĂ©ploiement de votre application sur un serveur ou dans le nuage rend votre travail accessible aux utilisateurs finaux. La surveillance permet de s’assurer que l’application fonctionne correctement et de dĂ©tecter les problèmes avant qu’ils n’affectent les utilisateurs. Heroku est un excellent outil pour le dĂ©ploiement rapide d’applications ou AWS pour une infrastructure plus robuste. Utilisez Prometheus et Grafana pour la surveillance.

Configurez des alertes pour être informé des problèmes en temps réel. Effectuez des tests de charge pour vous assurer que votre application peut gérer les utilisateurs attendus.

# Prometheus configuration
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'my_app'
    static_configs:
      - targets: ['localhost:9090']
# Launch Prometheus
prometheus --config.file=prometheus.yml

# Launch Grafana
docker run -d -p 3000:3000 grafana/grafana

Il convient Ă©galement de mentionner setuptool, une bibliothèque Python qui facilite la crĂ©ation, la distribution, l’installation et la gestion des paquets Python. Il s’agit d’un outil essentiel pour crĂ©er des paquets Python standardisĂ©s qui peuvent ĂŞtre facilement distribuĂ©s via des plateformes telles que PyPI (Python Package Index).

9. Bonus
#

9.1. Respecter les conventions de codage PEP8
#

Les conventions de codage PEP8 amĂ©liorent la lisibilitĂ© et la maintenabilitĂ© de votre code. IntĂ©grez Flake8 dans votre Ă©diteur de texte ou votre IDE pour obtenir un retour d’information en temps rĂ©el sur les violations du PEP8.

pip install flake8
flake8 src/  # Checks src file for PEP8 compliance

Conventions de dénomination, par exemple, conformément à la PEP8 :

  • classes : MyGreatClass. Majuscules au dĂ©but du mot
  • exceptions : MyGreatError. Similaire aux classes, mais avec une erreur Ă  la fin.
  • fonctions : my_function(). Minuscules et traits de soulignement
  • mĂ©thodes : my_method(self). Minuscules, soulignĂ©s et self comme premier paramètre
  • variables : ma_variable. Identique aux fonctions
  • constantes : I_WILL_NEVER_CHANGE. Tout en majuscules, avec des traits d’union si nĂ©cessaire.

9.2. Écrire un code modulaire et réutilisable
#

Le code modulaire est plus facile Ă  tester, Ă  dĂ©boguer et Ă  rĂ©utiliser dans diffĂ©rents projets. Utilisez des fonctions et des classes pour encapsuler la logique de l’entreprise. Documentez chaque fonction Ă  l’aide de docstrings.

# src/utils/data_preprocessing.py
def clean_data(df):
    """Cleans data by removing missing values."""
    return df.dropna()

# src/models/train_model.py
def train_model(X, y):
    """Trains a model and returns the model object."""
    from sklearn.ensemble import RandomForestClassifier
    model = RandomForestClassifier()
    model.fit(X, y)
    return model

9.3. Gestion des secrets et des variables d’environnement
#

Les secrets (tels que les clĂ©s d’API et les mots de passe) ne doivent jamais ĂŞtre codĂ©s en dur dans le code pour des raisons de sĂ©curitĂ©.

Outil recommandĂ© : dotenv pour charger les variables d’environnement Ă  partir d’un fichier .env.

Utilisez des gestionnaires de secrets tels que AWS Secrets Manager ou HashiCorp Vault pour stocker et accéder aux secrets en toute sécurité.

# .env
SECRET_KEY=secret_key
DATABASE_URL=postgres://user:password@localhost/dbname
# src/config.py
from dotenv import load_dotenv
import os

load_dotenv()

SECRET_KEY = os.getenv('SECRET_KEY')
DATABASE_URL = os.getenv('DATABASE_URL')

Sources
#

Tools:

Bonus:

Some inspiration …

Thibault Clément - Intechnia
Auteur
Thibault Clément - Intechnia
Data scientist