Un guide d’introduction pour vous aider à mettre en production un modèle plus puissant
Si vous êtes un data scientist ou un aspirant, vous avez probablement entendu dire que la plupart des modèles ML n’atteignent pas la phase de production (Article sur le rythme de l’aventure). Il y a des raisons à cela, mais on peut affirmer que le parcours d’apprentissage actuel de la science des données se concentre sur la construction d’un modèle ML et l’amélioration des métriques. Bien que ces éléments soient importants, mettre votre modèle en production est la façon dont un scientifique des données peut avoir un impact sur une entreprise. Ici, je présente le principe le plus élémentaire des MLOps afin que vous puissiez aider votre entreprise à mettre en production un modèle plus puissant.
Après le grand succès de DevOps dans l’industrie informatique, d’autres domaines ont également inclus ces « Opérations » dans leur routine quotidienne. Mais qu’est-ce que MLOps exactement ? Eh bien, selon Wikipédia :
« MLOps ou ML Ops est un ensemble de pratiques qui vise à déployer et à maintenir des modèles d’apprentissage automatique en production de manière fiable et efficace. »
En d’autres termes, au sein d’une entreprise, MLOps est la standardisation des pratiques d’expérimentation, de développement et de codage qui vous aideront à mettre un modèle ML en production plus rapidement, de manière plus fiable et moins lourde.
Il s’agit de développer le modèle, de le mettre en production, de le suivre et de déclencher une reconversion si nécessaire. Cela peut être très complexe, et toutes les entreprises n’ont pas résolu ce problème. Mais en tant que data scientist, vous vous demandez peut-être : comment puis-je commencer ? Après tout, vous êtes un élément crucial du processus.
Comme vu précédemment, la fiabilité est au cœur des MLOps. Cela signifie que tout le code que vous exécutez localement dans votre environnement Jupyter ou Python doit produire le même résultat dans l’environnement de production. Ce n’est pas difficile à résoudre quand il y a des graines aléatoires. Vous pouvez utiliser la même graine dans tout votre code, et tout ira bien. Mais les choses peuvent devenir un peu plus difficiles en ce qui concerne la configuration de l’environnement et les dépendances.
La reproductibilité est le mot. Comment pouvez-vous vous assurer que votre code peut être reproduit sur une autre machine ?
Docker est une plate-forme open source qui facilite et simplifie la création et la gestion de systèmes isolés. Vous pourriez dire que c’est quelque chose comme une machine virtuelle, mais ce n’est pas exactement cela. Vous pouvez utiliser Docker pour transformer votre modèle en « package ». Pour rendre les choses plus claires, sautons dans le code.
En tant que projet guide, nous travaillerons avec le jeu de données Titanic. Supposons que vous souhaitiez que votre modèle soit prêt pour la production à l’aide d’une image Docker. Nous allons travailler sur une API REST, qui peut être utilisée pour d’innombrables autres problèmes.
Le code entier peut être trouvé dans ce dépôt J’ai créé, et bien que je commenterai le code ici, le code de travail complet ne peut être trouvé que dans le référentiel. Assurez-vous de le vérifier.
Pour répliquer ce projet dans votre environnement local, vous devez avoir Python installé (j’utilise python 3.8) et le moteur Docker. Si vous n’avez pas Docker, vous pouvez consulter la documentation pour savoir comment procéder :
https://docs.docker.com/engine/install/.
Après avoir installé le Docker, créez un nouveau dossier pour notre projet et créez un nouvel environnement virtuel avec les éléments suivants :
python3 -m venv .env
source .env/bin/activate
Comme l’accent est mis ici sur l’utilisation de Docker et non sur la modélisation, nous utiliserons un simple classificateur Gradient Boosting avec les fonctionnalités numériques dont nous disposons. Si vous clonez le dépôt, installez les dépendances avec la commande suivante :
pip install -r requirements
Et exécutez le script d’entraînement avec cette commande :
python -m train_titanic
Nous avons maintenant un artefact de modèle à utiliser dans notre API.
L’étape suivante consiste à créer un module qui prédira si un passager donné survivra. Ce module s’appelle titanic_model
. Il a une classe principale pour gérer tout ce qui concerne le mode, y compris les éléments suivants :
- chargement du modèle et du scaler à utiliser
- créer le pipeline de prédiction qui inclut la mise à l’échelle des fonctionnalités en fonction du scaler utilisé dans la formation et de la prédiction elle-même
class TitanicModel:
def __init__(self):
self.model = self._load_artifact(filename="titanic_classifier")@staticmethod
def _load_artifact(
filename: str,
) -> Union[pd.DataFrame, GradientBoostingClassifier, StandardScaler]:
...
def predict(
self, pclass: int, sex: str, age: Union[float, int], fare: Union[float, int]
) -> bool:
predictions = self.model.predict([[
pclass, encoded_sex, scaled_age, scaled_fare
]]).tolist()
return bool(predictions[0])
Maintenant que nous avons du code Python contenant notre modèle, nous pouvons empaqueter notre modèle. C’est la première étape vers la reproductibilité. Après cette étape, on peut pip installer notre code et le module titanic_model
sera disponible dans la console Python.
Pour ce faire, nous devons créer un setup.py
à la racine de notre projet avec des instructions pour installer notre code.
De setuptools
nous importons le setup
fonction et transmettez quelques informations (y compris où rechercher le code Python) à cette fonction. Voici à quoi cela ressemble :
from setuptools import find_packages, setupsetup(
name="titanic",
version="0.1",
url="https://github.com/danielKatagiri/basic-mlops",
description="Package to create a predictor for the Titanic dataset",
packages=find_packages(exclude=["train*"]),
install_requires=install_requires
)
Maintenant, vous pouvez tester si tout fonctionne en installant le package dans un nouvel environnement virtuel (afin que l’environnement actuel ne soit pas sale). Voici le code pour le faire :
deactivate
python3 -m venv .env2
source .env2/bin/activate
python3 -m pip install .
python3 -m pip freeze | grep titanic
Si tout est OK, vous devriez voir le paquet titanic==0.1
dans la sortie. Vous pouvez maintenant supprimer cet environnement virtuel nouvellement créé et activer l’ancien, comme indiqué ci-dessous :
deativate
rm -rf .env2/
source .env/bin/activate
Maintenant que nous avons une classe qui gère la prédiction et que notre code python est installable par pip, nous pouvons créer une application FastAPI qui encapsulera notre modèle dans un app.py
dossier. Il s’agit de l’API REST, ce qui signifie que notre modèle peut désormais recevoir des requêtes HTTP avec les fonctionnalités et y répondre avec la prédiction.
Le app.py
fichier crée un Passenger
modèle utilisant Pydantic. Ceci est nécessaire pour que FastAPI valide l’entrée envoyée par la requête HTTP. Ensuite, le script crée un FastAPI
instance avec une route de prédiction qui recevra un GET
demander.
class Passenger(BaseModel):
pclass: int
sex: str
age: Union[float, int]
fare: Union[float, int]def create_app():
application = FastAPI()
model = TitanicModel()
@application.get("/predict")
async def predict(
pclass: int, sex: str, age: Union[float, int], fare: Union[float, int]
):
return model.predict(pclass=pclass, sex=sex, age=age, fare=fare)
return application
if __name__ == "__main__":
app = create_app()
uvicorn.run(app, host="0.0.0.0", port=8080)
Maintenant que le code de l’API est terminé, vous pouvez le tester en exécutant python app.py
dans votre borne.
Pour le dernier acte de notre émission, nous allons écrire du code pour le moteur Docker afin de créer notre application et de la compiler en tant qu’image Docker. Comme c’est peut-être la première fois que vous regardez le code « Docker », je vais le commenter plus en détail.
# First, we choose the base image. Theses base images can be found at
# As our code is running in python, we can choose
# the python image as our base image
FROM python:3.8-slim-buster# In the TitanicModel class, you can check the `_load_artifact` method.
# It tries to find the artifacts used by the model in a specific folder
# determined by the enviroment variable `ARTIFACTS_HOME`. So here we are
# setting this environment variable to be in /home/artifacts
ENV ARTIFACTS_HOME='/home/artifacts/'
# This folder does not exists yet, so this next command creates the path
# for us
RUN mkdir -p $ARTIFACTS_HOME
# Now we will copy our local created artifacts to this folder within our image
# In this example, we are copying from the local file system, but idealy these
# artifacts will be stored in a Model Registry (MLFlow, Google storage,
# VertexAI, S3, ...)
COPY ./artifacts/* $ARTIFACTS_HOME
# This next line copies the files from our project into the /package folder
# and sets this new folder as working directory. It would be as if the docker
# engine running this piece of code did a `cd package` when running.
COPY . /package
WORKDIR /package
# We are now going to upgrade our pip and install the package, as we did before
# in the virtual environment. After installing, we delete this `package` folder
RUN pip3 install --upgrade pip
RUN pip install . && rm -rf /package
# Now we set our working directory to be a `app` folder and copy the `app.py`
# file into it, so that our FastAPI application is available in the image
WORKDIR /app
COPY app.py .
# Now that everythin is set up, we can call the command to run the FastAPI
# application
CMD ["python", "app.py"]
Pour tester si tout fonctionne, vous pouvez créer l’image en exécutant docker build -t titanic
. Cette commande indique à Docker de créer une image. Le -t titanic
marque cette nouvelle image, et le .
Le paramètre indique à Docker de le construire dans le dossier actuel.
Si l’image a été construite avec succès, vous pouvez l’exécuter en exécutant docker run --rm -it -p 8080:8080
. Vous pouvez maintenant accéder localhost:8080/docs
dans votre navigateur pour voir le swagger généré par FastAPI.
Pour faire une requête à l’aide de curl, exécutez :
curl -X GET “http://localhost:8080/predict?pclass=3&sex=male&age=22&fare=7.25"
et ça devrait revenir false
.
Si vous pouviez reproduire les étapes jusqu’à présent, vous disposez d’une image docker personnalisée qui encapsule votre API REST avec un modèle ML fonctionnant en arrière-plan. Désormais, l’équipe responsable du déploiement de votre modèle n’aura plus qu’à se soucier de la création d’une machine virtuelle ou d’un déploiement K8s qui exécute votre image (et quelques autres éléments, mais sans encapsuler votre modèle quelque part).
Vous pouvez reproduire ces principes pour d’autres types de problèmes, tels que la prédiction par lots.
Merci d’avoir lu et faites-moi savoir si vous avez des idées sur le sujet.