Example #1
0
    def default_input_fn(self, input_data, content_type):
        """Take request data and deserialize it into an object for prediction.
        When an InvokeEndpoint operation is made against an Endpoint running SageMaker model server,
        the model server receives two pieces of information:

            - The request's content type, for example "application/json"
            - The request data

        The ``input_fn`` is responsible for preprocessing request data before prediction.

        Args:
            input_data (obj): the request data
            content_type (str): the request's content type

        Returns:
            mxnet.nd.array: an MXNet NDArray

        Raises:
            sagemaker_containers.beta.framework.errors.UnsupportedFormatError: if an unsupported
                content type is used.
        """
        if content_type in self.VALID_CONTENT_TYPES:
            np_array = encoders.decode(input_data, content_type)
            return mx.nd.array(np_array).as_in_context(_context())
        else:
            raise errors.UnsupportedFormatError(content_type)
Example #2
0
    def default_input_fn(self, input_data, content_type):
        """Take request data and deserialize it into an object for prediction.
        When an InvokeEndpoint operation is made against an Endpoint running SageMaker model server,
        the model server receives two pieces of information:

            - The request's content type, for example "application/json"
            - The request data

        The ``input_fn`` is responsible for preprocessing request data before prediction.

        Args:
            input_data (obj): the request data
            content_type (str): the request's content type

        Returns:
            mxnet.io.NDArrayIter: data ready for prediction.

        Raises:
            sagemaker_containers.beta.framework.errors.UnsupportedFormatError: if an unsupported
                accept type is used.
        """
        if content_type not in self.VALID_CONTENT_TYPES:
            raise errors.UnsupportedFormatError(content_type)

        np_array = encoders.decode(input_data, content_type)
        ndarray = mx.nd.array(np_array).as_in_context(_context())

        # We require model to only have one input
        [data_shape] = self._model.data_shapes

        # Reshape flattened CSV as specified by the model
        if content_type == content_types.CSV:
            _, target_shape = data_shape
            ndarray = ndarray.reshape(target_shape)

        # Batch size is first dimension of model input
        model_batch_size = data_shape[1][0]
        pad_rows = max(0, model_batch_size - ndarray.shape[0])

        # If ndarray has fewer rows than model_batch_size, then pad it with zeros.
        if pad_rows:
            num_pad_values = pad_rows
            for dimension in ndarray.shape[1:]:
                num_pad_values *= dimension
            padding_shape = tuple([pad_rows] + list(ndarray.shape[1:]))
            padding = mx.ndarray.zeros(shape=padding_shape)
            ndarray = mx.ndarray.concat(ndarray, padding, dim=0)

        model_input = mx.io.NDArrayIter(ndarray, batch_size=model_batch_size,
                                        last_batch_handle='pad')

        if pad_rows:
            # Update the getpad method on the model_input data iterator to return the amount of
            # padding. MXNet will ignore the last getpad() rows during Module predict.
            def _getpad():
                return pad_rows

            model_input.getpad = _getpad

        return model_input
Example #3
0
def request(data, content_type=content_types.JSON):
    data = encoders.encode(data, content_type)
    headers = {'Content-type': content_type, 'Accept': content_type}
    response = requests.post(REQUEST_URL, data=data, headers=headers)

    data = response.text if content_type in content_types.UTF8_TYPES else response.content

    return encoders.decode(data, content_type)
Example #4
0
 def predict(self,X,features_names):
     print("predict")
     r = requests.post(
         self.endpoint+"/invocations",
         json = X.tolist())
     if r.status_code == 200:
         result = encoders.decode(r.content,r.headers.get('content-type'))
         if len(result.shape) == 1:
             result = numpy.expand_dims(result, axis=0)
             return result
     else:
         print("Error from server:",r)
         raise SagemakerServerError(r.json())
def default_input_fn(input_data, content_type):
    """A default input_fn that can handle JSON, CSV and NPZ formats.

    Args:
        input_data: the request payload serialized in the content_type format
        content_type: the request content_type

    Returns: input_data deserialized into torch.FloatTensor or torch.cuda.FloatTensor depending if cuda is available.
    """
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    np_array = encoders.decode(input_data, content_type)
    tensor = torch.FloatTensor(
        np_array) if content_type in content_types.UTF8_TYPES else torch.from_numpy(np_array)
    return tensor.to(device)
Example #6
0
def default_input_fn(input_data, content_type):
    """Takes request data and de-serializes the data into an object for prediction.
        When an InvokeEndpoint operation is made against an Endpoint running SageMaker model server,
        the model server receives two pieces of information:
            - The request Content-Type, for example "application/json"
            - The request data, which is at most 5 MB (5 * 1024 * 1024 bytes) in size.
        The input_fn is responsible to take the request data and pre-process it before prediction.
    Args:
        input_data (obj): the request data.
        content_type (str): the request Content-Type.
    Returns:
        (obj): data ready for prediction.
    """
    np_array = encoders.decode(input_data, content_type)
    return np_array.astype(
        np.float32) if content_type in content_types.UTF8_TYPES else np_array
def main(deploy_data: dict, train_data: dict, capture_prefix: str):
    inference_id_prefix = 'sts_'  # the same used in testendpoint.py

    # Load config from environment and set required defaults
    # AWS especific
    AWS_DEFAULT_REGION = os.getenv('AWS_DEFAULT_REGION', 'eu-west-1')
    AWS_PROFILE = os.getenv('AWS_PROFILE', 'default')
    AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID', None)
    AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY', None)
    b3_session, sm_client, sm_runtime, sm_session = get_sm_session(
        region=AWS_DEFAULT_REGION,
        profile_name=AWS_PROFILE,
        aws_access_key_id=AWS_ACCESS_KEY_ID,
        aws_secret_access_key=AWS_SECRET_ACCESS_KEY)

    # read test data
    test_data = load_dataset(train_data['train']['test'],
                             'test.csv',
                             sagemaker_session=sm_session)
    print(f"Loadding {train_data['train']['test']}")
    Y_val = test_data.iloc[:, 0].to_numpy()
    print(f"Test dataset shape: {Y_val.shape}")

    # list capture files, this is just as an example. Not used right
    # now but could be.
    capture_files = sorted(
        S3Downloader.list("{}/{}".format(
            deploy_data['monitor']['s3_capture_upload_path'],
            deploy_data['endpoint']['name']),
                          sagemaker_session=sm_session))
    # just the files with the prefix
    filtered = list(
        filter(lambda file_name: capture_prefix in file_name, capture_files))
    print(f"Detected {len(filtered)} capture files")

    capture_records = []
    for c_file in filtered:
        print(f"Processing: {c_file}")
        # read the capture data directly from S3
        content = S3Downloader.read_file(c_file, sagemaker_session=sm_session)
        records = [json.loads(l) for l in content.split("\n")[:-1]]

        capture_records.extend(records)

    print(f"No. of records {len(capture_records)} captured")
    captured_predictions = {}

    for obj in capture_records:
        # Extract inference ID
        inference_id = obj["eventMetadata"]["inferenceId"]
        # current version of script start in 1 when id=0
        # remove the prefix and get the id
        req_id = int(inference_id[len(inference_id_prefix):])

        # Extract result given by the model
        Y_pred_value = encoders.decode(
            obj["captureData"]["endpointOutput"]["data"],
            # i have fixed this value here becouse
            # obj["captureData"]["endpointOutput"]["observedContentType"]
            # some times include the encoding like: text/csv; utf-8
            # and encoders.decode() will give error.
            content_types.CSV)
        captured_predictions[req_id] = Y_pred_value  # np.array

    # save and upload the ground truth labels
    print("Generating labels")
    fake_records = []
    for i, label in captured_predictions.items():
        val = ground_truth_with_id(i, label, Y_val, inference_id_prefix)
        fake_records.append(json.dumps(val))

    data_to_upload = "\n".join(fake_records)
    target_s3_uri = "{}/{}/{}.jsonl".format(
        deploy_data['monitor']['ground truth uri'], capture_prefix,
        uuid.uuid4().hex)
    print(f"Uploading ground truth to {target_s3_uri} ...", end="")
    S3Uploader.upload_string_as_file_body(data_to_upload,
                                          target_s3_uri,
                                          sagemaker_session=sm_session)
    print("Done !")
Example #8
0
def default_input_fn(input_data, content_type):
    np_array = encoders.decode(input_data, content_type)
    return np_array.astype(
        np.float32) if content_type in content_types.UTF8_TYPES else np_array