WIKI
AI-300 Machine Learning Operations Engineer

03 · Orchestrer l'entraînement des modèles dans Azure Machine Learning

26 min de lecture Mis à jour le 21 octobre 2026
Sur cette page

Version : 1.1 · Date : 2026-10-21 · Domaine 2 de l'examen : Implement machine learning model lifecycle and operations (25 à 30 %)

En une phrase : dans Azure Machine Learning, tout entraînement est un job (un script, un environment, un compute) ; MLflow trace ses métriques sans configuration, le sweep job et AutoML cherchent les meilleurs réglages, le distributed training répartit le travail sur plusieurs GPU et plusieurs nœuds, et le pipeline enchaîne le tout de façon reproductible.

Entraîner dans Azure Machine Learning : du notebook au meilleur modèle

Ce que l'examen demande#

Bloc Orchestrate model training du guide d'étude AI-300 :

# Compétence mesurée (guide officiel, en anglais) Section
1 Configure experiment tracking with MLflow 2
2 Use automated machine learning to explore optimal models 6
3 Use notebooks for experimentation and exploration 3
4 Automate hyperparameter tuning 5
5 Run model training scripts 4
6 Manage distributed training for large and deep learning models 7
7 Implement training pipelines 8
8 Compare model performance across jobs 9

Le workspace, les compute targets, les environments, les components et les registries sont détaillés au chapitre 01 ; l'automatisation par GitHub Actions au chapitre 02 ; l'enregistrement et le déploiement du modèle obtenu au chapitre 04. Les besoins propres aux LLM (fine-tuning, choix et dimensionnement GPU) sont aux chapitres 07 et 08.


1. Les bases à maîtriser#

1.1 Le vocabulaire ML minimal pour un architecte#

Terme En clair
Modèle Une fonction apprise à partir d'exemples : elle reçoit des entrées (features) et produit une prédiction
Entraînement Ajuster les paramètres du modèle (les poids d'un réseau de neurones) pour réduire l'erreur sur les données d'entraînement
Hyperparamètre Un réglage choisi avant l'entraînement et non appris : learning rate, batch size, nombre de couches, nombre d'arbres
Epoch / batch Un epoch = un passage complet sur les données ; un batch = le paquet d'exemples traité à chaque pas
Métrique La note du modèle : accuracy, AUC (classification), RMSE, R² (régression), loss pendant l'entraînement
Validation, test Données mises de côté pour mesurer le modèle sur des exemples qu'il n'a pas vus pendant l'entraînement
Surapprentissage (overfitting) Le modèle « apprend par cœur » : excellent sur l'entraînement, mauvais sur la validation. On le voit quand les deux courbes de loss divergent
Deep learning Réseaux de neurones profonds ; très gourmands en calcul, d'où les GPU et le distributed training

1.2 Les objets d'Azure Machine Learning pour entraîner#

Objet Rôle Détail
Job L'unité d'exécution : un script lancé dans un environment sur un compute Types : command, sweep, automl, pipeline (et spark, parallel)
Experiment Le dossier qui regroupe les jobs d'un même sujet experiment_name dans le YAML ou le SDK
Environment Image Docker + dépendances Python Curated environments fournis (ex. ACPT, Azure Container for PyTorch) ou personnalisés (chapitre 01)
Compute Où le job tourne Compute instance (poste de travail), compute cluster, serverless compute, Kubernetes attaché
Data asset, datastore Les données en entrée et en sortie Types d'entrée uri_file, uri_folder, mltable
Component Une étape réutilisable et versionnée Brique des pipelines

Important pour l'examen : le SDK Python v2 (azure-ai-ml) et la CLI v2 (az ml) n'ont aucune fonction de logging : on trace avec MLflow. Les anciennes API du SDK v1 (Run.log) ne sont plus la réponse.

flowchart TD
    A["Besoin d'entraînement"] --> B{"J'explore ou j'industrialise ?"}
    B -- "J'explore" --> N["Notebook sur compute instance"]
    B -- "J'industrialise" --> C{"Je connais l'algorithme ?"}
    C -- "Non, données tabulaires, vision ou NLP" --> AU["AutoML job"]
    C -- "Oui" --> D{"Réglages à chercher ?"}
    D -- "Oui" --> S["Sweep job autour d'un command job"]
    D -- "Non" --> E{"Un seul GPU suffit ?"}
    E -- "Oui" --> CJ["Command job"]
    E -- "Non" --> DT["Command job + distribution PyTorch, DeepSpeed, TensorFlow ou MPI"]
    AU --> P["Pipeline job pour enchaîner préparation, entraînement, évaluation"]
    S --> P
    CJ --> P
    DT --> P

2. Configurer l'experiment tracking avec MLflow#

2.1 Ce qui est automatique#

Un workspace Azure Machine Learning est un serveur MLflow : il a sa propre tracking URI (azureml://…). Dans un notebook sur compute instance ou dans un job sur compute cluster ou serverless, la tracking URI est déjà configurée : on écrit du MLflow standard, rien d'autre.

Contexte À faire
Job Azure Machine Learning Rien : mlflow.start_run() est même inutile, le run est démarré automatiquement
Notebook sur compute instance mlflow.set_experiment(), puis start_run() / end_run() (ou un bloc with)
Poste local, Azure Databricks, Azure Synapse pip install mlflow azureml-mlflow, puis mlflow.set_tracking_uri(<tracking URI du workspace>) et une authentification

Récupérer la tracking URI :

az ml workspace show --query mlflow_tracking_uri
from azure.ai.ml import MLClient
from azure.identity import DefaultAzureCredential

ml_client = MLClient.from_config(credential=DefaultAzureCredential())
uri = ml_client.workspaces.get(ml_client.workspace_name).mlflow_tracking_uri

Piège : avec un workspace en private link, la tracking URI a un format différent ; ne pas la construire à la main, la lire par le SDK ou la CLI.

2.2 Ce qu'on trace#

import mlflow

mlflow.autolog()                                    # paramètres, métriques et modèle capturés selon le framework (scikit-learn, PyTorch…)

mlflow.log_param("num_epochs", 20)                  # un paramètre
mlflow.log_params({"dropout_rate": 0.6, "objective": "binary_crossentropy"})
mlflow.log_metric("val_accuracy", 0.91)             # une métrique ; loggée plusieurs fois = une courbe
mlflow.log_artifact("confusion_matrix.png")         # un fichier
  • mlflow.autolog(log_models=False) trace tout sauf le modèle, si on veut l'enregistrer soi-même.
  • run.data.metrics ne rend que la dernière valeur d'une métrique ; la courbe complète s'obtient avec MlflowClient().get_metric_history().
  • Le nom de l'experiment se fixe dans le job (experiment_name) : inutile de l'écrire dans le script.

2.3 Les droits#

Les rôles intégrés AzureML Data Scientist et Contributor permettent le tracking et le registry MLflow. Pour un rôle personnalisé : Microsoft.MachineLearningServices/workspaces/experiments/* et …/jobs/* pour le tracking, …/models/*/* pour le model registry. Hors d'Azure, pour un traitement sans utilisateur (CI, Databricks), MLflow s'authentifie avec un service principal par les variables AZURE_TENANT_ID, AZURE_CLIENT_ID et AZURE_CLIENT_SECRET (secret rangé dans Key Vault, jamais en clair) ou un certificat.


3. Explorer dans des notebooks#

Élément À retenir
Compute instance Poste de travail géré, mono-nœud, propre à son créateur (seul lui l'utilise) ; Jupyter, JupyterLab, VS Code (web ou desktop), drivers CUDA, cuDNN, NCCL, Intel MPI préinstallés
Fichiers Les User files sont stockés à part de la VM et partagés entre les compute instances du workspace
Paquets %pip ou %conda (installe dans le kernel courant), pas !pip
Coûts Idle shutdown (inactivité de 15 minutes à 3 jours) ou schedule de démarrage / arrêt. Arrêtée, l'instance ne facture plus le calcul mais toujours le disque, l'IP publique et le load balancer
Sécurité No public IP, réseau virtuel, Azure Policy pour interdire SSH ou imposer un VNet (chapitre 02)
Pas de Spot Les VM Spot / basse priorité ne sont pas possibles pour une compute instance (usage interactif)

Piège : si le workspace a une managed identity, la compute instance ne s'arrête par inactivité que si cette identité a le rôle Contributor sur le workspace.

Interactive jobs : pour déboguer dans le conteneur du job lui-même (y compris un job distribué sur un compute cluster), on ajoute des training applications au job : JupyterLab, VS Code, TensorBoard ou SSH (JupyterLabJobService, VsCodeJobService, TensorBoardJobService, SshJobService). On garde le nœud avec sleep 1h en fin de commande (sleep infinity oblige à annuler le job à la main pour arrêter la facturation). Seul le propriétaire du job accède aux applications, sur le nœud choisi (--node-index) :

az ml job show-services --name <job> --node-index 0
az ml job connect-ssh --name <job> --node-index 0 --private-key-file-path ~/.ssh/id_rsa

Limites : distribution PyTorch, TensorFlow ou MPI seulement ; VS Code et le débogueur (debugpy) ne marchent pas avec un workspace en private link.


4. Exécuter un script d'entraînement avec un command job#

Anatomie d'un command job

Le command job est la brique de base : le code est téléversé comme snapshot, l'environment fournit les dépendances, le compute fournit la machine, les ${{inputs.x}} sont remplacés au lancement.

# job.yml : command job sur un compute cluster GPU
$schema: https://azuremlschemas.azureedge.net/latest/commandJob.schema.json
code: src
command: >-
  python train.py --data ${{inputs.training_data}} --epochs ${{inputs.epochs}} --lr ${{inputs.learning_rate}}
inputs:
  training_data:
    type: uri_folder
    path: azureml:credit-data:1          # data asset versionné
  epochs: 10
  learning_rate: 0.01
outputs:
  model_output:
    type: uri_folder
environment: azureml:AzureML-acpt-pytorch-2.8-cuda12.6@latest
compute: azureml:gpu-cluster
experiment_name: credit-training
display_name: credit-train-baseline
run_id=$(az ml job create -f job.yml --query name -o tsv)   # soumet le job
az ml job show -n $run_id --web                             # ouvre le job dans le studio
az ml job stream -n $run_id                                 # suit les logs

Équivalent Python :

from azure.ai.ml import MLClient, command, Input
from azure.identity import DefaultAzureCredential

ml_client = MLClient.from_config(credential=DefaultAzureCredential())

job = command(
    code="./src",
    command="python train.py --data ${{inputs.training_data}} --lr ${{inputs.learning_rate}}",
    inputs={"training_data": Input(type="uri_folder", path="azureml:credit-data:1"), "learning_rate": 0.01},
    environment="azureml:AzureML-acpt-pytorch-2.8-cuda12.6@latest",
    compute="gpu-cluster",              # omis = serverless compute
    experiment_name="credit-training",
)
returned_job = ml_client.jobs.create_or_update(job)
print(returned_job.services["Studio"].endpoint)     # lien vers le job dans le studio

4.1 Serverless compute#

Sans compute, un command, sweep ou AutoML job part sur serverless compute : Azure Machine Learning crée, dimensionne et supprime le calcul. Par défaut : un nœud, une VM CPU choisie selon le quota, le coût et la taille de disque, VM dédiées, région du workspace. On précise ce qu'il faut avec resources et queue_settings :

resources:
  instance_type: Standard_NC24ads_A100_v4   # VM GPU voulue
  instance_count: 2                          # nombre de nœuds
queue_settings:
  job_tier: Spot                             # Standard (dédié, défaut) ou Spot
identity:
  type: user_identity                        # ou managed (managed identity du compute)
Point Ce qu'il faut savoir
Quota Serverless consomme le même quota que les compute clusters ; un serverless évite l'échec « quota insuffisant » en choisissant une taille disponible
Attente Pas d'attente de scale-down ni de file derrière un autre job du même cluster
Pipelines default_compute: azureml:serverless (CLI) ou default_compute="serverless" (SDK)
Réseau Utilise l'isolation réseau managée du workspace
Low-priority Les VM low-priority sont retirées depuis le 31/03/2026 : un cluster tier: low_priority tourne désormais en Spot (tarif Spot variable, éviction possible)

4.2 Lire les logs#

Studio > Jobs > le job > Outputs + logs : user_logs/std_log.txt contient les print, stdout et stderr de chaque processus (un fichier par processus dans un job distribué) ; system_logs contient les journaux de la plateforme (préparation, interactive capability…).


5. Automatiser le hyperparameter tuning avec un sweep job#

Sweep job : tester des hyperparamètres et couper les mauvais essais tôt

Un sweep job (classe SweepJob) lance de nombreux trials, chacun étant le même command job avec d'autres hyperparamètres.

Réglage Options
Search space Discret : Choice (liste, range), QUniform, QLogUniform, QNormal, QLogNormal ; continu : Uniform, LogUniform, Normal, LogNormal
Sampling Grid : toutes les combinaisons, Choice uniquement ; Random (option rule="sobol" quasi aléatoire, avec seed) : discret et continu ; Bayesian : s'appuie sur les essais précédents, accepte choice, uniform, quniform
Objectif primary_metric (nom exactement égal à celui loggé par MLflow) et goal : maximize ou minimize
Early termination Bandit (slack_factor ratio ou slack_amount absolu), Median stopping, Truncation selection (truncation_percentage 1 à 99), aucune par défaut ; paramètres evaluation_interval et delay_evaluation
Limits max_total_trials (1 à 1 000), max_concurrent_trials, timeout du sweep, trial_timeout par trial ; le premier seuil atteint arrête tout
from azure.ai.ml.sweep import Choice, Uniform, MedianStoppingPolicy

command_job_for_sweep = job(                       # le command job devient une fonction : on remplace des inputs
    learning_rate=Uniform(min_value=0.001, max_value=0.1),
    batch_size=Choice(values=[16, 32, 64]),
)
sweep_job = command_job_for_sweep.sweep(
    compute="gpu-cluster",
    sampling_algorithm="bayesian",
    primary_metric="val_accuracy",                 # le script fait mlflow.log_metric("val_accuracy", ...)
    goal="maximize",
)
sweep_job.set_limits(max_total_trials=40, max_concurrent_trials=4, timeout=7200)   # bayesian : >= 20 x nb d'hyperparamètres
sweep_job.early_termination = MedianStoppingPolicy(delay_evaluation=5, evaluation_interval=1)
returned = ml_client.create_or_update(sweep_job)

À retenir sur les policies :

  • Bandit : avec slack_factor=0.2 et un meilleur trial à 0,8 (objectif maximiser), tout trial sous 0,8 / 1,2 = 0,66 est arrêté à l'intervalle évalué.
  • Median stopping (evaluation_interval=1, delay_evaluation=5) : réglage prudent, environ 25 à 35 % d'économie sans perte sur la métrique selon Microsoft.
  • Bandit avec peu de marge ou Truncation avec un fort pourcentage : économies plus agressives.
  • Bayesian : moins de trials en parallèle donne une meilleure convergence (chaque essai profite des précédents).

Le meilleur trial se récupère avec az ml job download --name <sweep> --output-name model ; le studio affiche le Parallel Coordinates Chart et les nuages de points 2D / 3D. Chaque trial repart de zéro (modèle et data loaders reconstruits) : préparer les données une fois en amont, dans une étape de pipeline.


6. Explorer les modèles avec AutoML#

AutoML : Azure Machine Learning choisit l'algorithme et ses hyperparamètres

AutoML essaie des algorithmes et des hyperparamètres à votre place et rend un modèle prêt à déployer.

Point À retenir
Tâches Tabulaire : classification, regression, forecasting ; vision : image classification, object detection ; NLP : text classification, entity recognition
Données MLTable obligatoire en SDK / CLI v2 (fichier MLTable décrivant le format) ; target_column_name
Validation par défaut > 20 000 lignes : 10 % mis de côté ; 1 000 à 20 000 lignes : 3 folds ; < 1 000 lignes : 10 folds ; sinon validation_data ou n_cross_validations
primary_metric Classification : accuracy, AUC_weighted (meilleur choix si classes déséquilibrées), norm_macro_recall… ; régression : r2_score, normalized_root_mean_squared_error, normalized_mean_absolute_error, spearman_correlation
Featurization auto (défaut), custom (imputer, types de colonnes, transformers bloqués), off ; elle fait partie du modèle et s'applique aussi en prédiction
set_limits timeout_minutes (défaut 6 jours), trial_timeout_minutes, max_trials (défaut 1 000), max_concurrent_trials, enable_early_termination
set_training allowed_training_algorithms / blocked_training_algorithms, ensembles (vote, stack), modèles compatibles ONNX
Compute Compute cluster, compute instance (concurrence = nombre de cœurs) ou serverless ; vision et NLP prennent une VM GPU automatiquement
from azure.ai.ml import automl, Input
from azure.ai.ml.constants import AssetTypes

classification_job = automl.classification(
    compute="cpu-cluster",
    experiment_name="churn-automl",
    training_data=Input(type=AssetTypes.MLTABLE, path="./data/training-mltable-folder"),
    target_column_name="churn",
    primary_metric="AUC_weighted",          # classes déséquilibrées
    n_cross_validations=5,
    enable_model_explainability=True,
)
classification_job.set_limits(timeout_minutes=120, trial_timeout_minutes=20, max_trials=30,
                              max_concurrent_trials=4, enable_early_termination=True)
classification_job.set_training(blocked_training_algorithms=["logistic_regression"])
returned = ml_client.jobs.create_or_update(classification_job)

Grandes volumétries : AutoML distribué pour LightGBM (classification, régression, jusqu'à environ 1 To, training_mode=distributed, max_nodes ≥ 4, trials séquentiels) et TCNForecaster (forecasting, environ 200 Go). Pas de cross-validation, d'ensembles, d'ONNX ni de génération de code dans ce mode. Deux exécutions identiques peuvent donner des scores un peu différents : les algorithmes ont une part d'aléatoire.


7. Gérer le distributed training#

7.1 Data parallelism ou model parallelism#

Data parallelism ou model parallelism

Data parallelism Model parallelism
Principe Le modèle est copié sur chaque GPU, chacun traite une partition des données ; les gradients sont synchronisés à chaque lot Le modèle est découpé entre GPU, qui travaillent sur les mêmes données
Condition Le modèle entier doit tenir sur chaque GPU Le modèle est trop gros pour un GPU
Complexité Simple : DistributedDataParallel (DDP) en PyTorch, tf.distribute.Strategy en TensorFlow Plus complexe ; outillé par des bibliothèques comme DeepSpeed
Usage Plus de 90 % des cas selon Microsoft Très gros modèles (LLM)

7.2 PyTorch distribué dans un job#

Un job PyTorch distribué : 2 nœuds × 4 GPU = 8 processus

  1. Dans le script : torch.distributed.init_process_group(backend="nccl", init_method="env://") (nccl pour les GPU ; gloo et mpi existent).
  2. Dans le job : distribution.type: pytorch, process_count_per_instance = nombre de GPU par nœud (sinon un seul processus par nœud), resources.instance_count = nombre de nœuds. Pas besoin de torch.distributed.launch.
  3. Azure Machine Learning définit MASTER_ADDR, MASTER_PORT, WORLD_SIZE (nombre total de processus = de GPU) et NODE_RANK sur chaque nœud, puis RANK (rang global) et LOCAL_RANK (rang dans le nœud) par processus.
  4. Les tâches à faire une fois par nœud (préparation des données) se font sur LOCAL_RANK == 0.
# distributed-job.yml : 2 nœuds × 4 GPU
$schema: https://azuremlschemas.azureedge.net/latest/commandJob.schema.json
code: src
command: python train.py --epochs ${{inputs.epochs}} --data ${{inputs.data}}
inputs:
  epochs: 10
  data:
    type: uri_folder
    path: azureml:imagenet-subset:1
environment: azureml:AzureML-acpt-pytorch-2.8-cuda12.6@latest
compute: azureml:gpu-cluster-ib          # SKU RDMA (« r ») pour InfiniBand
distribution:
  type: pytorch
  process_count_per_instance: 4          # = GPU par nœud
resources:
  instance_count: 2                      # nœuds
# train.py (extrait) : initialisation DDP, les variables viennent d'Azure Machine Learning
import os, torch, torch.distributed as dist

dist.init_process_group(backend="nccl", init_method="env://")
local_rank = int(os.environ["LOCAL_RANK"])
torch.cuda.set_device(local_rank)
model = torch.nn.parallel.DistributedDataParallel(build_model().cuda(local_rank), device_ids=[local_rank])
# ... boucle d'entraînement ; un seul processus (rang 0) écrit les checkpoints pour éviter 8 écritures du même fichier
sequenceDiagram
    autonumber
    participant U as Ingénieur
    participant AML as Azure Machine Learning
    participant N0 as Node 0 (4 processus)
    participant N1 as Node 1 (4 processus)
    U->>AML: az ml job create (distribution pytorch, 2 nœuds)
    AML->>N0: provisionne, MASTER_ADDR, WORLD_SIZE=8, NODE_RANK=0
    AML->>N1: provisionne, WORLD_SIZE=8, NODE_RANK=1
    N0->>N1: init_process_group (nccl) : les 8 processus se trouvent
    loop Chaque lot
        N0->>N1: synchronisation des gradients (InfiniBand si SKU RDMA)
    end
    N0->>AML: métriques MLflow, outputs, checkpoints

7.3 DeepSpeed, TensorFlow, MPI#

Framework Dans Azure Machine Learning
DeepSpeed Pris en charge nativement, montée en charge quasi linéaire avec la taille du modèle et le nombre de GPU ; lancement par distribution PyTorch ou MPI, launcher DeepSpeed et autotuning de la configuration ds ; inclus dans l'environment ACPT (avec ONNX Runtime Training, MSCCL) ; exemples dans le dépôt azureml-examples/cli/jobs/deepspeed
TensorFlow distribution.type: tensorflow avec worker_count (et parameter_server_count pour l'ancienne stratégie parameter server de TensorFlow 1.x) ; Azure Machine Learning définit TF_CONFIG sur chaque worker
MPI distribution.type: mpi avec process_count_per_instance ; utilisé aussi par Horovod et DeepSpeed

Microsoft Learn ne publie pas de YAML DeepSpeed : il renvoie au dépôt Azure/azureml-examples (cli/jobs/deepspeed). À l'examen, retenir le principe : un command job avec distribution.type: pytorch (ou mpi), un environment qui contient DeepSpeed (ACPT) et le fichier de configuration ds passé au script. Le détail du fichier ds relève de DeepSpeed, pas d'Azure.

7.4 InfiniBand et choix des VM#

  • Le passage à l'échelle n'est linéaire que si les GPU communiquent vite entre nœuds : InfiniBand (faible latence, RDMA avec SR-IOV), disponible sur certaines VM NC, ND et H.
  • En général, seules les tailles avec un « r » (RDMA) ont le matériel InfiniBand : Standard_NC24rs_v3 oui, Standard_NC24s_v3 non (mêmes 24 cœurs, 448 Go, 4 GPU). L'ancien Standard_NC24r est RDMA sans SR-IOV, donc sans InfiniBand.
  • Sur un compute cluster de ces tailles, l'image système contient déjà le driver Mellanox OFED nécessaire.
  • Quota : les GPU ont un quota par famille de VM ; le demander avant le jour J (Spot a un quota distinct).

7.5 Résister aux interruptions#

Un entraînement de plusieurs heures sur Spot peut être évincé : écrire des checkpoints réguliers sur un datastore et savoir reprendre au dernier. L'ancien outil de checkpoint rapide Nebula (nebulaml) est déprécié et absent des images ACPT récentes : on s'appuie sur les mécanismes de PyTorch, PyTorch Lightning ou DeepSpeed.

Pour les LLM : fine-tuning managé, choix entre Foundry, Azure Machine Learning et AKS (KAITO), dimensionnement des GPU et coût : voir les chapitres 07 et 08, et le parcours AKS 06.


8. Construire des training pipelines#

Pipeline d'entraînement : des components reliés par leurs entrées et sorties

Un pipeline job enchaîne des étapes ; chaque étape est un job isolé (son environment, son compute) et la sortie de l'une devient l'entrée de la suivante. Les étapes sont des components : métadonnées (nom, version), interface (inputs, outputs), commande, code et environment. Un component enregistré est versionné, réutilisable par l'équipe et partageable entre workspaces par un registry (chapitre 01).

# train.yml : command component
$schema: https://azuremlschemas.azureedge.net/latest/commandComponent.schema.json
name: train_credit_model
version: 1
type: command
inputs:
  training_data: {type: uri_folder}
  learning_rate: {type: number, default: 0.01}
outputs:
  model_output: {type: mlflow_model}
code: ./train_src
environment: azureml:AzureML-acpt-pytorch-2.8-cuda12.6@latest
command: >-
  python train.py --data ${{inputs.training_data}} --lr ${{inputs.learning_rate}} --model ${{outputs.model_output}}
from azure.ai.ml import dsl, Input, load_component
from azure.ai.ml.entities import ResourceConfiguration

prep = load_component(source="./prep/prep.yml")
train = ml_client.components.get(name="train_credit_model", version="1")     # component déjà enregistré

@dsl.pipeline(description="Préparer puis entraîner", default_compute="serverless")
def credit_pipeline(raw_data):
    prep_step = prep(input_data=raw_data)
    train_step = train(training_data=prep_step.outputs.training_data, learning_rate=0.01)
    train_step.resources = ResourceConfiguration(instance_type="Standard_NC6s_v3", instance_count=1)   # GPU pour cette étape seulement
    return {"model": train_step.outputs.model_output}

pipeline_job = credit_pipeline(raw_data=Input(type="uri_folder", path="azureml:credit-raw:1"))
ml_client.jobs.create_or_update(pipeline_job, experiment_name="credit-pipeline")
Façon de créer Usage
Python : @dsl.pipeline, load_component(), ml_client.components.create_or_update() Le plus souple, testable
YAML : type: pipeline, jobs:, ${{parent.inputs.x}}, ${{parent.jobs.step.outputs.y}} Versionné dans Git, lancé par az ml job create depuis la CI (chapitre 02)
Studio Designer Glisser-déposer de components enregistrés

Une étape AutoML peut aussi faire partie du pipeline : son output best_model (type mlflow_model) alimente l'étape suivante. Un pipeline component peut enfin être déployé derrière un batch endpoint (chapitre 04).


9. Comparer les performances entre jobs#

Outil Ce qu'il permet
Studio > Jobs Liste des jobs par experiment, onglet Metrics (graphiques, lissage, plusieurs métriques sur un graphe, vues partageables)
Comparer (preview) Sélectionner des jobs ou des modèles et comparer paramètres, métriques et tags (fonction à activer dans le panneau des préversions)
Sweep job Metrics chart, Parallel Coordinates Chart, nuages 2D et 3D entre hyperparamètres et primary_metric
MLflow search_runs() Comparer par programme, sur un ou plusieurs experiments (search_all_experiments=True) ; résultat en DataFrame pandas
import mlflow

runs = mlflow.search_runs(
    experiment_names=["credit-training"],
    filter_string="metrics.val_accuracy > 0.85 AND params.optimizer = 'adam'",   # AND seulement, pas de OR
)
best = runs.sort_values("metrics.val_accuracy", ascending=False).head(5)        # trier sur une métrique : pandas

Limites Azure Machine Learning à connaître : order_by accepte les attributs (attributes.start_time, attributes.duration, ce dernier ajouté par Azure Machine Learning) mais pas metrics.*, params.* ni tags.* → trier avec pandas ; filtres sur les paramètres avec =, !=, LIKE seulement ; pas de OR.


10. Labs conseillés#

Dans un abonnement de test, avec un workspace dédié (chapitre 01). Coûts indicatifs : une compute instance CPU coûte peu par heure ; les VM GPU coûtent nettement plus et ont un quota à demander. Arrêter la compute instance et supprimer le groupe de ressources à la fin.

  1. MLflow sans effort : sur une compute instance, notebook scikit-learn avec mlflow.autolog() ; relancer avec deux valeurs d'un hyperparamètre. Attendu : deux runs dans l'experiment, paramètres et métriques visibles dans le studio, modèle en artifact.
  2. Du notebook au command job : transformer le notebook en train.py, le lancer par az ml job create -f job.yml sans compute (serverless). Attendu : le job tourne sans cluster créé, logs dans user_logs/std_log.txt, mêmes métriques MLflow.
  3. Sweep job : search space de 2 hyperparamètres, sampling random, max_total_trials=12, max_concurrent_trials=4, MedianStoppingPolicy. Attendu : certains trials arrêtés tôt, Parallel Coordinates Chart lisible, meilleur trial téléchargé.
  4. AutoML : un jeu tabulaire en MLTable, classification avec max_trials=10. Attendu : classement des modèles, featurization summary, explications du meilleur modèle.
  5. Distribué (si quota GPU) : job PyTorch avec instance_count: 2 et process_count_per_instance = nombre de GPU de la VM ; le script affiche RANK, LOCAL_RANK, WORLD_SIZE. Attendu : un std_log par processus avec des rangs différents ; ajouter un service SSH et sleep 30m pour lancer nvidia-smi sur le nœud 1, puis annuler le job.

11. Pièges d'examen#

Situation dans la question Réponse attendue Pourquoi
Logger des métriques avec le SDK v2 MLflow (mlflow.log_metric) Le SDK v2 n'a pas de fonction de logging
Tracer depuis un poste local ou Databricks Installer azureml-mlflow et fixer la tracking URI du workspace Automatique seulement sur le compute Azure Machine Learning
Un job appelle mlflow.start_run() sans raison Inutile dans un job : le run est déjà démarré —
Le sweep ne trouve pas sa métrique primary_metric doit avoir exactement le nom loggé La policy et le classement s'appuient dessus
Grid sampling avec un Uniform Impossible : grid = Choice seulement Grid énumère des valeurs discrètes
Économiser sans perdre de bons trials Median stopping, evaluation_interval=1, delay_evaluation=5 Réglage prudent recommandé
Économiser davantage Bandit avec faible slack ou Truncation avec fort pourcentage Plus agressif
Bayesian sampling efficace Peu de trials concurrents, max_total_trials ≥ 20 × nombre d'hyperparamètres Chaque essai profite des précédents
AutoML avec des classes très déséquilibrées primary_metric = AUC_weighted Les métriques à seuil (accuracy) optimisent mal
Données d'entrée d'AutoML en SDK v2 MLTable Format attendu par AutoML v2
La featurization AutoML en production Elle est dans le modèle, appliquée automatiquement aux nouvelles données —
Job PyTorch sur 2 nœuds de 4 GPU qui n'utilise qu'un GPU par nœud Fixer process_count_per_instance: 4 Par défaut : 1 processus par nœud
Valeur de WORLD_SIZE instance_count × process_count_per_instance (= nombre de GPU) —
Faut-il torch.distributed.launch ? Non Azure Machine Learning lance les processus et définit les variables
Multi-nœuds lent, gains non linéaires VM avec InfiniBand : taille avec « r » (RDMA, SR-IOV) La communication inter-nœuds limite
Le modèle ne tient pas sur un GPU Model parallelism, par exemple avec DeepSpeed Le data parallelism exige le modèle entier par GPU
tier: low_priority aujourd'hui Tourne en Spot (retrait des low-priority au 31/03/2026) Tarif Spot variable, éviction possible : checkpoints
Compute instance en Spot Impossible Usage interactif
Compute instance qui ne s'arrête jamais malgré l'idle shutdown Donner Contributor sur le workspace à sa managed identity, vérifier qu'aucune application custom ne tourne Conditions de l'idle shutdown
Déboguer un job distribué en cours Interactive job : JupyterLab, VS Code, TensorBoard ou SSH par node index Seul le propriétaire du job y accède
Trier des runs par métrique avec order_by Pas pris en charge : trier le DataFrame avec pandas order_by = attributs seulement
Filtre avec OR dans search_runs Pas pris en charge : faire deux requêtes Seul AND existe
Recharger les données dans chaque trial Préparer une fois dans une étape de pipeline Chaque trial repart de zéro

12. Scénarios corrigés#

1. Une data scientist entraîne sur son portable avec MLflow et veut voir ses runs dans le workspace de l'équipe. Que faire ?

  • A. Installer azure-ai-ml et appeler ml_client.log_metric()
  • B. Installer mlflow et azureml-mlflow, puis mlflow.set_tracking_uri() avec la tracking URI du workspace
  • C. Rien, c'est automatique partout
  • D. Exporter un CSV et le téléverser comme data asset

B. Hors du compute Azure Machine Learning, il faut le plugin et la tracking URI. A : le SDK v2 n'a pas de logging. C : vrai seulement sur compute instance et jobs.

2. Un sweep job sur 4 hyperparamètres utilise le sampling bayesian avec max_total_trials=20 et max_concurrent_trials=20. Les résultats sont médiocres. Deux corrections ?

Monter max_total_trials à au moins 80 (20 × 4) et réduire max_concurrent_trials : la méthode bayésienne profite des trials déjà terminés, ce qui est impossible si tous partent en même temps.

3. L'équipe veut couper les trials peu prometteurs sans risquer d'éliminer le futur meilleur. Quelle policy ?

Median stopping avec evaluation_interval=1 et delay_evaluation=5 : le réglage prudent recommandé (environ 25 à 35 % d'économie sans perte sur la métrique principale).

4. Un modèle de détection de fraude (0,5 % de fraudes) est entraîné avec AutoML et primary_metric="accuracy". Il prédit « pas de fraude » partout avec 99,5 % d'accuracy. Que changer ?

primary_metric="AUC_weighted" : les métriques à seuil comme l'accuracy optimisent mal les jeux très déséquilibrés.

5. Un job PyTorch sur deux Standard_NC24rs_v3 (4 GPU chacun) affiche WORLD_SIZE=2. Pourquoi, et comment corriger ?

process_count_per_instance n'est pas renseigné : Azure Machine Learning lance un seul processus par nœud. Le fixer à 4 : WORLD_SIZE passe à 8 et les 8 GPU travaillent.

6. Le même entraînement passe de 1 à 4 nœuds mais ne va que 1,5 fois plus vite. Les VM sont des Standard_NC24s_v3. Piste principale ?

Pas d'InfiniBand : la synchronisation des gradients passe par Ethernet. Utiliser la taille RDMA Standard_NC24rs_v3 (le « r »), dont l'image contient le driver OFED.

7. Un LLM de taille moyenne ne tient pas dans la mémoire d'un GPU, même avec un petit batch. Quelle approche ?

Model parallelism : le data parallelism exige le modèle complet sur chaque GPU. Azure Machine Learning prend en charge DeepSpeed (distribution PyTorch ou MPI, environment ACPT).

8. Pour réduire le coût, un cluster d'entraînement est créé avec tier: low_priority. Quel est le comportement en 2026 et que faut-il prévoir ?

Depuis le 31/03/2026, les nœuds sont alloués en Spot : tarif variable et éviction possible. Écrire des checkpoints réguliers dans un datastore et savoir reprendre au dernier.

9. Un job distribué se fige au bout de 20 minutes sur le nœud 1 seulement. L'ingénieur veut inspecter ce nœud en direct.

Relancer le job avec un interactive job (service SSH ou VS Code) et sleep en fin de commande, puis az ml job connect-ssh --node-index 1. Attention : VS Code et debugpy ne fonctionnent pas avec un workspace en private link ; SSH reste possible selon le réseau.

10. Une équipe relance chaque semaine : préparation des données, entraînement GPU, évaluation, enregistrement si la métrique est bonne. Elle veut que chaque étape tourne sur la bonne machine et soit réutilisable par d'autres projets.

Un pipeline job fait de components enregistrés (et partagés par un registry) : default_compute serverless ou CPU, et resources GPU sur la seule étape d'entraînement. Le pipeline est lancé depuis la CI (chapitre 02).


13. Pour aller plus loin#

  • Responsible AI dashboard et évaluation du modèle obtenu : chapitre 04.
  • Spark jobs (serverless Spark) pour préparer de gros volumes de données avant l'entraînement.
  • Coût d'un entraînement : mesurer l'utilisation GPU (métriques du job) avant de choisir plus de nœuds ; un job qui n'utilise ses GPU qu'à 30 % est en général limité par le chargement des données (voir diagnosing data loading bottlenecks).
  • Entraînement de LLM en mission : arbre de décision prompt, RAG, fine-tuning, entraînement complet, et choix de la plateforme : chapitre 08.

14. Fiche à retenir#

  • Tout est un job : command, sweep, AutoML, pipeline ; sans compute indiqué → serverless compute.
  • Le SDK v2 ne logge rien : MLflow ; automatique sur compute instance et jobs, azureml-mlflow + tracking URI ailleurs.
  • autolog(), log_param(s), log_metric, log_artifact ; rôle AzureML Data Scientist ou Contributor.
  • Compute instance : mono-nœud, personnelle, idle shutdown 15 min à 3 jours, pas de Spot ; %pip dans le kernel.
  • Interactive jobs : JupyterLab, VS Code, TensorBoard, SSH ; sleep ; seul le propriétaire ; pas de VS Code en private link.
  • Sweep : search space, sampling grid (Choice) / random (Sobol) / bayesian, primary_metric au nom exact, policies Bandit / Median stopping / Truncation, limits.
  • AutoML : MLTable, règles de validation (20 000 / 1 000 lignes), AUC_weighted si déséquilibre, featurization dans le modèle.
  • Data parallelism par défaut (> 90 %), model parallelism si le modèle ne tient pas sur un GPU (DeepSpeed).
  • PyTorch : nccl, process_count_per_instance = GPU par nœud, instance_count = nœuds, variables MASTER_ADDR, WORLD_SIZE, NODE_RANK, RANK, LOCAL_RANK fournies.
  • TensorFlow : worker_count, TF_CONFIG ; MPI : type: mpi.
  • InfiniBand : SKU avec « r » (RDMA + SR-IOV), driver OFED préinstallé.
  • Low-priority retiré le 31/03/2026 → Spot ; checkpoints obligatoires ; Nebula déprécié.
  • Pipelines : components versionnés, @dsl.pipeline ou YAML, compute par étape, registry pour partager.
  • Comparer : studio, sweep charts, search_runs (pas d'order_by sur les métriques, pas de OR).

Références#

Toutes lues le 21/10/2026 sur Microsoft Learn :

Sur cette page
Échap

Tape au moins 2 lettres. Plusieurs mots : tous doivent apparaître.