0

Sagemaker で Detectron2 モデルを実装するために、このガイドに従っています。トレーニング側とバッチ変換側の両方で、すべてがうまく見えます。

ただし、コードを少し調整して、ペイロードを送信して呼び出すことができるエンドポイントを作成しようとしましたが、問題が発生しています。

このノートブックの最後で、SageMaker モデル オブジェクトを作成した後:

model = PyTorchModel(
    name="d2-sku110k-model",
    model_data=training_job_artifact,
    role=role,
    sagemaker_session=sm_session,
    entry_point="predict_sku110k.py",
    source_dir="container_serving",
    image_uri=serve_image_uri,
    framework_version="1.6.0",
    code_location=f"s3://{bucket}/{prefix_code}",
)

次のコードを追加しました。

predictor = model.deploy(initial_instance_count=1, instance_type='ml.m5.xlarge')

モデルが正常にデプロイされていることがわかります。

ただし、次のように画像を予測しようとすると:

predictor.predict(input)

次のエラーが表示されます。

ModelError: InvokeEndpoint 操作の呼び出し時にエラーが発生しました (ModelError): メッセージ "Type [application/x-npy] not support this type yet Traceback (most recent call last): File "/opt を含むプライマリからサーバー エラー (500) を受信しました/conda/lib/python3.6/site-packages/sagemaker_inference/transformer.py"、126 行目、変換結果 = self._transform_fn(self._model、input_data、content_type、accept) ファイル"/opt/conda/lib/ python3.6/site-packages/sagemaker_inference/transformer.py"、215 行目、_default_transform_fn data = self._input_fn(input_data, content_type) ファイル "/opt/ml/model/code/predict_sku110k.py"、98 行目input_fn raise ValueError(err_msg) ValueError: タイプ [application/x-npy] はまだこのタイプをサポートしていません

さまざまな入力タイプを試しました: バイトエンコードされた画像 (cv2.imencode('.jpg', cv_img)[1].tobytes() で作成)、numpy 配列、BytesIO オブジェクト (io モジュールで作成) 、フォーム {'input': image} のディクショナリ。ここで、image は以前のいずれかです (これは、この形式が、私が少し前に作成した tensorflow エンドポイントで使用されたためです)。

関連する可能性があると思うので、エントリ ポイントとして使用される推論スクリプトもここにコピー ペーストします。

"""Code used for sagemaker batch transform jobs"""
from typing import BinaryIO, Mapping
import json
import logging
import sys
from pathlib import Path

import numpy as np
import cv2
import torch

from detectron2.engine import DefaultPredictor
from detectron2.config import CfgNode

##############
# Macros
##############

LOGGER = logging.Logger("InferenceScript", level=logging.INFO)
HANDLER = logging.StreamHandler(sys.stdout)
HANDLER.setFormatter(logging.Formatter("%(levelname)s | %(name)s | %(message)s"))
LOGGER.addHandler(HANDLER)

##########
# Deploy
##########
def _load_from_bytearray(request_body: BinaryIO) -> np.ndarray:
    npimg = np.frombuffer(request_body, np.uint8)
    return cv2.imdecode(npimg, cv2.IMREAD_COLOR)


def model_fn(model_dir: str) -> DefaultPredictor:
    r"""Load trained model

    Parameters
    ----------
    model_dir : str
        S3 location of the model directory

    Returns
    -------
    DefaultPredictor
        PyTorch model created by using Detectron2 API
    """
    path_cfg, path_model = None, None
    for p_file in Path(model_dir).iterdir():
        if p_file.suffix == ".json":
            path_cfg = p_file
        if p_file.suffix == ".pth":
            path_model = p_file

    LOGGER.info(f"Using configuration specified in {path_cfg}")
    LOGGER.info(f"Using model saved at {path_model}")

    if path_model is None:
        err_msg = "Missing model PTH file"
        LOGGER.error(err_msg)
        raise RuntimeError(err_msg)
    if path_cfg is None:
        err_msg = "Missing configuration JSON file"
        LOGGER.error(err_msg)
        raise RuntimeError(err_msg)

    with open(str(path_cfg)) as fid:
        cfg = CfgNode(json.load(fid))

    cfg.MODEL.WEIGHTS = str(path_model)
    cfg.MODEL.DEVICE = "cuda" if torch.cuda.is_available() else "cpu"

    return DefaultPredictor(cfg)


def input_fn(request_body: BinaryIO, request_content_type: str) -> np.ndarray:
    r"""Parse input data

    Parameters
    ----------
    request_body : BinaryIO
        encoded input image
    request_content_type : str
        type of content

    Returns
    -------
    np.ndarray
        input image

    Raises
    ------
    ValueError
        ValueError if the content type is not `application/x-image`
    """
    if request_content_type == "application/x-image":
        np_image = _load_from_bytearray(request_body)
    else:
        err_msg = f"Type [{request_content_type}] not support this type yet"
        LOGGER.error(err_msg)
        raise ValueError(err_msg)
    return np_image


def predict_fn(input_object: np.ndarray, predictor: DefaultPredictor) -> Mapping:
    r"""Run Detectron2 prediction

    Parameters
    ----------
    input_object : np.ndarray
        input image
    predictor : DefaultPredictor
        Detectron2 default predictor (see Detectron2 documentation for details)

    Returns
    -------
    Mapping
        a dictionary that contains: the image shape (`image_height`, `image_width`), the predicted
        bounding boxes in format x1y1x2y2 (`pred_boxes`), the confidence scores (`scores`) and the
        labels associated with the bounding boxes (`pred_boxes`)
    """
    LOGGER.info(f"Prediction on image of shape {input_object.shape}")
    outputs = predictor(input_object)
    fmt_out = {
        "image_height": input_object.shape[0],
        "image_width": input_object.shape[1],
        "pred_boxes": outputs["instances"].pred_boxes.tensor.tolist(),
        "scores": outputs["instances"].scores.tolist(),
        "pred_classes": outputs["instances"].pred_classes.tolist(),
    }
    LOGGER.info(f"Number of detected boxes: {len(fmt_out['pred_boxes'])}")
    return fmt_out


# pylint: disable=unused-argument
def output_fn(predictions, response_content_type):
    r"""Serialize the prediction result into the desired response content type"""
    return json.dumps(predictions)

モデルを呼び出すための正しい形式 (またはエンドポイントを使用するようにコードを調整する方法) を指摘できる人はいますか? request_content_type を「application/json」に変更しようと考えていますが、あまり役に立ちません。

編集:この SO スレッドに触発されたソリューションを試しましたが、私の場合はうまくいきませんでした。

4

1 に答える 1