前提条件 - Amazon SageMaker

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

前提条件

注記

AWS SDK for Python (Boto3)、、または SageMaker コンソールを使用してモデルをコンパイルする場合は AWS CLI、このセクションの手順に従います。

SageMaker Neo コンパイルモデルを作成するには、以下が必要です。

  1. Docker イメージ Amazon ECR URI。こちらのリストから、ニーズに合ったものを選択できます。

  2. エントリポイントスクリプトファイル

    1. PyTorch および MXNetモデルの場合:

      を使用してモデルをトレーニングした場合 SageMaker、トレーニングスクリプトは以下で説明する関数を実装する必要があります。トレーニングスクリプトは推論時にエントリポイントスクリプトとして機能します。TrainingMNIST、Compilation、Deployment with MXNet Module および SageMaker Neo に詳述されている例では、トレーニングスクリプト (mnist.py) は必要な関数を実装します。

      を使用してモデルをトレーニングしなかった場合 SageMakerは、推論時に使用できるエントリポイントスクリプト (inference.py) ファイルを指定する必要があります。フレームワーク、MXNetまたは に基づいて PyTorch、推論スクリプトの場所は、 の SageMaker Python SDKモデルディレクトリ構造または のモデルディレクトリ構造 PyTorchに準拠している必要があります。 MxNet

      Neo Inference Optimized Container イメージを PyTorch および GPUインスタンスタイプMXNetCPUで使用する場合、推論スクリプトは次の関数を実装する必要があります。

      • model_fn: モデルをロードします。(オプション)

      • input_fn: 受信リクエストペイロードを numpy 配列に変換します。

      • predict_fn: 予測を実行します。

      • output_fn: 予測出力をレスポンスペイロードに変換します。

      • または、transform_fn を定義して、input_fnpredict_fnoutput_fn を結合します。

      以下は、 および code (Gluon と Modulecode/inference.py) の () という名前のディレクトリ内のinference.pyスクリプトの例です。 PyTorch MXNet この例では、まずモデルをロードし、次に の画像データでモデルを提供します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. inf1 インスタンスまたは ONNX、XGBoost、Keras のコンテナイメージの場合

      その他のすべての Neo 推論最適化コンテナイメージ、または Inferentia インスタンスタイプの場合、エントリポイントスクリプトには次の Neo Deep Learning Runtime 用の関数を実装する必要があります。

      • neo_preprocess: 受信リクエストペイロードを numpy 配列に変換します。

      • neo_postprocess: Neo Deep Learning Runtime の予測出力をレスポンス本体に変換します。

        注記

        上記の 2 つの関数は、MXNet、 PyTorch、または の機能を使用しません TensorFlow。

      これらの関数の使用例については、「Neo モデルコンパイルサンプルノートブック」を参照してください。

    3. TensorFlow モデルの場合

      モデルにデータを送信する前にモデルに前処理および後処理のカスタムロジックが必要である場合は、推論時に使えるエントリポイントスクリプト (inference.py) ファイルを指定する必要があります。スクリプトには input_handler 関数と output_handler 関数のペア、または単一のハンドラ関数のどちらかを実装します。

      注記

      ハンドラ関数が実装されている場合、input_handleroutput_handler は無視されます。

      以下の inference.py スクリプトのコード例は、コンパイルモデルと合わせて、イメージ分類モデルに対するカスタムの前処理および後処理を実行するものです。 SageMaker クライアントはイメージファイルをapplication/x-imageコンテンツタイプとしてinput_handler関数に送信し、そこで に変換されますJSON。変換されたイメージファイルは、 を使用して Tensorflow Model Server (TFX) 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

      カスタムの前処理または後処理がない場合、 SageMaker クライアントはファイルイメージを SageMaker エンドポイントに送信する前にJSON、同様の方法で に変換します。

      詳細については、 SageMaker Python の TensorFlow 「サービスエンドポイントへのデプロイSDK」を参照してください。

  3. コンパイルされたモデルアーティファクトURIを含む Amazon S3 バケット。