<jupyter_start><jupyter_text>Lab: Bring your own script with Amazon SageMaker  Sklearn script mode training and servingScript mode is a training script format for a number of supported frameworks that lets you execute the training script in SageMaker with minimal modification. The [SageMaker Python SDK](https://github.com/aws/sagemaker-python-sdk) handles transferring your script to a SageMaker training instance. On the training instance, SageMaker's native SKlearn support sets up training-related environment variables and executes your training script. In this tutorial, we use the SageMaker Python SDK to launch a training job and deploy the trained model.Script mode supports training with a Python script, a Python module, or a shell script. In this example, we use a Python script to train a classification model on the [Iris dataset](https://archive.ics.uci.edu/ml/datasets/iris). In this example, we will show how easily you can train a SageMaker using scikit-learn and with SageMaker Python SDK. In addition, this notebook demonstrates how to perform real time inference with the [SageMaker SKlearn container](https://docs.aws.amazon.com/sagemaker/latest/dg/pre-built-docker-containers-scikit-learn-spark.html).   Set up the environmentLet's start by setting up the environment:<jupyter_code>from sagemaker.sklearn.estimator import SKLearn
from sagemaker import get_execution_role
import os
import tarfile
import pandas as pd
import sagemaker

sagemaker_session = sagemaker.Session()

bucket = sagemaker_session.default_bucket()
#prefix = 'sagemaker/DEMO-BYO'

role = sagemaker.get_execution_role()<jupyter_output><empty_output><jupyter_text>Training datawe download the Iris data from UCI Machine Learning repository directly from the web.<jupyter_code>!wget https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data<jupyter_output>--2021-08-09 07:29:34--  https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data
Resolving archive.ics.uci.edu (archive.ics.uci.edu)... 172.16.17.32
Connecting to archive.ics.uci.edu (archive.ics.uci.edu)|172.16.17.32|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4551 (4.4K) [application/x-httpd-php]
Saving to: ‘iris.data.1’

iris.data.1         100%[===================>]   4.44K  --.-KB/s    in 0s      

2021-08-09 07:29:35 (148 MB/s) - ‘iris.data.1’ saved [4551/4551]<jupyter_text>Train and test splitWe split the data into train and test set<jupyter_code>data = pd.read_csv('iris.data', 
                   names=['sepal length', 'sepal width', 
                          'petal length', 'petal width', 
                          'label'])

# Shuffle the data to make deploy_test samples random
data = data.sample(frac=1).reset_index(drop=True)
train = data[:-10]
test = data[-10:]
train.to_csv('train.csv')
test.to_csv('test.csv')
len(test)<jupyter_output><empty_output><jupyter_text>Load our data to our S3 ready for training using our script.<jupyter_code>import boto3

s3_session = boto3.Session().resource('s3')

s3_session.Bucket(bucket).Object('train/train.csv').upload_file('train.csv')
s3_session.Bucket(bucket).Object('test/test.csv').upload_file('test.csv')<jupyter_output><empty_output><jupyter_text>Construct a script for brining your own SKlearn script to SageMakerYour Scikit-learn training script must be a Python 3.6 compatible source file.The training script is similar to a training script you might run outside of SageMaker, but you can access useful properties about the training environment through various environment variables. For example:- SM_MODEL_DIR: A string representing the path to the directory to write model artifacts to. These artifacts are uploaded to S3 for model hosting.- SM_OUTPUT_DATA_DIR: A string representing the filesystem path to write output artifacts to. Output artifacts may include checkpoints, graphs, and other files to save, not including model artifacts. These artifacts are compressed and uploaded to S3 to the same S3 prefix as the model artifacts.- Supposing two input channels, ‘train’ and ‘test’, were used in the call to the Scikit-learn estimator’s fit() method, the following will be set, following the format “SM_CHANNEL_[channel_name]”:- SM_CHANNEL_TRAIN: A string representing the path to the directory containing data in the ‘train’ channel- SM_CHANNEL_TEST: Same as above, but for the ‘test’ channel.In order to save your trained Scikit-learn model for deployment on SageMaker, your training script should save your model to a certain filesystem path called model_dir. This value is accessible through the environment variable SM_MODEL_DIR.Load the model: before a model can be served, it must be loaded. The SageMaker Scikit-learn model server loads your model by invoking a 'model_fn' function that you must provide in your scriptServe a Model: after the SageMaker model server has loaded your model by calling model_fn, SageMaker will serve your model. Model serving is the process of responding to inference requests, received by SageMaker InvokeEndpoint API calls. The SageMaker Scikit-learn model server breaks request handling into three steps:-input processing,-prediction, and-output processing.Here is the entire script and you can see all these details explained above in the script.<jupyter_code>!pygmentize 'BYO_sklearn_main.py'

sklearn_estimator = SKLearn('BYO_sklearn_main.py',
                            instance_type='ml.m4.xlarge',
                            framework_version='0.20.0',
                            role=role)<jupyter_output><empty_output><jupyter_text>Calling `fit`To start a training job, we call `estimator.fit(training_data_uri)`.An S3 location is used here as the input. fit creates a default channel named 'training', which points to this S3 location. In the training script we can then access the training data from the location stored in SM_CHANNEL_TRAINING. fit accepts a couple other types of input as well. See the API doc [here](https://sagemaker.readthedocs.io/en/stable/estimators.htmlsagemaker.estimator.EstimatorBase.fit) for details.When training starts, the Scikit-learn container executes BYO_sklearn_main.py, passing hyperparameters and model_dir from the estimator as script arguments. Because we didn't define either in this example, no hyperparameters are passed, and model_dir defaults to `s3:///`, so the script execution is as follows:`BYO_sklearn_main.py --model_dir s3:///`When training is complete, the training job will upload the saved model to S3 for deployment.<jupyter_code>sklearn_estimator.fit({'train': 's3://{}/train/train.csv'.format(bucket),
                        'test': 's3://{}/test/test.csv'.format(bucket)})<jupyter_output>2021-08-09 07:29:50 Starting - Starting the training job...
2021-08-09 07:30:14 Starting - Launching requested ML instancesProfilerReport-1628494190: InProgress
...
2021-08-09 07:30:46 Starting - Preparing the instances for training.........
2021-08-09 07:32:15 Downloading - Downloading input data...
2021-08-09 07:32:51 Training - Downloading the training image...
2021-08-09 07:33:18 Training - Training image download completed. Training in progress..[34m2021-08-09 07:33:19,084 sagemaker-containers INFO     Imported framework sagemaker_sklearn_container.training[0m
[34m2021-08-09 07:33:19,087 sagemaker-training-toolkit INFO     No GPUs detected (normal if no gpus installed)[0m
[34m2021-08-09 07:33:19,098 sagemaker_sklearn_container.training INFO     Invoking user training script.[0m
[34m2021-08-09 07:33:19,483 sagemaker-training-toolkit INFO     No GPUs detected (normal if no gpus installed)[0m
[34m2021-08-09 07:33:22,536 sagemaker-training-toolkit INFO     No GPUs detected (n[...]<jupyter_text>DeployWe are now ready to deploy our model to Sagemaker hosting services and make real time predictions<jupyter_code>predictor = sklearn_estimator.deploy(instance_type='ml.m4.xlarge',
                                     initial_instance_count=1)<jupyter_output>-------------!<jupyter_text>Let's now send some data to our model to predict- the data shouldbe sent in the accepted format and the code below just does that.<jupyter_code>test=pd.read_csv("test.csv").values.tolist()
test
request_body = ""
for row in test:
    request_body += ",".join([str(n) for n in row[1:-1]]) + "\n"
request_body = request_body[:-1]

print(request_body)
client = boto3.client('sagemaker-runtime')

endpoint=predictor.endpoint_name


content_type = "text/csv"

response = client.invoke_endpoint(
    EndpointName=endpoint,
    ContentType=content_type,
    Body=request_body
    )

response['Body'].read()<jupyter_output><empty_output><jupyter_text>Bring your own model saved on s3 In the previous section, we have import the model from training to hosting. In this section, we will demonstrate how to bring your own model to an endpoint without the training step. We will use the [SKLearnModel](https://github.com/aws/sagemaker-python-sdk/blob/master/src/sagemaker/sklearn/model.pyL67) class provided by SageMaker python sdk to create the model object.<jupyter_code>from sagemaker.sklearn.model import SKLearnModel
from time import gmtime, strftime

model_name = 'Iris-sklearn-byom-'+ strftime("%Y-%m-%d-%H-%M-%S", gmtime())
model_data = 's3://{}/{}/output/model.tar.gz'.format(bucket,sklearn_estimator.latest_training_job.job_name)

sklearn_model = SKLearnModel(
                    model_data=model_data,
                    role=role,
                    entry_point='BYO_sklearn_main.py',
                    framework_version='0.20.0')
%%time
predictor_byom = sklearn_model.deploy(initial_instance_count=1, instance_type='ml.m4.xlarge')
client = boto3.client('sagemaker-runtime')

endpoint_byom=predictor_byom.endpoint_name
print(endpoint_byom)

content_type = "text/csv"

response_byom = client.invoke_endpoint(
    EndpointName=endpoint,
    ContentType=content_type,
    Body=request_body
    )

response_byom['Body'].read()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09363070122563794, 'fraction_numerical': 0.031946955997588906, 'mean_word_length': 4.552147239263804, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 35, 'https://': 7, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '543679', 'license': 'MIT-0', 'n_tokens_mistral': 3170, 'n_tokens_neox': 2908, 'n_words': 977, 'path': 'byo-sklearn.ipynb', 'repo_name': 'tom5610/amazon-sagemaker-immersion-day', 'size': '9958'}