{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Making predictions using streaming aggregated features\n", "\n", "All prior notebooks have been setting up our end to end solution. Now that all those steps are complete, it is time to see the solution in action. In this notebook, we will send credit card transactions to our source Kafka topic and show that we can detect fraud. We take advantage of multiple online feature groups in the Amazon SageMaker Feature Store. One of those feature groups is refreshed by a processing job, which we would run nightly to provide aggregate features looking back one week. The other feature group uses streaming ingestion to aggregate features that look back over a rolling 10-minute window.\n", "\n", "![SegmentLocal](images/streaming_prediction.png \"connection\")\n", "\n", "### Recap of what is in place\n", "\n", "Here is a recap of what we have done so far:\n", "\n", "1. In [notebook 0](./0_prepare_transactions_dataset.ipynb), We generated a synthetic dataset of transactions, including simulated fraud attacks.\n", "2. In [notebook 1](./1_setup.ipynb), we created our two feature groups. In that same notebook, we also created a Kinesis data stream and a Kinesis Data Analytics SQL application that consumes the transaction stream and produces aggregate features. These features are provided in near real time to Lambda, and they look back over a 10 minute window.\n", "3. In [notebook 2](./2_batch_ingestion.ipynb), we used a SageMaker Processing Job to create aggregated features and used them to feed both the training dataset as well as an online feature group.\n", "4. In [notebook 3](./3_train_and_deploy_model.ipynb), we trained and deployed an XGBoost model to detect fraud.\n", "5. Our [CloudFormation template](https://console.aws.amazon.com/cloudformation/home) deployed a pair of Lambda functions. One listens to the MSK topic output and keeps the `` feature group up to date. The other Lambda listens to the Kinesis data stream for transactions, pulls a set of features from multiple feature groups, and invokes our fraud detection endpoint, as seen in the above picture.\n", "\n", "**Recommended settings to run this notebook in SageMaker Studio:**\n", "\n", "- Image: Data Science\n", "- Kernel: Python3\n", "- Instance type: ml.m5.large (2 vCPU + 8 GiB)\n", "\n", "**Important Note:**\n", "\n", "DO NOT \"Run All Cells\" on this notebook, manual steps are needed for successful execution\n", "\n", "Do not proceed with this notebook unless upstream notebooks noted in recap are fully executed including the manual steps." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Imports and overall setup\n", "\n", "### Imports and initialization" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "!pip install pykafka" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "from datetime import datetime\n", "from pykafka import KafkaClient\n", "import numpy as np\n", "import pandas as pd\n", "import sagemaker\n", "import boto3\n", "import json\n", "import time" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The MSK cluster required would be created via the CloudFormation template. Retrieve the connection string for the pre-created MSK cluster using steps shown in this animation. Use that connection string in cell below.\n", "\n", "![SegmentLocal](images/get-msk-cluster-connection-string.gif \"connection\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "LOCAL_DIR = './data'\n", "BUCKET = sagemaker.Session().default_bucket()\n", "PREFIX = 'testing'\n", "TOPIC_NAME = 'cctopic'\n", "KAFKA_HOST = ''\n", "\n", "s3_client = boto3.Session().client('s3')\n", "kinesis_client = boto3.client('kinesis')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "# The exact name of the Lambda function is controlled by our CloudFormation template, \n", "# so we access that here. We will use this to help get to the proper CloudWatch log group to see the\n", "# results of our testing.\n", "%store -r\n", "predict_lambda_name" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ensure Lambda knows which SageMaker endpoint to use\n", "In our previous notebook that deploys a SageMaker endpoint, we allow the endpoint name to be generated on the fly instead of hard-coding a specific endpoint name. Our Lambda function that invokes the endpoint thus needs a way to know the endpoint name. We handle that through a Lambda environment variable.\n", "\n", "This section of code simply takes care of updating end ENDPOINT_NAME Lambda environment variable. It is important to do so before we start feeding transactions into our Kinesis stream." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "lambda_client = boto3.client('lambda')\n", "\n", "# Grab the latest endpoint name we used in the previous notebook, as well as the ARN for the lambda\n", "%store -r\n", "print(f'Updating Lambda to use endpoint: {endpoint_name} for ARN: {lambda_to_model_arn}')\n", "\n", "variables = lambda_client.get_function_configuration(FunctionName=lambda_to_model_arn)['Environment']['Variables']\n", "variables['ENDPOINT_NAME'] = endpoint_name\n", "resp = lambda_client.update_function_configuration(\n", " FunctionName=lambda_to_model_arn,\n", " Environment={\n", " 'Variables': variables\n", " }\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Access the transaction test dataset" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "test_file_path = './data/test.csv'\n", "test_df = pd.read_csv(test_file_path)\n", "test_df.head()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "test_df.head()\n", "print(test_df.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Test out the solution, end to end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### First, a few utility functions" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "def get_cloudwatch_logs_url(start_time, end_time):\n", " log_group_name = '/aws/lambda/' + predict_lambda_name \n", " # get the latest log stream for our Lambda that makes fraud predictions\n", " cw_client = boto3.client('logs')\n", " last_cw_evt = 0\n", " while last_cw_evt < int(start_test_time * 1000):\n", " streams = cw_client.describe_log_streams(logGroupName=log_group_name,\n", " orderBy='LastEventTime',\n", " descending=True)['logStreams']\n", " last_cw_evt = streams[0]['lastIngestionTime'] #'lastEventTimestamp']\n", " latest_stream = str(streams[0]['logStreamName']).replace('/', '$252F').replace('[$LATEST]', '$255B$2524LATEST$255D')\n", " if last_cw_evt < int(start_test_time * 1000):\n", " print('waiting for updated log stream...')\n", " time.sleep(10)\n", "\n", " # produce a valid URL to get to that log stream\n", " region = boto3.session.Session().region_name\n", " log_group_escaped = log_group_name.replace('/', '$252F')\n", " cw_url = f'https://console.aws.amazon.com/cloudwatch/home?region={region}#logsV2:log-groups/log-group/{log_group_escaped}'\n", " time_filter = f'$26start$3D{int(start_test_time * 1000) - 10000}$26end$3D{int(end_test_time * 1000) + 40000}'\n", " full_cw_url = f'{cw_url}/log-events/{latest_stream}$3FfilterPattern$3DPrediction+{time_filter}'\n", " print('Updated log stream is ready.')\n", " return full_cw_url" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "def put_to_topic(topic_name, cc_num, merchant, amount, zip_code, timestamp):\n", " \n", " client = KafkaClient(hosts = KAFKA_HOST)\n", " topic = client.topics[TOPIC_NAME]\n", " payload = {\n", " 'cc_num': int(cc_num),\n", " 'merchant': merchant,\n", " 'amount': amount,\n", " 'zip_code': zip_code,\n", " 'trans_ts': timestamp\n", " }\n", " ret_status = True\n", " data = json.dumps(payload)\n", " encoded_message = data.encode(\"utf-8\")\n", " \n", " \n", " print(f'Sending transaction on card: {cc_num}...')\n", " \n", " with topic.get_sync_producer() as producer:\n", " \n", " result=producer.produce(encoded_message)\n", " #error handling - TODO\n", "\n", " \n", " return ret_status" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "def simulate_fraud_kafka(topic_name, cc_num):\n", " min_wait = 1; max_wait = 2\n", " for i in range(10):\n", " random_amt = round(np.random.uniform(1.00, 50.00), 2)\n", " seconds_to_wait = np.random.uniform(min_wait, max_wait)\n", " print(f'waiting {seconds_to_wait:.1f} seconds to send trans {i}...')\n", " time.sleep(seconds_to_wait)\n", " put_to_topic(topic_name, int(cc_num), 'Random Corp', random_amt, '03099', time.time())" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Send some transactions, and see the results\n", "To show that the solution works, we send a single transaction to each of three different credit cards. Then, we simulate a fraud attack on a 4th credit card by sending many transactions in quick succession. The output from our Lambda function is then shown from CloudWatch log streams. Here's an example of what you should see as a result:\n", "\n", "![SegmentLocal](images/log_results.png \"connection\")\n", "\n", "As expected, the first three one-off transactions are predicted as NOT FRAUD. Of the ten fraudulent transactions, the first is predicted as NOT FRAUD, and the rest are all correctly identified as FRAUD. Notice how the aggregate features are kept current, helping drive more accurate predictions.\n", "\n", "Now let's give it a shot." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "#KAFKA - Simulate\n", "cc_nums = test_df.cc_num.unique()[10:14]\n", "\n", "start_test_time = time.time() \n", "\n", "put_to_topic(TOPIC_NAME, cc_nums[0], 'Merchant-0', round(np.random.uniform(100, 5000), 2), 'zip-0', time.time())\n", "put_to_topic(TOPIC_NAME, cc_nums[1], 'Merchant-1', round(np.random.uniform(100, 5000), 2), 'zip-1', time.time())\n", "put_to_topic(TOPIC_NAME, cc_nums[2], 'Merchant-2', round(np.random.uniform(100, 5000), 2), 'zip-2', time.time())\n", "\n", "print('\\nNow simulate a fraud attack...')\n", "fraud_cc_num = cc_nums[3]\n", "simulate_fraud_kafka(TOPIC_NAME, fraud_cc_num)\n", "\n", "end_test_time = time.time()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Results can be seen in Apache Flink dashboard created as part of the Setup notebook.\n", "\n", "![SegmentLocal](images/apache-flink-dashboard.png \"connection\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Results can also be seen in the CloudWatch log stream of our Lambda function\n", "The following cell dynamically creates a link to view the results. It waits for the CloudWatch log stream to have the output events from the transactions we just sent. The URL also hones in on the output from the specific timeframe of the transactions." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "from IPython.core.display import display, HTML\n", "\n", "full_cw_url = get_cloudwatch_logs_url(start_test_time, end_test_time)\n", "display(HTML(f'Review results in this log stream Lambda fraud detection results'))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "##### KDA application monitoring\n", "\n", "When transactions are sent to the source MSK topic, they are aggregated and sent to the target MSK topic from where the associated feature group is populated. \n", "\n", "![SegmentLocal](images/kda-app-workflow.png \"connection\")\n", "\n", "Verify record transmission in the Apache Flink dashboard that gets created in the last manual step of 1_setup.ipynb." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "##### AWS Glue Catalogs\n", "\n", "Additionally, you can check out the AWS Glue tables and related metadata by navigating to the AWS Glue console.\n", "\n", "![SegmentLocal](images/glue-tables.png \"connection\")" ] }, { "cell_type": "code", "execution_count": null, "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 } ], "instance_type": "ml.g4dn.xlarge", "kernelspec": { "display_name": "Python 3 (Data Science)", "language": "python", "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-east-1:081325390199: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" }, "vscode": { "interpreter": { "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" } } }, "nbformat": 4, "nbformat_minor": 4 }