Plusieurs outils existent dans le but d’essayer de résoudre les problèmes évoqués dans la première partie de l’article et nous faciliter la vie. Certains de ces outils sont open source et d’autres sont payants, chacun apportant des solutions à différents problèmes (souvent les mêmes).
Dans cette partie la suite, on présentera deux solutions open sources (DVC et MLflow), accompagnées de Git, qui, combinées permettent de résoudre la plupart des problèmes de versionning que nous, data scientists, rencontrons au quotidien.
Nous allons utiliser Git pour gérer les versions de notre code et des fichiers de configurations, DVC pour gérer les données, la gestion des pipelines et les modèles, et MLflow sera utilisé pour le déploiement et la comparaison des métriques des différentes expérimentations.
Git
Git est un logiciel de gestion de versions décentralisé. C’est un logiciel libre créé par Linus Torvalds, auteur du noyau Linux, et distribué selon les termes de la licence publique générale GNU version 2. En 2016, il s’agit du logiciel de gestion de versions le plus populaire qui est utilisé par plus de douze millions de personnes. (Wikipedia)
Nos amis développeurs connaissent bien la bête, c’est d’ailleurs leur outil préféré voir le seul qu’ils utilisent pour garder l’historique des modifications de leurs codes sources. C’est donc sans surprise l’outil que nous allons utiliser pour gérer le versionning de notre code, surtout que les deux autres outils que nous allons utiliser s’entendent parfaitement avec Git.
Git est aussi idéal car la plupart des hébergeurs de code sur la toile le supportent ( e.g Github, Gitlab, Bitbucket …), on peut donc facilement déployer notre projet dans des serveurs distant sans avoir à gérer la maintenance et donc bien dormir la nuit.
Dans ce billet, on va pas s’attarder sur le fonctionnement de Git, car beaucoup d’articles et de tutos expliquant les soubassements et les ingrédients de Git existent déjà, pour ne citer que certains :
Documentation officielle , Progit 2
Pourquoi ne nous limitons nous pas seulement à Git ? ¨Pourquoi nous compliquer la vie ? Humm, à vrai dire, nous n’allons pas essayer de changer le rôle de Git, mais plutôt d’ajouter de nouvelles briques à ce bâtiment déjà bien fourni, pour héberger les parties qui sont intrinsèques au monde de la data science(i.e données et modèles).
Git n’a pas été fait pour gérer des fichiers de grande taille, toutes les personnes ayant essayé de le faire ont dû tôt ou tard mordre la poussière, surtout en essayant d’uploader ces fichiers sur un serveur distant. Etant donné que nous allons jongler avec des données de très grande taille, il serait plus avisé de fouiller dans d’autres coins, cela est aussi valable pour les modèles que nous allons obtenir.
Cependant, il existe des solutions qui ont été créées spécifiquement dans le but de gérer les fichiers volumineux avec Git telles que Git-LFS ou Git-annex , mais ces solutions n’ont pas été pensées pour notre monde remplis de caprices, raison pour laquelle on va exploiter d’autres solutions taillées sur mesure pour cohabiter avec les magiciens que nous sommes 🙂 .
DVC(Data Science Version Control)
DVC est un outil de versionning open source pour le data science. Il est agnostique aux différentes librairies de machine learning (e.g Scikit learn, Tensor Flow….) et aux langages de programmation. En d’autres termes tout ce qui peut s’exécuter avec une ligne de commande dans un terminal peut être utilisé avec DVC. Il se positionne au dessus de Git, en se concentrant uniquement sur la gestion des différentes versions des données, des modèles mais aussi de leurs liaisons avec le code source (Une pierre trois coups:) ), tout ça d’une manière si élégante (même David Beckham en serait envieux), laissant à Git la tâche de versionner le code source et les fichiers de configurations (e.g ceux créés par DVC).
La figure 2 montre le workflow général d’un versionning fait avec DVC. À ce stade vous devez certainement vous dire que c’est de la science fiction. Nous allons donc voir en détail, comment DVC réussit ce tour de magie. Avant de continuer je dois vous avouer un truc : DVC ressemble beaucoup à Git sur son fonctionnement mais surtout au niveau de ses commandes(Iphone et Huawei? je vous laisse deviner qui est qui)

Installation de dvc
DVC peut être installé via pip install dvc ou via apt-get (linux ) et homebrew ( osx ), pour plus d’informations sur la procédure d’installation
1-Gestion des données
DVC comme à l’image de son compatriote(t’as le droit de dire ca?) Git, utilise des commandes pour traquer les données. Il y a principalement deux commandes pour dire à DVC de gérer le versionnement d’un fichier ou d’un dossier:
- dvc add dossier/fichier : cette commande permet de donner manuellement la main à DVC pour gérer le dossier ou le fichier donné en entrée tout en demandant à git de l’ignorer en l’ajoutant dans le .gitignore.
- dvc run commande : permet d’exécuter un script(commande) avec des entrées et des sorties, après exécution de la commande dvc prend la main sur les fichiers d’entrée(code et données) et les fichiers de sorties(données et/ou modèles)
Mais c’est quoi cette prise de main dont tu nous parle depuis ?
Ravi que vous ayez posé cette question, j’en salive déja, tellement c’est élégant et finement joué par DVC (Bon je calme ma joie), ok, allons dans le vif du sujet.
Vous vous rappelez quand je disais que dvc était presque la copie de Git, eh bien c’est le moment de justifier cette “accusation”.
Pour gérer les différentes versions des données et modèles, dvc crée un dossier .dvc au niveau de la racine du projet tout comme le dossier .git crée par Git, et comme si cela ne suffisait pas la commande pour initier dvc dans un projet est … dvc init. Bon blague à part tout ça est fait dans l’objectif de rendre la prise en main de dvc facile, car la plupart des gens connaissent Git, il est donc inutile de les fatiguer avec des nouvelles commandes à mémoriser car contrairement aux modèles nos capacités de mémorisation sont trop éphémères(heureusement).
Là où les choses sont différentes c’est dans le contenu des dossiers .git et .dvc. Ehh oui ! les créateurs de DVC ont quand même de la matière à vendre. Dans le dossier .dvc, on retrouve un dossier cache (ignoré par Git) contenant les différentes versions de nos données et modèles(i.e tous les dossiers/fichiers traqués par dvc), c’est donc dans ce dossier que DVC vient récupérer dans le domaine du possible (car les données peuvent aussi êtres sauvegardées dans un serveur distant, patience patience on va en parler dans la suite) les données demandées.
Quand DVC contrôle un dossier/fichier, il crée un fichier avec l’extension .dvc ({dossier|fichier}.dvc) où il stocke toutes les informations nécessaires pour retrouver le fichier dans le dossier .cache telles que le hash md5 ( https://fr.wikipedia.org/wiki/MD5 ) du fichier. En plus de cela, il va automatiquement ajouter ce fichier dans le .gitignore pour dire à son ami Git de lui laisser la responsabilité du tracking du fichier en question.
La question qui se pose maintenant c’est comment dvc lie les fichiers dans le dossier .cache avec les fichiers dans notre espace de travail (le dossier de notre projet). C’est la où la magie de DVC opère, pour chaque fichier traqué par DVC, un link est créé entre le fichier et le fichier situé au niveau du dossier .cache (avec la bonne version bien sûr).
De là deux questions émergent :
Comment dvc identifie la bonne version à lier avec le fichier se trouvant dans notre espace de travail ?
Pour répondre à cette question on va analyser le contenu du fichier “data1.xml.dvc” créé après l’exécution de la commande dvc add :
EX : dvc add data1.xml
data1.xml.dvc
md5: c864bbaa763461692f917d7390334bee
outs:
– cache: true
md5: 51efaecfd3502c661ffa70b7f2b753b4
metric: false
path: data1.xml
wdir: .
- le premier md5 correspond au hash du fichier dvc qui a été créé
- on a ensuite les sorties qui indiquent si la sortie doit être placé en cache, le hash du fichier concerné ici data1.xml indiquée par l’attribut path.
À partir de ces informations dvc a la capacité de savoir si le fichier dans le cache est le même que le fichier dans l’espace de travail mais aussi de gérer le versionning de ce fichier.
En effet si le fichier est changé, et qu’on l’ajoute avec dvc add, le fichier dvc correspondant sera modifié et il y aura alors deux versions dans le cache, il suffit alors de récupérer le fichier dvc correspondant à travers Git et dvc aura les informations nécessaires pour rapatrier la bonne version du fichier contenant les données.
C’est quoi un lien et comment ce lien est fait dans DVC?
Un lien = Un “raccourci”.
Hummm, tu n’aides pas vraiment là.
Bon ok, en système d’exploitation, un lien permet de rediriger un fichier vers un autre ce lien peut se faire de différentes manières.
Dvc utilise 4 types de liens en fonction du système d’exploitation de l’utilisateur sous cette ordre de préférence, à moins que l’utilisateur lui force la main:
- Un reflink : c’est un nouveau type de lien supporté par les derniers systèmes d’exploitation, tels que la dernière version de osx, qui gère les liens avec plusieurs blocs au lieu d’un seul par fichier, ceci permet d’éviter de copier tout le contenu d’un fichier quand il est modifié et qu’on veut quand même garder les deux versions, ainsi seul le bloc concerné est dupliqué.
EX : Prenons pour exemple un fichier qui occupe 10 blocs, si on crée un reflink et on modifie le fichier, supposons que seul le bloc 5 à été modifié, on aura donc maintenant 11 blocs au total et donc un seul bloc à été recréé et les deux fichiers contiennent toujours les neufs autres blocs(efficacité ils disent)
- Un lien dur : Dans ce type de lien, un nouveau fichier est créé pointant vers le même inode que le fichier original, une seule copie est donc gardée, raison pour laquelle la modification d’un affecte l’autre, on peut donc perdre des données par accident.
- Un lien symbolique : presque identique au lien dur, sauf que le nouveau fichier au lieu de pointer vers le même inode va pointer vers le fichier original, et donc le lien ici est plus fort entre les deux, car si on supprimer le fichier original, le lien ne sera plus valide et une erreur sera déclenchée.
- le vieux Ctrl+C/Ctrl+V : C’est le dernier recours de dvc, ici comme vous en doutez, le fichier est tout simplement copié vers le dossier cache. ceci a comme conséquence de ralentir la récupération des données depuis le cache vers l’espace de travail mais aussi d’occuper beaucoup plus de mémoire.
Il n’est donc pas surprenant de voir dvc préfère cette ordre pour gérer les liaisons entre les fichiers dans le cache et dans notre espace de travail.
Pour rebondir encore sur les similarités de dvc avec git (eh oui, quand y’en a plus y’en a encore), on va parler des autres commandes qui permettent de versionner les données, mais aussi faire un tour sur la communication de DVC avec des serveurs distants(e.g S3) :
- dvc commit ~ git commit
- dvc push ~ git push
- dvc pull ~ git pull
- dvc checkout ~ git checkout
Admirez la parfaite symétrie avec Git!
Ouvrons le capot pour voir ce que ces commandes essaient de nous cacher sous cet habillage de Git.
dvc push et dvc pull fonctionnent quasiment comme Git à l’exception des serveurs distants avec lesquels elles communiquent, DVC communique avec des serveurs de stockage de fichiers(surprise du siècle), souvent dans le cloud tels que S3, Google Cloud Storage mais aussi HDFS ou un serveur dédié.
Les configurations pour cette communication sont faites à l’intérieur du fichier .dvc/config. ce fichier peut être modifié à la main ou avec la commande dvc config [option à modifier]
Exemple de contenu du fichier config
[‘remote « myremote »‘]
url = /tmp/dvc-storage
[core]
remote = myremote
On peut voir qu’on indique à dvc le nom du repository distant à utiliser pour répliquer les données dans le cache, le chemin spécifié est juste un dossier local, on pourrait tout à fait indiquer un lien dans le cloud tel que s3://….
La commande dvc checkout(illustrée par la figure 3) attaque le dossier cache pour récupérer les fichiers indiqués dans les fichiers .dvc créés par les commandes qui donnent le contrôle d’un fichier à dvc.

Une notion importante est à expliquer ici, les fichiers .dvc sont toujours versionnés par Git, c’est ca qui permet aux commande pull et checkout de DVC de pouvoir voyager dans le temps à travers ces fichiers pour placer les bonnes versions des fichiers(données et modèles) dans l’espace de travail actuel.
Pour en connaître d’avantage sur ces commandes, je vous encourage à lire la documentation dvc (c’est la meilleure documentation que j’ai jamais lu).
2-Gestion des pipelines dans un projet de data science
Dans tout projet data science, il y a plusieurs étapes à exécuter, très souvent séquentielles et répétitives, telles que l’acquisition des données, la création des features jusqu’à l’obtention du modèle. La figure 4 permet de schématiser ce pipeline.

Avoir une trace de ses étapes est primordial pour la reproductibilité des expérimentations, mais aussi pour le partage d’expérimentation entre les membres d’une équipe. Par exemple chacun peut se concentrer sur une étape en utilisant les sorties des autres étapes et dvc s’occupera de gérer automatiquement les dépendances et le séquencement des étapes.
Bien sur, comme toujours dans le domaine, la magie est juste le côté visible de l’iceberg, pour réussir ce tour de passe passe, dvc se base sur sa commande run et donc cela suppose que l’exécution de chaque étape est faite avec la commande dvc run mentionnée précédemment.
Alors dvc run comment tu fais ?
Analysons d’abord la syntaxe de la commande :
dvc run -f Dvcfile \
-d train.py -d data -d matrix.pkl \
-o model.pkl \
python train.py matrix.pkl model.pkl
À chaque fois que la commande dvc run est exécutée, elle reçoit non seulement la commande(ici python train.py) à exécuter, mais aussi les dépendances avec l’option -d et les sorties avec l’option -o, ceci permet à dvc de prendre le contrôle sur les fichiers(dépendances et sorties), mais aussi de sauvegarder les dépendances et les sorties dans le fichier .dvc résultant afin de pouvoir reproduire l’étape ou les étapes avec juste la commande dvc repro (Admirez la beauté intérieure de cette commande).
dvc run permet la création dynamique de pipeline, car pour chaque exécution on peut donner les sorties d’une étape précédente (exécutée avec dvc run) comme dépendance à une autre étape et ainsi de suite. dvc traque automatiquement ces dépendances entre les étapes, ce qui lui permet de créer implicitement des pipelines 🙂
L’option f indique le nom du fichier qui sera créé pour enregistrer les informations sur l’étape en cours d’exécution, si cette option n’est pas fournie, dvc crée automatiquement un fichier avec le nom de la première sortie indiquée en ajoutant l’extension .dvc.
N.B : les dépendances et sorties fournies à la commande dvc run ne sont pas directement liées à la commande donnée en entrée à dvc run. ces paramètres sont surtout là pour permettre à dvc de prendre la main sur les fichiers utilisés ou créés par la commande (script) exécutée. En d’autres termes, l’exécution du script ne prend pas en compte ces paramètres, seul dvc est concerné.
N.B :Il est recommandé de donner les sorties et les entrées en argument de la commande à exécuter, ceci permet de ne pas se tromper dans les dépendances et les sorties indiquées à la commande dvc run.
Contenu du fichier Dvcfile
cmd: python train.py matrix.pkl model.pkl
deps:
– md5: abe54bd55fd3643ad05705c2a852bec4
path: train.py
– md5: 2d06b4e4890dd35fcac069d3d91e977f
path: matrix.pkl
md5: ce99c88bc6102b52d39347ac8292709b
outs:
– cache: true
md5: 443c2129e5398d14c4c81ca7472cdb41
metric: false
path: model.pkl
wdir: .
Nous pouvons voir que dvc sauvegarde la commande utilisée pour exécuter l’étape en question, mais aussi les dépendances et les sorties accompagnées de leur hash md5 pour pouvoir traquer les modifications sur ces fichiers.
dvc repro Dvcfile
Pour reproduire cette étape il suffit just de taper la commande ci-dessus et dvc s’occupe du reste en prenant en compte les étapes bien avant celle-ci telles que l’étape utilisée pour créer les features dans matrix.pkl.
Cerise sur le gâteau, cette commande repro analyse les changements effectués sur les dépendances et s’il n’y a pas eu de changement, aucun calcul n’est effectué. Lorsque le fichier .dvc dépend de la sortie d’une autre étape la commande repro remonte pour recréer le pipeline complet et exécute uniquement les étapes qui ont vu leurs dépendances être modifiées depuis la dernière exécution (l’economie ca vous parle ?)

Affichage d’un pipeline avec dvc pipeline show
3-Gestion des modèles en data science

La gestion des modèles(Figure 5) est identique à celle des données, on associe un fichier .dvc à un modèle donnée pour gérer les différentes versions(gérées par Git) et le modèle en question est géré par dvc(sauvegardé dans le cache).
Pour une bonne gestion des modèles et des dépendances entre le code source et les données, il est conseillé (“obligatoire”) de créer une nouvelle branche pour chaque expérimentation pour faciliter la reproductibilité à travers les différentes expérimentations.
Malheureusement DVC ne gère pas l’aspect déploiement, tout comme la comparaison des modèles de manière graphique, du moins pas actuellement.