

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.

# Conditions préalables
<a name="neo-deployment-hosting-services-prerequisites"></a>

**Note**  
Suivez les instructions de cette section si vous avez compilé votre modèle à l'aide de AWS SDK pour Python (Boto3) AWS CLI, ou de la console SageMaker AI. 

Pour créer un modèle SageMaker compilé au format NEO, vous avez besoin des éléments suivants :

1. Un URI Amazon ECR d'image Docker. Vous pouvez en sélectionner un répondant à vos besoins dans [cette liste](https://docs.aws.amazon.com/sagemaker/latest/dg/neo-deployment-hosting-services-container-images.html). 

1. Un fichier de script de point d'entrée :

   1. **Pour PyTorch et MXNet modèles :**

      *Si vous avez entraîné votre modèle à l'aide de l' SageMaker IA*, le script d'entraînement doit implémenter les fonctions décrites ci-dessous. Le script d'entraînement sert de script de point d'entrée pendant l'inférence. Dans l'exemple détaillé dans [Formation, compilation et déploiement MNIST avec MXNet Module et SageMaker Neo](https://sagemaker-examples.readthedocs.io/en/latest/sagemaker_neo_compilation_jobs/mxnet_mnist/mxnet_mnist_neo.html), le script d'entraînement (`mnist.py`) implémente les fonctions requises.

      *Si vous n'avez pas entraîné votre modèle à l'aide de l' SageMaker IA*, vous devez fournir un fichier de script de point d'entrée (`inference.py`) qui peut être utilisé au moment de l'inférence. En fonction du framework MXNet ou du script d'inférence PyTorch, l'emplacement du script d'inférence doit être conforme à la structure de [répertoire de modèles du SDK SageMaker Python pour MxNet ou à la structure](https://sagemaker.readthedocs.io/en/stable/frameworks/mxnet/using_mxnet.html#model-directory-structure) de [répertoire de modèles](https://sagemaker.readthedocs.io/en/stable/frameworks/pytorch/using_pytorch.html#model-directory-structure) pour. PyTorch 

      Lorsque vous utilisez des images Neo Inference Optimized Container avec **PyTorch**et **MXNet**sur des types d'instances de CPU et de GPU, le script d'inférence doit implémenter les fonctions suivantes : 
      + `model_fn` : charge le modèle. (Facultatif)
      + `input_fn` : convertit la charge utile de demande entrante en un tableau numpy.
      + `predict_fn` : réalise la prédiction.
      + `output_fn` : convertit la sortie de la prédiction en charge utile de réponse.
      + En variante, vous pouvez définir `transform_fn` de sorte à combiner `input_fn`, `predict_fn` et `output_fn`.

      Vous trouverez ci-dessous des exemples de `inference.py` script dans un répertoire nommé `code` (`code/inference.py`) for **PyTorch et MXNet (Gluon and Module).** Les exemples chargent d'abord le modèle, puis le servent sur des données d'image sur un GPU : 

------
#### [ MXNet Module ]

      ```
      import numpy as np
      import json
      import mxnet as mx
      import neomx  # noqa: F401
      from collections import namedtuple
      
      Batch = namedtuple('Batch', ['data'])
      
      # Change the context to mx.cpu() if deploying to a CPU endpoint
      ctx = mx.gpu()
      
      def model_fn(model_dir):
          # The compiled model artifacts are saved with the prefix 'compiled'
          sym, arg_params, aux_params = mx.model.load_checkpoint('compiled', 0)
          mod = mx.mod.Module(symbol=sym, context=ctx, label_names=None)
          exe = mod.bind(for_training=False,
                         data_shapes=[('data', (1,3,224,224))],
                         label_shapes=mod._label_shapes)
          mod.set_params(arg_params, aux_params, allow_missing=True)
          
          # Run warm-up inference on empty data during model load (required for GPU)
          data = mx.nd.empty((1,3,224,224), ctx=ctx)
          mod.forward(Batch([data]))
          return mod
      
      
      def transform_fn(mod, image, input_content_type, output_content_type):
          # pre-processing
          decoded = mx.image.imdecode(image)
          resized = mx.image.resize_short(decoded, 224)
          cropped, crop_info = mx.image.center_crop(resized, (224, 224))
          normalized = mx.image.color_normalize(cropped.astype(np.float32) / 255,
                                        mean=mx.nd.array([0.485, 0.456, 0.406]),
                                        std=mx.nd.array([0.229, 0.224, 0.225]))
          transposed = normalized.transpose((2, 0, 1))
          batchified = transposed.expand_dims(axis=0)
          casted = batchified.astype(dtype='float32')
          processed_input = casted.as_in_context(ctx)
      
          # prediction/inference
          mod.forward(Batch([processed_input]))
      
          # post-processing
          prob = mod.get_outputs()[0].asnumpy().tolist()
          prob_json = json.dumps(prob)
          return prob_json, output_content_type
      ```

------
#### [ MXNet Gluon ]

      ```
      import numpy as np
      import json
      import mxnet as mx
      import neomx  # noqa: F401
      
      # Change the context to mx.cpu() if deploying to a CPU endpoint
      ctx = mx.gpu()
      
      def model_fn(model_dir):
          # The compiled model artifacts are saved with the prefix 'compiled'
          block = mx.gluon.nn.SymbolBlock.imports('compiled-symbol.json',['data'],'compiled-0000.params', ctx=ctx)
          
          # Hybridize the model & pass required options for Neo: static_alloc=True & static_shape=True
          block.hybridize(static_alloc=True, static_shape=True)
          
          # Run warm-up inference on empty data during model load (required for GPU)
          data = mx.nd.empty((1,3,224,224), ctx=ctx)
          warm_up = block(data)
          return block
      
      
      def input_fn(image, input_content_type):
          # pre-processing
          decoded = mx.image.imdecode(image)
          resized = mx.image.resize_short(decoded, 224)
          cropped, crop_info = mx.image.center_crop(resized, (224, 224))
          normalized = mx.image.color_normalize(cropped.astype(np.float32) / 255,
                                        mean=mx.nd.array([0.485, 0.456, 0.406]),
                                        std=mx.nd.array([0.229, 0.224, 0.225]))
          transposed = normalized.transpose((2, 0, 1))
          batchified = transposed.expand_dims(axis=0)
          casted = batchified.astype(dtype='float32')
          processed_input = casted.as_in_context(ctx)
          return processed_input
      
      
      def predict_fn(processed_input_data, block):
          # prediction/inference
          prediction = block(processed_input_data)
          return prediction
      
      def output_fn(prediction, output_content_type):
          # post-processing
          prob = prediction.asnumpy().tolist()
          prob_json = json.dumps(prob)
          return prob_json, output_content_type
      ```

------
#### [ PyTorch 1.4 and Older ]

      ```
      import os
      import torch
      import torch.nn.parallel
      import torch.optim
      import torch.utils.data
      import torch.utils.data.distributed
      import torchvision.transforms as transforms
      from PIL import Image
      import io
      import json
      import pickle
      
      
      def model_fn(model_dir):
          """Load the model and return it.
          Providing this function is optional.
          There is a default model_fn available which will load the model
          compiled using SageMaker Neo. You can override it here.
      
          Keyword arguments:
          model_dir -- the directory path where the model artifacts are present
          """
      
          # The compiled model is saved as "compiled.pt"
          model_path = os.path.join(model_dir, 'compiled.pt')
          with torch.neo.config(model_dir=model_dir, neo_runtime=True):
              model = torch.jit.load(model_path)
              device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
              model = model.to(device)
      
          # We recommend that you run warm-up inference during model load
          sample_input_path = os.path.join(model_dir, 'sample_input.pkl')
          with open(sample_input_path, 'rb') as input_file:
              model_input = pickle.load(input_file)
          if torch.is_tensor(model_input):
              model_input = model_input.to(device)
              model(model_input)
          elif isinstance(model_input, tuple):
              model_input = (inp.to(device) for inp in model_input if torch.is_tensor(inp))
              model(*model_input)
          else:
              print("Only supports a torch tensor or a tuple of torch tensors")
              return model
      
      
      def transform_fn(model, request_body, request_content_type,
                       response_content_type):
          """Run prediction and return the output.
          The function
          1. Pre-processes the input request
          2. Runs prediction
          3. Post-processes the prediction output.
          """
          # preprocess
          decoded = Image.open(io.BytesIO(request_body))
          preprocess = transforms.Compose([
              transforms.Resize(256),
              transforms.CenterCrop(224),
              transforms.ToTensor(),
              transforms.Normalize(
                  mean=[
                      0.485, 0.456, 0.406], std=[
                      0.229, 0.224, 0.225]),
          ])
          normalized = preprocess(decoded)
          batchified = normalized.unsqueeze(0)
          # predict
          device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
          batchified = batchified.to(device)
          output = model.forward(batchified)
      
          return json.dumps(output.cpu().numpy().tolist()), response_content_type
      ```

------
#### [ PyTorch 1.5 and Newer ]

      ```
      import os
      import torch
      import torch.nn.parallel
      import torch.optim
      import torch.utils.data
      import torch.utils.data.distributed
      import torchvision.transforms as transforms
      from PIL import Image
      import io
      import json
      import pickle
      
      
      def model_fn(model_dir):
          """Load the model and return it.
          Providing this function is optional.
          There is a default_model_fn available, which will load the model
          compiled using SageMaker Neo. You can override the default here.
          The model_fn only needs to be defined if your model needs extra
          steps to load, and can otherwise be left undefined.
      
          Keyword arguments:
          model_dir -- the directory path where the model artifacts are present
          """
      
          # The compiled model is saved as "model.pt"
          model_path = os.path.join(model_dir, 'model.pt')
          device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
          model = torch.jit.load(model_path, map_location=device)
          model = model.to(device)
      
          return model
      
      
      def transform_fn(model, request_body, request_content_type,
                          response_content_type):
          """Run prediction and return the output.
          The function
          1. Pre-processes the input request
          2. Runs prediction
          3. Post-processes the prediction output.
          """
          # preprocess
          decoded = Image.open(io.BytesIO(request_body))
          preprocess = transforms.Compose([
                                      transforms.Resize(256),
                                      transforms.CenterCrop(224),
                                      transforms.ToTensor(),
                                      transforms.Normalize(
                                          mean=[
                                              0.485, 0.456, 0.406], std=[
                                              0.229, 0.224, 0.225]),
                                          ])
          normalized = preprocess(decoded)
          batchified = normalized.unsqueeze(0)
          
          # predict
          device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
          batchified = batchified.to(device)
          output = model.forward(batchified)
          return json.dumps(output.cpu().numpy().tolist()), response_content_type
      ```

------

   1.  **Pour les instances inf1 ou les images de conteneur onnx, xgboost, keras** 

      Pour toutes les autres images de conteneur optimisées pour l'inférence Neo, ou les types d'instances Inferentia, le script de point d'entrée doit mettre en œuvre les fonctions suivantes pour le Runtime Deep Learning Neo : 
      + `neo_preprocess` : convertit la charge utile de demande entrante en un tableau numpy.
      + `neo_postprocess` : convertit la sortie de la prédiction du Runtime Deep Learning Neo dans le corps de la réponse.
**Note**  
Les deux fonctions précédentes n'utilisent aucune des fonctionnalités de MXNet PyTorch, ou TensorFlow.

      Pour obtenir des exemples d’utilisation de ces fonctions, consultez [Exemples de blocs-notes de compilation de modèles Neo](https://docs.aws.amazon.com//sagemaker/latest/dg/neo.html#neo-sample-notebooks). 

   1. **Pour les TensorFlow modèles**

      Si votre modèle nécessite une logique de pré- et de post-traitement personnalisée avant l'envoi des données au modèle, vous devez spécifier un fichier script de point d'entrée `inference.py` utilisable au moment de l'inférence. Le script doit mettre en œuvre une paire de fonctions `input_handler` et `output_handler` ou une seule fonction de gestionnaire. 
**Note**  
Veuillez noter que si la fonction de gestionnaire est mise en œuvre, `input_handler` et `output_handler` sont ignorées. 

      Voici un exemple de code de script `inference.py` que vous pouvez assembler avec le modèle de compilation pour effectuer un pré- et un post-traitement personnalisé sur un modèle de classification d'image. Le client SageMaker AI envoie le fichier image en tant que type de `application/x-image` contenu à la `input_handler` fonction, où il est converti en JSON. Le fichier image converti est ensuite envoyé au [serveur de modèles Tensorflow (TFX)](https://www.tensorflow.org/tfx/serving/api_rest) à l'aide de l'API REST. 

      ```
      import json
      import numpy as np
      import json
      import io
      from PIL import Image
      
      def input_handler(data, context):
          """ Pre-process request input before it is sent to TensorFlow Serving REST API
          
          Args:
          data (obj): the request data, in format of dict or string
          context (Context): an object containing request and configuration details
          
          Returns:
          (dict): a JSON-serializable dict that contains request body and headers
          """
          f = data.read()
          f = io.BytesIO(f)
          image = Image.open(f).convert('RGB')
          batch_size = 1
          image = np.asarray(image.resize((512, 512)))
          image = np.concatenate([image[np.newaxis, :, :]] * batch_size)
          body = json.dumps({"signature_name": "serving_default", "instances": image.tolist()})
          return body
      
      def output_handler(data, context):
          """Post-process TensorFlow Serving output before it is returned to the client.
          
          Args:
          data (obj): the TensorFlow serving response
          context (Context): an object containing request and configuration details
          
          Returns:
          (bytes, string): data to return to client, response content type
          """
          if data.status_code != 200:
              raise ValueError(data.content.decode('utf-8'))
      
          response_content_type = context.accept_header
          prediction = data.content
          return prediction, response_content_type
      ```

      S'il n'y a pas de prétraitement ou de post-traitement personnalisé, le client SageMaker AI convertit l'image du fichier en JSON de la même manière avant de l'envoyer au point de terminaison SageMaker AI. 

      Pour plus d'informations, consultez la section [Déploiement vers TensorFlow des points de terminaison du SDK SageMaker Python](https://sagemaker.readthedocs.io/en/stable/frameworks/tensorflow/deploying_tensorflow_serving.html#providing-python-scripts-for-pre-pos-processing). 

1. L'URI du compartiment Amazon S3 qui contient les artefacts du modèle compilé. 