{ "cells": [ { "cell_type": "markdown", "id": "89e1fb16", "metadata": {}, "source": [ "\n", "## Bring Your Own Algorithm to SageMaker\n", "### Architecture of this notebook \n", "\n", "\n", "\"architecture\"\n", "\n", "\n", "### 1. Training\n", "a. [Bring Your Own Container](#byoc)\n", "\n", "b. [Training locally](#local_train)\n", "\n", "c. [Trigger remote training job](#remote_train)\n", "\n", "d. [Test locally](#local_test)\n", "\n", "### 2. Deploy EndPoint\n", "[Deploy model to SageMaker Endpoint](#deploy_endpoint)\n", "\n", "### 3. Build Lambda Function\n", "a. [Construct lambda function](#build_lambda_function)\n", "\n", "b. [Test lambda](#lambda_test)\n", "\n", "### 4. Configure API Gateway\n", "\n", "a. [Construct and setting api gateway](#api-gateway)\n", "\n", "b. [Configure for passing binary media to Lambda Function](#binary-content)\n", "\n", "c. [test api gateway](#test-api)\n" ] }, { "cell_type": "markdown", "id": "16465ef9", "metadata": {}, "source": [ "### BYOC (Bring Your Own Container) for Example Audio Classification Algorithm\n", "\n" ] }, { "cell_type": "markdown", "id": "fb3ba248", "metadata": {}, "source": [ "* prepare necessry variables\n", "using `boto3` to get region and account_id for later usage - ECR uri construction " ] }, { "cell_type": "code", "execution_count": null, "id": "59e0ca34", "metadata": {}, "outputs": [], "source": [ "import boto3 \n", "\n", "session = boto3.session.Session()\n", "region = session.region_name\n", "client = boto3.client(\"sts\")\n", "account_id = client.get_caller_identity()[\"Account\"]\n", "algorithm_name = \"vgg16-audio\"" ] }, { "cell_type": "markdown", "id": "d7c8d54f", "metadata": {}, "source": [ "#### 3 elements to build bring your own container \n", "* `build_and_push.sh` is the script communicating with ECR \n", "* `Dockerfile` defines the training and serving environment \n", "* `code/train` and `code/serve` defines entry point of our container " ] }, { "cell_type": "code", "execution_count": null, "id": "25666268", "metadata": { "scrolled": true }, "outputs": [], "source": [ "!./build_and_push.sh" ] }, { "cell_type": "code", "execution_count": null, "id": "a25fdd51", "metadata": {}, "outputs": [], "source": [ "!cat Dockerfile" ] }, { "cell_type": "code", "execution_count": null, "id": "c73d2b73", "metadata": {}, "outputs": [], "source": [ "!cat build_and_push.sh" ] }, { "cell_type": "markdown", "id": "b0409012", "metadata": {}, "source": [ "* construct image uri by account_id, region and algorithm_name" ] }, { "cell_type": "code", "execution_count": null, "id": "b74e5c16", "metadata": {}, "outputs": [], "source": [ "image_uri=f\"{account_id}.dkr.ecr.{region}.amazonaws.com/{algorithm_name}\"\n", "image_uri" ] }, { "cell_type": "markdown", "id": "7ca14500", "metadata": {}, "source": [ "* prepare necessary variables/object for training " ] }, { "cell_type": "code", "execution_count": null, "id": "9da9a16b", "metadata": {}, "outputs": [], "source": [ "import sagemaker \n", "session = sagemaker.session.Session()\n", "bucket = session.default_bucket()" ] }, { "cell_type": "code", "execution_count": null, "id": "2bfb9fc3", "metadata": {}, "outputs": [], "source": [ "from sagemaker import get_execution_role\n", "\n", "role = get_execution_role()\n", "print(role)\n", "\n", "s3_path = f\"s3://{bucket}/data/competition\"\n", "s3_path" ] }, { "cell_type": "markdown", "id": "d9c8cfa9", "metadata": {}, "source": [ "### Dataset Description - \n", "\n", "Dataset used in this workshop can be obtained from [Dog Bark Sound AI competition](https://tbrain.trendmicro.com.tw/Competitions/Details/15) hold by the world leading pet camera brand [Tomofun](https://en.wikipedia.org/wiki/Tomofun). The url below will be invalid after workshop. " ] }, { "cell_type": "code", "execution_count": null, "id": "0b982b91", "metadata": {}, "outputs": [], "source": [ "# s3://tomofun-audio-classification-yianc\n", "# data/data.zip\n", "!wget -O data.zip https://tinyurl.com/ydzvotsd\n", "!unzip data.zip \n", "!aws s3 cp --recursive ./input/data/competition/ $s3_path" ] }, { "cell_type": "markdown", "id": "3c6eb82c", "metadata": {}, "source": [ "### Train model in a docker container with terminal interface \n", "" ] }, { "cell_type": "markdown", "id": "46d54159", "metadata": {}, "source": [ "* start container in interactive mode\n", "```\n", "IMAGE_ID=$(sudo docker images --filter=reference=vgg16-audio --format \"{{.ID}}\")\n", "nvidia-docker run -it -v $PWD:/opt/ml --entrypoint '' $IMAGE_ID bash \n", "```\n", "* train model based on README.md\n", "```\n", "python train.py --csv_path=/opt/ml/input/data/competition/meta_train.csv --data_dir=/opt/ml/input/data/competition/train --epochs=50 --val_split 0.1\n", "```" ] }, { "cell_type": "code", "execution_count": null, "id": "61859c2c", "metadata": {}, "outputs": [], "source": [ "from datetime import datetime\n", "now = datetime.now()\n", "timestamp = datetime.timestamp(now)\n", "job_name = \"audio-{}\".format(str(int(timestamp))) \n", "job_name" ] }, { "cell_type": "markdown", "id": "d4ba9776", "metadata": {}, "source": [ "### Start SageMaker Training Job\n", "\n", "* sagemaker training jobs can run either locally or remotely " ] }, { "cell_type": "code", "execution_count": null, "id": "f5c92feb", "metadata": {}, "outputs": [], "source": [ "mode = 'remote'\n", "if mode == 'local':\n", " csess = sagemaker.local.LocalSession()\n", "else: \n", " csess = session\n", "\n", "print(csess)\n", "estimator = sagemaker.estimator.Estimator( \n", " role=role,\n", " image_uri=image_uri,\n", " instance_count=1,\n", "# instance_type='local_gpu',\n", " instance_type='ml.p3.8xlarge',\n", " sagemaker_session=csess,\n", " volume_size=100, \n", " debugger_hook_config=False\n", " )" ] }, { "cell_type": "code", "execution_count": null, "id": "b2ad6d30", "metadata": {}, "outputs": [], "source": [ "estimator.fit(inputs={\"competition\":s3_path}, job_name=job_name)" ] }, { "cell_type": "code", "execution_count": null, "id": "5d10001b", "metadata": {}, "outputs": [], "source": [ "estimator.model_data" ] }, { "cell_type": "code", "execution_count": null, "id": "2fe806c1", "metadata": {}, "outputs": [], "source": [ "model_s3_path = estimator.model_data\n", "\n", "!aws s3 cp $model_s3_path . \n", "!tar -xvf model.tar.gz\n", "!mkdir -p model \n", "!mv final_model.pkl model/" ] }, { "cell_type": "markdown", "id": "31fdc1f1", "metadata": {}, "source": [ "### Test Model Locally \n", "\n", "\n", "* start container in interactive mode\n", "```\n", "IMAGE_ID=$(sudo docker images --filter=reference=vgg16-audio --format \"{{.ID}}\")\n", "nvidia-docker run -it -v $PWD:/opt/ml --entrypoint '' $IMAGE_ID bash \n", "```\n", "* test model based on README.md\n", "```\n", "python test.py --test_csv /opt/ml/input/data/competition/meta_train.csv --data_dir /opt/ml/input/data/competition/train --model_name VGGish --model_path /opt/ml/model --saved_root results/test --saved_name test_result\n", "```" ] }, { "cell_type": "markdown", "id": "324979a4", "metadata": {}, "source": [ "### Deploy SageMaker Endpoint \n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "ee7dce3a", "metadata": {}, "outputs": [], "source": [ "predictor = estimator.deploy(instance_type='ml.p2.xlarge', initial_instance_count=1, serializer=sagemaker.serializers.IdentitySerializer())\n", "# predictor = estimator.deploy(instance_type='local_gpu', initial_instance_count=1, serializer=sagemaker.serializers.IdentitySerializer())" ] }, { "cell_type": "code", "execution_count": null, "id": "694d5673", "metadata": {}, "outputs": [], "source": [ "endpoint_name = predictor.endpoint_name" ] }, { "cell_type": "markdown", "id": "4ebf4cd3", "metadata": {}, "source": [ "### You can deploy by using model file directly \n", "\n", "The Source code is as below. we can use model locally trained to deploy a sagemaker endpoint " ] }, { "cell_type": "markdown", "id": "3fb6b174", "metadata": {}, "source": [ "#### get example model file from s3 \n", "```\n", "source_model_data_url = 'https://tinyurl.com/yh7tw3hj'\n", "!wget -O model.tar.gz $source_model_data_url\n", "\n", "MODEL_PATH = f's3://{bucket}/model'\n", "model_data_s3_uri = f'{MODEL_PATH}/model.tar.gz'\n", "!aws s3 cp model.tar.gz $model_data_s3_uri\n", "```\n" ] }, { "cell_type": "markdown", "id": "f5d35f98", "metadata": {}, "source": [ "#### build endpoint from the model file \n", "```\n", "import time \n", "\n", "mode = 'remote'\n", "\n", "if mode == 'local':\n", " csess = sagemaker.local.LocalSession()\n", "else:\n", " csess = session\n", "\n", "model = sagemaker.model.Model(image_uri, \n", " model_data = model_data_s3_uri,\n", " role = role,\n", " predictor_cls = sagemaker.predictor.Predictor,\n", " sagemaker_session = csess)\n", "\n", "now = datetime.now()\n", "timestamp = datetime.timestamp(now)\n", "new_endpoint_name = \"audio-{}\".format(str(int(timestamp))) \n", "object_detector = model.deploy(initial_instance_count = 1,\n", " instance_type = 'ml.p2.xlarge',\n", "# instance_type = 'local_gpu',\n", " endpoint_name = new_endpoint_name,\n", " serializer = sagemaker.serializers.IdentitySerializer())\n", "```" ] }, { "cell_type": "markdown", "id": "4ea4712f", "metadata": {}, "source": [ "### You can also update endpoint based on following example code \n", "\n", "```\n", "new_detector = sagemaker.predictor.Predictor(endpoint_name = endpoint_name) \n", "new_detector.update_endpoint(model_name=model.name, initial_instance_count = 1,\n", " instance_type = 'ml.p2.xlarge')\n", "```" ] }, { "cell_type": "code", "execution_count": null, "id": "800266b9", "metadata": {}, "outputs": [], "source": [ "import json \n", "file_name = \"./input/data/competition/train/train_00002.wav\"\n", "with open(file_name, 'rb') as image:\n", " f = image.read()\n", " b = bytearray(f)\n", "results = predictor.predict(b)\n", "detections = json.loads(results)\n", "print(detections) " ] }, { "cell_type": "markdown", "id": "99277225", "metadata": {}, "source": [ "### Create Lambda Function \n", "" ] }, { "cell_type": "code", "execution_count": null, "id": "18eb9018", "metadata": {}, "outputs": [], "source": [ "import time \n", "iam = boto3.client(\"iam\")\n", "\n", "role_name = \"AmazonSageMaker-LambdaExecutionRole\"\n", "assume_role_policy_document = {\n", " \"Version\": \"2012-10-17\",\n", " \"Statement\": [\n", " {\n", " \"Effect\": \"Allow\",\n", " \"Principal\": {\n", " \"Service\": [\"sagemaker.amazonaws.com\", \"lambda.amazonaws.com\"]\n", " },\n", " \"Action\": \"sts:AssumeRole\"\n", " }\n", " ]\n", "}\n", "\n", "create_role_response = iam.create_role(\n", " RoleName = role_name,\n", " AssumeRolePolicyDocument = json.dumps(assume_role_policy_document)\n", ")\n", "\n", "\n", "# Now add S3 support\n", "iam.attach_role_policy(\n", " PolicyArn='arn:aws:iam::aws:policy/AmazonS3FullAccess',\n", " RoleName=role_name\n", ")\n", "\n", "iam.attach_role_policy(\n", " PolicyArn='arn:aws:iam::aws:policy/AmazonSQSFullAccess',\n", " RoleName=role_name\n", ")\n", "\n", "iam.attach_role_policy(\n", " PolicyArn='arn:aws:iam::aws:policy/AmazonSageMakerFullAccess',\n", " RoleName=role_name\n", ")\n", "time.sleep(60) # wait for a minute to allow IAM role policy attachment to propagate\n", "\n", "lambda_role_arn = create_role_response[\"Role\"][\"Arn\"]\n", "print(lambda_role_arn)" ] }, { "cell_type": "code", "execution_count": null, "id": "6176ccc0", "metadata": {}, "outputs": [], "source": [ "%%bash -s \"$bucket\" \n", "cd invoke_endpoint \n", "zip -r invoke_endpoint.zip .\n", "aws s3 cp invoke_endpoint.zip s3://$1/lambda/" ] }, { "cell_type": "code", "execution_count": null, "id": "67438c92", "metadata": {}, "outputs": [], "source": [ "import os\n", "cwd = os.getcwd()\n", "!aws lambda create-function --function-name invoke_endpoint --zip-file fileb://$cwd/invoke_endpoint/invoke_endpoint.zip --handler lambda_function.lambda_handler --runtime python3.7 --role $lambda_role_arn" ] }, { "cell_type": "code", "execution_count": null, "id": "e796c8d7", "metadata": {}, "outputs": [], "source": [ "endpoint_name = predictor.endpoint_name\n", "bucket_key = \"audio-demo\"\n", "variables = f\"ENDPOINT_NAME={endpoint_name}\"\n", "env = \"Variables={\"+variables+\"}\"\n", "\n", "!aws lambda update-function-configuration --function-name invoke_endpoint --environment \"$env\"\n" ] }, { "cell_type": "markdown", "id": "917f4344", "metadata": {}, "source": [ "### Test Material \n", "\n", "```\n", "{\n", " \"content\": \"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\"\n", "}\n", "```" ] }, { "cell_type": "markdown", "id": "7ad204bd", "metadata": {}, "source": [ "### Configure API Gateway \n", "\n", "* Finally, we need an API to have the service accessible\n", "* This API accepts image POST to it and pass the image to ```invoke_image_object_detection```\n", "\n", "```curl -X POST -H 'content-type: application/octet-stream' --data-binary @$f $OD_API | jq .``` \n", "\n", "* we can create it by console also by aws cli " ] }, { "cell_type": "code", "execution_count": null, "id": "3633b5a5", "metadata": {}, "outputs": [], "source": [ "!aws lambda add-permission \\\n", " --function-name invoke_endpoint \\\n", " --action lambda:InvokeFunction \\\n", " --statement-id apigateway \\\n", " --principal apigateway.amazonaws.com \n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "248453d7", "metadata": {}, "outputs": [], "source": [ "!sed \"s//$account_id/g\" latestswagger2-template.json > latestswagger2-tmp.json \n", "!sed \"s//$region/g\" latestswagger2-tmp.json > latestswagger2.json " ] }, { "cell_type": "code", "execution_count": null, "id": "e41a793c", "metadata": {}, "outputs": [], "source": [ "api_info = !aws apigateway import-rest-api \\\n", " --fail-on-warnings \\\n", " --body 'file:////home/ec2-user/SageMaker/incremental-training-mlops/01-byoc/latestswagger2.json' " ] }, { "cell_type": "code", "execution_count": null, "id": "9fe10210", "metadata": {}, "outputs": [], "source": [ "api_info" ] }, { "cell_type": "code", "execution_count": null, "id": "efd65142", "metadata": {}, "outputs": [], "source": [ "api_obj = json.loads(''.join(api_info))\n", "api_id = api_obj['id']\n", "api_id" ] }, { "cell_type": "code", "execution_count": null, "id": "1172b911", "metadata": {}, "outputs": [], "source": [ "!aws apigateway create-deployment --rest-api-id $api_id --stage-name dev" ] }, { "cell_type": "markdown", "id": "a9b544d7", "metadata": {}, "source": [ "### Manually Setup API-Gateway in Console\n", "\n" ] }, { "cell_type": "markdown", "id": "15e0d063", "metadata": {}, "source": [ "#### Create Restful API \n", "\"rest_api\"" ] }, { "cell_type": "markdown", "id": "811cd55d", "metadata": {}, "source": [ "#### Create resource and methods \n", "* click the drop down manual and name your resource \n", "\"create_resource\"\n", "\n", "* focus on the resource just created, click the drop down manual and select create method, then select backend lambda function \n", "\"create_method\"\n", "\"create_method\"\n" ] }, { "cell_type": "markdown", "id": "b3c37d2b", "metadata": {}, "source": [ "### Configurations for passing the binary content to backend\n", "* Add binary media type in ```Settings``` of this API \n", "* Configure which attribute to extract and fill it in event in Lambda integration" ] }, { "cell_type": "markdown", "id": "b0165600", "metadata": {}, "source": [ "\"binary_media\"\n", "\"config\n", "\"config" ] }, { "cell_type": "markdown", "id": "134039cc", "metadata": {}, "source": [ "### Test API Gateway \n", "" ] }, { "cell_type": "code", "execution_count": null, "id": "d35f9bd3", "metadata": {}, "outputs": [], "source": [ "api_endpoint = \"https://{}.execute-api.{}.amazonaws.com/dev/classify\".format(api_id, region)\n", "\n", "!curl -X POST -H 'content-type: application/octet-stream' --data-binary @./input/data/competition/train/train_00002.wav $api_endpoint\n" ] }, { "cell_type": "code", "execution_count": null, "id": "c7b02625", "metadata": {}, "outputs": [], "source": [ "%store endpoint_name \n", "%store lambda_role_arn\n", "%store model_s3_path " ] }, { "cell_type": "code", "execution_count": null, "id": "574e474b", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "conda_pytorch_latest_p36", "language": "python", "name": "conda_pytorch_latest_p36" }, "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.13" } }, "nbformat": 4, "nbformat_minor": 5 }