{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# TensorFlow MNIST Lift and Shift Exercise\n", "\n", "For this exercise notebook, you should be able to use the `Python 3 (TensorFlow 2.3 Python 3.7 CPU Optimized)` kernel on SageMaker Studio, or `conda_tensorflow2_p37` on classic SageMaker Notebook Instances.\n", "\n", "\n", "---\n", "\n", "## Introduction\n", "\n", "Your new colleague in the data science team (who isn't very familiar with SageMaker) has written a nice notebook to tackle an image classification problem with Keras: [Local Notebook.ipynb](Local%20Notebook.ipynb).\n", "\n", "It works OK with the simple MNIST data set they were working on before, but now they'd like to take advantage of some of the features of SageMaker to tackle bigger and harder challenges.\n", "\n", "**Can you help refactor the Local Notebook code, to show them how to use SageMaker effectively?**\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Getting Started\n", "\n", "First, check you can **run the [Local Notebook.ipynb](Local%20Notebook.ipynb) notebook through** - reviewing what steps it takes.\n", "\n", "**This notebook** sets out a structure you can use to migrate code into, and lists out some of the changes you'll need to make at a high level. You can either work directly in here, or duplicate this notebook so you still have an unchanged copy of the original.\n", "\n", "Try to work through the sections first with an MVP goal in mind (fitting the model to data in S3 via a SageMaker Training Job, and deploying/using the model through a SageMaker Endpoint). At the end, there are extension exercises to bring in more advanced functionality.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Dependencies\n", "\n", "Listing all our imports at the start helps to keep the requirements to run any script/file transparent up-front, and is specified by nearly every style guide including Python's official [PEP 8](https://www.python.org/dev/peps/pep-0008/#imports)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "!pip install \"ipycanvas<0.13\" \"ipywidgets<8\" matplotlib" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2\n", "\n", "# Python Built-Ins:\n", "import glob\n", "import os\n", "\n", "# External Dependencies:\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "# TODO: What else will you need?\n", "# Have a look at the documentation: https://sagemaker.readthedocs.io/en/stable/frameworks/tensorflow/using_tf.html\n", "# to see which libraries need to be imported to use sagemaker and the tensorflow estimator" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prepare the Data\n", "\n", "Let's download the image data from the Repository of Open Data on AWS and sample a subset like we did in the [Local Notebook.ipynb](Local%20Notebook.ipynb).\n", "\n", "**Check you understand** what data it's going to upload from this notebook, and where it's going to store it in S3, then start the upload running while you work on the rest." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "local_dir = \"/tmp/mnist\"\n", "training_dir = f\"{local_dir}/training\"\n", "testing_dir = f\"{local_dir}/testing\"\n", "\n", "# Download the MNIST data from the Registry of Open Data on AWS\n", "!rm -rf {local_dir}\n", "!mkdir -p {local_dir}\n", "!aws s3 cp s3://fast-ai-imageclas/mnist_png.tgz {local_dir} --no-sign-request\n", "\n", "# Un-tar the MNIST data, stripping the leading path element; this will leave us with directories\n", "# {local_dir}/testing/ and {local_dir/training/\n", "!tar zxf {local_dir}/mnist_png.tgz -C {local_dir}/ --strip-components=1 --no-same-owner\n", "\n", "# Get the list of files in tne training and testing directories recursively\n", "train_files = sorted(list(glob.iglob(os.path.join(training_dir, \"*/*.png\"), recursive=True)))\n", "test_files = sorted(list(glob.iglob(os.path.join(testing_dir, \"*/*.png\"), recursive=True)))\n", "\n", "print(f\"Training files: {len(train_files)}\")\n", "print(f\"Testing files: {len(test_files)}\")\n", "\n", "# Reduce the data by keeping every Nth file and dropping the rest of the files.\n", "reduction_factor = 2\n", "train_files_to_keep = train_files[::reduction_factor]\n", "test_files_to_keep = test_files[::reduction_factor]\n", "\n", "print(f\"Training files kept: {len(train_files_to_keep)}\")\n", "print(f\"Testing files kept: {len(test_files_to_keep)}\")\n", "\n", "# Delete all the files not to be kept\n", "for fname in set(train_files) ^ set(train_files_to_keep):\n", " os.remove(fname)\n", "\n", "for fname in set(test_files) ^ set(test_files_to_keep):\n", " os.remove(fname)\n", "\n", "print(\"Done!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set Up Execution Role, Session and S3 Bucket\n", "\n", "Now that we have downloaded and reduced the data in the local directory, we will need to upload it to Amazon S3 to make it available for Amazon Sagemaker training. \n", "\n", "Let's start by specifying:\n", "- The S3 bucket and prefix that you want to use for training and model data. This should be within the same region as the Notebook Instance, training, and hosting. If you don't specify a bucket, SageMaker SDK will create a default bucket following a pre-defined naming convention in the same region. \n", "- The IAM role ARN used to give SageMaker access to your data. It can be fetched using the **get_execution_role** method from sagemaker python SDK." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# TODO: This is where you can setup execution role, session and S3 bucket.\n", "# 1. Setup the SageMaker role\n", "role = ?\n", "# 2. Setup the SageMaker session\n", "sess = ?\n", "# 3. Setup the SageMaker default bucket\n", "bucket_name = ?\n", "\n", "# Have a look at the previous examples to find out how to do it" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Upload Data to Amazon S3\n", "Next is the part where you need to upload the images to Amazon S3 for Sagemaker training. You can refer to the previous example on how to do it using the [aws s3 sync](https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html) CLI command. The high-level command ```aws s3 sync``` command synchronizes the contents of the target bucket and source directory. It allows the use of options such as ```--delete``` that allows to remove objects from the target that are not present in the source and ```--exclude``` or ```--include``` options that filter files or objects to exclude or not exclude.\n", "\n", "> ⏰ **Note:** Uploading to Amazon S3 typically takes about 2-3 minutes assuming a `reduction_factor` of 2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# TODO: This is where you upload the training images using `aws s3 sync`.\n", "# Fill in the missing source local directory and the target S3 bucket and folder in the command below.\n", "!aws s3 sync --quiet --delete ??? ??? --exclude \"*.tgz\" && echo \"Done!\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can check your data is uploaded by finding your bucket in the [Amazon S3 Console](https://s3.console.aws.amazon.com/s3/home). Do you see the folders of images as expected?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data Input (\"Channels\") Configuration\n", "\n", "The draft code has **2 data sets**: One for training, and one for test/validation. (For classification, the folder location of each image is sufficient as a label).\n", "\n", "In SageMaker terminology, each input data set is a \"channel\" and we can name them however we like... Just make sure you're consistent about what you call each one!\n", "\n", "For a simple input configuration, a channel spec might just be the S3 URI of the folder. For configuring more advanced options, there's the [s3_input](https://sagemaker.readthedocs.io/en/stable/inputs.html) class in the SageMaker SDK.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# TODO: Define your 2 data channels\n", "# The data can be found in: \"s3://{bucket_name}/mnist/training\" and \"s3://{bucket_name}/mnist/testing\"\n", "\n", "inputs = # Look at the previous example to see how the inputs were defined" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Algorithm (\"Estimator\") Configuration and Run\n", "\n", "Instead of loading and fitting this data here in the notebook, we'll be creating a [TensorFlow Estimator](https://sagemaker.readthedocs.io/en/stable/sagemaker.tensorflow.html#tensorflow-estimator) through the SageMaker SDK, to run the code on a separate container that can be scaled as required.\n", "\n", "The [\"Using TensorFlow with the SageMaker Python SDK\"](https://sagemaker.readthedocs.io/en/stable/using_tf.html#train-a-model-with-tensorflow) docs give a good overview of this process. You should run your estimator in **script mode** (which is easier to follow than the old default legacy mode) and as **Python 3**.\n", "\n", "**Use the [src/main.py](src/main.py) file** as your entry point to port code into - which has already been created for you with some basic hints.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# TODO: Create your TensorFlow estimator\n", "\n", "# Note the TensorFlow class inherits from some cross-framework base classes with additional\n", "# constructor options:\n", "# https://sagemaker.readthedocs.io/en/stable/estimators.html\n", "# https://sagemaker.readthedocs.io/en/stable/frameworks/tensorflow/using_tf.html?highlight=%20TrainingInput#create-an-estimator\n", "\n", "# We are using tensorflow 1.14 and python 3\n", "# You can reuse the metrics definition from the previous example\n", "# (Optional) Look at the Tensorflow script and try to pass new hyperparameters\n", "\n", "estimator = ?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before running the actual training on SageMaker TrainingJob, it can be good to run it locally first using the code below. If there is any error, you can fix them first before running using SageMaker TrainingJob." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!python3 src/main.py --train {training_dir} --test {testing_dir} --output-data-dir data/local-output --model-dir data/local-model --epochs=1 --batch-size=128" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When you're ready to try your script in a SageMaker training job, you can call `estimator.fit()` as we did in previous exercises:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "# TODO: Call estimator.fit" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Deploy and Use Your Model (Real-Time Inference)\n", "\n", "If your training job has completed; and saved the model in the correct TensorFlow Serving-compatible format; it should now be pretty simple to deploy the model to a real-time endpoint.\n", "\n", "You can achieve this with the [Estimator API](https://sagemaker.readthedocs.io/en/stable/estimators.html)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# TODO: Deploy a real-time endpoint" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Reviewing the architecture from the example notebook, we set up the model to accept **batches** of **28x28** image tensors with **normalized 0-1 pixel values** and a **single color channel dimension**.\n", "\n", "Assuming you haven't [added any custom inference pre-processing](https://sagemaker.readthedocs.io/en/stable/frameworks/tensorflow/deploying_tensorflow_serving.html#providing-python-scripts-for-pre-post-processing) to the script (for example to accept encoded JPEGs/PNGs, or arbitrary image shapes), we'll need to replicate that same format when we use our endpoint.\n", "\n", "You can use the final \"Explore Results\" section of the local notebook as a guide. First, using the interactive widget:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create/reload the drawing widget:\n", "widget = util.draw.PixelDrawCanvas(pen_size=4)\n", "widget.display()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Load the image from the widget:\n", "img = widget.data.mean(-1, keepdims=True) / 255 # (Convert full-RGB 0-255 to grayscale 0-1)\n", "\n", "# TODO: Call your endpoint\n", "result = ?\n", "\n", "print(f\"Result confidences: {result}\")\n", "\n", "# Plot the result:\n", "plt.figure(figsize=(3, 3))\n", "fig = plt.subplot(1, 1, 1)\n", "ax = plt.imshow(img, cmap=\"gray\")\n", "fig.set_title(f\"Predicted Number {np.argmax(result[0])}\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, to load and classify images from the test set:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# TODO: Choose an image\n", "\n", "# TODO: Load the image\n", "img = ?\n", "\n", "# Expand out the \"batch\" dimension, and before sending to the model\n", "reqdata = np.expand_dims(img, 0)\n", "\n", "# TODO: Call the predictor with reqdata\n", "result = ?\n", "\n", "# Plot the result:\n", "plt.figure(figsize=(3, 3))\n", "fig = plt.subplot(1, 1, 1)\n", "ax = plt.imshow(np.squeeze(img), cmap=\"gray\")\n", "fig.set_title(f\"Predicted Number {np.argmax(result['predictions'][0])}\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Further Improvements\n", "\n", "If you've got the basic train/deploy/call cycle working, congratulations! This core pattern of experimenting in the notebook but executing jobs on scalable hardware is at the heart of the SageMaker data science workflow.\n", "\n", "There are still plenty of ways we can use the tools better though: Read on for the next challenges!\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. Cut training costs easily with SageMaker Managed Spot Mode\n", "\n", "AWS Spot Instances let you take advantage of unused capacity in the AWS cloud, at up to a 90% discount versus standard on-demand pricing! For small jobs like this, taking advantage of this discount is as easy as adding a couple of parameters to the Estimator constructor:\n", "\n", "https://sagemaker.readthedocs.io/en/stable/estimators.html\n", "\n", "Note that in general, spot capacity is offered at a discounted rate because it's interruptible based on instantaneous demand... Longer-running training jobs should implement checkpoint saving and loading, so that they can efficiently resume if interrupted part way through. More information can be found on the [Managed Spot Training in Amazon SageMaker](https://docs.aws.amazon.com/sagemaker/latest/dg/model-managed-spot-training.html) page of the [SageMaker Developer Guide](https://docs.aws.amazon.com/sagemaker/latest/dg/).\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2. Parameterize your algorithm\n", "\n", "Being able to change the parameters of your algorithm at run-time (without modifying the `main.py` script each time) is helpful for making your code more re-usable... But even more so because it's a pre-requisite for automatic hyperparameter tuning!\n", "\n", "Job parameter parsing should ideally be factored into a separate function, and as a best practice should accept setting values through **both** command line flags (as demonstrated in the [official MXNet MNIST example](https://github.com/awslabs/amazon-sagemaker-examples/blob/master/hyperparameter_tuning/mxnet_mnist/mnist.py)) **and** the [SageMaker Hyperparameter environment variable(s)](https://docs.aws.amazon.com/sagemaker/latest/dg/docker-container-environmental-variables-user-scripts.html). Perhaps the official MXNet example could be improved by setting environment-variable-driven defaults to the algorithm hyperparameters, the same as it already does for channels?\n", "\n", "Refactor your job to accept **epochs** and **batch size** as optional parameters, and show how you can set these before each training run through the [Estimator API](https://sagemaker.readthedocs.io/en/stable/estimators.html).\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3. Tune your network hyperparameters\n", "\n", "Re-use the same approach as before to parameterize some features in the structure of your network: Perhaps the sizes of the `Conv2D` kernels? The number, type, node count, or activation function of layers in the network? No need to stray too far away from the sample architecture!\n", "\n", "Instead of manually (or programmatically) calling `estimator.fit()` with different hyperparameters each time, we can use SageMaker's Bayesian Hyperparameter Tuning functionality to explore the space more efficiently!\n", "\n", "The SageMaker SDK Docs give a great [overview](https://sagemaker.readthedocs.io/en/stable/overview.html#sagemaker-automatic-model-tuning) of using the HyperparameterTuner, which you can refer to if you get stuck.\n", "\n", "First, we'll need to define a specific **metric** to optimize for, which is really a specification of how to scrape metric values from the algorithm's console logs. \n", "\n", "Next, use the [\\*Parameter](https://sagemaker.readthedocs.io/en/stable/tuner.html) classes (`ContinuousParameter`, `IntegerParameter` and `CategoricalParameter`) to define appropriate ranges for the hyperparameters whose combination you want to optimize.\n", "\n", "With the original estimator, target metric and parameter ranges defined, you'll be able to create a [HyperparameterTuner](https://sagemaker.readthedocs.io/en/stable/tuner.html) and use that to start a hyperparameter tuning job instead of a single model training job.\n", "\n", "Pay attention to likely run time and resource consumption when selecting the maximum total number of training jobs and maximum parallel jobs of your hyperparameter tuning run... You can always view and cancel ongoing hyperparameter tuning jobs through the SageMaker Console.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Additional Challenges\n", "\n", "If you have time, the following challenges are trickier, and might stretch your SageMaker knowledge even further!\n", "\n", "**Batch Transform / Additional Inference Formats**: As discussed in this notebook, the deployed endpoint expects a particular tensor data format for requests... This complicates the usually-simple task of re-purposing the same model for batch inference (since our data in S3 is in JPEG format). The SageMaker TensorFlow SDK docs provide guidance on accepting custom formats in the [\"Create Python Scripts for Custom Input and Output Formats\"](https://sagemaker.readthedocs.io/en/stable/using_tf.html#create-python-scripts-for-custom-input-and-output-formats) section. If you can refactor your algorithm to accept JPEG requests when deployed as a real-time endpoint, you'll be able to run it as a batch [Transformer](https://sagemaker.readthedocs.io/en/stable/transformer.html) against images in S3 with a simple `estimator.transformer()` call.\n", "\n", "**Optimized Training Formats**: A dataset like this (containing many tiny objects) may take much less time to load in to the algorithm if we either converted it to the standard Numpy format that Keras distributes it in (just 4 files X_train, Y_train, X_test, Y_test); or *streaming* the data with [SageMaker Pipe Mode](https://aws.amazon.com/blogs/machine-learning/using-pipe-input-mode-for-amazon-sagemaker-algorithms/), instead of downloading it up-front.\n", "\n", "**Experiment Tracking**: The [SageMaker Experiments](https://docs.aws.amazon.com/sagemaker/latest/dg/experiments.html) feature gives a more structured way to track trials across multiple related experiments (for example, different HPO runs, or between HPO and regular model training jobs). You can use the [official SageMaker Experiments Example](https://github.com/awslabs/amazon-sagemaker-examples/tree/master/sagemaker-experiments) for guidance on how to track the experiments in this notebook... and should note that the [SageMaker Experiments SDK Docs](https://sagemaker-experiments.readthedocs.io/en/latest/) are maintained separately, since it's a different Python module.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Clean-Up\n", "\n", "Remember to clean up any persistent resources that aren't needed anymore to save costs: The most significant of these are real-time prediction endpoints, and this SageMaker Notebook Instance.\n", "\n", "The SageMaker SDK [Predictor](https://sagemaker.readthedocs.io/en/stable/predictors.html) class provides an interface to clean up real-time prediction endpoints; and SageMaker Notebook Instances can be stopped through the SageMaker Console when you're finished.\n", "\n", "You might also like to clean up any S3 buckets / content we created, to prevent ongoing storage costs.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# TODO: Clean up any endpoints/etc to release resources" ] } ], "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.t3.medium", "kernelspec": { "display_name": "Python 3 (TensorFlow 2.3 Python 3.7 CPU Optimized)", "language": "python", "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-east-1:081325390199:image/tensorflow-2.3-cpu-py37-ubuntu18.04-v1" }, "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" } }, "nbformat": 4, "nbformat_minor": 4 }