{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f8acc98c-07fe-4d78-abe4-52510e2f7c4d",
   "metadata": {},
   "source": [
    "# YoloV8 Model Inference in Amazon SageMaker\n",
    "This notebook will demonstrate how to create an endpoint for real time inference with the trained YoloV8 (see [1] and [2]) model.\n",
    "\n",
    "References:\n",
    "----\n",
    "[1] https://docs.ultralytics.com/ </br>\n",
    "[2] https://github.com/ultralytics/ultralytics"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ee535e76-caf1-437c-b9cb-911718b13fd0",
   "metadata": {},
   "source": [
    "## 1. SageMaker Initialization\n",
    "First we upgrade SageMaker to the latest version. If your notebook is already using latest Sagemaker 2.x API, you may skip the next cell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a61d6dc-d23a-4ed8-88c6-548ff177d712",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "! pip install --upgrade pip\n",
    "! python3 -m pip install --upgrade sagemaker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6abe8f55-6bd4-442c-b571-7e2a45f220ce",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import boto3\n",
    "import sagemaker\n",
    "from sagemaker import get_execution_role\n",
    "\n",
    "role = (\n",
    "    get_execution_role()\n",
    ")  # provide a pre-existing role ARN as an alternative to creating a new role\n",
    "print(f\"SageMaker Execution Role:{role}\")\n",
    "\n",
    "client = boto3.client('sts')\n",
    "account = client.get_caller_identity()['Account']\n",
    "print(f'AWS account:{account}')\n",
    "\n",
    "session = boto3.session.Session()\n",
    "aws_region = session.region_name\n",
    "print(f\"AWS region:{aws_region}\")\n",
    "\n",
    "container_name = \"inference-container\""
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "cf18f5ea-f785-4c34-a0c3-a8c26a621e7b",
   "metadata": {},
   "source": [
    "## 2. Build, Test and Push Amazon SageMaker Serving Container Images\n",
    "For this step, the [IAM Role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) attached to this Studio notebook needs full access to [Amazon ECR service](https://aws.amazon.com/ecr/) and access to [Amazon EC2 service](https://aws.amazon.com/ec2/). Check this [page](https://github.com/aws-samples/sagemaker-studio-docker-cli-extension#prerequsites) for prerequistes to use this notebook on SageMaker Studio. We use prebuild [YoloV8 docker image](https://hub.docker.com/r/ultralytics/ultralytics/tags) as a base to build on top and configure it to work with SageMaker."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "8f8b31f9-d308-4c11-a6d9-64220d754bbf",
   "metadata": {
    "tags": []
   },
   "source": [
    "### 2.1. Use local Mode to develop and test our code"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "28b0d4ad-72cd-4411-ab19-1c6d6baccbbf",
   "metadata": {},
   "source": [
    "#### 2.1.1. Docker Environment Preparation on SageMaker Studio Notebooks\n",
    "By default, SageMaker Studio does not support docker operations. This [github repo](https://github.com/aws-samples/sagemaker-studio-docker-cli-extension) enables us to build, test and push images on Studio. You can skip this step if you running this notebook on your local machine or on Amazon SageMaker Notebook Instance.\n",
    "</br></br>\n",
    "Run the below cell to clone [SageMaker Studio Docker CLI extension](https://github.com/aws-samples/sagemaker-studio-docker-cli-extension) and install required dependencies missing from **Data Science** kernel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "875f92a5-d391-44f4-94a4-b85ca0eb63e8",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!cd ~ && git clone https://github.com/aws-samples/sagemaker-studio-docker-cli-extension\n",
    "\n",
    "# fix dependancies\n",
    "!conda update --force -y conda\n",
    "!conda install -y pyyaml==5.4.1\n",
    "#!apt-get install -y procps\n",
    "\n",
    "# setup the extension\n",
    "!cd ~/sagemaker-studio-docker-cli-extension && ./setup.sh"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "457c9f8a-608c-4f20-8f5b-1dbb2d80534e",
   "metadata": {},
   "source": [
    "We will use **m5.xlarge** instance to build and test YoloV8 SageMaker docker image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a00eec62-d8a4-4675-a8d0-2b1de6d10e20",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!sdocker create-host --instance-type m5.xlarge"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "5c1885e9-e297-42b0-9765-8c5be5b39776",
   "metadata": {
    "tags": []
   },
   "source": [
    "#### 2.1.2. Build docker image\n",
    "We first build docker image to test it in local mode before deploying it to ECR"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cd53c111-4d14-4a1e-8d05-3c6b8a3e562c",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!cd inference-container && docker build . -t yolov8-sagemaker-inference:latest"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "87edce2a-068f-4236-af2d-0de4a6c1ef79",
   "metadata": {},
   "source": [
    "#### 2.2.1. Create Local Inference Endpoint"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "5e873a86-0b30-441a-83c6-5836cd71445e",
   "metadata": {},
   "source": [
    "##### 2.2.1.1. Define Amazon SageMaker Model\n",
    "We first download pretrained model, then we define SageMaker model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "368662b7-3087-4500-8299-5e6972b9af3e",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!mkdir -p inference-container/model && cd inference-container/model && wget https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8n-pose.pt"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "e850e866",
   "metadata": {},
   "source": [
    "The container can have the following environment variables:\n",
    "\n",
    "| Env           | Value                     |\n",
    "|---------------|---------------------------|\n",
    "| SM_MODEL_NAME | Name of YoloV8 model      |\n",
    "| SM_TRACKING   | `Enabled` or `Disabled`   |\n",
    "| SM_HP_CLASSES | List of classes ex. `[0]` |\n",
    "| SM_HP_CONF    | Default `0.25`            |\n",
    "| SM_HP_IOU     | Default `0.7`             |\n",
    "| SM_HP_HALF    | Default `False`           |\n",
    "| SM_HP_TRACKER | `botsort` or `bytetrack`  |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e7e11a77-6843-4121-b2a8-b18f947e1f66",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from sagemaker.local import LocalSession\n",
    "\n",
    "sagemaker_session = LocalSession()\n",
    "sagemaker_session.config = {'local': {'local_code': True}}\n",
    "\n",
    "image_uri = \"yolov8-sagemaker-inference:latest\"\n",
    "model_name = \"yolov8-model-1\" # set the name of the model\n",
    "\n",
    "model_uri = \"file://inference-container/model/yolov8n-pose.pt\" # define the local pretrained model URI manually.\n",
    "\n",
    "serving_container_def = {\n",
    "    'Image': image_uri,\n",
    "    'ModelDataUrl': model_uri,\n",
    "    'Mode': 'SingleModel',\n",
    "    'Environment': {\n",
    "                    'SM_MODEL_NAME' : 'yolov8n-pose.pt'\n",
    "                   }\n",
    "}\n",
    "\n",
    "create_model_response = sagemaker_session.create_model(name=model_name, \n",
    "                                                       role=role, \n",
    "                                                       container_defs=serving_container_def)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "1edbf312-38ff-4f3b-8bcb-1cc3b72efed9",
   "metadata": {},
   "source": [
    "##### 2.2.1.2. Create Endpoint Configuration\n",
    "Next, we set the name of the Amaozn SageMaker hosted service endpoint configuration.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c0172c8e-b1ad-4aab-884c-e58e8db01773",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "endpoint_config_name = f\"{model_name}-endpoint-config\"\n",
    "print(endpoint_config_name)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "d007261f-0b9a-446c-896f-3bc198ccd707",
   "metadata": {},
   "source": [
    "Then create the local Amazon SageMaker hosted service endpoint configuration that uses one a local endpoint container for testing purposes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f25964e5-b54b-4b00-b001-31f03646490d",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "epc = sagemaker_session.create_endpoint_config(\n",
    "    name=endpoint_config_name,\n",
    "    model_name=model_name,\n",
    "    initial_instance_count=1,\n",
    "    instance_type=\"local\",\n",
    ")\n",
    "print(epc)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "80e9240e-81aa-4f1d-aee3-56d7e98a3355",
   "metadata": {},
   "source": [
    "Next we specify the Amazon SageMaker endpoint name for the endpoint used to serve the model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a85172d9-a58f-438a-86d3-1b724389439f",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "endpoint_name = f\"{model_name}-endpoint\"\n",
    "print(endpoint_name)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "3dd2da8f-7af9-411e-84dc-a7b132533f49",
   "metadata": {},
   "source": [
    "##### 2.2.1.3. Create Endpoint\n",
    "In this step, we create the Amazon SageMaker endpoint using the endpoint configuration we created above."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a8dca9bd-5e9f-4d7f-afc3-e259f32067c5",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "ep = sagemaker_session.create_endpoint(\n",
    "    endpoint_name=endpoint_name, config_name=endpoint_config_name, wait=True\n",
    ")\n",
    "print(ep)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "939acbd0-3e45-4b3d-a9ea-95598f9b035d",
   "metadata": {},
   "source": [
    "### 2.2.2. Test Local Endpoint"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ff70e515-513a-42a8-9435-343f3f8fedf1",
   "metadata": {},
   "source": [
    "#### 2.2.2.1. Visualization Helper Functions\n",
    "Draw the bounding box, pose sekeleton and ID for each tracked object in the raw frames."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4466fe0d-0d23-4f87-85b9-f831f79000f7",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!apt-get update && apt-get install ffmpeg libsm6 libxext6  -y\n",
    "!pip install opencv-python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e1dae137-4a5e-45e3-b0aa-2300909baeca",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "pose_palette = np.array([[255, 128, 0], [255, 153, 51], [255, 178, 102], [230, 230, 0], [255, 153, 255],\n",
    "                                      [153, 204, 255], [255, 102, 255], [255, 51, 255], [102, 178, 255], [51, 153, 255],\n",
    "                                      [255, 153, 153], [255, 102, 102], [255, 51, 51], [153, 255, 153], [102, 255, 102],\n",
    "                                      [51, 255, 51], [0, 255, 0], [0, 0, 255], [255, 0, 0], [255, 255, 255]],\n",
    "                                     dtype=np.uint8)\n",
    "\n",
    "skeleton = [[16, 14], [14, 12], [17, 15], [15, 13], [12, 13], [6, 12], [7, 13], [6, 7], [6, 8], [7, 9],\n",
    "                         [8, 10], [9, 11], [2, 3], [1, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 7]]\n",
    "\n",
    "limb_color = pose_palette[[9, 9, 9, 9, 7, 7, 7, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16]]\n",
    "kpt_color = pose_palette[[16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9]]\n",
    "\n",
    "\n",
    "def get_color(idx):\n",
    "    idx = idx * 3\n",
    "    color = (75, 95, 230)\n",
    "\n",
    "    return color\n",
    "\n",
    "def draw_res(det_boxes, frame, frame_id, image_w):\n",
    "    i = 0\n",
    "    indexIDs = []\n",
    "    boxes = []\n",
    "    person_num = 0\n",
    "    conf = None\n",
    "    text_scale = max(1, image_w / 1600.)\n",
    "    text_thickness = 3\n",
    "    line_thickness = max(3, int(image_w/ 500.))\n",
    "    for det_box in det_boxes:\n",
    "        name, class_id, conf, box, track_id, keypoints = det_box.values()\n",
    "        indexIDs.append(track_id)\n",
    "        x1, y1, x2, y2 = box.values()\n",
    "        intbox = tuple(map(int, (x1, y1, x2, y2)))\n",
    "        textbox = tuple(map(int, (x1 - line_thickness, y1, x2 + line_thickness, y1 - 15)))\n",
    "        color = get_color(abs(int(track_id)))\n",
    "        cv2.rectangle(frame, textbox[0:2], textbox[2:4], color=color, thickness=-1)\n",
    "        cv2.rectangle(frame, intbox[0:2], intbox[2:4], color=color, thickness=line_thickness)\n",
    "        kx = keypoints[\"x\"]\n",
    "        ky = keypoints[\"y\"]\n",
    "        cv2.line(frame, (int(kx[skeleton[-2][0] - 1]), int(ky[skeleton[-2][0] - 1])), (int(kx[skeleton[-2][1] - 1]), int(ky[skeleton[-2][1] - 1])), tuple(limb_color[-2].tolist()), 2)\n",
    "        cv2.line(frame, (int(kx[skeleton[-1][0] - 1]), int(ky[skeleton[-1][0] - 1])), (int(kx[skeleton[-1][1] - 1]), int(ky[skeleton[-1][1] - 1])), tuple(limb_color[-1].tolist()), 2)\n",
    "        for i, (x, y) in enumerate(zip(kx, ky)):\n",
    "            cv2.line(frame, (int(kx[skeleton[i][0] - 1]), int(ky[skeleton[i][0] - 1])), (int(kx[skeleton[i][1] - 1]), int(ky[skeleton[i][1] - 1])), tuple(limb_color[i].tolist()), 2)\n",
    "            cv2.circle(frame, (int(x), int(y)), 3, tuple(kpt_color[i].tolist()), -1)\n",
    "        cv2.putText(frame, f\"ID: {str(track_id)} - {str(round(conf,4))}\", (intbox[0], intbox[1]), cv2.FONT_HERSHEY_PLAIN, text_scale, (255, 255, 255),thickness=2)\n",
    "        cv2.putText(frame, 'frame:{}'.format(frame_id), (int(25), int(25)),0, text_scale, (230,95,75),3)\n",
    "        i += 1\n",
    "    return frame"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "709a937c-6469-4483-8175-1dc395b5098f",
   "metadata": {},
   "source": [
    "#### 2.2.2.2. Invoke endpoint\n",
    "\n",
    "Next, we download a [video](https://motchallenge.net/sequenceVideos/MOT17-09-FRCNN-raw.mp4) from MOT17 dataset to test our endpoint. We create a directory input for saving the processed result, and then download video to input directory with MP4 format."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a04c8591-88ef-425a-a719-f2d532253f6a",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!mkdir -p input\n",
    "!mkdir -p output\n",
    "!cd input && wget \"https://motchallenge.net/sequenceVideos/MOT17-09-FRCNN-raw.mp4\" -O test.mp4"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "acf3803c-cb02-4878-9f21-4f311a0f7df6",
   "metadata": {},
   "source": [
    "After preparing the test data, we invoke the endpoint to run the real time inferece on the test video."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac2547ea-b4fb-4e83-88a5-123985955b1b",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import cv2\n",
    "import json\n",
    "import time\n",
    "import base64\n",
    "\n",
    "sm_runtime = sagemaker_session.sagemaker_runtime_client\n",
    "\n",
    "data_path = \"input/test.mp4\" \n",
    "cap = cv2.VideoCapture(data_path)\n",
    "frame_w  = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))\n",
    "frame_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n",
    "resize_factor = 1\n",
    "\n",
    "fourcc = cv2.VideoWriter_fourcc(*'MP4V')\n",
    "file_path = f\"output/out-t-{time.localtime().tm_min}-{time.localtime().tm_sec}.mp4\" \n",
    "out = cv2.VideoWriter(file_path, fourcc, 25, (int(frame_w / resize_factor), int(frame_h / resize_factor)))\n",
    "\n",
    "processing_time = 0\n",
    "frame_id = 0\n",
    "\n",
    "\n",
    "i = 0\n",
    "while True:\n",
    "    ret, frame = cap.read()\n",
    "    if ret != True:\n",
    "        break\n",
    "    \n",
    "    if resize_factor == 1:\n",
    "        res = frame\n",
    "    else:\n",
    "        res = cv2.resize(frame, dsize=(int(frame_w / resize_factor), int(frame_h / resize_factor)), interpolation=cv2.INTER_CUBIC)\n",
    "    Body = {\"frame_id\": frame_id}\n",
    "    Body[\"frame_w\"] = int(frame_w / resize_factor)\n",
    "    Body[\"frame_h\"] = int(frame_h / resize_factor)\n",
    "    Body[\"frame_data\"] = base64.b64encode(res).decode(\"utf-8\")\n",
    "    \n",
    "    request_time=time.time()\n",
    "    body = json.dumps(Body).encode(\"utf-8\")\n",
    "    response = sm_runtime.invoke_endpoint(EndpointName=ep, Body=body, ContentType=\"application/json\")\n",
    "\n",
    "    if frame_id > 0:\n",
    "        processing_time += (time.time() - request_time)\n",
    "    print(f'frame-{frame_id} Processing time: {(time.time() - request_time)}')\n",
    "    body = response[\"Body\"].read()\n",
    "    msg = body.decode(\"utf-8\")\n",
    "    data = json.loads(msg)\n",
    "    frame_res = draw_res(data[0], res, frame_id, int(frame_w / resize_factor))\n",
    "    out.write(frame_res)\n",
    "    frame_id += 1\n",
    "\n",
    "out.release()\n",
    "cap.release()\n",
    "print('average processing time: ', processing_time/frame_id)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "42a9b8d7-44e8-4a98-94b0-0732aa30719f",
   "metadata": {},
   "source": [
    "#### 2.2.3. Cleanup resources"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0e82166d-bb4a-4377-9b60-0e6e99e5c9af",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "sagemaker_session.delete_model(model_name)\n",
    "sagemaker_session.delete_endpoint_config(epc)\n",
    "sagemaker_session.delete_endpoint(ep)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "b39e44ec-2d80-4607-80fe-0627c7ddd932",
   "metadata": {},
   "source": [
    "### 2.3. Push tested image to ECR\n",
    "Now that we built and tested our image, we can push it to ECR to be able to use it with SageMaker Endpoints"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b4559a54-bbf0-4f08-ba52-a58110614c2c",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "%%bash\n",
    "\n",
    "set -x\n",
    "# This script shows how to build the Docker image and push it to ECR to be ready for use\n",
    "# by SageMaker.\n",
    "\n",
    "image=\"yolov8-sagemaker-inference\"\n",
    "tag=\"latest\"\n",
    "region=$REGION_NAME\n",
    "\n",
    "# Get the account number associated with the current IAM credentials\n",
    "account=$(aws sts get-caller-identity --query Account --output text)\n",
    "\n",
    "if [ $? -ne 0 ]\n",
    "then\n",
    "    exit 255\n",
    "fi\n",
    "\n",
    "\n",
    "fullname=\"${account}.dkr.ecr.${region}.amazonaws.com/${image}:${tag}\"\n",
    "\n",
    "# If the repository doesn't exist in ECR, create it.\n",
    "aws ecr describe-repositories --region ${region} --repository-names \"${image}\" > /dev/null 2>&1\n",
    "if [ $? -ne 0 ]; then\n",
    "    aws ecr create-repository --region ${region} --repository-name \"${image}\" > /dev/null\n",
    "fi\n",
    "\n",
    "\n",
    "# Build the docker image locally with the image name and then push it to ECR\n",
    "# with the full name.\n",
    "\n",
    "docker tag ${image}:${tag} ${fullname}\n",
    "\n",
    "# Get the login command from ECR and execute it directly\n",
    "$(aws ecr get-login --region ${region} --no-include-email)\n",
    "docker push ${fullname}\n",
    "if [ $? -eq 0 ]; then\n",
    "\techo \"Amazon ECR URI: ${fullname}\"\n",
    "else\n",
    "\techo \"Error: Image build and push failed\"\n",
    "\texit 1\n",
    "fi"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ee22e159-68a3-4f12-9cf0-b02635a34d6f",
   "metadata": {},
   "source": [
    "#### 2.3.1. Delete Docker Host\n",
    "Make sure to delete docker host after finishing with local mode to avoid extra charges"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "27d0bb07-9075-419d-b9e6-8574086c6dae",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!sdocker terminate-current-host"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "cff74aa3-c99d-41ca-8fd4-7b45e6103cd2",
   "metadata": {},
   "source": [
    "### 2.4. Deploy on SageMaker Endpoint\n",
    "Now that we pushed the inference image to ECR we can test it on SageMaker. First we package pretrained model into **.tar.gz** archive and upload to s3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7c400171",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "sagemaker_session = sagemaker.session.Session(boto_session=session)\n",
    "s3_bucket_name = sagemaker_session.default_bucket()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41b3ae28-82e4-48af-966d-135d9f7c91aa",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!cd inference-container/model  && tar -czvf model.tar.gz yolov8n-pose.pt && rm yolov8n-pose.pt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f3d7c54-c3f6-4cd1-9bfc-fdac6fa628c4",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!aws s3 cp inference-container/model/model.tar.gz s3://{s3_bucket_name}/yolov8/model/model.tar.gz"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "2430bfcd-4ec2-4000-a5c5-da2a245bac03",
   "metadata": {},
   "source": [
    "#### 2.4.1. Define SageMaker Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "acf0c96e-31d3-418d-a745-018450b596aa",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "image = \"yolov8-sagemaker-inference\"\n",
    "tag = \"latest\"\n",
    "region = os.getenv(\"AWS_REGION\")\n",
    "\n",
    "sagemaker_session = sagemaker.session.Session(boto_session=session)\n",
    "\n",
    "s3_bucket_name = sagemaker_session.default_bucket()\n",
    "\n",
    "image_uri = f\"{account}.dkr.ecr.{region}.amazonaws.com/{image}:{tag}\"\n",
    "model_name = \"yolov8-model-1\" # set the name of the model\n",
    "\n",
    "model_uri = f\"s3://{s3_bucket_name}/yolov8/model/model.tar.gz\" # define the local pretrained model URI manually.\n",
    "\n",
    "serving_container_def = {\n",
    "    'Image': image_uri,\n",
    "    'ModelDataUrl': model_uri,\n",
    "    'Mode': 'SingleModel',\n",
    "    'Environment': {\n",
    "                    'SM_MODEL_NAME' : 'yolov8n-pose.pt',\n",
    "                   }\n",
    "}\n",
    "\n",
    "create_model_response = sagemaker_session.create_model(name=model_name, \n",
    "                                                       role=role, \n",
    "                                                       container_defs=serving_container_def)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "5e7e0b13-f980-4a4f-896f-e829c366fca6",
   "metadata": {},
   "source": [
    "#### 2.4.2. Define SageMaker Endpoint Configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "03e51717-b8ad-4a68-9884-836421bd66f2",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "endpoint_config_name = f\"{model_name}-endpoint-config\"\n",
    "epc = sagemaker_session.create_endpoint_config(\n",
    "    name=endpoint_config_name,\n",
    "    model_name=model_name,\n",
    "    initial_instance_count=1,\n",
    "    instance_type=\"ml.m5.2xlarge\",\n",
    ")\n",
    "print(epc)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "38d44649-9489-4c57-b31a-9676ad271777",
   "metadata": {},
   "source": [
    "#### 2.4.3. Create SageMaker Endpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e4d95ce3-3c9a-44b4-89a0-cbba5d1c48b2",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "endpoint_name = f\"{model_name}-endpoint\"\n",
    "ep = sagemaker_session.create_endpoint(\n",
    "    endpoint_name=endpoint_name, config_name=endpoint_config_name, wait=True\n",
    ")\n",
    "print(ep)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "3ac2b013-16dc-405d-a110-3c459a5d9a50",
   "metadata": {},
   "source": [
    "#### 2.4.3. Test Endpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "49ec18cf-7755-42e1-b93b-75c774cd0bb4",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import cv2\n",
    "import json\n",
    "import time\n",
    "import base64\n",
    "\n",
    "sm_runtime = sagemaker_session.sagemaker_runtime_client\n",
    "\n",
    "data_path = \"input/test.mp4\" \n",
    "cap = cv2.VideoCapture(data_path)\n",
    "frame_w  = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))\n",
    "frame_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n",
    "resize_factor = 1\n",
    "\n",
    "fourcc = cv2.VideoWriter_fourcc(*'MP4V')\n",
    "file_path = f\"output/out-t-{time.localtime().tm_min}-{time.localtime().tm_sec}.mp4\" \n",
    "out = cv2.VideoWriter(file_path, fourcc, 25, (int(frame_w / resize_factor), int(frame_h / resize_factor)))\n",
    "\n",
    "processing_time = 0\n",
    "frame_id = 0\n",
    "\n",
    "\n",
    "i = 0\n",
    "while True:\n",
    "    ret, frame = cap.read()\n",
    "    if ret != True:\n",
    "        break\n",
    "        \n",
    "    if resize_factor == 1:\n",
    "        res = frame\n",
    "    else:\n",
    "        res = cv2.resize(frame, dsize=(int(frame_w / resize_factor), int(frame_h / resize_factor)), interpolation=cv2.INTER_CUBIC)\n",
    "    Body = {\"frame_id\": frame_id}\n",
    "    Body[\"frame_w\"] = int(frame_w / resize_factor)\n",
    "    Body[\"frame_h\"] = int(frame_h / resize_factor)\n",
    "    Body[\"frame_data\"] = base64.b64encode(res).decode(\"utf-8\")\n",
    "    \n",
    "    request_time=time.time()\n",
    "    body = json.dumps(Body).encode(\"utf-8\")\n",
    "    response = sm_runtime.invoke_endpoint(EndpointName=ep, Body=body, ContentType=\"application/json\")\n",
    "\n",
    "    if frame_id > 0:\n",
    "        processing_time += (time.time() - request_time)\n",
    "    print(f'frame-{frame_id} Processing time: {(time.time() - request_time)}')\n",
    "    body = response[\"Body\"].read()\n",
    "    msg = body.decode(\"utf-8\")\n",
    "    data = json.loads(msg)\n",
    "    frame_res = draw_res(data[0], res, frame_id, int(frame_w / resize_factor))\n",
    "    out.write(frame_res)\n",
    "    frame_id += 1\n",
    "\n",
    "out.release()\n",
    "cap.release()\n",
    "print('average processing time: ', processing_time/frame_id)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "814cd422-286b-4f3a-a402-16e827193574",
   "metadata": {},
   "source": [
    "#### 2.4.4. Cleanup resources"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f17a51e-e1c3-4804-ba0a-b3e17b2bcc04",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "sagemaker_session.delete_model(model_name)\n",
    "sagemaker_session.delete_endpoint_config(epc)\n",
    "sagemaker_session.delete_endpoint(ep)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "07972ee7-79a9-4402-aaa0-f6ef86be6c17",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "availableInstances": [
   {
    "_defaultOrder": 0,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.t3.medium",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 1,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.t3.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 2,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.t3.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 3,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.t3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 4,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 5,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 6,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 7,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 8,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 9,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 10,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 11,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 12,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5d.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 13,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5d.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 14,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5d.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 15,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5d.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 16,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5d.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 17,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5d.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 18,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5d.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 19,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 20,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": true,
    "memoryGiB": 0,
    "name": "ml.geospatial.interactive",
    "supportedImageNames": [
     "sagemaker-geospatial-v1-0"
    ],
    "vcpuNum": 0
   },
   {
    "_defaultOrder": 21,
    "_isFastLaunch": true,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.c5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 22,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.c5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 23,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.c5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 24,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.c5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 25,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 72,
    "name": "ml.c5.9xlarge",
    "vcpuNum": 36
   },
   {
    "_defaultOrder": 26,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 96,
    "name": "ml.c5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 27,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 144,
    "name": "ml.c5.18xlarge",
    "vcpuNum": 72
   },
   {
    "_defaultOrder": 28,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.c5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 29,
    "_isFastLaunch": true,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g4dn.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 30,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g4dn.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 31,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g4dn.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 32,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g4dn.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 33,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g4dn.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 34,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g4dn.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 35,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 61,
    "name": "ml.p3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 36,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 244,
    "name": "ml.p3.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 37,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 488,
    "name": "ml.p3.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 38,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.p3dn.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 39,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.r5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 40,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.r5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 41,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.r5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 42,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.r5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 43,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.r5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 44,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.r5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 45,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.r5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 46,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.r5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 47,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 48,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 49,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 50,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 51,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 52,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 53,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.g5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 54,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.g5.48xlarge",
    "vcpuNum": 192
   },
   {
    "_defaultOrder": 55,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 56,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4de.24xlarge",
    "vcpuNum": 96
   }
  ],
  "instance_type": "ml.t3.medium",
  "kernelspec": {
   "display_name": "Python 3 (Data Science)",
   "language": "python",
   "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:ap-southeast-2:452832661640:image/datascience-1.0"
  },
  "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.7.10"
  },
  "toc-autonumbering": false,
  "toc-showtags": false
 },
 "nbformat": 4,
 "nbformat_minor": 5
}