{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Step 3 of the Workshop \n", "\n", "\n", "## Contents\n", "1. [Introduction](#Introduction)\n", "1. [Step 3 - ML With SageMaker](#Step-3---ML-With-SageMaker)\n", " 1. [Setup](#Setup-and-How-to-Instructions)\n", " 1. [Redshift Data API](#Redshit-Data-API)\n", " 1. [Data Exploration](#Data-Exploration)\n", " 1. [Amazon SageMaker Model Training](#Amazon-SageMaker-Model-Training)\n", " 1. [Create Model](#Create-Model)\n", " 1. [Create Amazon SageMaker Endpoint](#Create-Amazon-SageMaker-Endpoint)\n", "1. [Bring Remote Model to Redshift](#Bring-Remote-Model-to-Redshift)\n", " 1. [Create BYOM](#Create-BYOM)\n", " \n", "\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Introduction\n", "\n", "Using Amazon Sagemaker Studio we are going to complete Step 3. Step 3 is about training and creating a Random Cut Forest Machine Model using Amazon Sagemaker.\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Step 3 - ML With SageMaker\n", "\n", "Amazon SageMaker Random Cut Forest (RCF) is an algorithm designed to detect anomalous data points within a dataset. More details about the data set can be found here [Campaign Data set](https://archive.ics.uci.edu/ml/datasets/bank+marketing)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Setup and How to Instructions\n", "\n", "This notebook uses below parameters which are set by running below code. \n", "\n", "1. REDSHIFT_IAM_ROLE: The IAM role arn attached to Redshift Cluster.\n", "2. REDSHIFT_USER: Database users to run SQL commands\n", "3. REDSHIFT_ENDPOINT: Redshift Cluster end point.\n", "4. SAGEMAKER_S3_BUCKET: S3 Bucket to store training input/output\n", "\n", "## How to Run the commands:\n", "Select your cell and hit **Shift+Enter** or Click on Run button from menu options.</br>\n", "Cell is finished running when * turns into a Number.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Import Libraries and setup buckets" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1- {'Name': 'mod-4d97d0e707c84ed8-redshifts3bucket-1l7ieun44asq', 'CreationDate': datetime.datetime(2021, 10, 22, 3, 31, 32, tzinfo=tzlocal())}\n", "2- mod-4d97d0e707c84ed8-redshifts3bucket-1l7ieun44asq\n" ] } ], "source": [ "import boto3\n", "import time\n", "import pandas as pd\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import json\n", "import botocore\n", "import sagemaker\n", "import sys\n", "\n", "\n", "session = boto3.session.Session()\n", "region = session.region_name\n", "\n", "def get_workshop_parameters():\n", " s3 = boto3.client('s3')\n", " response = s3.list_buckets()\n", " for bucket in response['Buckets']:\n", " print('1-',bucket)\n", " if 'mod' in bucket[\"Name\"]:\n", " s3_bucket= bucket[\"Name\"]\n", " print('2-',s3_bucket)\n", " break\n", " obj = s3.get_object(Bucket=s3_bucket, Key='workshop/sagemaker_config.json')\n", " config = json.loads(obj['Body'].read().decode('utf-8'))\n", " return config\n", "\n", "config = get_workshop_parameters()\n", "\n", "REDSHIFT_IAM_ROLE=config.get('REDSHIFT_IAM_ROLE')\n", "REDSHIFT_USER=config.get('REDSHIFT_USER')\n", "REDSHIFT_ENDPOINT = config.get('REDSHIFT_ENDPOINT')\n", "SAGEMAKER_S3_BUCKET=config.get('SAGEMAKER_S3_BUCKET')\n", "SAGEMAKER_ENDPOINT=config.get('SAGEMAKER_ENDPOINT')\n", "\n", "bucket = SAGEMAKER_S3_BUCKET\n", "prefix = \"sagemaker/rcf-marketing-campaign\"\n", "execution_role = sagemaker.get_execution_role()\n", "region = boto3.Session().region_name" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Redshift Data API" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this step, we are creating function run_sql, which we will use to get SQL query output directly into pandas dataframe. We will also use this function to run DDL statements" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def run_sql(sql_text):\n", " client = boto3.client(\"redshift-data\")\n", " res = client.execute_statement(Database=REDSHIFT_ENDPOINT.split('/')[1], DbUser=REDSHIFT_USER, Sql=sql_text,\n", " ClusterIdentifier=REDSHIFT_ENDPOINT.split('.')[0])\n", " query_id = res[\"Id\"]\n", " done = False\n", " while not done:\n", " time.sleep(1)\n", " status_description = client.describe_statement(Id=query_id)\n", " status = status_description[\"Status\"]\n", " if status == \"FAILED\":\n", " raise Exception('SQL query failed:' + query_id + \": \" + status_description[\"Error\"])\n", " elif status == \"FINISHED\":\n", " if status_description['ResultRows']>0:\n", " results = client.get_statement_result(Id=query_id)\n", " metadata=dict()\n", " column_labels = []\n", " #dtypes = []\n", " for i in range(len(results[\"ColumnMetadata\"])): column_labels.append(results[\"ColumnMetadata\"][i]['label'])\n", " for i in range(len(results[\"ColumnMetadata\"])): \n", " if (results[\"ColumnMetadata\"][i]['typeName'])=='varchar':\n", " typ='str'\n", " elif ((results[\"ColumnMetadata\"][i]['typeName'])=='int4' or (results[\"ColumnMetadata\"][i]['typeName'])=='numeric') :\n", " typ='float'\n", " else:\n", " typ = 'str'\n", " metadata[results[\"ColumnMetadata\"][i]['label']]=typ \n", " #dtypes.append(typ)\n", " \n", " \n", " records = []\n", " \n", " for record in results.get('Records'):\n", " records.append([list(rec.values())[0] for rec in record])\n", " df = pd.DataFrame(np.array(records), columns=column_labels)\n", " df = df.astype(metadata)\n", " return df\n", " else:\n", " return query_id\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data Exploration\n", "\n", "Data set is alerady loaded on Amazon Data warehouse. Kim loads the campaign data-set into a Data frame using a call to Redshift Data API and explore it.\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>customerid</th>\n", " <th>serialnumber</th>\n", " <th>age</th>\n", " <th>job</th>\n", " <th>marital</th>\n", " <th>education</th>\n", " <th>is_default</th>\n", " <th>balance</th>\n", " <th>housing</th>\n", " <th>loan</th>\n", " <th>contact</th>\n", " <th>day</th>\n", " <th>month</th>\n", " <th>duration</th>\n", " <th>campaign</th>\n", " <th>days_since_last_contact</th>\n", " <th>previous</th>\n", " <th>poutcome</th>\n", " <th>accepted</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>0178-SZBHO</td>\n", " <td>102.0</td>\n", " <td>40.0</td>\n", " <td>entrepreneur</td>\n", " <td>married</td>\n", " <td>tertiary</td>\n", " <td>no</td>\n", " <td>3571.0</td>\n", " <td>no</td>\n", " <td>no</td>\n", " <td>unknown</td>\n", " <td>9.0</td>\n", " <td>jun</td>\n", " <td>222.0</td>\n", " <td>3.0</td>\n", " <td>-1.0</td>\n", " <td>0.0</td>\n", " <td>unknown</td>\n", " <td>no</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>0181-RITDD</td>\n", " <td>103.0</td>\n", " <td>48.0</td>\n", " <td>technician</td>\n", " <td>divorced</td>\n", " <td>secondary</td>\n", " <td>yes</td>\n", " <td>20.0</td>\n", " <td>no</td>\n", " <td>no</td>\n", " <td>cellular</td>\n", " <td>27.0</td>\n", " <td>aug</td>\n", " <td>145.0</td>\n", " <td>3.0</td>\n", " <td>-1.0</td>\n", " <td>0.0</td>\n", " <td>unknown</td>\n", " <td>no</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>0186-CAERR</td>\n", " <td>104.0</td>\n", " <td>51.0</td>\n", " <td>unemployed</td>\n", " <td>married</td>\n", " <td>tertiary</td>\n", " <td>no</td>\n", " <td>1634.0</td>\n", " <td>yes</td>\n", " <td>no</td>\n", " <td>cellular</td>\n", " <td>22.0</td>\n", " <td>jul</td>\n", " <td>168.0</td>\n", " <td>4.0</td>\n", " <td>-1.0</td>\n", " <td>0.0</td>\n", " <td>unknown</td>\n", " <td>no</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>0187-QSXOE</td>\n", " <td>105.0</td>\n", " <td>27.0</td>\n", " <td>admin.</td>\n", " <td>married</td>\n", " <td>secondary</td>\n", " <td>no</td>\n", " <td>-247.0</td>\n", " <td>yes</td>\n", " <td>yes</td>\n", " <td>unknown</td>\n", " <td>4.0</td>\n", " <td>jun</td>\n", " <td>344.0</td>\n", " <td>2.0</td>\n", " <td>-1.0</td>\n", " <td>0.0</td>\n", " <td>unknown</td>\n", " <td>no</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>0187-WZNAB</td>\n", " <td>106.0</td>\n", " <td>32.0</td>\n", " <td>unemployed</td>\n", " <td>single</td>\n", " <td>secondary</td>\n", " <td>no</td>\n", " <td>0.0</td>\n", " <td>no</td>\n", " <td>no</td>\n", " <td>cellular</td>\n", " <td>27.0</td>\n", " <td>may</td>\n", " <td>123.0</td>\n", " <td>2.0</td>\n", " <td>-1.0</td>\n", " <td>0.0</td>\n", " <td>unknown</td>\n", " <td>no</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " customerid serialnumber age job marital education \\\n", "0 0178-SZBHO 102.0 40.0 entrepreneur married tertiary \n", "1 0181-RITDD 103.0 48.0 technician divorced secondary \n", "2 0186-CAERR 104.0 51.0 unemployed married tertiary \n", "3 0187-QSXOE 105.0 27.0 admin. married secondary \n", "4 0187-WZNAB 106.0 32.0 unemployed single secondary \n", "\n", " is_default balance housing loan contact day month duration campaign \\\n", "0 no 3571.0 no no unknown 9.0 jun 222.0 3.0 \n", "1 yes 20.0 no no cellular 27.0 aug 145.0 3.0 \n", "2 no 1634.0 yes no cellular 22.0 jul 168.0 4.0 \n", "3 no -247.0 yes yes unknown 4.0 jun 344.0 2.0 \n", "4 no 0.0 no no cellular 27.0 may 123.0 2.0 \n", "\n", " days_since_last_contact previous poutcome accepted \n", "0 -1.0 0.0 unknown no \n", "1 -1.0 0.0 unknown no \n", "2 -1.0 0.0 unknown no \n", "3 -1.0 0.0 unknown no \n", "4 -1.0 0.0 unknown no " ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "marketing_data = run_sql('Select * from marketing_campaign_raw_data ;')\n", "marketing_data.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Investigate the data. \n", "Look for patterns or issues in underlying data. Balance attribute shows significant spike." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "<AxesSubplot:>" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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TZ/R8uXLGThwINOmTeOWW27h6NGjPPXUUwC88Uauh3QXKCIiglmzZlG1alV2797N0KFDiYiIYMwY09MwHnnkEW666Sa++OIL/P392bFjBwEBAXTs2JGPP/6Y119/nYMHTQNVh4eHF1jeoEGDWL9+PdOmTePGG28kJiaG+Ph4AM6cOUOvXr0YPHgw3377LQcOHGDo0KEEBwfbBDKzZ89m1KhRbNy4kb///ZuhTwzlprY30fi+xmzevJlKlSoxc+ZM7rjjDvz9/QFITk6mV69evPPOOwQHBzN79mx69+7NwYMHqVmzZr51q1GjBj/99BP33XcfBw8eJDIykpCQEJe3tSsk2BBClCo6y8jZ19cVnNDNqr7VERXo71Ta5ORkvv76a7799ltuv/12wHTAqV69uiXNkCFDLH/XrVuXadOm0bZtW5KTkwkPD+fxxx/n9ddfZ9OmTbRt25asrCzmzp3L5MmTATh58iTR0dF0796dgIAAatasSdu2bQus28mTJwkLC+Puu+8mIiKCWrVqcdNNN+W7TK9evXjuuecAU8vC1KlTWb16NY0aNeK7777jwoULbN682XIJpl69epZl3333Xf7zn//w2GOPWdb17bffZsyYMYUKNl577TXL37Vr1+all15i4cKFlmDj5MmTjB49mkaNGgFQv359S/qoqCiUUkRH2z9L1LFDhw7x/fffs3LlSrp3726pf47PP/+cGjVq8Omnn6KUolGjRpw9e5axY8fy+uuv4+dnurjQvHlzy7rWrFOTj6d/zMa/N/LEfU9QsWJFAMqWLWtTrxtvvJEbb7zR8v6dd95h0aJFLF68mGHDhhVYt5zPolKlSsXST0UuowghRDE7evQomZmZdOjQwTKtfPnyNGzY0PJ++/bt9OnTh1q1ahEREUHXrl0B08ESoEqVKtx111188803ACxZsoT09HQeeOABAB544AHS0tKoW7cuQ4cOZdGiRU5dmrj99tupVasWdevW5dFHH2XevHmkpqbmu0zz5s0tf+ccrHMu+ezYsYObbropz74eW7du5a233iI8PNzyGjp0KOfOnSuwXEd+/PFHOnXqRHR0NOHh4YwfP96yzQBGjRrFk08+Sffu3Zk4caLlklNh7NixA39/f7p06eJw/v79++nQoYNNi9fNN99McnIyp0+ftkyz3n4AFStX5GL8xXzLTklJYcyYMTRp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\n", "text/plain": [ "<Figure size 600x400 with 1 Axes>" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "\n", "import matplotlib\n", "import matplotlib.pyplot as plt\n", "\n", "matplotlib.rcParams[\"figure.dpi\"] = 100\n", "\n", "marketing_data.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Preparing the data for Machine Learning " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For machine learning model we need to one hot encode the values, marketing_campaing data set is already hot encoded using Redshift SQL and is in view marketing_campaign_encoded_data. Kim loads this data into a data frame to train the Random Cut Forest Model.\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>age</th>\n", " <th>balance</th>\n", " <th>day</th>\n", " <th>duration</th>\n", " <th>campaign</th>\n", " <th>days_since_last_contact</th>\n", " <th>previous</th>\n", " <th>job_blue_collor</th>\n", " <th>job_entrepreneur</th>\n", " <th>job_housemaid</th>\n", " <th>...</th>\n", " <th>marital_married</th>\n", " <th>marital_single</th>\n", " <th>education_secondary</th>\n", " <th>education_tertiary</th>\n", " <th>education_unknown</th>\n", " <th>default_yes</th>\n", " <th>housing_yes</th>\n", " <th>loan_yes</th>\n", " <th>contact_telephone</th>\n", " <th>contact_unknown</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>40.0</td>\n", " <td>3571.0</td>\n", " <td>9.0</td>\n", " <td>222.0</td>\n", " <td>3.0</td>\n", " <td>-1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>...</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>48.0</td>\n", " <td>20.0</td>\n", " <td>27.0</td>\n", " <td>145.0</td>\n", " <td>3.0</td>\n", " <td>-1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>...</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>51.0</td>\n", " <td>1634.0</td>\n", " <td>22.0</td>\n", " <td>168.0</td>\n", " <td>4.0</td>\n", " <td>-1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>...</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>27.0</td>\n", " <td>-247.0</td>\n", " <td>4.0</td>\n", " <td>344.0</td>\n", " <td>2.0</td>\n", " <td>-1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>...</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>32.0</td>\n", " <td>0.0</td>\n", " <td>27.0</td>\n", " <td>123.0</td>\n", " <td>2.0</td>\n", " <td>-1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>...</td>\n", " <td>0.0</td>\n", " <td>1.0</td>\n", " <td>1.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "<p>5 rows × 39 columns</p>\n", "</div>" ], "text/plain": [ " age balance day duration campaign days_since_last_contact previous \\\n", "0 40.0 3571.0 9.0 222.0 3.0 -1.0 0.0 \n", "1 48.0 20.0 27.0 145.0 3.0 -1.0 0.0 \n", "2 51.0 1634.0 22.0 168.0 4.0 -1.0 0.0 \n", "3 27.0 -247.0 4.0 344.0 2.0 -1.0 0.0 \n", "4 32.0 0.0 27.0 123.0 2.0 -1.0 0.0 \n", "\n", " job_blue_collor job_entrepreneur job_housemaid ... marital_married \\\n", "0 0.0 1.0 0.0 ... 1.0 \n", "1 0.0 0.0 0.0 ... 0.0 \n", "2 0.0 0.0 0.0 ... 1.0 \n", "3 0.0 0.0 0.0 ... 1.0 \n", "4 0.0 0.0 0.0 ... 0.0 \n", "\n", " marital_single education_secondary education_tertiary education_unknown \\\n", "0 0.0 0.0 1.0 0.0 \n", "1 0.0 1.0 0.0 0.0 \n", "2 0.0 0.0 1.0 0.0 \n", "3 0.0 1.0 0.0 0.0 \n", "4 1.0 1.0 0.0 0.0 \n", "\n", " default_yes housing_yes loan_yes contact_telephone contact_unknown \n", "0 0.0 0.0 0.0 0.0 1.0 \n", "1 1.0 0.0 0.0 0.0 0.0 \n", "2 0.0 1.0 0.0 0.0 0.0 \n", "3 0.0 1.0 1.0 0.0 1.0 \n", "4 0.0 0.0 0.0 0.0 0.0 \n", "\n", "[5 rows x 39 columns]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "marketing_encoded_data = run_sql(\"\"\"\n", "select\n", " age, \n", " balance, \n", " day,\n", " duration,\n", " campaign,\n", " days_since_last_contact,\n", " previous,\n", " case when job ='blue-collar' then 1 else 0 end as job_blue_collor,\n", " case when job ='entrepreneur' then 1 else 0 end as job_entrepreneur,\n", " case when job ='housemaid' then 1 else 0 end as job_housemaid,\n", " case when job ='management' then 1 else 0 end as job_management,\n", " case when job ='retired' then 1 else 0 end as job_retired,\n", " case when job ='self-employed' then 1 else 0 end as job_self_employed,\n", " case when job ='student'then 1 else 0 end as job_student,\n", " case when job ='technician' then 1 else 0 end as job_technician,\n", " case when job ='unemployed' then 1 else 0 end as job_unemployed,\n", " case when job ='unknown' then 1 else 0 end as job_unknown,\n", " case when job ='services' then 1 else 0 end as job_services,\n", " case when month='jan' Then 1 else 0 end as month_jan,\n", " case when month='feb' Then 1 else 0 end as month_feb,\n", " case when month='mar' Then 1 else 0 end as month_mar,\n", " case when month='may' Then 1 else 0 end as month_may,\n", " case when month='jun' Then 1 else 0 end as month_jun,\n", " case when month='jul' Then 1 else 0 end as month_jul,\n", " case when month='aug' Then 1 else 0 end as month_aug,\n", " case when month='sep' Then 1 else 0 end as month_sep,\n", " case when month='oct' Then 1 else 0 end as month_oct,\n", " case when month='nov' Then 1 else 0 end as month_nov,\n", " case when month='dec' Then 1 else 0 end as month_dec,\n", " case when marital='married' Then 1 else 0 end as marital_married,\n", " case when marital='single' Then 1 else 0 end as marital_single,\n", " case when education='secondary' Then 1 else 0 end as education_secondary,\n", " case when education='tertiary' Then 1 else 0 end as education_tertiary,\n", " case when education='unknown' Then 1 else 0 end as education_unknown,\n", " case when is_default='yes' Then 1 else 0 end as default_yes,\n", " case when housing='yes' Then 1 else 0 end as housing_yes,\n", " case when loan='yes' Then 1 else 0 end as loan_yes,\n", " case when contact='telephone' Then 1 else 0 end as contact_telephone,\n", " case when contact='unknown' Then 1 else 0 end as contact_unknown\n", "from marketing_campaign_raw_data;\n", "\"\"\"\n", ")\n", "marketing_encoded_data.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Amazon SageMaker Model Training\n", "## Note:\n", "- Create Model and Create Amazon SageMaker Endpoint creation takes about **10 to 15 minutes**. To save your time we already precreated the model and endpoint. You can initiate below Create Model command and then move a head to [Step-4: Bring Remote Model to Redshift](#Step-4:-Bring-Remote-Model-to-Redshift). When you have a momment you can come back and check the status of Create Model and continue with rest of steps provided here.\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create Model and Amazon SageMaker Endpoint\n", "\n", "Next, we configure a SageMaker training job to train the Random Cut Forest (RCF) algorithm onto the Marketing Campaign Data. After that, we will create an inference endpoint using the SageMaker Python SDK `deploy()` function from that job. \n", "\n", "We specify the instance type where inference is computed as well as an initial number of instances to spin up. We used a single node of `ml.m4.xlarge` instance type for that.\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Defaulting to the only supported framework/algorithm version: 1. Ignoring framework/algorithm version: 1.\n", "Defaulting to the only supported framework/algorithm version: 1. Ignoring framework/algorithm version: 1.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "2021-10-22 19:58:48 Starting - Starting the training job...\n", "2021-10-22 19:59:11 Starting - Launching requested ML instancesProfilerReport-1634932728: InProgress\n", ".........\n", "2021-10-22 20:00:40 Starting - Preparing the instances for training............\n", "2021-10-22 20:02:32 Downloading - Downloading input data...\n", "2021-10-22 20:03:12 Training - Downloading the training image...\n", "2021-10-22 20:03:46 Uploading - Uploading generated training model\n", "2021-10-22 20:03:46 Completed - Training job completed\n", ".." ] }, { "name": "stderr", "output_type": "stream", "text": [ "Defaulting to the only supported framework/algorithm version: 1. Ignoring framework/algorithm version: 1.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Training seconds: 86\n", "Billable seconds: 86\n", "-------!" ] }, { "name": "stderr", "output_type": "stream", "text": [ "The endpoint attribute has been renamed in sagemaker>=2.\n", "See: https://sagemaker.readthedocs.io/en/stable/v2.html for details.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Endpoint name: randomcutforest-2021-10-22-20-04-00-789\n", "Training job name: randomcutforest-2021-10-22-19-58-48-050\n" ] } ], "source": [ "from sagemaker import RandomCutForest\n", "session = sagemaker.Session()\n", "\n", "\n", "rcf = RandomCutForest(\n", " role=execution_role,\n", " instance_count=1,\n", " instance_type=\"ml.m4.xlarge\",\n", " data_location=f\"s3://{bucket}/{prefix}/\",\n", " output_path=f\"s3://{bucket}/{prefix}/output\",\n", " num_samples_per_tree=512,\n", " num_trees=50,\n", ")\n", "\n", "newData=marketing_encoded_data.to_numpy()\n", "rcf.fit(rcf.record_set(newData))\n", "\n", "rcf_inference = rcf.deploy(initial_instance_count=1, instance_type=\"ml.m4.xlarge\")\n", "\n", "print(f\"Endpoint name: {rcf_inference.endpoint}\")\n", "print(f\"Training job name: {rcf.latest_training_job.job_name}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you see the message\n", "\n", "> `Training job name: randomcutforest-xxx-xxx-..`\n", "\n", "at the bottom of the output logs then that means training successfully completed and the output RCF model was stored in the specified output path. You can also view information about and the status of a training job using the AWS SageMaker console. Just click on the \"Jobs\" tab and select training job matching the training job name.\n", "\n", "You now have a functioning SageMaker RCF inference endpoint. You can confirm the endpoint configuration and status by navigating to the \"Endpoints\" tab in the AWS SageMaker console and selecting the endpoint matching the endpoint name, below: " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Data Serialization/Deserialization\n", "\n", "We can pass data in a variety of formats to our inference endpoint. In this example we will demonstrate passing CSV-formatted data. Other available formats are JSON-formatted and RecordIO Protobuf. We make use of the SageMaker Python SDK utilities `csv_serializer` and `json_deserializer` when configuring the inference endpoint." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "from sagemaker.serializers import CSVSerializer\n", "from sagemaker.deserializers import JSONDeserializer\n", "\n", "rcf_inference.serializer = CSVSerializer()\n", "rcf_inference.deserializer = JSONDeserializer()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's pass the training dataset, in CSV format, to the inference endpoint so we can automatically detect the anomalies we saw with our eyes in the plots, above. Note that the serializer and deserializer will automatically take care of the datatype conversion from Numpy NDArrays.\n", "\n", "For starters, let's only pass in the first six datapoints so we can see what the output looks like.\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'scores': [{'score': 0.8194548904}, {'score': 0.4672802341}, {'score': 0.6835655051}, {'score': 0.7037489429}, {'score': 0.4637495449}, {'score': 0.6890112207}]}\n" ] } ], "source": [ "results = rcf_inference.predict(\n", " newData[:6], initial_args={\"ContentType\": \"text/csv\", \"Accept\": \"application/json\"}\n", ")\n", "print(results)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### At this point, you have successfully trained and created Random Cut Forest on Amazon Sagemeaker. It is ready to called from Amazon Redshift. \n", "Use below create model statement to deploy a machine learning model onto Redshift Cluster.\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Bring Remote Model to Amazon Redshift\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create BYOM \n", "\n", "We are going to pass sagemaker endpoint and Redshift IAM Role to Create Model Statement.\n", "\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "The endpoint attribute has been renamed in sagemaker>=2.\n", "See: https://sagemaker.readthedocs.io/en/stable/v2.html for details.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "randomcutforest-2021-10-22-20-04-00-789\n" ] } ], "source": [ "SAGEMAKER_ENDPOINT = rcf_inference.endpoint\n", "print(SAGEMAKER_ENDPOINT) " ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "eb62d223-d330-4da7-97b7-d7cd6a8e5266\n" ] } ], "source": [ "sql_text=(\"drop model if exists public.marketing_campaign_anomalies_2;\\\n", "CREATE MODEL public.marketing_campaign_anomalies_2\\\n", " FUNCTION marketing_campaign_anomalies_function_2 (float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t\\\n", " ,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t, \\\n", "float\t,float\t,float\t,float\t,float\t,float\t,float\t,float\t)\\\n", " RETURNS decimal(10,6)\\\n", " SAGEMAKER'{}'\\\n", " IAM_ROLE'{}'\\\n", "\")\n", "df=run_sql(sql_text.format(SAGEMAKER_ENDPOINT,REDSHIFT_IAM_ROLE))\n", "print(df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lets run show model command to check the status of the model. Please notice the values set for different keys. For Example, Model Name, Model State and Function Name. " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>Key</th>\n", " <th>Value</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>Model Name</td>\n", " <td>marketing_campaign_anomalies_2</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>Schema Name</td>\n", " <td>public</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>Owner</td>\n", " <td>awsuser</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>Creation Time</td>\n", " <td>Fri, 22.10.2021 20:07:33</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>Model State</td>\n", " <td>READY</td>\n", " </tr>\n", " <tr>\n", " <th>5</th>\n", " <td></td>\n", " <td></td>\n", " </tr>\n", " <tr>\n", " <th>6</th>\n", " <td>PARAMETERS:</td>\n", " <td></td>\n", " </tr>\n", " <tr>\n", " <th>7</th>\n", " <td>Endpoint</td>\n", " <td>randomcutforest-2021-10-22-20-04-00-789</td>\n", " </tr>\n", " <tr>\n", " <th>8</th>\n", " <td>Function Name</td>\n", " <td>marketing_campaign_anomalies_function_2</td>\n", " </tr>\n", " <tr>\n", " <th>9</th>\n", " <td>Inference Type</td>\n", " <td>Remote</td>\n", " </tr>\n", " <tr>\n", " <th>10</th>\n", " <td>Function Parameter Types</td>\n", " <td>float8 float8 float8 float8 float8 float8 floa...</td>\n", " </tr>\n", " <tr>\n", " <th>11</th>\n", " <td>IAM Role</td>\n", " <td>arn:aws:iam::222252186592:role/mod-4d97d0e707c...</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " Key \\\n", "0 Model Name \n", "1 Schema Name \n", "2 Owner \n", "3 Creation Time \n", "4 Model State \n", "5 \n", "6 PARAMETERS: \n", "7 Endpoint \n", "8 Function Name \n", "9 Inference Type \n", "10 Function Parameter Types \n", "11 IAM Role \n", "\n", " Value \n", "0 marketing_campaign_anomalies_2 \n", "1 public \n", "2 awsuser \n", "3 Fri, 22.10.2021 20:07:33 \n", "4 READY \n", "5 \n", "6 \n", "7 randomcutforest-2021-10-22-20-04-00-789 \n", "8 marketing_campaign_anomalies_function_2 \n", "9 Remote \n", "10 float8 float8 float8 float8 float8 float8 floa... \n", "11 arn:aws:iam::222252186592:role/mod-4d97d0e707c... " ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = run_sql(\"SHOW MODEL public.marketing_campaign_anomalies_2\")\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Inference\n", "##### Now you have deployed BYOM remote inference, lets check it works without any errors. " ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>customerid</th>\n", " <th>score</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>0178-SZBHO</td>\n", " <td>0.815752</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>0181-RITDD</td>\n", " <td>0.471745</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>0186-CAERR</td>\n", " <td>0.681663</td>\n", " </tr>\n", " <tr>\n", " <th>3</th>\n", " <td>0187-QSXOE</td>\n", " <td>0.701432</td>\n", " </tr>\n", " <tr>\n", " <th>4</th>\n", " <td>0187-WZNAB</td>\n", " <td>0.462517</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " customerid score\n", "0 0178-SZBHO 0.815752\n", "1 0181-RITDD 0.471745\n", "2 0186-CAERR 0.681663\n", "3 0187-QSXOE 0.701432\n", "4 0187-WZNAB 0.462517" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "customer_scores = run_sql(\"\"\"\n", " SELECT customerid,\n", " Marketing_campaign_anomalies_function_2(\n", " age, balance, day, duration,campaign,days_since_last_contact, previous, job_blue_collor, job_entrepreneur, job_housemaid, job_management, job_retired, job_self_employed,\n", " job_services,job_student, job_technician, job_unemployed, job_unknown, month_aug,\n", " month_dec,month_feb, month_jan, month_jul, month_jun, month_mar, month_may,month_nov,month_oct, month_sep, marital_married, marital_single,\n", " education_secondary,education_tertiary, education_unknown, default_yes, housing_yes, loan_yes\n", " ,contact_telephone, contact_unknown) AS score\n", "FROM marketing_campaign_encoded_data a\n", "LIMIT 5 \n", "\"\"\");\n", "customer_scores.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Conclusion\n", "\n", "---\n", "\n", "We used Amazon SageMaker Random Cut Forest to detect anomalous datapoints in a marketing campaign dataset. We used Redshift Data API to connect to Amazon Redshift and run SQL commands. \n", "\n", "We then used Redshift ML to demonstrate how you can do inference on unsupervised algorithms(such as Random Cut Forest). This allows you to democratize Machine learning by doing predictions with Redshift SQL Commands.\n", "\n" ] } ], "metadata": { "celltoolbar": "Tags", "instance_type": "ml.t3.medium", "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.13" }, "notice": "Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the \"License\"). You may not use this file except in compliance with the License. A copy of the License is located at http://aws.amazon.com/apache2.0/ or in the \"license\" file accompanying this file. This file is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License." }, "nbformat": 4, "nbformat_minor": 4 }