{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Deploying Voting ensemble Sklearn models on SageMaker"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"rm: cannot remove ‘src’: No such file or directory\r\n"
]
}
],
"source": [
"!rm modelscript_ensemble_sklearn.py\n",
"!rm *.joblib\n",
"!rm src"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.7617053998632947\n"
]
}
],
"source": [
"# Voting Ensemble for Classification\n",
"import pandas\n",
"from sklearn import model_selection\n",
"from sklearn.linear_model import LogisticRegression\n",
"from sklearn.tree import DecisionTreeClassifier\n",
"from sklearn.svm import SVC\n",
"from sklearn.ensemble import VotingClassifier\n",
"\n",
"# Get Data\n",
"url = \"https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv\"\n",
"names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']\n",
"dataframe = pandas.read_csv(url, names=names)\n",
"array = dataframe.values\n",
"X = array[:,0:8]\n",
"Y = array[:,8]\n",
"\n",
"# Fit\n",
"kfold = model_selection.KFold(n_splits=10)\n",
"# create the sub models\n",
"estimators = []\n",
"model1 = LogisticRegression(solver='newton-cg')\n",
"estimators.append(('logistic', model1))\n",
"model2 = DecisionTreeClassifier()\n",
"estimators.append(('cart', model2))\n",
"model3 = SVC()\n",
"estimators.append(('svm', model3))\n",
"# create the ensemble model\n",
"ensemble = VotingClassifier(estimators)\n",
"\n",
"ensemble.fit(X,Y)\n",
"results = model_selection.cross_val_score(ensemble, X, Y, cv=kfold)\n",
"print(results.mean())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Save model files"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mWARNING: You are using pip version 20.3.3; however, version 21.0.1 is available.\r\n",
"You should consider upgrading via the '/home/ec2-user/anaconda3/envs/python3/bin/python -m pip install --upgrade pip' command.\u001b[0m\r\n"
]
}
],
"source": [
"!pip install joblib -q\n",
"from joblib import dump"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"logistic\n",
"cart\n",
"svm\n"
]
},
{
"data": {
"text/plain": [
"['ensemble.joblib']"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"for estimator in ensemble.estimators:\n",
" print(estimator[0])\n",
" dump(estimator[1],estimator[0]+'.joblib')\n",
"\n",
"dump(ensemble,'ensemble.joblib')"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"cart.joblib ensemble.joblib logistic.joblib svm.joblib\r\n"
]
}
],
"source": [
"!ls *.joblib"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([1.])"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ensemble.predict(X[0].reshape(1,8))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 1 : Write a model transform script\n",
"\n",
"#### Make sure you have a ...\n",
"\n",
"- \"load_model\" function\n",
" - input args are model path\n",
" - returns loaded model object\n",
" - model name is the same as what you saved the model file as (see above step)\n",
"
\n",
"- \"predict\" function\n",
" - input args are the loaded model object and a payload\n",
" - returns the result of model.predict\n",
" - make sure you format it as a single (or multiple) string return inside a list for real time (for mini batch)\n",
" - from a client, a list or string or np.array that is sent for prediction is interpreted as bytes. Do what you have to for converting back to list or string or np.array\n",
" - return the error for debugging\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Writing modelscript_ensemble_sklearn.py\n"
]
}
],
"source": [
"%%writefile modelscript_ensemble_sklearn.py\n",
"import sklearn\n",
"from joblib import load\n",
"import numpy as np\n",
"import os\n",
"\n",
"#Return loaded model\n",
"def load_model(modelpath):\n",
" print(modelpath)\n",
" \n",
" # Either load individually\n",
" print(\"loading individuals\")\n",
" logistic = load(os.path.join(modelpath,'logistic.joblib'))\n",
" cart = load(os.path.join(modelpath,'cart.joblib'))\n",
" svm = load(os.path.join(modelpath,'svm.joblib'))\n",
" \n",
" # Or load the entire ensemble\n",
" print(\"loading ensemble\")\n",
" ensemble = load(os.path.join(modelpath,'ensemble.joblib'))\n",
" print(\"loaded\")\n",
" return ensemble\n",
"\n",
"# return prediction based on loaded model (from the step above) and an input payload\n",
"def predict(model, payload):\n",
" try:\n",
" # locally, payload may come in as an np.ndarray\n",
" if type(payload)==np.ndarray:\n",
" out = [str(model.predict(payload.reshape((1,8))))]\n",
" # in remote / container based deployment, payload comes in as a stream of bytes\n",
" else:\n",
"\n",
" out = [str(model.predict(np.frombuffer(payload).reshape((1,8))))]\n",
" except Exception as e:\n",
" out = [type(payload),str(e)] #useful for debugging!\n",
" \n",
" return out"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Does this work locally? (not \"_in a container locally_\", but _actually_ in local)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
".\n",
"loading individuals\n",
"loading ensemble\n",
"loaded\n"
]
}
],
"source": [
"from modelscript_ensemble_sklearn import *\n",
"model = load_model('.')"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['[1.]']"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"predict(model,X[0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### ok great! Now let's install ezsmdeploy\n",
"In some cases, installs fail due to an existing package installed called greenlet.\n",
"This is not a direct dependency of ezsmdeploy but interferes with the installation. \n",
"To fix this, either install in a virtualenv as seen above, or do:\n",
"pip install ezsmdeploy[locust] --ignore-installed greenlet"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mWARNING: Skipping ezsmdeploy as it is not installed.\u001b[0m\n",
"Collecting ezsmdeploy==1.0.8\n",
" Downloading ezsmdeploy-1.0.8-py3-none-any.whl (23 kB)\n",
"Requirement already satisfied: boto3>=1.14.12 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from ezsmdeploy==1.0.8) (1.16.63)\n",
"Requirement already satisfied: shortuuid==1.0.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from ezsmdeploy==1.0.8) (1.0.1)\n",
"Requirement already satisfied: sagemaker-studio-image-build==0.5.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from ezsmdeploy==1.0.8) (0.5.0)\n",
"Requirement already satisfied: yaspin==0.16.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from ezsmdeploy==1.0.8) (0.16.0)\n",
"Requirement already satisfied: sagemaker==2.16.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from ezsmdeploy==1.0.8) (2.16.1)\n",
"Requirement already satisfied: smdebug-rulesconfig==0.1.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from sagemaker==2.16.1->ezsmdeploy==1.0.8) (0.1.5)\n",
"Requirement already satisfied: numpy>=1.9.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from sagemaker==2.16.1->ezsmdeploy==1.0.8) (1.19.5)\n",
"Requirement already satisfied: protobuf>=3.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from sagemaker==2.16.1->ezsmdeploy==1.0.8) (3.14.0)\n",
"Requirement already satisfied: packaging>=20.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from sagemaker==2.16.1->ezsmdeploy==1.0.8) (20.8)\n",
"Requirement already satisfied: importlib-metadata>=1.4.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from sagemaker==2.16.1->ezsmdeploy==1.0.8) (3.4.0)\n",
"Requirement already satisfied: google-pasta in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from sagemaker==2.16.1->ezsmdeploy==1.0.8) (0.2.0)\n",
"Requirement already satisfied: protobuf3-to-dict>=0.1.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from sagemaker==2.16.1->ezsmdeploy==1.0.8) (0.1.5)\n",
"Requirement already satisfied: botocore<1.20.0,>=1.19.63 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from boto3>=1.14.12->ezsmdeploy==1.0.8) (1.19.63)\n",
"Requirement already satisfied: s3transfer<0.4.0,>=0.3.0 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from boto3>=1.14.12->ezsmdeploy==1.0.8) (0.3.4)\n",
"Requirement already satisfied: jmespath<1.0.0,>=0.7.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from boto3>=1.14.12->ezsmdeploy==1.0.8) (0.10.0)\n",
"Requirement already satisfied: urllib3<1.27,>=1.25.4 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from botocore<1.20.0,>=1.19.63->boto3>=1.14.12->ezsmdeploy==1.0.8) (1.26.2)\n",
"Requirement already satisfied: python-dateutil<3.0.0,>=2.1 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from botocore<1.20.0,>=1.19.63->boto3>=1.14.12->ezsmdeploy==1.0.8) (2.8.1)\n",
"Requirement already satisfied: typing-extensions>=3.6.4 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from importlib-metadata>=1.4.0->sagemaker==2.16.1->ezsmdeploy==1.0.8) (3.7.4.3)\n",
"Requirement already satisfied: zipp>=0.5 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from importlib-metadata>=1.4.0->sagemaker==2.16.1->ezsmdeploy==1.0.8) (3.4.0)\n",
"Requirement already satisfied: pyparsing>=2.0.2 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from packaging>=20.0->sagemaker==2.16.1->ezsmdeploy==1.0.8) (2.4.7)\n",
"Requirement already satisfied: six>=1.9 in /home/ec2-user/anaconda3/envs/python3/lib/python3.6/site-packages (from protobuf>=3.1->sagemaker==2.16.1->ezsmdeploy==1.0.8) (1.15.0)\n",
"Installing collected packages: ezsmdeploy\n",
"Successfully installed ezsmdeploy-1.0.8\n",
"\u001b[33mWARNING: You are using pip version 20.3.3; however, version 21.0.1 is available.\n",
"You should consider upgrading via the '/home/ec2-user/anaconda3/envs/python3/bin/python -m pip install --upgrade pip' command.\u001b[0m\n"
]
}
],
"source": [
"!pip uninstall -y ezsmdeploy\n",
"!pip install ezsmdeploy==1.0.8"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"import ezsmdeploy"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### If you have been running other inference containers in local mode, stop existing containers to avoid conflict"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"!docker container stop $(docker container ls -aq) >/dev/null"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Deploy locally"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### tar all models"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"!rm model.tar.gz\n",
"!find ./ -name \"*.joblib\" | tar -czf model.tar.gz -T -"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[K0:00:00.082217 | compressed model(s)\n",
"\u001b[K0:00:00.205353 | uploaded model tarball(s) ; check returned modelpath\n",
"\u001b[K0:00:00.206102 | added requirements file\n",
"\u001b[K0:00:00.207730 | added source file\n",
"\u001b[K0:00:00.208891 | added Dockerfile\n",
"\u001b[K0:00:00.210776 | added model_handler and docker utils\n",
"\u001b[K0:00:00.210855 | building docker container\n",
"\u001b[K0:00:43.321145 | built docker container\n",
"\u001b[K2m∙∙∙\u001b[0m \u001b[K"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"update_endpoint is a no-op in sagemaker>=2.\n",
"See: https://sagemaker.readthedocs.io/en/stable/v2.html for details.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[K0:00:43.453548 | created model(s). Now deploying on local\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[KAttaching to tmpctykbmbm_algo-1-tj704_1\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m Starting the inference server with 64 workers.\n",
"\u001b[32m∙●∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [9] [INFO] Starting gunicorn 20.0.4\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [9] [INFO] Listening at: unix:/tmp/gunicorn.sock (9)\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [9] [INFO] Using worker: gevent\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [13] [INFO] Booting worker with pid: 13\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [14] [INFO] Booting worker with pid: 14\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [15] [INFO] Booting worker with pid: 15\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [16] [INFO] Booting worker with pid: 16\n",
"\u001b[32m∙∙●\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [18] [INFO] Booting worker with pid: 18\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [24] [INFO] Booting worker with pid: 24\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [85] [INFO] Booting worker with pid: 85\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [212] [INFO] Booting worker with pid: 212\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [214] [INFO] Booting worker with pid: 214\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [215] [INFO] Booting worker with pid: 215\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [344] [INFO] Booting worker with pid: 344\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [345] [INFO] Booting worker with pid: 345\n",
"\u001b[32m●∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [409] [INFO] Booting worker with pid: 409\n",
"\u001b[32m∙●∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [476] [INFO] Booting worker with pid: 476\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [666] [INFO] Booting worker with pid: 666\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [730] [INFO] Booting worker with pid: 730\n",
"\u001b[32m∙∙●\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [795] [INFO] Booting worker with pid: 795\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:49 +0000] [796] [INFO] Booting worker with pid: 796\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [923] [INFO] Booting worker with pid: 923\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1115] [INFO] Booting worker with pid: 1115\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1180] [INFO] Booting worker with pid: 1180\n",
"\u001b[32m●∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1244] [INFO] Booting worker with pid: 1244\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1309] [INFO] Booting worker with pid: 1309\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1373] [INFO] Booting worker with pid: 1373\n",
"\u001b[32m∙●∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1438] [INFO] Booting worker with pid: 1438\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1565] [INFO] Booting worker with pid: 1565\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1567] [INFO] Booting worker with pid: 1567\n",
"\u001b[32m∙∙●\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1631] [INFO] Booting worker with pid: 1631\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1695] [INFO] Booting worker with pid: 1695\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1696] [INFO] Booting worker with pid: 1696\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1762] [INFO] Booting worker with pid: 1762\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [1905] [INFO] Booting worker with pid: 1905\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [2018] [INFO] Booting worker with pid: 2018\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [2020] [INFO] Booting worker with pid: 2020\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [2021] [INFO] Booting worker with pid: 2021\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [2086] [INFO] Booting worker with pid: 2086\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [2151] [INFO] Booting worker with pid: 2151\n",
"\u001b[32m●∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [2152] [INFO] Booting worker with pid: 2152\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:50 +0000] [2153] [INFO] Booting worker with pid: 2153\n",
"\u001b[32m∙●∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [2475] [INFO] Booting worker with pid: 2475\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [2474] [INFO] Booting worker with pid: 2474\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [2524] [INFO] Booting worker with pid: 2524\n",
"\u001b[32m∙∙●\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [2540] [INFO] Booting worker with pid: 2540\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [2686] [INFO] Booting worker with pid: 2686\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [2796] [INFO] Booting worker with pid: 2796\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [2797] [INFO] Booting worker with pid: 2797\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [2927] [INFO] Booting worker with pid: 2927\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [2903] [INFO] Booting worker with pid: 2903\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [2929] [INFO] Booting worker with pid: 2929\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3418] [INFO] Booting worker with pid: 3418\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3309] [INFO] Booting worker with pid: 3309\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3478] [INFO] Booting worker with pid: 3478\n",
"\u001b[32m●∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3502] [INFO] Booting worker with pid: 3502\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3501] [INFO] Booting worker with pid: 3501\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3503] [INFO] Booting worker with pid: 3503\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3506] [INFO] Booting worker with pid: 3506\n",
"\u001b[32m∙●∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3634] [INFO] Booting worker with pid: 3634\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3699] [INFO] Booting worker with pid: 3699\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3726] [INFO] Booting worker with pid: 3726\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3744] [INFO] Booting worker with pid: 3744\n",
"\u001b[32m∙∙●\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3844] [INFO] Booting worker with pid: 3844\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [3845] [INFO] Booting worker with pid: 3845\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [4139] [INFO] Booting worker with pid: 4139\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:06:51 +0000] [4301] [INFO] Booting worker with pid: 4301\n",
"\u001b[32m∙●∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m /opt/ml/model\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m loading individuals\n",
"\u001b[32m∙∙●\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m loading ensemble\n",
"\u001b[32m∙∙∙\u001b[0m \u001b[K\u001b[36malgo-1-tj704_1 |\u001b[0m loaded\n",
"!\u001b[36malgo-1-tj704_1 |\u001b[0m 172.18.0.1 - - [12/Feb/2021:01:06:52 +0000] \"GET /ping HTTP/1.1\" 200 1 \"-\" \"python-urllib3/1.26.2\"\n",
"\u001b[K0:00:49.014930 | deployed model\n",
"\u001b[K\u001b[32m0:00:49.015318 | Done! ✔\u001b[0m \n"
]
}
],
"source": [
"ez = ezsmdeploy.Deploy(model = 'model.tar.gz', # if you intend to add models later, pass model as list, otherwise str\n",
" script = 'modelscript_ensemble_sklearn.py',\n",
" requirements = ['scikit-learn=='+sklearn.__version__,'numpy','joblib'], #or pass in the path to requirements.txt\n",
" instance_type = 'local',\n",
" wait = True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Test containerized version locally"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[36malgo-1-tj704_1 |\u001b[0m received input data\r\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m b'\\x00\\x00\\x00\\x00\\x00\\x00\\x18@\\x00\\x00\\x00\\x00\\x00\\x80b@\\x00\\x00\\x00\\x00\\x00\\x00R@\\x00\\x00\\x00\\x00\\x00\\x80A@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xcd\\xcc\\xcc\\xcc\\xcc\\xcc@@\\xaa\\xf1\\xd2Mb\\x10\\xe4?\\x00\\x00\\x00\\x00\\x00\\x00I@'\r\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m /opt/ml/model\r\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m loading individuals\r\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m loading ensemble\r\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m loaded\r\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m predictions from model\r\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m ['[1.]']\r\n"
]
},
{
"data": {
"text/plain": [
"'[1.]'"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[36malgo-1-tj704_1 |\u001b[0m 172.18.0.1 - - [12/Feb/2021:01:07:29 +0000] \"POST /invocations HTTP/1.1\" 200 4 \"-\" \"python-urllib3/1.26.2\"\r\n"
]
}
],
"source": [
"out = ez.predictor.predict(X[0].reshape((1,8)).tobytes()).decode()\n",
"out"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:07:29 +0000] [9] [INFO] Handling signal: term\n",
"\u001b[36malgo-1-tj704_1 |\u001b[0m [2021-02-12 01:07:30 +0000] [212] [INFO] Worker exiting (pid: 212)\n",
"\u001b[36mtmpctykbmbm_algo-1-tj704_1 exited with code 0\n",
"\u001b[0mAborting on container exit...\n"
]
}
],
"source": [
"!docker container stop $(docker container ls -aq) >/dev/null"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Deploy on SageMaker"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[K0:00:00.081814 | compressed model(s)\n",
"\u001b[K0:00:00.277634 | uploaded model tarball(s) ; check returned modelpath\n",
"\u001b[K0:00:00.278338 | added requirements file\n",
"\u001b[K0:00:00.279678 | added source file\n",
"\u001b[K0:00:00.280726 | added Dockerfile\n",
"\u001b[K0:00:00.282357 | added model_handler and docker utils\n",
"\u001b[K0:00:00.282483 | building docker container\n",
"\u001b[K0:00:43.422978 | built docker container\n",
"\u001b[K2m●∙∙\u001b[0m \u001b[K"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"update_endpoint is a no-op in sagemaker>=2.\n",
"See: https://sagemaker.readthedocs.io/en/stable/v2.html for details.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[K0:00:43.630886 | created model(s). Now deploying on ml.m5.xlarge\n",
"\u001b[K0:07:15.817639 | deployed model\n",
"\u001b[K0:07:15.818150 | estimated cost is $0.3 per hour\n",
"\u001b[K\u001b[32m0:07:15.818299 | Done! ✔\u001b[0m \n"
]
}
],
"source": [
"ezonsm = ezsmdeploy.Deploy(model = 'model.tar.gz', \n",
" script = 'modelscript_ensemble_sklearn.py',\n",
" requirements = ['scikit-learn=='+sklearn.__version__,'numpy','joblib'], #or pass in the path to requirements.txt\n",
" prefix = 'testingprefix',\n",
" wait = True)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"# !./src/build-docker.sh test"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'[1.]'"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"out = ezonsm.predictor.predict(X[0].reshape((1,8)).tobytes()).decode()\n",
"out"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"ezonsm.predictor.delete_endpoint()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "conda_python3",
"language": "python",
"name": "conda_python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.10"
}
},
"nbformat": 4,
"nbformat_minor": 4
}