Lernen durch Bestärkung (Vorschau) mit Azure Machine Learning

GILT FÜR:Python SDK azureml v1

Warnung

Das vertiefende Lernen für Azure Machine Learning über das azureml.contrib.train.rl-Paket wird ab Juni 2022 nicht mehr unterstützt. Wir empfehlen unseren Kunden, die Bibliothek Ray on Azure Machine Learning für Experimente zum vertiefenden Lernen mit Azure Machine Learning zu verwenden. Ein Beispiel finden Sie im Notebook Vertiefendes Lernen in Azure Machine Learning – Pong-Problem.

In diesem Artikel erfahren Sie, wie Sie einen RL-Agent (Reinforcement Learning, Lernen durch Bestärkung) trainieren, damit er das Videospiel Pong spielen kann. Sie verwenden dabei die Open-Source-Python-Bibliothek Ray RLlib mit Azure Machine Learning, um komplexe verteilte RL-Aufträge zu verwalten.

In diesem Artikel wird Folgendes behandelt:

  • Einrichten eines Experiments
  • Definieren von Haupt- und Workerknoten
  • Erstellen eines RL-Estimators
  • Reichen Sie ein Experiment ein, um einen Auftrag zu starten
  • Anzeigen der Ergebnisse

Dieser Artikel basiert auf dem RLlib Pong-Beispiel, das im Azure Machine Learning-Notebook-GitHub-Repository zu finden ist.

Voraussetzungen

Führen Sie diesen Code in einer dieser Umgebungen aus. Wir empfehlen Ihnen, die Azure Machine Learning-Compute-Instanz zu testen, die den schnellsten Start ermöglicht. Sie können die Beispielnotebooks für vertiefendes Lernen schnell auf einer Azure Machine Learning-Compute-Instanz klonen und ausführen.

  • Azure Machine Learning-Computeinstanz

    • Erfahren Sie in Schnellstart: Ausführen von Jupyter Notebooks in Studio, wie Sie Beispielnotebooks klonen.
      • Klonen Sie den Ordner SDK v1 > how-to-use-azureml anstelle von SDK v2 > Tutorials
    • Führen Sie das Setup-Notebook für virtuelle Netzwerke unter /how-to-use-azureml/reinforcement-learning/setup/devenv_setup.ipynb aus, um die Netzwerkports zu öffnen, die für das verteilte Lernen durch Bestärkung verwendet werden.
    • Führen Sie das Beispielnotebook /how-to-use-azureml/reinforcement-learning/atari-on-distributed-compute/pong_rllib.ipynb aus.
  • Ihr eigener Jupyter Notebook-Server

Trainieren eines Agents, der Pong spielt

Das Lernen durch Bestärkung ist eine Methode des maschinellen Lernens, die durch das Ausführen von Tätigkeiten lernt. Während andere Techniken für maschinelles Lernen durch passives Übernehmen von Eingabedaten und Finden von darin enthaltenen Mustern lernen, verwendet RL Trainings-Agents, um aktiv Entscheidungen zu treffen und aus ihren Ergebnissen zu lernen.

Ihre Trainings-Agents lernen in einer simulierten Umgebung, Pong zu spielen. Trainings-Agents treffen mit jedem Frame des Spiels eine Entscheidung, um das Paddle nach oben oder unten zu verschieben oder die Position beizubehalten. Sie treffen anhand des Zustands des Spiels (ein RGB-Bild des Bildschirms) eine Entscheidung.

RL setzt Belohnungen ein, um dem Agent mitzuteilen, ob seine Entscheidungen erfolgreich sind. In diesem Beispiel erhält der Agent eine positive Belohnung, wenn er einen Punkt erhält, und eine negative Belohnung, wenn ein Punkt gegen ihn erzielt wird. Über viele Iterationen hinweg lernt der Trainings-Agent, eine Aktion ausgehend vom aktuellen Zustand auszuführen, die die Summe der erwarteten zukünftigen Belohnungen optimiert. Für eine solche Optimierung in RL werden in der Regel Deep Neural Networks (DNN) verwendet.

Das Training ist beendet, wenn der Agent im Durchschnitt 18 Belohnungen pro Trainingsepoche erhält. Das heißt, dass der Agent seinen Gegner in Spielen mit bis zu 21 Punkten um durchschnittlich mindestens 18 Punkte geschlagen hat.

Die Iteration durch Simulation und erneutes Trainieren eines DNN ist rechenintensiv und erfordert große Datenmengen. Eine Möglichkeit zum Verbessern der Leistung von RL-Aufträgen besteht in der Parallelisierung, sodass mehrere Trainings-Agents gleichzeitig agieren und lernen können. Das Verwalten einer verteilten RL-Umgebung kann jedoch eine komplexe Aufgabe sein.

Azure Machine Learning stellt das Framework bereit, um das komplexe Hochskalieren Ihrer RL-Workloads zu handhaben.

Einrichten der Umgebung

Richten Sie die lokale RL-Umgebung wie folgt ein:

  1. Laden der erforderlichen Python-Pakete
  2. Initialisieren des Arbeitsbereichs
  3. Erstellen von Experimenten
  4. Angeben eines konfigurierten virtuellen Netzwerks

Importieren von Bibliotheken

Importieren Sie die erforderlichen Python-Pakete, um den Rest dieses Beispiels auszuführen.

# Azure ML Core imports
import azureml.core
from azureml.core import Workspace
from azureml.core import Experiment
from azureml.core.compute import AmlCompute
from azureml.core.compute import ComputeTarget
from azureml.core.runconfig import EnvironmentDefinition
from azureml.widgets import RunDetails
from azureml.tensorboard import Tensorboard

# Azure ML Reinforcement Learning imports
from azureml.contrib.train.rl import ReinforcementLearningEstimator, Ray
from azureml.contrib.train.rl import WorkerConfiguration

Initialisieren eines Arbeitsbereichs

Initialisieren Sie ein Arbeitsbereichsobjekt aus der Datei config.json, die im Abschnitt Voraussetzungen erstellt wurde. Wenn Sie diesen Code in einer Azure Machine Learning-Computeinstanz ausführen, wurde die Konfigurationsdatei bereits für Sie erstellt.

ws = Workspace.from_config()

Erstellen eines Experiments für Lernen durch Bestärkung

Erstellen Sie ein Experiment, um Ihren Auftrag für vertiefendes Lernen nachzuverfolgen. In Azure Machine Learning sind Experimente logische Sammlungen von zusammenhängenden Versuchen, um Auftragsprotokolle, Verlauf, Ergebnisse und mehr zu organisieren.

experiment_name='rllib-pong-multi-node'

exp = Experiment(workspace=ws, name=experiment_name)

Festlegen eines virtuellen Netzwerks

Für RL-Aufträge, die mehrere Computeziele verwenden, müssen Sie ein virtuelles Netzwerk mit geöffneten Ports festlegen, mithilfe derer Worker- und Hauptknoten miteinander kommunizieren können.

Das virtuelle Netzwerk kann sich in einer beliebigen Ressourcengruppe befinden. Es sollte sich jedoch in derselben Region wie Ihr Arbeitsbereich befinden. Weitere Informationen zum Einrichten des virtuellen Netzwerks finden Sie im Notebook zum Einrichten eines Arbeitsbereichs im Abschnitt „Voraussetzungen“. Hier geben Sie den Namen des virtuellen Netzwerks in der Ressourcengruppe an.

vnet = 'your_vnet'

Definieren von Haupt- und Workercomputezielen

In diesem Beispiel werden separate Computeziele für die Ray-Haupt- und Workerknoten verwendet. Mit diesen Einstellungen können Sie Ihre Computeressourcen abhängig von der erwarteten Workload auf- oder abskalieren. Legen Sie die Anzahl der Knoten und die Größe der einzelnen Knoten basierend auf Ihren Anforderungen fest.

Hauptcomputingziele

Sie können einen mit GPU ausgestatteten Hauptcluster verwenden, um die Deep Learning-Leistung zu verbessern. Der Hauptknoten trainiert das neuronale Netz, das der Agent verwendet, um Entscheidungen zu treffen. Der Hauptknoten sammelt auch Datenpunkte von den Workerknoten, um das neuronale Netz zu trainieren.

Der Hauptcompute verwendet einen einzelnen virtuellen STANDARD_NC6-Computer (VM). Er verfügt über sechs virtuelle CPUs, auf die die Arbeit verteilt wird.

from azureml.core.compute import AmlCompute, ComputeTarget

# choose a name for the Ray head cluster
head_compute_name = 'head-gpu'
head_compute_min_nodes = 0
head_compute_max_nodes = 2

# This example uses GPU VM. For using CPU VM, set SKU to STANDARD_D2_V2
head_vm_size = 'STANDARD_NC6'

if head_compute_name in ws.compute_targets:
    head_compute_target = ws.compute_targets[head_compute_name]
    if head_compute_target and type(head_compute_target) is AmlCompute:
        print(f'found head compute target. just use it {head_compute_name}')
else:
    print('creating a new head compute target...')
    provisioning_config = AmlCompute.provisioning_configuration(vm_size = head_vm_size,
                                                                min_nodes = head_compute_min_nodes, 
                                                                max_nodes = head_compute_max_nodes,
                                                                vnet_resourcegroup_name = ws.resource_group,
                                                                vnet_name = vnet_name,
                                                                subnet_name = 'default')

    # create the cluster
    head_compute_target = ComputeTarget.create(ws, head_compute_name, provisioning_config)
    
    # can poll for a minimum number of nodes and for a specific timeout. 
    # if no min node count is provided it will use the scale settings for the cluster
    head_compute_target.wait_for_completion(show_output=True, min_node_count=None, timeout_in_minutes=20)
    
     # For a more detailed view of current AmlCompute status, use get_status()
    print(head_compute_target.get_status().serialize())

Hinweis

Sie können sich dafür entscheiden, virtuelle Computer mit niedriger Priorität zu verwenden, um einige oder alle Ihre Workloads auszuführen. Weitere Informationen finden Sie unter Erstellen eines virtuellen Computers mit niedriger Priorität.

Workercomputingcluster

In diesem Beispiel werden vier STANDARD_D2_V2-VMs für das Workercomputeziel verwendet. Jeder Workerknoten hat zwei verfügbare CPUs für insgesamt acht verfügbare CPUs.

GPUs sind für die Workerknoten nicht erforderlich, da sie kein Deep Learning ausführen. Die Worker führen die Spielsimulationen aus und sammeln Daten.

# choose a name for your Ray worker cluster
worker_compute_name = 'worker-cpu'
worker_compute_min_nodes = 0 
worker_compute_max_nodes = 4

# This example uses CPU VM. For using GPU VM, set SKU to STANDARD_NC6
worker_vm_size = 'STANDARD_D2_V2'

# Create the compute target if it hasn't been created already
if worker_compute_name in ws.compute_targets:
    worker_compute_target = ws.compute_targets[worker_compute_name]
    if worker_compute_target and type(worker_compute_target) is AmlCompute:
        print(f'found worker compute target. just use it {worker_compute_name}')
else:
    print('creating a new worker compute target...')
    provisioning_config = AmlCompute.provisioning_configuration(vm_size = worker_vm_size,
                                                                min_nodes = worker_compute_min_nodes, 
                                                                max_nodes = worker_compute_max_nodes,
                                                                vnet_resourcegroup_name = ws.resource_group,
                                                                vnet_name = vnet_name,
                                                                subnet_name = 'default')

    # create the cluster
    worker_compute_target = ComputeTarget.create(ws, worker_compute_name, provisioning_config)
    
    # can poll for a minimum number of nodes and for a specific timeout. 
    # if no min node count is provided it will use the scale settings for the cluster
    worker_compute_target.wait_for_completion(show_output=True, min_node_count=None, timeout_in_minutes=20)
    
     # For a more detailed view of current AmlCompute status, use get_status()
    print(worker_compute_target.get_status().serialize())

Erstellen eines Estimators für Lernen durch Bestärkung

Übermitteln Sie mit dem ReinforcementLearningEstimator einen Trainingsauftrag an Azure Machine Learning.

Azure Machine Learning verwendet Schätzerklassen, um Informationen zur Auftragskonfiguration zu kapseln. So können Sie festlegen, wie eine Skriptausführung konfiguriert werden soll.

Definieren einer Workerkonfiguration

Das WorkerConfiguration-Objekt teilt Azure Machine Learning mit, wie der Workercluster, der das Eingabeskript ausführt, initialisiert werden soll.

# Pip packages we will use for both head and worker
pip_packages=["ray[rllib]==0.8.3"] # Latest version of Ray has fixes for isses related to object transfers

# Specify the Ray worker configuration
worker_conf = WorkerConfiguration(
    
    # Azure ML compute cluster to run Ray workers
    compute_target=worker_compute_target, 
    
    # Number of worker nodes
    node_count=4,
    
    # GPU
    use_gpu=False, 
    
    # PIP packages to use
    pip_packages=pip_packages
)

Definieren von Skriptparametern

Das Einstiegsskript pong_rllib.py akzeptiert eine Liste von Parametern, die definieren, wie der Trainingsauftrag ausgeführt wird. Wenn diese Parameter über den Estimator als Kapselungsebene übergeben werden, ist es einfach, Skriptparameter zu ändern und Konfigurationen unabhängig voneinander auszuführen.

Wenn Sie den richtigen Wert für num_workers festlegen, nutzen Sie die Parallelisierung optimal. Legen Sie die Anzahl der Worker auf denselben Wert wie die Anzahl der verfügbaren CPUs fest. Wenden Sie für dieses Beispiel die folgende Berechnung an:

Der Hauptknoten ist ein Standard_NC6 mit sechs vCPUs. Der Workercluster besteht aus vier Standard_D2_V2-VMs mit jeweils zwei CPUs für insgesamt acht CPUs. Allerdings müssen Sie eine CPU von der Workeranzahl subtrahieren, da eine für die Hauptknotenrolle reserviert werden muss.

6 CPUs + 8 CPUs - 1 Haupt-CPU = 13 gleichzeitige Worker. Azure Machine Learning verwendet Haupt- und Workercluster, um Computeressourcen zu unterscheiden. Allerdings unterscheidet Ray nicht zwischen Haupt- und Workerrolle, und alle CPUs sind als Workerthreads verfügbar.

training_algorithm = "IMPALA"
rl_environment = "PongNoFrameskip-v4"

# Training script parameters
script_params = {
    
    # Training algorithm, IMPALA in this case
    "--run": training_algorithm,
    
    # Environment, Pong in this case
    "--env": rl_environment,
    
    # Add additional single quotes at the both ends of string values as we have spaces in the 
    # string parameters, outermost quotes are not passed to scripts as they are not actually part of string
    # Number of GPUs
    # Number of ray workers
    "--config": '\'{"num_gpus": 1, "num_workers": 13}\'',
    
    # Target episode reward mean to stop the training
    # Total training time in seconds
    "--stop": '\'{"episode_reward_mean": 18, "time_total_s": 3600}\'',
}

Definieren des Estimators für Lernen durch Bestärkung

Verwenden Sie die Parameterliste und das Workerkonfigurationsobjekt, um den Estimator zu erstellen.

# RL estimator
rl_estimator = ReinforcementLearningEstimator(
    
    # Location of source files
    source_directory='files',
    
    # Python script file
    entry_script="pong_rllib.py",
    
    # Parameters to pass to the script file
    # Defined above.
    script_params=script_params,
    
    # The Azure ML compute target set up for Ray head nodes
    compute_target=head_compute_target,
    
    # Pip packages
    pip_packages=pip_packages,
    
    # GPU usage
    use_gpu=True,
    
    # RL framework. Currently must be Ray.
    rl_framework=Ray(),
    
    # Ray worker configuration defined above.
    worker_configuration=worker_conf,
    
    # How long to wait for whole cluster to start
    cluster_coordination_timeout_seconds=3600,
    
    # Maximum time for the whole Ray job to run
    # This will cut off the job after an hour
    max_run_duration_seconds=3600,
    
    # Allow the docker container Ray runs in to make full use
    # of the shared memory available from the host OS.
    shm_size=24*1024*1024*1024
)

Eingabeskript

Das Einstiegsskriptpong_rllib.pytrainiert ein neuronales Netz mithilfe der OpenAI Gym-UmgebungPongNoFrameSkip-v4. OpenAI Gyms sind standardisierte Schnittstellen, mit denen Algorithmen für Lernen durch Bestärkung für klassische Atari-Spiele getestet werden können.

In diesem Beispiel wird ein Trainingsalgorithmus verwendet, der als IMPALA (Importance Weighted Actor-Learner Architecture, nach Bedeutung gewichtete Akteur-Lerner-Architektur) bezeichnet wird. IMPALA parallelisiert jeden einzelnen Lernakteur so, dass er über viele Computeknoten hinweg skaliert wird, ohne die Geschwindigkeit oder Stabilität zu beeinträchtigen.

Ray Tune orchestriert die IMPALA-Workeraufgaben.

import ray
import ray.tune as tune
from ray.rllib import train

import os
import sys

from azureml.core import Run
from utils import callbacks

DEFAULT_RAY_ADDRESS = 'localhost:6379'

if __name__ == "__main__":

    # Parse arguments
    train_parser = train.create_parser()

    args = train_parser.parse_args()
    print("Algorithm config:", args.config)

    if args.ray_address is None:
        args.ray_address = DEFAULT_RAY_ADDRESS

    ray.init(address=args.ray_address)

    tune.run(run_or_experiment=args.run,
             config={
                 "env": args.env,
                 "num_gpus": args.config["num_gpus"],
                 "num_workers": args.config["num_workers"],
                 "callbacks": {"on_train_result": callbacks.on_train_result},
                 "sample_batch_size": 50,
                 "train_batch_size": 1000,
                 "num_sgd_iter": 2,
                 "num_data_loader_buffers": 2,
                 "model": {
                    "dim": 42
                 },
             },
             stop=args.stop,
             local_dir='./logs')

Protokollieren der Rückruffunktion

Das Einstiegsskript verwendet eine Hilfsfunktion, um eine benutzerdefinierte RLlib-Rückruffunktion zu definieren, die Metriken in Ihrem Azure Machine Learning-Arbeitsbereich protokolliert. Erfahren Sie im Abschnitt Überwachen und Anzeigen von Ergebnissen wie Sie diese Metriken anzeigen können.

'''RLlib callbacks module:
    Common callback methods to be passed to RLlib trainer.
'''
from azureml.core import Run

def on_train_result(info):
    '''Callback on train result to record metrics returned by trainer.
    '''
    run = Run.get_context()
    run.log(
        name='episode_reward_mean',
        value=info["result"]["episode_reward_mean"])
    run.log(
        name='episodes_total',
        value=info["result"]["episodes_total"])

Übermitteln eines Auftrags

Eine Ausführung verarbeitet den Ausführungsverlauf laufender oder abgeschlossener Aufträge.

run = exp.submit(config=rl_estimator)

Hinweis

Die Ausführung kann 30 bis 45 Minuten in Anspruch nehmen.

Überwachen und Anzeigen von Ergebnissen

Verwenden Sie das Azure Machine Learning Jupyter-Widget, um den Status Ihrer Aufträge in Echtzeit anzuzeigen. Das Widget zeigt zwei untergeordnete Aufträge an: einen für Leiter und einen für Arbeiter.

from azureml.widgets import RunDetails

RunDetails(run).show()
run.wait_for_completion()
  1. Warten Sie, bis das Widget geladen ist.
  2. Wählen Sie den Hauptauftrag in der Liste der Aufträge aus.

Wählen Sie Klicken Sie hier, um den Auftrag im Azure Machine Learning Studio zu sehen, um weitere Informationen zum Auftrag im Studio zu erhalten. Sie können diese Informationen abrufen, während der Auftrag läuft oder nachdem er abgeschlossen ist.

Liniendiagramm zum Widget der Auftragsdetails

Der Plot episode_reward_mean zeigt die durchschnittliche Anzahl der Punkte an, die pro Trainingsepoche erreicht wurden. Sie sehen, dass die Leistung des Trainings-Agents zu Beginn schlecht war und er die Spiele verloren hat, ohne auch nur einen Punkt zu bekommen (reward_mean: -21). Innerhalb von 100 Iterationen hat der Trainings-Agent gelernt, den Computergegner um einen durchschnittlichen Wert von 18 Punkten zu schlagen.

Wenn Sie die Protokolle des untergeordneten Auftrags durchsuchen, sehen Sie die Auswertungsergebnisse, die in der Datei driver_log.txt erfasst wurden. Möglicherweise müssen Sie einige Minuten warten, bis diese Metriken auf der Auftragsseite verfügbar werden.

In kurzer Zeit haben Sie gelernt, mehrere Computeressourcen zu konfigurieren, um einen Agent für vertiefendes Lernen so zu trainieren, dass er sehr gut Pong gegen einen Computergegner spielt.

Nächste Schritte

In diesem Artikel haben Sie erfahren, wie Sie einen Agent für Lernen durch Bestärkung mithilfe eines IMPALA-Agents trainieren. Weitere Beispiele finden Sie im GitHub-Repository für Lernen durch Bestärkung von Azure Machine Learning.