

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Invoquer une fonction à distance
<a name="train-remote-decorator-invocation"></a>

Pour invoquer une fonction dans le décorateur @remote, utilisez l’une des méthodes suivantes :
+ [Utilisation d’un décorateur @remote pour invoquer une fonction](#train-remote-decorator-invocation-decorator).
+ [Utilisation de l’API `RemoteExecutor` pour invoquer une fonction](#train-remote-decorator-invocation-api).

Si vous utilisez la méthode @remote decorator pour invoquer une fonction, la tâche d’entraînement attendra que la fonction soit terminée avant de démarrer une nouvelle tâche. Toutefois, si vous utilisez l’API `RemoteExecutor`, vous pouvez exécuter plusieurs tâches en parallèle. Les sections suivantes montrent les deux manières d’invoquer une fonction.

## Utilisation d’un décorateur @remote pour invoquer une fonction
<a name="train-remote-decorator-invocation-decorator"></a>

Vous pouvez utiliser le décorateur @remote pour annoter une fonction. SageMaker L'IA transformera le code du décorateur en une tâche de SageMaker formation. La tâche d’entraînement invoquera ensuite la fonction dans le décorateur et attendra la fin de la tâche. L'exemple de code suivant montre comment importer les bibliothèques requises, démarrer une instance SageMaker AI et annoter une multiplication matricielle avec le décorateur @remote.

```
from sagemaker.remote_function import remote
import numpy as np

@remote(instance_type="{{ml.m5.large}}")
def matrix_multiply(a, b):
    return np.matmul(a, b)
    
a = np.array([[1, 0],
             [0, 1]])
b = np.array([1, 2])

assert (matrix_multiply(a, b) == np.array([1,2])).all()
```

Le décorateur est défini comme suit.

```
def remote(
    *,
    **kwarg):
        ...
```

Lorsque vous invoquez une fonction décorée, le SDK SageMaker Python charge toutes les exceptions déclenchées par une erreur dans la mémoire locale. Dans l’exemple de code suivant, le premier appel à la fonction de division se termine correctement et le résultat est chargé dans la mémoire locale. Lors du deuxième appel à la fonction de division, le code renvoie une erreur et cette erreur est chargée dans la mémoire locale.

```
from sagemaker.remote_function import remote
import pytest

@remote()
def divide(a, b):
    return a/b

# the underlying job is completed successfully 
# and the function return is loaded
assert divide(10, 5) == 2

# the underlying job fails with "AlgorithmError" 
# and the function exception is loaded into local memory 
with pytest.raises(ZeroDivisionError):
    divide(10, 0)
```

**Note**  
La fonction décorée est exécutée en tant que tâche distante. Si le thread est interrompu, la tâche sous-jacente ne sera pas arrêtée.

### Comment modifier la valeur d’une variable locale
<a name="train-remote-decorator-invocation-decorator-value"></a>

La fonction de décorateur est exécutée sur une machine distante. La modification d’une variable non locale ou d’arguments d’entrée dans une fonction décorée ne modifiera pas la valeur locale.

Dans l’exemple de code suivant, une liste et un dictionnaire sont ajoutés dans la fonction de décoration. Cela ne change pas lorsque la fonction de décorateur est invoquée.

```
a = []

@remote
def func():
    a.append(1)

# when func is invoked, a in the local memory is not modified        
func() 
func()

# a stays as []
    
a = {}
@remote
def func(a):
    # append new values to the input dictionary
    a["key-2"] = "value-2"
    
a = {"key": "value"}
func(a)

# a stays as {"key": "value"}
```

Pour modifier la valeur d’une variable locale déclarée dans une fonction de décoration, renvoyez la variable depuis la fonction. L’exemple de code suivant montre que la valeur d’une variable locale est modifiée lorsqu’elle est renvoyée par la fonction.

```
a = {"key-1": "value-1"}

@remote
def func(a):
    a["key-2"] = "value-2"
    return a

a = func(a)

-> {"key-1": "value-1", "key-2": "value-2"}
```

### Sérialisation et désérialisation des données
<a name="train-remote-decorator-invocation-input-output"></a>

Lorsque vous invoquez une fonction distante, l' SageMaker IA sérialise automatiquement les arguments de votre fonction pendant les étapes d'entrée et de sortie. Les arguments et les retours des fonctions sont sérialisés à l'aide de [https://github.com/cloudpipe/cloudpickle](https://github.com/cloudpipe/cloudpickle) cloudpickle. SageMaker L'IA prend en charge la sérialisation des objets et fonctions Python suivants. 
+ Built-in Objets Python, notamment des dicts, des listes, des flottants, des entiers, des chaînes, des valeurs booléennes et des tuples
+ Tableaux numpy
+ Dataframes Pandas
+ Scikit-learn ensembles de données et estimateurs
+ PyTorch modèles
+ TensorFlow modèles
+ La classe Booster pour XGBoost

Les éléments suivants peuvent être utilisés avec certaines restrictions.
+ Dask DataFrames
+ La classe XGBoost Dmatrix
+ TensorFlow ensembles de données et sous-classes
+ PyTorch modèles

La section suivante contient les meilleures pratiques pour utiliser les classes Python précédentes avec certaines limitations de votre fonction à distance, des informations sur l'endroit où SageMaker AI stocke vos données sérialisées et comment gérer l'accès à celles-ci.

#### Bonnes pratiques pour les classes Python avec une prise en charge limitée de la sérialisation de données distantes
<a name="train-remote-decorator-invocation-input-output-bestprac"></a>

Vous pouvez utiliser les classes Python répertoriées dans cette section avec certaines restrictions. Les sections suivantes présentent les bonnes pratiques relatives à l’utilisation des classes Python suivantes.
+ [Dask ](https://www.dask.org/) DataFrames
+ La classe XGBoost DMatric
+ TensorFlow ensembles de données et sous-classes
+ PyTorch modèles

##### Bonnes pratiques relatives à Dask
<a name="train-remote-decorator-invocation-input-output-bestprac-dask"></a>

[Dask](https://www.dask.org/) est une bibliothèque open source utilisée pour le calcul parallèle dans Python. Cette section montre ce qui suit.
+ Comment transmettre un Dask à votre DataFrame fonction de télécommande
+ Comment convertir les statistiques récapitulatives d'un Dask DataFrame en Pandas DataFrame

##### Comment transmettre un Dask à votre DataFrame fonction de télécommande
<a name="train-remote-decorator-invocation-input-output-bestprac-dask-pass"></a>

[Les Dask DataFrames ](https://docs.dask.org/en/latest/dataframe.html) sont souvent utilisés pour traiter de grands ensembles de données car ils peuvent contenir des ensembles de données nécessitant plus de mémoire que celle disponible. Cela est dû au fait qu'un Dask DataFrame ne charge pas vos données locales en mémoire. Si vous transmettez un Dask DataFrame comme argument de fonction à votre fonction distante, Dask peut transmettre une référence aux données de votre disque local ou de votre stockage cloud, au lieu des données elles-mêmes. Le code suivant montre un exemple de transmission d'un Dask DataFrame dans votre fonction de télécommande qui fonctionnera à vide. DataFrame

```
#Do not pass a Dask DataFrame  to your remote function as follows
def clean(df: dask.DataFrame ):
    cleaned = df[] \ ...
```

Dask chargera les données du Dask DataFrame en mémoire uniquement lorsque vous utilisez le. DataFrame Si vous souhaitez utiliser un Dask DataFrame dans une fonction à distance, indiquez le chemin d'accès aux données. Ensuite, Dask lira le jeu de données directement à partir du chemin de données que vous spécifiez lors de l’exécution du code.

L'exemple de code suivant montre comment utiliser un Dask DataFrame dans la fonction `clean` de télécommande. Dans l'exemple de code, `raw_data_path` est transmis à clean au lieu de Dask DataFrame. Lorsque le code s’exécute, le jeu de données est lu directement depuis l’emplacement d’un compartiment Amazon S3 spécifié dans `raw_data_path`. Ensuite, la `persist` fonction conserve l'ensemble de données en mémoire pour faciliter la `random_split` fonction suivante et le réécrit sur le chemin des données de sortie dans un compartiment S3 à l'aide des fonctions de l' DataFrame API Dask.

```
import dask.dataframe as dd

@remote(
   instance_type='{{ml.m5.24xlarge}}',
   volume_size={{300}}, 
   keep_alive_period_in_seconds={{600}})
#pass the data path to your remote function rather than the Dask DataFrame  itself
def clean(raw_data_path: str, output_data_path: str: split_ratio: list[float]):
    df = dd.read_parquet(raw_data_path) #pass the path to your DataFrame 
    cleaned = df[(df.column_a >= 1) & (df.column_a < 5)]\
        .drop(['column_b', 'column_c'], axis=1)\
        .persist() #keep the data in memory to facilitate the following random_split operation

    train_df, test_df = cleaned.random_split(split_ratio, random_state=10)

    train_df.to_parquet(os.path.join(output_data_path, 'train')
    test_df.to_parquet(os.path.join(output_data_path, 'test'))
    
clean("{{s3://amzn-s3-demo-bucket/raw/}}", "{{s3://amzn-s3-demo-bucket/cleaned/}}", split_ratio={{[0.7, 0.3]}})
```

##### Comment convertir les statistiques récapitulatives d'un Dask DataFrame en Pandas DataFrame
<a name="train-remote-decorator-invocation-input-output-bestprac-dask-pd"></a>

Les statistiques récapitulatives d'un Dask DataFrame peuvent être converties en Pandas DataFrame en invoquant la `compute` méthode comme indiqué dans l'exemple de code suivant. Dans l'exemple, le compartiment S3 contient un Dask volumineux DataFrame qui ne peut pas être inséré dans la mémoire ou dans une trame de données Pandas. Dans l'exemple suivant, une fonction à distance analyse l'ensemble de données et renvoie un Dask DataFrame contenant les statistiques de sortie de `describe` à un Pandas DataFrame.

```
executor = RemoteExecutor(
    instance_type='{{ml.m5.24xlarge}}',
    volume_size={{300}}, 
    keep_alive_period_in_seconds={{600}})

future = executor.submit(lambda: dd.read_parquet("{{s3://amzn-s3-demo-bucket/raw/}}").describe().compute())

future.result()
```

##### Bonnes pratiques pour la classe XGBoost DMatric
<a name="train-remote-decorator-invocation-input-output-bestprac-xgboost"></a>

DMatrix est une structure de données interne utilisée par XGBoost pour charger des données. Un objet DMatrix ne peut pas être pickle afin de pouvoir passer facilement d’une session de calcul à une autre. Le passage direct d’instances DMatrix échouera avec une `SerializationError`.

##### Comment transmettre un objet de données à votre fonction distante et l’entraîner avec XGBoost
<a name="train-remote-decorator-invocation-input-output-bestprac-xgboost-pass"></a>

Pour convertir un Pandas DataFrame en une instance DMatrix et l'utiliser pour l'entraînement à votre fonction à distance, transmettez-le directement à la fonction à distance, comme indiqué dans l'exemple de code suivant.

```
import xgboost as xgb

@remote
def train(df, params):
    #Convert a pandas dataframe into a DMatrix DataFrame and use it for training
    dtrain = DMatrix(df) 
    return xgb.train(dtrain, params)
```

##### Meilleures pratiques pour les TensorFlow ensembles de données et les sous-classes
<a name="train-remote-decorator-invocation-input-output-bestprac-tf"></a>

TensorFlow les ensembles de données et les sous-classes sont des objets internes utilisés TensorFlow pour charger des données pendant l'entraînement. TensorFlow les ensembles de données et les sous-classes ne peuvent pas être sélectionnés afin de pouvoir passer facilement d'une session de calcul à l'autre. La transmission directe de jeux de données ou de sous-classes Tensorflow échouera avec une `SerializationError`. Utilisez les I/O API Tensorflow pour charger des données depuis le stockage, comme indiqué dans l'exemple de code suivant.

```
import tensorflow as tf
import tensorflow_io as tfio

@remote
def train(data_path: str, params):
    
    dataset = tf.data.TextLineDataset(tf.data.Dataset.list_files(f"{data_path}/*.txt"))
    ...
    
train("{{s3://amzn-s3-demo-bucket/data}}", {})
```

##### Meilleures pratiques pour les PyTorch modèles
<a name="train-remote-decorator-invocation-input-output-bestprac-pytorch"></a>

PyTorch les modèles sont sérialisables et peuvent être transmis entre votre environnement local et la fonction distante. Si votre environnement local et votre environnement distant ont des types d’appareils différents (tels que des GPU et CPU), vous ne pouvez pas renvoyer un modèle entraîné dans votre environnement local. Par exemple, si le code suivant est développé dans un environnement local sans GPU mais exécuté dans une instance avec des GPU, le renvoi direct du modèle entraîné entraînera une `DeserializationError`.

```
# Do not return a model trained on GPUs to a CPU-only environment as follows

@remote(instance_type='{{ml.g4dn.xlarge}}')
def train(...):
    if torch.cuda.is_available():
        device = torch.device("cuda")
    else:
        device = torch.device("cpu") # a device without GPU capabilities
    
    model = Net().to(device)
    
    # train the model
    ...
    
    return model
    
model = train(...) #returns a DeserializationError if run on a device with GPU
```

Pour reconvertir un modèle entraîné dans un environnement GPU en un modèle ne contenant que les fonctionnalités du processeur, utilisez directement les I/O API du PyTorch modèle, comme indiqué dans l'exemple de code ci-dessous.

```
import s3fs

model_path = "{{s3://amzn-s3-demo-bucket/folder/}}"

@remote(instance_type='{{ml.g4dn.xlarge}}')
def train(...):
    if torch.cuda.is_available():
        device = torch.device("cuda")
    else:
        device = torch.device("cpu")
    
    model = Net().to(device)
    
    # train the model
    ...
    
    fs = s3fs.FileSystem()
    with fs.open(os.path.join(model_path, 'model.pt'), 'wb') as file:
        torch.save(model.state_dict(), file) #this writes the model in a device-agnostic way (CPU vs GPU)
    
train(...) #use the model to train on either CPUs or GPUs

model = Net()
fs = s3fs.FileSystem()with fs.open(os.path.join(model_path, 'model.pt'), 'rb') as file:
    model.load_state_dict(torch.load(file, map_location=torch.device('cpu')))
```

#### Où SageMaker l'IA stocke vos données sérialisées
<a name="train-remote-decorator-invocation-input-output-storage"></a>

Lorsque vous invoquez une fonction distante, l' SageMaker IA sérialise automatiquement les arguments de votre fonction et renvoie des valeurs pendant les étapes d'entrée et de sortie. Ces données sérialisées sont stockées dans un répertoire racine de votre compartiment S3. Vous spécifiez le répertoire racine, `<s3_root_uri>`, dans un fichier de configuration. Le paramètre `job_name` est automatiquement généré pour vous. 

Dans le répertoire racine, SageMaker AI crée un `<job_name>` dossier contenant votre répertoire de travail actuel, votre fonction sérialisée, les arguments de votre fonction sérialisée, les résultats et toutes les exceptions résultant de l'invocation de la fonction sérialisée.

Sous `<job_name>`, le répertoire `workdir` contient une archive compressée de votre répertoire de travail actuel. L’archive compressée inclut tous les fichiers Python de votre répertoire de travail ainsi que le fichier `requirements.txt`, qui spécifie les dépendances nécessaires pour exécuter votre fonction distante.

Voici un exemple de structure de dossiers sous un compartiment S3 que vous spécifiez dans votre fichier de configuration. 

```
{{<s3_root_uri>}}/ # specified by s3_root_uri or S3RootUri
    <job_name>/ #automatically generated for you
        workdir/workspace.zip # archive of the current working directory (workdir)
        function/ # serialized function
        arguments/ # serialized function arguments
        results/ # returned output from the serialized function including the model
        exception/ # any exceptions from invoking the serialized function
```

Le répertoire racine que vous spécifiez dans votre compartiment S3 n’est pas destiné au stockage à long terme. Les données sérialisées sont étroitement liées à la version Python et à la version du framework de machine learning (ML) utilisées lors de la sérialisation. Si vous mettez à niveau la version Python ou le framework de machine learning, vous ne pourrez peut-être pas utiliser vos données sérialisées. Procédez plutôt comme suit.
+ Stockez votre modèle et les artefacts de votre modèle dans un format indépendant de votre version Python et de votre framework de machine learning.
+ Si vous mettez à niveau votre Python ou framework de machine learning, accédez aux résultats de votre modèle depuis votre stockage à long terme.

**Important**  
Pour supprimer vos données sérialisées après un certain temps, définissez une [configuration à durée de vie](https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-set-lifecycle-configuration-intro.html) sur votre compartiment S3.

**Note**  
Les fichiers sérialisés avec le module Python [pickle](https://docs.python.org/3/library/pickle.html) peuvent être moins portables que d’autres formats de données tels que CSV, Parquet et JSON. Méfiez-vous du chargement de fichiers pickle provenant de sources inconnues.

Pour plus d’informations sur les éléments à inclure dans un fichier de configuration pour une fonction distante, consultez [Fichier de configuration](https://docs.aws.amazon.com/sagemaker/latest/dg/train-remote-decorator-config.html).

#### Accès à vos données sérialisées
<a name="train-remote-decorator-invocation-input-output-access"></a>

Par défaut, SageMaker AI stocke les données sérialisées dans le compartiment SageMaker AI par défaut, qui peut être partagé entre les projets. Pour empêcher toute modification non autorisée, utilisez le `s3_root_uri` paramètre du `@remote` décorateur ou`RemoteExecutor`. Spécifiez un compartiment ou un préfixe S3 dédié pour les arguments, les résultats et les archives de code de vos fonctions sérialisées.

**Important**  
Restreignez l'accès en écriture à l'`s3_root_uri`emplacement pour empêcher toute altération des données sérialisées. Appliquez une politique de [ bucket ](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html) à votre emplacement S3 dédié. Accordez un accès en écriture uniquement au rôle d'exécution de l' SageMaker IA utilisé par vos tâches afin d'empêcher d'autres administrateurs de modifier les données.

L'exemple suivant montre comment spécifier un emplacement S3 dédié avec le `@remote` décorateur :

```
from sagemaker.remote_function import remote

@remote(
    instance_type="{{ml.m5.xlarge}}",
    s3_root_uri="{{s3://amzn-s3-demo-bucket/sagemaker-jobs}}"
)
def my_training_function(data):
    # Your training logic here
    return model
```

Par défaut, AWS Key Management Service (AWS KMS) chiffre les données sérialisées. Vous pouvez configurer l'emplacement de stockage et les paramètres de chiffrement dans un fichier de configuration. Vous pouvez partager le fichier de configuration entre les projets et les tâches. Pour plus d'informations sur le fichier de configuration, voir Fichier [ de configuration](https://docs.aws.amazon.com/sagemaker/latest/dg/train-remote-decorator-config.html).

## Utilisation de l’API `RemoteExecutor` pour invoquer une fonction
<a name="train-remote-decorator-invocation-api"></a>

Vous pouvez utiliser l'`RemoteExecutor`API pour invoquer une fonction. SageMaker Le SDK AI Python transformera le code contenu dans l'`RemoteExecutor`appel en une tâche de formation à l' SageMaker IA. La tâche d’entraînement invoquera ensuite la fonction en tant qu’opération asynchrone et renverra un objet Future. Si vous utilisez l’API `RemoteExecutor`, vous pouvez exécuter plusieurs tâches d’entraînement en parallèle. Pour plus d’informations sur les objets Future dans Python, consultez [Objets Future](https://docs.python.org/3/library/asyncio-future.html).

L'exemple de code suivant montre comment importer les bibliothèques requises, définir une fonction, démarrer une instance d' SageMaker IA et utiliser l'API pour soumettre une demande d'exécution de `2` tâches en parallèle.

```
from sagemaker.remote_function import RemoteExecutor

def matrix_multiply(a, b):
    return np.matmul(a, b)


a = np.array([[1, 0],
             [0, 1]])
b = np.array([1, 2])

with RemoteExecutor(max_parallel_job=2, instance_type="{{ml.m5.large}}") as e:
    future = e.submit(matrix_multiply, a, b)

assert (future.result() == np.array([1,2])).all()
```

La classe `RemoteExecutor` est une implémentation de la bibliothèque [concurrent.futures.Executor](https://docs.python.org/3/library/concurrent.futures.html).

L’exemple de code suivant montre comment définir et appeler une fonction avec `RemoteExecutorAPI`. Dans cet exemple, `RemoteExecutor` soumettra `4` tâches au total, mais uniquement `2` en parallèle. Les deux dernières tâches réutiliseront les clusters avec une surcharge minimale.

```
from sagemaker.remote_function.client import RemoteExecutor

def divide(a, b):
    return a/b 

with RemoteExecutor(max_parallel_job=2, keep_alive_period_in_seconds=60) as e:
    futures = [e.submit(divide, a, 2) for a in [3, 5, 7, 9]]

for future in futures:
    print(future.result())
```

Le paramètre `max_parallel_job` sert uniquement de mécanisme de limitation du débit sans optimiser l’allocation des ressources de calcul. Dans l’exemple de code précédent, `RemoteExecutor` ne réserve pas de ressources de calcul pour les deux tâches parallèles avant que les tâches ne soient soumises. Pour plus d’informations sur `max_parallel_job` ou sur d’autres paramètres du décorateur @remote, consultez [Spécification des classes et méthodes de fonctions distantes](https://sagemaker.readthedocs.io/en/stable/api/sagemaker_train.html).

### Classe Future pour l’API `RemoteExecutor`
<a name="train-remote-decorator-invocation-api-future"></a>

Une classe Future est une classe publique qui représente la fonction de retour de la tâche d’entraînement lorsqu’elle est invoquée de manière asynchrone. La classe Future implémente la classe [concurrent.futures.Future](https://docs.python.org/3/library/concurrent.futures.html). Cette classe peut être utilisée pour effectuer des opérations sur la tâche sous-jacente et charger des données en mémoire.