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)
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
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)
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)
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 !")
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