L'expérimentation dans un Delivery de Machine Learning

le 07/03/2022 par Capucine Claude
Tags: Data & AI, Data Science

La méthode du Lean Product Management dont s'inspire fortement Accelerate dans sa vision du Delivery vise à construire le bon produit, au bon moment. Cette philosophie cherche surtout à permettre aux organisations de s'adapter aux changements continus auxquels est confronté un produit tout au long de son cycle de vie. L'expérimentation fait partie des pratiques de cette méthode et appartient au groupe de capabilities Product and processes du modèle Accelerate. Et même si cette capability rime souvent avec risques et/ou perte de temps, elle est nécessaire si l'on veut tirer profit des nouvelles technologies, des nouveaux outils qui font leur apparition régulièrement sur le marché, si l'on veut tester de nouvelles techniques ou pratiques et si l'on cherche à améliorer régulièrement nos manières de fonctionner. Mais pour que l'expérimentation porte ses fruits, il faut qu'elle soit bien appréhendée par les équipes et intégrée intelligemment dans leur processus de travail.

Pourquoi est-ce encore plus important de bien maîtriser l'expérimentation dans un contexte de Machine Learning ?

Comme dans tous les articles de la série Accelerate for Machine Learning, nous avons cherché à comprendre quel serait le meilleur moyen d'adapter cette capability à un contexte de ML. Et contrairement à d'autres capabilities où le lien avec le Machine Learning peut sembler moins évident, l'expérimentation semble faire partie intégrante de ce type de projets.

En effet, le Machine Learning a une forte culture de l'expérimentation. D'ailleurs beaucoup de data scientists viennent du monde de la recherche et des mathématiques. Pour développer le produit (le modèle surtout), ils sont souvent obligés de passer par des phases d'expérimentation pour trouver le meilleur modèle, l'optimiser, essayer plusieurs combinaisons de features différentes, trouver les bonnes métriques… Bref, les expérimentations sont plus nombreuses et surtout plus critiques.

On a aussi plus d'incertitudes à cause de l'aspect "non déterministe" du ML. L'expérimentation est donc parfois essentielle pour dérisquer certains choix.

Finalement, ce domaine étant relativement récent, les stacks techniques et les approches ne sont pas toujours matures. Étant assez populaire aussi, de nouveaux outils font régulièrement leur apparition et ceux-ci doivent être testés et validés avant d'être intégrés dans un quelconque projet.

Nous avons donc trouvé pertinent de creuser ce sujet-là et d'explorer des pratiques et des idées pour bien maîtriser cette capability, d’autant qu’en tant qu’Octo, nous avons accompagné un industriel français dans son projet d’automatiser sa chaîne de contrôle qualité via de l’inspection visuelle appuyée sur un modèle de machine learning. C’est fortes de cette expérience que nous allons vous partager les quelques conseils que nous avons compris parfois à nos dépens mais surtout à force de pratique. Nous appellerons ce projet le projet Alpha dans la suite de cet article pour plus de simplicité.

1- Les expérimentations doivent répondre à une réalité observée sur le terrain

La première règle d'or que nous avons touché du doigt est le fait que les expérimentations doivent être la conséquence d’une réalité terrain, qu’elle émane des utilisateurs ou de l’équipe de développement dont les douleurs sont parfois négligées.

Dans un contexte de ML, la prise en compte des retours utilisateurs est essentielle pour l'élaboration d'un modèle efficace et performant. Cela semble évident d’un point de vue théorique mais sur le terrain on se rend rapidement compte que les constats d’inefficacité sont partagés mais finalement ignorés par manque de temps ou de moyens; et c’est là que se situe le terrain de jeu de l’expérimentation.

Prenons un exemple issu du projet Alpha pour illustrer cette idée. Du point de vue de l’équipe de développement : le ré-entraînement était identifié comme pénible par les data scientists parce que répétitif et chronophage, comme par les Product Owners (PO) parce que dépendant de l’équipe de développement.

L’équipe a donc mené une expérimentation encadrée pour tenter d’automatiser ce réentraînement. 3 jours de travail, 2 data scientists et un point d’étape plus tard, une première solution (pas encore une solution cible) permettait aux PO de les lancer eux-mêmes très rapidement via des pipelines, en essayant les paramètres qui leur paraissaient intéressants à tester au vu des retours obtenus en usine.

Des conséquences intéressantes ont émergé suite à cela :

  • La première conséquence a été que les PO ont été autonomisés sur ce sujet et l’équipe de développement s'est déchargée d’une tâche ce qui lui a permis de tourner ses compétences vers des sujets à plus forte valeur ajoutée.
  • La seconde conséquence a été l’apparition au backlog et dans la roadmap d’un nouveau sujet : celui de construire une solution plus pérenne et d’aller plus loin encore comme en automatisant l’évaluation des modèles par exemple, suite logique au réentrainement.
  • La dernière conséquence a été qu’elle a ouvert la voie à de nouvelles expérimentations orientées utilisateurs comme par exemple d’expérimenter le réentraînement avec des jeux de données différents pour en améliorer les performances.

C’est le “cercle vertueux de l’expérimentation” : que l’on valide ou invalide l’hypothèse initiale, cette première recherche permet d’aller plus loin.

Mais comment arriver à efficacement identifier ces pain points dans un contexte de ML et donc ces expérimentations ? Voici trois pistes, l’une orientée utilisateur et les autres plus process :

  • Les produits de ML, comme des produits plus “traditionnels” servent des utilisateurs et il faut aller les interroger pour mieux comprendre leurs points de friction et comment le produit peut y répondre. Il est donc nécessaire de créer des points de rencontre réguliers avec ces “vrais” utilisateurs finaux, que cela soit au début, au milieu ou à la fin de la construction du produit. En la matière on peut tout imaginer et tout combiner : de simples sessions d’observation du quotidien de l’utilisateur, que cela soit avec l’outil en place ou sans, des tests utilisateurs, des interviews etc.
  • On peut essayer de matérialiser la chaîne de valeur sous forme de Kanban en adaptant la méthode traditionnelle au contexte de ML (comme suggéré dans cet article) et cela afin d’identifier les zones d’inefficacités et tenter de les améliorer
  • Il est également important de visualiser les travaux en cours pour mieux repérer les goulots d'étranglement sur lesquels l'équipe pourrait agir.

Une fois des points de douleurs identifiés, il est important de se poser avec toute ou une partie de l’équipe et les utilisateurs pour prioriser ces douleurs selon le gain attendu et une première idée des chances de succès. Si nécessaire, un vote rapide en fin de session permettra d’identifier le ou les prochains sujets d’expérimentation.

2- … et ce n'est pas grave si les expérimentations échouent...

La deuxième règle d'or que nous avons identifiée, et mentionnée ci-dessus d'ailleurs, est qu'une expérimentation peut échouer. Et ce n'est pas grave. L'objectif d'une expérimentation est surtout d'éprouver une hypothèse. Plus encore, dans un contexte de ML, il est normal et courant que des expérimentations échouent. On peut même dire qu'une expérimentation qui échoue est une expérimentation réussie dans le sens où elle a permis à l'équipe d'invalider une hypothèse et de soit passer à autre chose soit vouloir expérimenter différemment.

Quand nous travaillions sur le projet Alpha, nous avions eu besoin d'un outil pour permettre aux experts métier d'annoter les images. A ce moment-là, nous nous sommes posés une question que beaucoup d'équipes de développement doivent se poser régulièrement : build or buy ? En d'autres termes, est-ce que nous développons une solution from scratch ou est-ce que nous en achetons une clé en main ?

Pour trancher, nous avons expérimenté le développement d'une interface simple pour l'annotation d'images. Finalement, parce que le coût de maintien était élevé, que l’expertise manquait dans l’équipe et que le développement d’un outil d’annotation n’était pas le sujet sur lequel nous voulions apporter de la valeur, nous avons opté pour Labelbox, un outil qui semblait répondre à notre problématique et dont l'intégration allait accélérer la mise en place de notre solution de réentraînement.

Certes, l'expérimentation a duré un certain temps et le code produit ne fut jamais utilisé. Mais cette tentative était nécessaire pour mesurer la quantité de travail à fournir pour créer l'interface adéquate et pour comprendre la faisabilité de la solution. Après tout, quoi de mieux qu'une vraie expérience - et de vraies données - pour prendre une décision éclairée ?

3. …en revanche, il faut cadrer les expérimentations pour qu'elles restent efficaces…

Puisqu'il n'existe pas de garanties suffisantes pour déterminer l'aboutissement d'une expérimentation, il est important de rester pragmatique et d'établir un cadre pour chacune des expérimentations. Certes, celles-ci font partie intégrante de l'univers du ML mais ce n'est pas une raison pour les bâcler. Il s'agirait plutôt de garder la cible en vue. A-t-on vraiment besoin de tester ce dernier modèle de Machine Learning quand j'ai des performances satisfaisantes en production ? Ce nouveau framework, avec ce que ça implique en temps d'intégration et d'assimilation pour l'équipe, est-il indispensable ? Est-il judicieux de passer 6 mois à tester ce nouvel outil quand, en parallèle, je n'arrive toujours pas à livrer en production ce que j'ai déjà accompli ? Certes, l'expérimentation fait partie intégrante de l'univers du ML mais les équipes de développement comme les POs doivent veiller à la pertinence des expérimentations. Pour ce faire :

  • Celles-ci devraient présenter une valeur ajoutée au produit ou à l'équipe.
  • Outre la pertinence du sujet et son niveau de priorité, les expérimentations devraient être limitées dans la durée et avoir un périmètre fixe et restreint. Cela ne sert à rien de tester plein d'hypothèses en même temps car, pour pouvoir valider l'utilité de l'une d'entre elles, il faudrait fixer le reste des paramètres.
  • Il est aussi intéressant de définir une durée pour l'expérimentation afin de ne pas avoir un effet tunnel. Si celle-ci est complexe et s'étend dans la durée, une solution serait de mettre en place des jalons pour partager au reste de l'équipe l'avancement, se demander si ça vaut le coup de continuer ou pas, réajuster les objectifs et le périmètre.

Bien cadrer une expérimentation permet également de ne pas se lancer dans des expérimentations inutiles : c’est lors de cette phase qu’il faut trouver la bonne balance entre expérimentation et utilité pour ne pas dépenser de l’énergie sur un sujet dont on n’est pas certain qu’il apportera de la valeur. A titre d’exemple, peut être que si nous avions cadré plus en profondeur le besoin d’outil d’annotation mentionné plus haut, nous nous serions rendus compte qu’une solution sur étagère était plus adaptée.

Autre composante importante d'une expérimentation réussie : un objectif mesurable. Sur le projet Alpha, nous nous étions demandé si un modèle d'inspection par usine serait plus efficace qu'un modèle global. Dans ce cas-là, l'indicateur de réussite de l'expérience était le recall et la précision des modèles par rapport au modèle global qui existe déjà. Nous avions défini un seuil minimal qui permettrait de valider l'hypothèse de l'expérimentation. Si celui-ci était atteint, nous procéderions au déploiement de ce modèle dans les usines en question.

4. … ainsi que les anticiper et les intégrer dans le flux de travail pour éviter les mauvaises surprises

Puisque l’on part du principe qu’il est crucial pour un produit de ML d’expérimenter afin de maximiser la valeur produite, il faut lui permettre de s’intégrer au flux de travail non pas comme un sujet “en plus” à traiter sur un coin de table; mais bien comme une tâche à part entière.

Comment intégrer ces tâches dans le flux de travail ?

Le spike est un véritable atout lorsqu’il s’agit de planifier ces travaux. En tant que PBI (product backlog item) au même titre qu’une user story, il est cadré et priorisé selon une valeur métier attendue; en revanche sa différence réside dans le fait qu’il soit limité dans le temps et que son objet soit de l’innovation.

Le sujet de cette innovation et son cadrage doivent, comme énoncé plus haut, se baser sur une réalité terrain et tenter d’y apporter une réponse. Pour ce qui est du temps à y allouer et de sa priorisation, elle va se faire selon deux axes : la valeur métier attendue ainsi que le temps de développement supposé nécessaire pour atteindre cette valeur métier. Une note de valeur peut donc être allouée à chaque spike, ce qui permet d’évaluer, en fonction de critères fixés par l’équipe, si le temps à investir est réaliste par rapport à la valeur attendue et ainsi orienter soit vers une ré-estimation du temps à y consacrer soit à la dé-priorisation du sujet.

Lorsqu’un spike est embarqué, à la fin du temps alloué, le ou les membres de l’équipe ayant travaillé sur le sujet présentent leurs conclusions au reste de l’équipe avec une suggestion pour la suite : stop ou encore ? Ainsi une décision collégiale (PO / tech) peut être prise : continuer à investir du temps sur le sujet en créant les tickets associés si l’expérimentation est concluante et qui rejoindront donc le flux de travail habituel ou arrêter les travaux si elle ne l’est pas.

Ainsi un spike peut donner lieu à un ou des nouveaux spikes pour valider ou invalider les hypothèses suivantes et qui devront évidemment suivre les mêmes règles que les précédents. Ou bien, si l’expérimentation est fructueuse, elle peut donner lieu à une réintégration du sujet à la roadmap, avec les tickets afférents prévus dans le flux de développement. Ou encore, ne pas donner de suite si cela n’est pas nécessaire.

Cycles expérimentation / développement (inspiré de (Agile France) Danse avec les unicorns : la data science en agile, de l’exploration à l’adoption

Quel avantage tire-t-on de cette intégration ?

Grâce à ces spikes on peut également sensibiliser les autres parties prenantes un peu plus éloignées de la réalité du produit, souvent plus frileux sur ce genre de sujet, (un client, un directeur de projet …) à l’expérimentation : ils sont prévus, cadrés et ne perturbent pas le flux, on peut donc se concentrer sur le fond du sujet lorsqu’ils sont abordés et c’est au PO d’en comprendre suffisamment bien  la valeur et la faisabilité pour pouvoir les défendre. C’est d’ailleurs une différence majeure entre un PO sur un delivery “classique” et un produit ML : il a un véritable rôle d’acculturation et doit se mettre en position de comprendre les tenants et les aboutissants de chaque ticket du backlog et plus particulièrement de ces sujets d’expérimentation afin d’être en mesure d’en expliciter la valeur auprès d’un public moins averti mais néanmoins décideur. Il devient ainsi le garant de l’autonomie de l’équipe sur le sujet, critère de succès maintes fois évoqué par Accelerate.

Et l'équipe tech dans tout ça ?

Enfin, l’équipe tech comme le PO doivent porter une attention toute particulière au basculement entre les deux mindsets : build et expérimentation. On l’a vu plus haut avec la représentation des cycles expérimentation développement : les deux sont liés et associés au sein des mêmes cycles, il est donc facile de tomber dans certains travers : d'un côté, utiliser directement du code exploratoire en production et s'appuyer sur des outils d'exploration (type Jupyter Notebook) pour écrire du code de production, d'un autre côté, essayer de parfaire le code exploratoire dont on ne connaît même pas la finalité, ce qui peut faire perdre un temps précieux. En effet, le basculement continu entre les deux mindsets dont on parle ci-dessus n'est pas anodin et devrait, s'il est maîtrisé, servir à tirer le plus de valeur possible des expérimentations. Idéalement, à l'issue de la phase exploratoire, le data scientist extrairait les bouts de code qui seraient réutilisables dans d'autres expérimentations ou pour de l'industrialisation, ce qui accélérerait sensiblement ses prochaines expérimentations ou mises en production.

5- Et finalement suivre les expérimentations, les visualiser et les partager

Puisqu’une expérimentation doit être limitée et notamment dans le temps, afin d’éviter l’effet tunnel on peut légitimement se demander : que se passe-t-il une fois ce temps écoulé ? Le principe du spike veut qu’à la fin du temps imparti l’équipe se réunisse autour des conclusions de ceux qui ont mené l’expérimentation pour prendre une décision de stop ou encore. Mais comment présenter ces conclusions au mieux afin de permettre à tous les membres de l’équipe tech mais aussi non tech de prendre la décision de façon éclairée ? L’idée est que, dans la mesure du possible, on ne montre pas des bouts de code mais on essaye de faire une démonstration de ce qui a été réalisé; ainsi on ne montre pas un bout de code qui permet d’automatiser un ré-entraînement, mais on montre comment on lance une pipeline de réentraînement sur AzureDevOps avec toutes les étapes qui se déclenchent seules, on ne montre pas un bout de code qui permet d’ajouter une variable pour créer un dataset d'entraînement, on montre comment et quel script on peut lancer pour réaliser cette action et où le dataset se situe une fois le script exécuté etc.

Exemple issu du projet Alpha : on ne montre pas du code mais on montre des pipelines qui démontrent le résultat de l’expérimentation

Grâce à cette visualisation, on permet à tous de se projeter dans le résultat potentiel et ainsi la prise d’une réelle décision collégiale : tous sont concentrés sur l’apport de valeur et non pas sur un bout de code qui hypothétiquement fonctionne. Aussi, et parce que l’équipe n’est pas toujours la seule à vouloir suivre ses expérimentations, pouvoir les démontrer de façon intelligible permet à tous, même en dehors de l’équipe, de pouvoir en saisir la portée.

Cette capitalisation et ce partage dans le cadre de ces expérimentations est clé : elle permet de créer des synergies entre les équipes et de maximiser le temps investi sur ces expérimentations. Ainsi, en plus de s’attacher à rendre ces résultats visibles pour tous, il faut également créer les espaces de partage nécessaires : des communautés de pratiques, qu’elles soient orientées produit ou tech, des BBL - formats courts de présentation sur l’heure du déjeuner, un mail envoyé à tous etc.

On pourrait également aller encore plus loin que les seuls résultats visibles et tenter d’accoler des métriques à cette expérimentation (ex: un réentrainement qui prenait 3 jours en prend maintenant 1).

Finalement, voici ce qu’on en retient :

→ Qu’elles réussissent ou qu’elles échouent, il y a toujours un apprentissage

→ Lorsqu’elles sont issues d’une réalité terrain, qu’elles soient orientées utilisateurs ou équipe, on maximise leurs chances de succès

→ Expérimenter mais pas sans condition : dans un cadre de temps et d’objet défini

→ Régulièrement basculer entre expérimentation et build, extraire ce qui est réutilisable pour accélérer judicieusement les mises en production et les expérimentations à venir

→ Laisser de la place dans la roadmap pour les expérimentations, notamment à travers les spikes

→ Le PO a un rôle déterminant dans le fait de faire comprendre à l’écosystème l’importance de ces expérimentations et devient ainsi le garant de l’autonomie de l’équipe sur le sujet

→ Il faut les rendre visibles pour : capitaliser,  démontrer leur intérêt et pouvoir décider de façon collégiale si on les intègre ou non comme sujet à part entière dans la roadmap