Se connecter à une instance de calcul Azure ML depuis Visual Studio Code

Dans un précédent article, nous explorions la procédure pour lancer simplement du code sur des machines distantes Azure ML (compute target) depuis l’environnement de développement (IDE) Visual Studio Code.

Dans les raccourcis disponibles au niveau du menu des instances de calcul, nous disposons dorénavant d’un lien permettant de lancer l’ouverture de Visual Studio Code.

Quel est l’avantage de travailler de la sorte ? Réponse : vous disposez de toute la puissance de l’IDE de Microsoft (en particulier pour les commandes Git), sans toutefois être dépendant de votre poste local.

Vous ne pouvez bien sûr utiliser qu’une instance qui vous est personnellement assignée.

Cliquez sur le lien VS Code et votre navigateur lèvera tout d’abord une alerte. Cochez la case “Toujours autoriser…” pour ne plus voir cette pop-up.

C’est maintenant au tour de VSC de faire une demande d’autorisation avant de lancer la connexion à distance.

En tâche de fond, nous assistons à l’installation d’un VS Code server sur l’instance de calcul.

Il ne reste plus qu’à “faire confiance” aux fichiers qui seront maintenant accessible depuis l’éditeur local.

Plusieurs alertes peuvent être levées par VS Code selon votre paramétrage. Ainsi, il faudra choisir un interpréteur Python (mais attention, ce n’est pas une distribution installée sur votre poste local !) ainsi que s’authentifier vis à vis de l’extension Azure pour VS Code (à installer également au préalable).

Si le choix entre Python2 et Python3 ne fait plus débat, le choix de la version mineure de Python est important pour votre projet, car celle-ci conditionne les versions de packages nécessaires par la suite.

Le réflexe pourrait alors être de choisir l’interpréteur Python du poste local mais nous voulons justement exécuter le code à distance. Une sélection dans la fenêtre ci-dessous n’est donc pas nécessaire.

Etape à ne PAS réaliser

Allons plutôt voir dans le coin en bas à droite de notre éditeur.

Un clic sur “Jupyter Server” va lancer un autre menu : “Pick how to connect to Jupyter“.

Nous choisissons ici “Azure ML Compute Instances” puis naviguons jusqu’à l’instance voulue. Un message d’alerte concernant la facturation de cette VM va alors apparaître.

Un rechargement de VS Code pourra être nécessaire pour bien valider la connexion.

Le statut en bas à droite de l’IDE nous indique que le serveur Jupyter se trouve bien à distance (remote) et c’est donc lui qui exécutera le code.

Commençons par un commande simple dans un nouveau notebook.

Il est maintenant temps de choisir l’interpréteur Python de la machine distante (cliquer si besoin sur le bouton “sélectionner le noyau”).

Nous choisissons ici l’environnement Python 3.8, muni des packages azureml, qui nous permettront d’interagir avec le service Azure Machine Learning.

Vérification de la version du package azureml-core

Utiliser les commandes Git de VSC

C’est sans doute le plus grand des avantages à passer par l’IDE : pouvoir réaliser du contrôle de code source, avec les fonctionnalités Git intégrées dans VSC.

En cliquant sur le symbole Git du menu du gauche, nous déroulons une première fenêtre demandant de réaliser l’initialisation du repository.

Il est ensuite nécessaire de configurer le nom de l’utilisation ainsi que son adresse de courrier électronique.

Les changements (ici, tous les fichiers lors de l’initialisation) sont détectés par Git et il sera possible de les pousser (git push) sur le repository.

En cliquant ici sur Push, une alerte sera levée car une dernière configuration est nécessaire.

Il faut configurer l’URL du repository, par exemple une adresse GitHub.

Ceci se réalise au moyen de la commande ci-dessous, sur la branche principale (main).

git push --set-upstream <origin_branch> main

Ca y est ! Nous disposons maintenant d’une configuration très efficace pour travailler nos développements de Machine Learning, en lien avec le service Azure ML. Ce système permet également une véritable isolation des fichiers pour chaque développeur. Aucun risque qu’un.e collègue vienne modifier vos scripts, autrement qu’au travers d’un merge de branches.

Interagir avec Azure ML depuis Visual Studio Code

Travailler avec une ressource Azure Machine Learning peut se faire de plusieurs façons : approche “no code” depuis le Concepteur, Automated ML ou encore par scripts R ou Python exploitant le SDK azureml qui permet d’interagir avec tous les composants du studio.

C’est bien sûr cette dernière approche “full code” que nous allons privilégier. Il est possible de lancer les notebooks natifs du studio mais ceux-ci ne donnent pas à ce jour (avril 2021) la même expérience que les notebooks Jupyter. Nous pouvons alors créer une instance de calcul qui se déploiera avec un serveur JupyterLab (ainsi que RStudio qu’il n’est pas impossible dans l’absolu d’utiliser… avec Python !).

Plusieurs limites apparaissent alors pour un usage professionnel, c’est-à-dire vérifiant un niveau de sécurité au travers de l’isolement des développements, de leur versionning et de leur déploiement en production. Si les instances de calcul sont personnelles (attribuées à un et un seul utilisateur, nominativement), les scripts enregistrés sont visibles par toutes les personnes disposant d’une ressource. De plus, il n’y a pas (à ce jour) de possibilité de lier les notebooks et autres fichiers à un dépôt (repository) de type Git. Enfin, si l’on pousse la réflexion sur le passage à l’échelle, il faudra envisager d’exécuter les scripts sur un cluster de calcul plutôt que sur l’instance de calcul elle-même.

Nous allons répondre à toutes ces problématiques par l’utilisation de l’IDE de Microsoft : Visual Studio Code. Au préalable, il faudra installer les extensions suivantes :

  • Python
  • Jupyter
  • Azure Account
  • Azure Machine Learning

En appuyant sur F1, nous pouvons nous authentifier sur Azure.

L’icône Azure donne alors la visibilité des ressources Azure Machine Learning et de tous les éléments qui les composent.

Nous souhaiterons en particulier utiliser un “compute cluster” pour exécuter un script Python. Nous allons pour cela créer un notebook d’interaction avec Azure Machine Learning qui pilotera l’exécution du script.

Pour assurer la gestion “Git” de nos fichiers, nous avons maintenant tous les outils à disposition. Il suffira d’utiliser les fonctions intégrées, par le menu ou en lignes de code, ce que nous développerons dans un autre article.

Les notebooks sont “suspects” pour VSC et il faudra déclarer qu’ils sont fiables (“trust“) à chaque ouverture. Pour simplifier ce processus, il est possible de modifier les paramètres pour accepter par défaut tous les notebooks.

Nous allons utiliser un serveur local Jupyter pour exécuter le code Python (et c’est une source d’économies !).

Les librairies spécifiques à Azure Machine Learning doivent bien sûr être installées dans cet environnement local.

!python -m pip install azureml-sdk --upgrade --user
!python -m pip install azureml-core --upgrade --user

Le package azureml-core évolue souvent, pensez à le mettre régulièrement à jour car les composants du studio Azure ML évolueront automatiquement.

Il faut maintenant nous authentifier vis à vis de ce service. Les informations nécessaires sont accessibles dans le fichier “config.json” téléchargeable depuis le portail Azure.

Nous donnons ces informations dans le code ci-dessous.

A l’exécution du code, une fenêtre va s’ouvrir dans un navigateur demandant de s’authentifier avec le compte Azure autorisé sur la ressource Azure ML. Une fois cette opération réalisée, la cellule du notebook est validée.

Ceci ne sera bien sûr pas envisageable dans une scénario tout automatisé et nous privilégierons alors l’authentification au travers d’un principal de service.

Nous pouvons vérifier la bonne connexion à la ressource avec l’instruction suivante :

print(ws.name, ws.location, ws.resource_group, ws.location, sep='\t')

Nous allons maintenant mettre en place les éléments qui permettront d’exécuter un script Python.

Ce schéma décrit le fonctionnement global :

  • VSC lance l’exécution (run) d’un script Python
  • exécuté sur un cluster de calcul
  • accompagné d’un environnement (les dépendances de packages)
  • loggé dans une expérience

Les éléments de script ci-dessous ont été piochés dans différents tutoriels disponibles sur le Web. Nous commençons par la cellule qui déclarer le cluster de calcul ou bien le crée à la volée s’il n’existe pas de cluster nommé de la sorte.

Les packages nécessaires au script Python sont déclarés dans un environnement.

Notez la dernière commande qui permet de sauvegarder cet environnement dans un fichier YAML.

env.python.conda_dependencies.save_to_file(".", "my_remote_env.yml")

Il sera alors possible de réutiliser directement ce fichier pour définir de nouveaux environnements. Voici son contenu.

Enfin, l’expérience s’instancie tout simplement, en relation avec l’espace de travail Azure ML.

Le script Python peut être écrit dans une cellule du notebook. Il pourra alors être donné en paramètre de l’objet ScriptRunConfig.

A l’intérieur du script Python, il sera certainement utile de retrouver la référence à l’exécution réalisée au sein de l’espace de travail. Ceci se fait en enchainant ces trois lignes de code, précédées de l’import de la librairie azureml-core.

from azureml.core.run import Run


run = Run.get_context()
exp = run.experiment
ws = run.experiment.workspace

La soumission du script au sein de l’expérience se fait alors par la commande ci-dessous.

run = exp.submit(config=src, tags=runtags)

Nous pouvons dès lors suivre l’évolution dans le studio Azure ML.

A noter que les widgets qui permettent de suivre l’exécution dans un notebook semblent ne pas être compatibles avec VSC.

Mais ce n’est là qu’un détail au regard de ce que nous gagnons à utiliser VSC : versionning du code, approche DevOps, diminution des coûts de développement.

Le notebook utilisé dans cet article est disponible sur ce repository.

Utiliser (encore) des notebooks sous Azure

Au 15 janvier 2021, le service Azure Notebooks disparaît complètement. Nous cherchons donc une alternative en version SaaS, toujours sur Azure et celle-ci se trouve dans le portail Azure Machine Learning.

Un article d’introduction à ce service est disponible dans les archives de ce blog.

Quelques nouveautés sont disponibles et annoncées à l’ouverture d’un premier notebook. Nous reviendrons sur ces nouveautés dans la suite de cet article.

Nous pouvons alors nommer un nouveau fichier, à l’extension classique .ipynb.

Nous retrouvons ce qui caractérise les notebooks : des cellules de code, suivies par les sorties des différentes instructions, ou bien des cellules de type formaté en Markdown.

Il n’est pourtant pas possible d’exécuter du code immédiatement, il faut au préalable relier ce notebook à une instance de calcul, déjà définie dans le portail (menu “Compute”).

Dans le menu dédié aux ressources de calcul, nous retrouvons des raccourcis vers l’utilisation d’une interface Jupyter, JupyterLab ou encore RStudio.

La nécessité d’une instance de calcul rend ce service payant, et facturé au temps d’utilisation de la machine virtuelle définie. Il sera très important de ne pas oublier d’éteindre la machine après utilisation, il n’existe à ce jour aucun système natif d’extinction planifiée !

Les utilisateurs férus de Visual Studio Code (VSC) peuvent travailler à distance avec l’environnement de calcul d’Azure Machine Learning. En installant conjointement les extensions Python et Jupyter, il était déjà possible de travailler avec un notebook (fichier reconnu par son extension .ipynb) dans l’IDE de Microsoft. En ajoutant l’extension Azure Machine Learning, nous pouvons nous connecter à la ressource Azure.

Les “objets” de l’espace Azure ML sont alors visibles depuis le menu Azure de VSC.

Il est possible de réaliser des actions à distance sur les instances de calcul.

Par défaut, un notebook dans VSC utilise le serveur Jupyter local. Mais il est possible de désigner un serveur à distance (“remote“) en cliquant sur le bouton en haut à droite indiquant “Jupyter Server : local”.

Nous obtenons la boîte de dialogues ci-dessous.

La succession de choix proposés permettra d’associer le notebook à une instance de calcul Azure ML.

Une composante indispensable de l’approche par le code est le gestion du versionnig, par un service compatible avec Git (GitHub, GitLab, Bitbucket, Azure DevOps, etc.), comme décrit sur ce lien.

Nous allons bénéficier ici de l’affichage en terminal présentés parmi les nouvelles (janvier 2021) fonctionnalités disponibles.

Nous devons tout d’abord créer une clé SSH au moyen de la commande ci-dessous :

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

La clé SSH doit être enregistrée dans le chemin /home/azureuser/.ssh qui est spécifique à l’instance de calcul (valider par Entrée le prompt proposé après la commande précédente). Il est alors possible de saisir une passphrase, facultative mais fortement conseillée. Un fichier id_rsa.pub est ainsi créé et son contenu peut être copié (ctrl + inser).

Nous utiliserons dans cet article Azure DevOps, où nous allons pouvoir saisir cette clé publique.

De retour dans le terminal, nous pouvons lancer la commande de test :

ssh -T git@ssh.dev.azure.com

Le résultat attendu est le suivant :

Depuis le repository Azure DevOps, nous obtenons la syntaxe SSH qui viendra compléter une instruction git remote, lancée depuis le terminal.

Si cela n’a pas fait, dans le terminal et depuis le chemin voulu, saisir la commande git init pour initialiser le répertoire. Définir également l’utilisateur qui réalisera les instructions de commit :

git config --global user.email "you@example.com"
git config --global user.name "Your Name"

La commande git remote add origin peut alors être exécutée avec succès.

Il pourra être nécessaire de passer la commande git add . pour ajouter l’intégralité du contenu dans ce qui doit être géré par git, puis un git commit.

De même, le repository Azure doit avoir été initialisé, par exemple avec un fichier readme.md et disposer ainsi d’une branche (main ou master).

git push -u origin --all

Enfin, un rappel des commandes Git indispensables est donné ici : Git · GitHub

Une autre nouvelle intéressante consiste à “nettoyer” le notebook avant de le publier. C’est en effet un reproche souvent fait aux notebooks : ceux-ci mélangent code, sorties et commentaires et ne sont pas optimaux pour les tests unitaires et le déploiement dans un environnement de production.

La fonctionnalité “Gather” (documentation officielle) sur une cellule permet de créer un autre notebook qui conservera uniquement les cellules de code dépendant de la cellule sélectionnée.