Prérequis - Amazon SageMaker

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.

Prérequis

Note

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

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

  1. Une image Docker Amazon ECRURI. Vous pouvez en sélectionner un répondant à vos besoins dans cette liste.

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

    1. Pour PyTorch et MXNet modèles :

      Si vous avez entraîné votre modèle en utilisant SageMaker, 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 MNISTEntraînement, compilation et déploiement avec MXNet Module et SageMaker Neo, le script d'entraînement (mnist.py) implémente les fonctions requises.

      Si vous n'avez pas entraîné votre modèle avec SageMaker, vous devez fournir un fichier de script de point d'entrée (inference.py) qui peut être utilisé au moment de l'inférence. Selon le framework MXNet ou le script d'inférence PyTorch, l'emplacement du script d'inférence doit être conforme à la structure de répertoire de SDK modèles SageMaker Python pour MxNet ou à la structure de répertoire de modèles pour PyTorch.

      Lorsque vous utilisez des images Neo Inference Optimized Container avec PyTorchCPUet MXNetsur des types d'GPUinstance, 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.

      Voici 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 diffusent 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
    2. 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, veuillez consulter Neo Model Compilation Sample Notebooks (Exemples de blocs-notes de compilation de modèles Neo).

    3. 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 SageMaker client envoie le fichier image en tant que type de application/x-image contenu à la input_handler fonction, où il est convertiJSON. Le fichier image converti est ensuite envoyé au serveur de modèles Tensorflow (TFX) à l'aide du. REST API

      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 SageMaker client convertit l'image du fichier de la même JSON manière avant de l'envoyer au SageMaker point de terminaison.

      Pour plus d'informations, consultez le Déploiement vers des points TensorFlow de terminaison de service en SageMaker Python SDK.

  3. Le compartiment Amazon S3 URI qui contient les artefacts du modèle compilé.