From 20ec2253435cb0cc10f57f3806c3a43e6c26ec10 Mon Sep 17 00:00:00 2001 From: Paula Ledgerwood Date: Fri, 26 Apr 2019 11:16:33 -0700 Subject: [PATCH 1/2] Initial commit to add notebooks from AzureMlCli repo --- .../deployment/accelerated-models/README.md | 74 ++ .../accelerated-models-object-detection.ipynb | 490 ++++++++++ .../accelerated-models-quickstart.ipynb | 544 +++++++++++ .../accelerated-models-training.ipynb | 849 ++++++++++++++++++ .../deployment/accelerated-models/meeting.jpg | Bin 0 -> 75394 bytes .../accelerated-models/snowleopardgaze.jpg | Bin 0 -> 80556 bytes 6 files changed, 1957 insertions(+) create mode 100644 how-to-use-azureml/deployment/accelerated-models/README.md create mode 100644 how-to-use-azureml/deployment/accelerated-models/accelerated-models-object-detection.ipynb create mode 100644 how-to-use-azureml/deployment/accelerated-models/accelerated-models-quickstart.ipynb create mode 100644 how-to-use-azureml/deployment/accelerated-models/accelerated-models-training.ipynb create mode 100644 how-to-use-azureml/deployment/accelerated-models/meeting.jpg create mode 100644 how-to-use-azureml/deployment/accelerated-models/snowleopardgaze.jpg diff --git a/how-to-use-azureml/deployment/accelerated-models/README.md b/how-to-use-azureml/deployment/accelerated-models/README.md new file mode 100644 index 00000000..fca1fba5 --- /dev/null +++ b/how-to-use-azureml/deployment/accelerated-models/README.md @@ -0,0 +1,74 @@ + +# Notebooks for Microsoft Azure Machine Learning Hardware Accelerated Models SDK + +Easily create and train a model using various deep neural networks (DNNs) as a featurizer for deployment to Azure or a Data Box Edge device for ultra-low latency inferencing using FPGA's. These models are currently available: + +* ResNet 50 +* ResNet 152 +* DenseNet-121 +* VGG-16 +* SSD-VGG + +To learn more about the azureml-accel-model classes, see the section [Model Classes](#model-classes) below or the [Azure ML Python SDK documentation](https://docs.microsoft.com/en-us/python/api/overview/azure/ml/intro?view=azure-ml-py). + +### Step 1: Create an Azure ML workspace +Follow [these instructions](https://docs.microsoft.com/en-us/azure/machine-learning/service/quickstart-create-workspace-with-python) to install the Azure ML SDK on your local machine, create an Azure ML workspace, and set up your notebook environment, which is required for the next step. + +### Step 2: Install the Azure ML Accelerated Models SDK +Once you have set up your environment, install the Azure ML Accel Models SDK. This package requires tensorflow >= 1.6,<2.0 to be installed. + +If you already have tensorflow >= 1.6,<2.0 installed in your development environment, you can install the SDK package using: + +`` +pip install azureml-accel-models +`` + +If you do not have tensorflow >= 1.6,<2.0 and are using a CPU-only development environment, our SDK with tensorflow can be installed using: + +`` +pip install azureml-accel-models[cpu] +`` + +If your machine supports GPU (for example, on an [Azure DSVM](https://docs.microsoft.com/en-us/azure/machine-learning/data-science-virtual-machine/overview)), then you can leverage the tensorflow-gpu functionality using: + +`` +pip install azureml-accel-models[gpu] +`` + +### Step 3: Follow our notebooks + +The notebooks in this repo walk through the following scenarios: +* [Quickstart](accelerated-models-quickstart.ipynb), deploy and inference a ResNet50 model trained on ImageNet +* [Object Detection](accelerated-models-object-detection.ipynb), deploy and inference an SSD-VGG model that can do object detection +* [Training models](accelerated-models-training.ipynb), train one of our accelerated models on the Kaggle Cats and Dogs dataset to see how to improve accuracy on custom datasets + + +## Model Classes +As stated above, we support 5 Accelerated Models. Here's more information on their input and output tensors. + +**Available models and output tensors** + +The available models and the corresponding default classifier output tensors are below. This is the value that you would use during inferencing if you used the default classifier. +* Resnet50, QuantizedResnet50 (output_tensors = "classifier_1/resnet_v1_50/predictions/Softmax:0") +* Resnet152, QuantizedResnet152 (output_tensors = "classifier/resnet_v1_152/predictions/Softmax:0") +* Densenet121, QuantizedDensenet121 (output_tensors = "classifier/densenet121/predictions/Softmax:0") +* Vgg16, QuantizedVgg16 (output_tensors = "classifier/vgg_16/fc8/squeezed:0") +* SsdVgg, QuantizedSsdVgg (output_tensors = ['ssd_300_vgg/block4_box/Reshape_1:0', 'ssd_300_vgg/block7_box/Reshape_1:0', 'ssd_300_vgg/block8_box/Reshape_1:0', 'ssd_300_vgg/block9_box/Reshape_1:0', 'ssd_300_vgg/block10_box/Reshape_1:0', 'ssd_300_vgg/block11_box/Reshape_1:0', 'ssd_300_vgg/block4_box/Reshape:0', 'ssd_300_vgg/block7_box/Reshape:0', 'ssd_300_vgg/block8_box/Reshape:0', 'ssd_300_vgg/block9_box/Reshape:0', 'ssd_300_vgg/block10_box/Reshape:0', 'ssd_300_vgg/block11_box/Reshape:0']) + +For more information, please reference the azureml.accel.models package in the [Azure ML Python SDK documentation](https://docs.microsoft.com/en-us/python/api/overview/azure/ml/?view=azure-ml-py). + +**Input tensors** + +The input_tensors value defaults to "Placeholder:0" and is created in the [Image Preprocessing](#construct-model) step in the line: +`` +in_images = tf.placeholder(tf.string) +`` + +You can change the input_tensors name by doing this: +`` +in_images = tf.placeholder(tf.string, name="images") +`` + + +## Resources +* [Read more about FPGAs](https://docs.microsoft.com/en-us/azure/machine-learning/service/concept-accelerate-with-fpgas) \ No newline at end of file diff --git a/how-to-use-azureml/deployment/accelerated-models/accelerated-models-object-detection.ipynb b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-object-detection.ipynb new file mode 100644 index 00000000..4338aa67 --- /dev/null +++ b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-object-detection.ipynb @@ -0,0 +1,490 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Copyright (c) Microsoft Corporation. All rights reserved.\n", + "\n", + "Licensed under the MIT License." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Azure ML Hardware Accelerated Object Detection" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This tutorial will show you how to deploy an object detection service based on the SSD-VGG model in just a few minutes using the Azure Machine Learning Accelerated AI service.\n", + "\n", + "We will use the SSD-VGG model accelerated on an FPGA. Our Accelerated Models Service handles translating deep neural networks (DNN) into an FPGA program.\n", + "\n", + "The steps in this notebook are: \n", + "1. [Setup Environment](#set-up-environment)\n", + "* [Construct Model](#construct-model)\n", + " * Image Preprocessing\n", + " * Featurizer\n", + " * Save Model\n", + " * Save input and output tensor names\n", + "* [Create Image](#create-image)\n", + "* [Deploy Image](#deploy-image)\n", + "* [Test the Service](#test-service)\n", + " * Create Client\n", + " * Serve the model\n", + "* [Cleanup](#cleanup)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 1. Set up Environment\n", + "### 1.a. Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import tensorflow as tf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.b. Retrieve Workspace\n", + "If you haven't created a Workspace, please follow [this notebook](\"../../../configuration.ipynb\") to do so. If you have, run the codeblock below to retrieve it. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core import Workspace\n", + "\n", + "ws = Workspace.from_config()\n", + "print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\\n')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 2. Construct model\n", + "### 2.a. Image preprocessing\n", + "We'd like our service to accept JPEG images as input. However the input to SSD-VGG is a float tensor of shape \\[1, 300, 300, 3\\]. The first dimension is batch, then height, width, and channels (i.e. NHWC). To bridge this gap, we need code that decodes JPEG images and resizes them appropriately for input to SSD-VGG. The Accelerated AI service can execute TensorFlow graphs as part of the service and we'll use that ability to do the image preprocessing. This code defines a TensorFlow graph that preprocesses an array of JPEG images (as TensorFlow strings) and produces a tensor that is ready to be featurized by SSD-VGG.\n", + "\n", + "**Note:** Expect to see TF deprecation warnings until we port our SDK over to use Tensorflow 2.0." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Input images as a two-dimensional tensor containing an arbitrary number of images represented a strings\n", + "import azureml.accel.models.utils as utils\n", + "tf.reset_default_graph()\n", + "\n", + "in_images = tf.placeholder(tf.string)\n", + "image_tensors = utils.preprocess_array(in_images, output_width=300, output_height=300, preserve_aspect_ratio=False)\n", + "print(image_tensors.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.b. Featurizer\n", + "The SSD-VGG model is different from our other models in that it generates 12 tensor outputs. These corresponds to x,y displacements of the anchor boxes and the detection confidence (for 21 classes). Because these outputs are not convenient to work with, we will later use a pre-defined post-processing utility to transform the outputs into a simplified list of bounding boxes with their respective class and confidence.\n", + "\n", + "For more information about the output tensors, take this example: the output tensor 'ssd_300_vgg/block4_box/Reshape_1:0' has a shape of [None, 37, 37, 4, 21]. This gives the pre-softmax confidence for 4 anchor boxes situated at each site of a 37 x 37 grid imposed on the image, one confidence score for each of the 21 classes. The first dimension is the batch dimension. Likewise, 'ssd_300_vgg/block4_box/Reshape:0' has shape [None, 37, 37, 4, 4] and encodes the (cx, cy) center shift and rescaling (sw, sh) relative to each anchor box. Refer to the [SSD-VGG paper](https://arxiv.org/abs/1512.02325) to understand how these are computed. The other 10 tensors are defined similarly." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.accel.models import SsdVgg\n", + "\n", + "saved_model_dir = os.path.join(os.path.expanduser('~'), 'models')\n", + "model_graph = SsdVgg(saved_model_dir, is_frozen = True)\n", + "\n", + "print('SSD-VGG Input Tensors:')\n", + "for idx, input_name in enumerate(model_graph.input_tensor_list):\n", + " print('{}, {}'.format(input_name, model_graph.get_input_dims(idx)))\n", + " \n", + "print('SSD-VGG Output Tensors:')\n", + "for idx, output_name in enumerate(model_graph.output_tensor_list):\n", + " print('{}, {}'.format(output_name, model_graph.get_output_dims(idx)))\n", + "\n", + "ssd_outputs = model_graph.import_graph_def(image_tensors, is_training=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.c. Save Model\n", + "Now that we loaded both parts of the tensorflow graph (preprocessor and SSD-VGG featurizer), we can save the graph and associated variables to a directory which we can register as an Azure ML Model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model_name = \"ssdvgg\"\n", + "model_save_path = os.path.join(saved_model_dir, model_name, \"saved_model\")\n", + "print(\"Saving model in {}\".format(model_save_path))\n", + "\n", + "output_map = {}\n", + "for i, output in enumerate(ssd_outputs):\n", + " output_map['out_{}'.format(i)] = output\n", + "\n", + "with tf.Session() as sess:\n", + " model_graph.restore_weights(sess)\n", + " tf.saved_model.simple_save(sess, \n", + " model_save_path, \n", + " inputs={'images': in_images}, \n", + " outputs=output_map)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.d. Important! Save names of input and output tensors\n", + "\n", + "These input and output tensors that were created during the preprocessing and classifier steps are also going to be used when **converting the model** to an Accelerated Model that can run on FPGA's and for **making an inferencing request**. It is very important to save this information!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "register model from file" + ] + }, + "outputs": [], + "source": [ + "input_tensors = in_images.name\n", + "# We will use the list of output tensors during inferencing\n", + "output_tensors = [output.name for output in ssd_outputs]\n", + "# However, for multiple output tensors, our AccelOnnxConverter will \n", + "# accept comma-delimited strings (lists will cause error)\n", + "output_tensors_str = \",\".join(output_tensors)\n", + "\n", + "print(input_tensors)\n", + "print(output_tensors)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 3. Create AccelContainerImage\n", + "Below we will execute all the same steps as in the [Quickstart](accelerated-models-quickstart.ipynb) to package the model we have saved locally into an accelerated Docker image saved in our workspace. To complete all the steps, it may take a few minutes. For more details on each step, check out the [Quickstart section on model registration](accelerated-models-quickstart.ipynb#register-model)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core import Workspace\n", + "from azureml.core.model import Model\n", + "from azureml.core.image import Image\n", + "from azureml.accel import AccelOnnxConverter\n", + "from azureml.accel import AccelContainerImage\n", + "\n", + "# Retrieve workspace\n", + "ws = Workspace.from_config()\n", + "print(\"Successfully retrieved workspace:\", ws.name, ws.resource_group, ws.location, ws.subscription_id, '\\n')\n", + "\n", + "# Register model\n", + "registered_model = Model.register(workspace = ws,\n", + " model_path = model_save_path,\n", + " model_name = model_name)\n", + "print(\"Successfully registered: \", registered_model.name, registered_model.description, registered_model.version, '\\n', sep = '\\t')\n", + "\n", + "# Convert model\n", + "convert_request = AccelOnnxConverter.convert_tf_model(ws, registered_model, input_tensors, output_tensors_str)\n", + "# If it fails, you can run wait_for_completion again with show_output=True.\n", + "convert_request.wait_for_completion(show_output=False)\n", + "converted_model = convert_request.result\n", + "print(\"\\nSuccessfully converted: \", converted_model.name, converted_model.url, converted_model.version, \n", + " converted_model.id, converted_model.created_time, '\\n')\n", + "\n", + "# Package into AccelContainerImage\n", + "image_config = AccelContainerImage.image_configuration()\n", + "# Image name must be lowercase\n", + "image_name = \"{}-image\".format(model_name)\n", + "image = Image.create(name = image_name,\n", + " models = [converted_model],\n", + " image_config = image_config, \n", + " workspace = ws)\n", + "image.wait_for_creation()\n", + "print(\"Created AccelContainerImage: {} {} {}\\n\".format(image.name, image.creation_state, image.image_location))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 4. Deploy image\n", + "Once you have an Azure ML Accelerated Image in your Workspace, you can deploy it to two destinations, to a Databox Edge machine or to an AKS cluster. \n", + "\n", + "### 4.a. Deploy to Databox Edge Machine using IoT Hub\n", + "See the sample [here](https://github.com/Azure-Samples/aml-real-time-ai/) for using the Azure IoT CLI extension for deploying your Docker image to your Databox Edge Machine.\n", + "\n", + "### 4.b. Deploy to AKS Cluster\n", + "Same as in the [Quickstart section on image deployment](accelerated-models-quickstart.ipynb#deploy-image), we are going to create an AKS cluster with FPGA-enabled machines, then deploy our service to it.\n", + "#### Create AKS ComputeTarget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core.compute import AksCompute, ComputeTarget\n", + "\n", + "# Uses the specific FPGA enabled VM (sku: Standard_PB6s)\n", + "# Authentication is enabled by default, but for testing we specify False\n", + "prov_config = AksCompute.provisioning_configuration(vm_size = \"Standard_PB6s\",\n", + " agent_count = 1)\n", + "\n", + "aks_name = 'my-aks-pb6-ssd-vgg'\n", + "# Create the cluster\n", + "aks_target = ComputeTarget.create(workspace = ws, \n", + " name = aks_name, \n", + " provisioning_configuration = prov_config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Provisioning an AKS cluster might take awhile (15 or so minutes), and we want to wait until it's successfully provisioned before we can deploy a service to it. If you interrupt this cell, provisioning of the cluster will continue. You can re-run it or check the status in your Workspace under Compute." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "aks_target.wait_for_completion(show_output = True)\n", + "print(aks_target.provisioning_state)\n", + "print(aks_target.provisioning_errors)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Deploy AccelContainerImage to AKS ComputeTarget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core.webservice import Webservice, AksWebservice\n", + "\n", + "# Set the web service configuration (for creating a test service, we don't want autoscale enabled)\n", + "aks_config = AksWebservice.deploy_configuration(autoscale_enabled=False,\n", + " num_replicas=1,\n", + " auth_enabled = False)\n", + "\n", + "aks_service_name ='my-aks-service'\n", + "\n", + "aks_service = Webservice.deploy_from_image(workspace = ws,\n", + " name = aks_service_name,\n", + " image = image,\n", + " deployment_config = aks_config,\n", + " deployment_target = aks_target)\n", + "aks_service.wait_for_deployment(show_output = True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 5. Test the service\n", + "\n", + "### 5.a. Create Client\n", + "The image supports gRPC and the TensorFlow Serving \"predict\" API. We have a client that can call into the docker image to get predictions. \n", + "\n", + "**Note:** If you chose to use auth_enabled=True when creating your AksWebservice.deploy_configuration(), see documentation [here](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.webservice(class)?view=azure-ml-py#get-keys--) on how to retrieve your keys and use either key as an argument to PredictionClient(...,access_token=key)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Using the grpc client in AzureML Accelerated Models SDK\n", + "from azureml.accel.client import PredictionClient\n", + "\n", + "address = aks_service.scoring_uri\n", + "ssl_enabled = address.startswith(\"https\")\n", + "address = address[address.find('/')+2:].strip('/')\n", + "port = 443 if ssl_enabled else 80\n", + "\n", + "# Initialize AzureML Accelerated Models client\n", + "client = PredictionClient(address=address,\n", + " port=port,\n", + " use_ssl=ssl_enabled,\n", + " service_name=aks_service.name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can adapt the client [code](https://github.com/Azure/aml-real-time-ai/blob/master/pythonlib/amlrealtimeai/client.py) to meet your needs. There is also an example C# [client](https://github.com/Azure/aml-real-time-ai/blob/master/sample-clients/csharp).\n", + "\n", + "The service provides an API that is compatible with TensorFlow Serving. There are instructions to download a sample client [here](https://www.tensorflow.org/serving/setup)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 5.b. Serve the model\n", + "The SSD-VGG model returns the confidence and bounding boxes for all possible anchor boxes. As mentioned earlier, we will use a post-processing routine to transform this into a list of bounding boxes (y1, x1, y2, x2) where x, y are fractional coordinates measured from left and top respectively. A respective list of classes and scores is also returned to tag each bounding box. Below we make use of this information to draw the bounding boxes on top the original image. Note that in the post-processing routine we select a confidence threshold of 0.5." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import cv2\n", + "from matplotlib import pyplot as plt\n", + "\n", + "colors_tableau = [(255, 255, 255), (31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120),\n", + " (44, 160, 44), (152, 223, 138), (214, 39, 40), (255, 152, 150),\n", + " (148, 103, 189), (197, 176, 213), (140, 86, 75), (196, 156, 148),\n", + " (227, 119, 194), (247, 182, 210), (127, 127, 127), (199, 199, 199),\n", + " (188, 189, 34), (219, 219, 141), (23, 190, 207), (158, 218, 229)]\n", + "\n", + "\n", + "def draw_boxes_on_img(img, classes, scores, bboxes, thickness=2):\n", + " shape = img.shape\n", + " for i in range(bboxes.shape[0]):\n", + " bbox = bboxes[i]\n", + " color = colors_tableau[classes[i]]\n", + " # Draw bounding box...\n", + " p1 = (int(bbox[0] * shape[0]), int(bbox[1] * shape[1]))\n", + " p2 = (int(bbox[2] * shape[0]), int(bbox[3] * shape[1]))\n", + " cv2.rectangle(img, p1[::-1], p2[::-1], color, thickness)\n", + " # Draw text...\n", + " s = '%s/%.3f' % (classes[i], scores[i])\n", + " p1 = (p1[0]-5, p1[1])\n", + " cv2.putText(img, s, p1[::-1], cv2.FONT_HERSHEY_DUPLEX, 0.4, color, 1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import azureml.accel._external.ssdvgg_utils as ssdvgg_utils\n", + "\n", + "result = client.score_file(path=\"meeting.jpg\", input_name=input_tensors, outputs=output_tensors)\n", + "classes, scores, bboxes = ssdvgg_utils.postprocess(result, select_threshold=0.5)\n", + "\n", + "img = cv2.imread('meeting.jpg', 1)\n", + "img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n", + "draw_boxes_on_img(img, classes, scores, bboxes)\n", + "plt.imshow(img)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 6. Cleanup\n", + "It's important to clean up your resources, so that you won't incur unnecessary costs. In the [next notebook](accelerated-models-training.ipynb) you will learn how to train a classfier on a new dataset using transfer learning." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "aks_service.delete()\n", + "aks_target.delete()\n", + "image.delete()\n", + "registered_model.delete()\n", + "converted_model.delete()" + ] + } + ], + "metadata": { + "authors": [ + { + "name": "coverste" + }, + { + "name": "paledger" + }, + { + "name": "sukha" + } + ], + "kernelspec": { + "display_name": "Python 3.6", + "language": "python", + "name": "python36" + }, + "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.5.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/how-to-use-azureml/deployment/accelerated-models/accelerated-models-quickstart.ipynb b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-quickstart.ipynb new file mode 100644 index 00000000..46209333 --- /dev/null +++ b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-quickstart.ipynb @@ -0,0 +1,544 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Copyright (c) Microsoft Corporation. All rights reserved.\n", + "\n", + "Licensed under the MIT License." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Azure ML Hardware Accelerated Models Quickstart" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This tutorial will show you how to deploy an image recognition service based on the ResNet 50 classifier using the Azure Machine Learning Accelerated Models service. Get more information about our service from our [documentation](https://docs.microsoft.com/en-us/azure/machine-learning/service/concept-accelerate-with-fpgas) or [forum](https://aka.ms/aml-forum).\n", + "\n", + "We will use an accelerated ResNet50 featurizer running on an FPGA. Our Accelerated Models Service handles translating deep neural networks (DNN) into an FPGA program.\n", + "\n", + "For more information about using other models besides Resnet50, see the [README](./README.md).\n", + "\n", + "The steps covered in this notebook are: \n", + "1. [Set up environment](#set-up-environment)\n", + "* [Construct model](#construct-model)\n", + " * Image Preprocessing\n", + " * Featurizer (Resnet50)\n", + " * Classifier\n", + " * Save Model\n", + "* [Register Model](#register-model)\n", + "* [Convert into Accelerated Model](#convert-model)\n", + "* [Create Image](#create-image)\n", + "* [Deploy](#deploy-image)\n", + "* [Test service](#test-service)\n", + "* [Clean-up](#clean-up)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 1. Set up environment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import tensorflow as tf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Retrieve Workspace\n", + "If you haven't created a Workspace, please follow [this notebook](https://github.com/Azure/MachineLearningNotebooks/blob/master/configuration.ipynb) to do so. If you have, run the codeblock below to retrieve it. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core import Workspace\n", + "\n", + "ws = Workspace.from_config()\n", + "print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\\n')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 2. Construct model\n", + "\n", + "There are three parts to the model we are deploying: pre-processing, featurizer with ResNet50, and classifier with ImageNet dataset. Then we will save this complete Tensorflow model graph locally before registering it to your Azure ML Workspace.\n", + "\n", + "### 2.a. Image preprocessing\n", + "We'd like our service to accept JPEG images as input. However the input to ResNet50 is a tensor. So we need code that decodes JPEG images and does the preprocessing required by ResNet50. The Accelerated AI service can execute TensorFlow graphs as part of the service and we'll use that ability to do the image preprocessing. This code defines a TensorFlow graph that preprocesses an array of JPEG images (as strings) and produces a tensor that is ready to be featurized by ResNet50.\n", + "\n", + "**Note:** Expect to see TF deprecation warnings until we port our SDK over to use Tensorflow 2.0." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Input images as a two-dimensional tensor containing an arbitrary number of images represented a strings\n", + "import azureml.accel.models.utils as utils\n", + "tf.reset_default_graph()\n", + "\n", + "in_images = tf.placeholder(tf.string)\n", + "image_tensors = utils.preprocess_array(in_images)\n", + "print(image_tensors.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.b. Featurizer\n", + "We use ResNet50 as a featurizer. In this step we initialize the model. This downloads a TensorFlow checkpoint of the quantized ResNet50." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.accel.models import QuantizedResnet50\n", + "save_path = os.path.expanduser('~/models')\n", + "model_graph = QuantizedResnet50(save_path, is_frozen = True)\n", + "feature_tensor = model_graph.import_graph_def(image_tensors)\n", + "print(model_graph.version)\n", + "print(feature_tensor.name)\n", + "print(feature_tensor.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.c. Classifier\n", + "The model we downloaded includes a classifier which takes the output of the ResNet50 and identifies an image. This classifier is trained on the ImageNet dataset. We are going to use this classifier for our service. The next [notebook](project-brainwave-trainsfer-learning.ipynb) shows how to train a classifier for a different data set. The input to the classifier is a tensor matching the output of our ResNet50 featurizer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "classifier_output = model_graph.get_default_classifier(feature_tensor)\n", + "print(classifier_output)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.d. Save Model\n", + "Now that we loaded all three parts of the tensorflow graph (preprocessor, resnet50 featurizer, and the classifier), we can save the graph and associated variables to a directory which we can register as an Azure ML Model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# model_name must be lowercase\n", + "model_name = \"resnet50\"\n", + "model_save_path = os.path.join(save_path, model_name)\n", + "print(\"Saving model in {}\".format(model_save_path))\n", + "\n", + "with tf.Session() as sess:\n", + " model_graph.restore_weights(sess)\n", + " tf.saved_model.simple_save(sess, model_save_path,\n", + " inputs={'images': in_images},\n", + " outputs={'output_alias': classifier_output})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.e. Important! Save names of input and output tensors\n", + "\n", + "These input and output tensors that were created during the preprocessing and classifier steps are also going to be used when **converting the model** to an Accelerated Model that can run on FPGA's and for **making an inferencing request**. It is very important to save this information! You can see our defaults for all the models in the [README](./README.md).\n", + "\n", + "By default for Resnet50, these are the values you should see when running the cell below: \n", + "* input_tensors = \"Placeholder:0\"\n", + "* output_tensors = \"classifier/resnet_v1_50/predictions/Softmax:0\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "register model from file" + ] + }, + "outputs": [], + "source": [ + "input_tensors = in_images.name\n", + "output_tensors = classifier_output.name\n", + "\n", + "print(input_tensors)\n", + "print(output_tensors)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 3. Register Model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add tags and descriptions to your models. Using tags, you can track useful information such as the name and version of the machine learning library used to train the model. Note that tags must be alphanumeric." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "register model from file" + ] + }, + "outputs": [], + "source": [ + "from azureml.core.model import Model\n", + "\n", + "registered_model = Model.register(workspace = ws,\n", + " model_path = model_save_path,\n", + " model_name = model_name)\n", + "\n", + "print(\"Successfully registered: \", registered_model.name, registered_model.description, registered_model.version, sep = '\\t')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 4. Convert Model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For conversion you need to provide names of input and output tensors. This information can be found from the model_graph you saved in step 2.e. above.\n", + "\n", + "**Note**: Conversion may take a while and on average for FPGA model it is about 1-3 minutes and it depends on model type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "register model from file" + ] + }, + "outputs": [], + "source": [ + "from azureml.accel import AccelOnnxConverter\n", + "\n", + "convert_request = AccelOnnxConverter.convert_tf_model(ws, registered_model, input_tensors, output_tensors)\n", + "# If it fails, you can run wait_for_completion again with show_output=True.\n", + "convert_request.wait_for_completion(show_output = False)\n", + "# If the above call succeeded, get the converted model\n", + "converted_model = convert_request.result\n", + "print(\"\\nSuccessfully converted: \", converted_model.name, converted_model.url, converted_model.version, \n", + " converted_model.id, converted_model.created_time, '\\n')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 5. Package the model into an Image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add tags and descriptions to image. Also, for FPGA model an image can only contain **single** model.\n", + "\n", + "**Note**: The following command can take few minutes. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core.image import Image\n", + "from azureml.accel import AccelContainerImage\n", + "\n", + "image_config = AccelContainerImage.image_configuration()\n", + "# Image name must be lowercase\n", + "image_name = \"{}-image\".format(model_name)\n", + "\n", + "image = Image.create(name = image_name,\n", + " models = [converted_model],\n", + " image_config = image_config, \n", + " workspace = ws)\n", + "image.wait_for_creation(show_output = False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 6. Deploy\n", + "Once you have an Azure ML Accelerated Image in your Workspace, you can deploy it to two destinations, to a Databox Edge machine or to an AKS cluster. \n", + "\n", + "### 6.a. Databox Edge Machine using IoT Hub\n", + "See the sample [here](https://github.com/Azure-Samples/aml-real-time-ai/) for using the Azure IoT CLI extension for deploying your Docker image to your Databox Edge Machine.\n", + "\n", + "### 6.b. Azure Kubernetes Service (AKS) using Azure ML Service\n", + "We are going to create an AKS cluster with FPGA-enabled machines, then deploy our service to it. For more information, see [AKS official docs](https://docs.microsoft.com/en-us/azure/machine-learning/service/how-to-deploy-and-where#aks).\n", + "\n", + "#### Create AKS ComputeTarget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core.compute import AksCompute, ComputeTarget\n", + "\n", + "# Uses the specific FPGA enabled VM (sku: Standard_PB6s)\n", + "# Authentication is enabled by default, but for testing we specify False\n", + "prov_config = AksCompute.provisioning_configuration(vm_size = \"Standard_PB6s\",\n", + " agent_count = 1)\n", + "\n", + "aks_name = 'my-aks-pb6'\n", + "# Create the cluster\n", + "aks_target = ComputeTarget.create(workspace = ws, \n", + " name = aks_name, \n", + " provisioning_configuration = prov_config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Provisioning an AKS cluster might take awhile (15 or so minutes), and we want to wait until it's successfully provisioned before we can deploy a service to it. If you interrupt this cell, provisioning of the cluster will continue. You can also check the status in your Workspace under Compute." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "aks_target.wait_for_completion(show_output = True)\n", + "print(aks_target.provisioning_state)\n", + "print(aks_target.provisioning_errors)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Deploy AccelContainerImage to AKS ComputeTarget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core.webservice import Webservice, AksWebservice\n", + "\n", + "#Set the web service configuration (for creating a test service, we don't want autoscale enabled)\n", + "aks_config = AksWebservice.deploy_configuration(autoscale_enabled=False,\n", + " num_replicas=1,\n", + " auth_enabled = False)\n", + "\n", + "aks_service_name ='my-aks-service'\n", + "\n", + "aks_service = Webservice.deploy_from_image(workspace = ws,\n", + " name = aks_service_name,\n", + " image = image,\n", + " deployment_config = aks_config,\n", + " deployment_target = aks_target)\n", + "aks_service.wait_for_deployment(show_output = True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 7. Test the service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 7.a. Create Client\n", + "The image supports gRPC and the TensorFlow Serving \"predict\" API. We have a client that can call into the docker image to get predictions.\n", + "\n", + "**Note:** If you chose to use auth_enabled=True when creating your AksWebservice, see documentation [here](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.webservice(class)?view=azure-ml-py#get-keys--) on how to retrieve your keys and use either key as an argument to PredictionClient(...,access_token=key)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Using the grpc client in AzureML Accelerated Models SDK\n", + "from azureml.accel.client import PredictionClient\n", + "\n", + "address = aks_service.scoring_uri\n", + "ssl_enabled = address.startswith(\"https\")\n", + "address = address[address.find('/')+2:].strip('/')\n", + "port = 443 if ssl_enabled else 80\n", + "\n", + "# Initialize AzureML Accelerated Models client\n", + "client = PredictionClient(address=address,\n", + " port=port,\n", + " use_ssl=ssl_enabled,\n", + " service_name=aks_service.name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can adapt the client [code](https://github.com/Azure/aml-real-time-ai/blob/master/pythonlib/amlrealtimeai/client.py) to meet your needs. There is also an example C# [client](https://github.com/Azure/aml-real-time-ai/blob/master/sample-clients/csharp).\n", + "\n", + "The service provides an API that is compatible with TensorFlow Serving. There are instructions to download a sample client [here](https://www.tensorflow.org/serving/setup)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 7.b. Serve the model\n", + "To understand the results we need a mapping to the human readable imagenet classes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "classes_entries = requests.get(\"https://raw.githubusercontent.com/Lasagne/Recipes/master/examples/resnet50/imagenet_classes.txt\").text.splitlines()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Score image with input and output tensor names\n", + "results = client.score_file(path=\"./snowleopardgaze.jpg\", \n", + " input_name=input_tensors, \n", + " outputs=output_tensors)\n", + "\n", + "# map results [class_id] => [confidence]\n", + "results = enumerate(results)\n", + "# sort results by confidence\n", + "sorted_results = sorted(results, key=lambda x: x[1], reverse=True)\n", + "# print top 5 results\n", + "for top in sorted_results[:5]:\n", + " print(classes_entries[top[0]], 'confidence:', top[1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 8. Clean-up\n", + "Run the cell below to delete your webservice, image, and model (must be done in that order). In the [next notebook](project-brainwave-custom-weights.ipynb) you will learn how to train a classfier on a new dataset using transfer learning and finetune the weights." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "aks_service.delete()\n", + "aks_target.delete()\n", + "image.delete()\n", + "registered_model.delete()\n", + "converted_model.delete()" + ] + } + ], + "metadata": { + "authors": [ + { + "name": "coverste" + }, + { + "name": "paledger" + }, + { + "name": "aibhalla" + } + ], + "kernelspec": { + "display_name": "Python 3.6", + "language": "python", + "name": "python36" + }, + "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.5.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/how-to-use-azureml/deployment/accelerated-models/accelerated-models-training.ipynb b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-training.ipynb new file mode 100644 index 00000000..0b6bc349 --- /dev/null +++ b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-training.ipynb @@ -0,0 +1,849 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Copyright (c) Microsoft Corporation. All rights reserved.\n", + "\n", + "Licensed under the MIT License." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Training with the Azure Machine Learning Accelerated Models Service" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook will introduce how to apply common machine learning techniques, like transfer learning, custom weights, and unquantized vs. quantized models, when working with our Azure Machine Learning Accelerated Models Service (Azure ML Accel Models).\n", + "\n", + "We will use Tensorflow for the preprocessing steps, ResNet50 for the featurizer, and the Keras API (built on Tensorflow backend) to build the classifier layers instead of the default ImageNet classifier used in Quickstart. Then we will train the model, evaluate it, and deploy it to run on an FPGA.\n", + "\n", + "#### Transfer Learning and Custom weights\n", + "We will walk you through two ways to build and train a ResNet50 model on the Kaggle Cats and Dogs dataset: transfer learning only and then transfer learning with custom weights.\n", + "\n", + "In using transfer learning, our goal is to re-purpose the ResNet50 model already trained on the [ImageNet image dataset](http://www.image-net.org/) as a basis for our training of the Kaggle Cats and Dogs dataset. The ResNet50 featurizer will be imported as frozen, so only the Keras classifier will be trained.\n", + "\n", + "With the addition of custom weights, we will build the model so that the ResNet50 featurizer weights as not frozen. This will let us retrain starting with custom weights trained with ImageNet on ResNet50 and then use the Kaggle Cats and Dogs dataset to retrain and fine-tune the quantized version of the model.\n", + "\n", + "#### Unquantized vs. Quantized models\n", + "The unquantized version of our models (ie. Resnet50, Resnet152, Densenet121, Vgg16, SsdVgg) uses native float precision (32-bit floats), which will be faster at training. We will use this for our first run through, then fine-tune the weights with the quantized version. The quantized version of our models (i.e. QuantizedResnet50, QuantizedResnet152, QuantizedDensenet121, QuantizedVgg16, QuantizedSsdVgg) will have the same node names as the unquantized version, but use quantized operations and will match the performance of the model when running on an FPGA.\n", + "\n", + "#### Contents\n", + "1. [Setup Environment](#setup)\n", + "* [Prepare Data](#prepare-data)\n", + "* [Construct Model](#construct-model)\n", + " * Preprocessor\n", + " * Classifier\n", + " * Model construction\n", + "* [Train Model](#train-model)\n", + "* [Test Model](#test-model)\n", + "* [Execution](#execution)\n", + " * [Transfer Learning](#transfer-learning)\n", + " * [Transfer Learning with Custom Weights](#custom-weights)\n", + "* [Create Image](#create-image)\n", + "* [Deploy Model](#deploy-model)\n", + "* [Test the service](#test-service)\n", + "* [Clean-up](#cleanup)\n", + "* [Appendix](#appendix)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 1. Setup Environment\n", + "#### 1.a. Please set up your environment as described in the [Quickstart](project-brainwave-quickstart.ipynb), meaning:\n", + "* Make sure your Workspace config.json exists and has the correct info\n", + "* Install Tensorflow\n", + "\n", + "#### 1.b. Download dataset into ~/catsanddogs \n", + "The dataset we will be using for training can be downloaded [here](https://www.microsoft.com/en-us/download/details.aspx?id=54765). Download the zip and extract to a directory named 'catsanddogs' under your user directory (\"~/catsanddogs\"). \n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 1.c. Import packages" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import tensorflow as tf\n", + "import numpy as np\n", + "from keras import backend as K\n", + "import sklearn\n", + "import tqdm" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 1.d. Create directories for later use\n", + "After you train your model in float32, you'll write the weights to a place on disk. We also need a location to store the models that get downloaded." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "custom_weights_dir = os.path.expanduser(\"~/custom-weights\")\n", + "saved_model_dir = os.path.expanduser(\"~/models\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 2. Prepare Data\n", + "Load the files we are going to use for training and testing. By default this notebook uses only a very small subset of the Cats and Dogs dataset. That makes it run relatively quickly." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import glob\n", + "import imghdr\n", + "datadir = os.path.expanduser(\"~/catsanddogs\")\n", + "\n", + "cat_files = glob.glob(os.path.join(datadir, 'PetImages', 'Cat', '*.jpg'))\n", + "dog_files = glob.glob(os.path.join(datadir, 'PetImages', 'Dog', '*.jpg'))\n", + "\n", + "# Limit the data set to make the notebook execute quickly.\n", + "cat_files = cat_files[:64]\n", + "dog_files = dog_files[:64]\n", + "\n", + "# The data set has a few images that are not jpeg. Remove them.\n", + "cat_files = [f for f in cat_files if imghdr.what(f) == 'jpeg']\n", + "dog_files = [f for f in dog_files if imghdr.what(f) == 'jpeg']\n", + "\n", + "if(not len(cat_files) or not len(dog_files)):\n", + " print(\"Please download the Kaggle Cats and Dogs dataset form https://www.microsoft.com/en-us/download/details.aspx?id=54765 and extract the zip to \" + datadir) \n", + " raise ValueError(\"Data not found\")\n", + "else:\n", + " print(cat_files[0])\n", + " print(dog_files[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Construct a numpy array as labels\n", + "image_paths = cat_files + dog_files\n", + "total_files = len(cat_files) + len(dog_files)\n", + "labels = np.zeros(total_files)\n", + "labels[len(cat_files):] = 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Split images data as training data and test data\n", + "from sklearn.model_selection import train_test_split\n", + "onehot_labels = np.array([[0,1] if i else [1,0] for i in labels])\n", + "img_train, img_test, label_train, label_test = train_test_split(image_paths, onehot_labels, random_state=42, shuffle=True)\n", + "\n", + "print(len(img_train), len(img_test), label_train.shape, label_test.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 3. Construct Model\n", + "We will define the functions to handle creating the preprocessor and the classifier first, and then run them together to actually construct the model with the Resnet50 featurizer in a single Tensorflow session in a separate cell.\n", + "\n", + "We use ResNet50 for the featurizer and build our own classifier using Keras layers. We train the featurizer and the classifier as one model. We will provide parameters to determine whether we are using the quantized version and whether we are using custom weights in training or not." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.a. Define image preprocessing step\n", + "Same as in the Quickstart, before passing image dataset to the ResNet50 featurizer, we need to preprocess the input file to get it into the form expected by ResNet50. ResNet50 expects float tensors representing the images in BGR, channel last order. We've provided a default implementation of the preprocessing that you can use.\n", + "\n", + "**Note:** Expect to see TF deprecation warnings until we port our SDK over to use Tensorflow 2.0." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import azureml.accel.models.utils as utils\n", + "\n", + "def preprocess_images(scaling_factor=1.0):\n", + " # Convert images to 3D tensors [width,height,channel] - channels are in BGR order.\n", + " in_images = tf.placeholder(tf.string)\n", + " image_tensors = utils.preprocess_array(in_images, 'RGB', scaling_factor)\n", + " return in_images, image_tensors" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.b. Define classifier\n", + "We use Keras layer APIs to construct the classifier. Because we're using the tensorflow backend, we can train this classifier in one session with our Resnet50 model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def construct_classifier(in_tensor, seed=None):\n", + " from keras.layers import Dropout, Dense, Flatten\n", + " from keras.initializers import glorot_uniform\n", + " K.set_session(tf.get_default_session())\n", + "\n", + " FC_SIZE = 1024\n", + " NUM_CLASSES = 2\n", + "\n", + " x = Dropout(0.2, input_shape=(1, 1, int(in_tensor.shape[3]),), seed=seed)(in_tensor)\n", + " x = Dense(FC_SIZE, activation='relu', input_dim=(1, 1, int(in_tensor.shape[3]),),\n", + " kernel_initializer=glorot_uniform(seed=seed), bias_initializer='zeros')(x)\n", + " x = Flatten()(x)\n", + " preds = Dense(NUM_CLASSES, activation='softmax', input_dim=FC_SIZE, name='classifier_output',\n", + " kernel_initializer=glorot_uniform(seed=seed), bias_initializer='zeros')(x)\n", + " return preds" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.c. Define model construction\n", + "Now that the preprocessor and classifier for the model are defined, we can define how we want to construct the model. \n", + "\n", + "Constructing the model has these steps: \n", + "1. Get preprocessing steps\n", + "* Get featurizer using the Azure ML Accel Models SDK:\n", + " * import the graph definition\n", + " * restore the weights of the model into a Tensorflow session\n", + "* Get classifier\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def construct_model(quantized, starting_weights_directory = None):\n", + " from azureml.accel.models import Resnet50, QuantizedResnet50\n", + " \n", + " # Convert images to 3D tensors [width,height,channel]\n", + " in_images, image_tensors = preprocess_images(1.0)\n", + "\n", + " # Construct featurizer using quantized or unquantized ResNet50 model\n", + " if not quantized:\n", + " featurizer = Resnet50(saved_model_dir)\n", + " else:\n", + " featurizer = QuantizedResnet50(saved_model_dir, custom_weights_directory = starting_weights_directory)\n", + "\n", + " features = featurizer.import_graph_def(input_tensor=image_tensors)\n", + " \n", + " # Construct classifier\n", + " preds = construct_classifier(features)\n", + " \n", + " # Initialize weights\n", + " sess = tf.get_default_session()\n", + " tf.global_variables_initializer().run()\n", + "\n", + " featurizer.restore_weights(sess)\n", + "\n", + " return in_images, image_tensors, features, preds, featurizer" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 4. Train Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def read_files(files):\n", + " \"\"\" Read files to array\"\"\"\n", + " contents = []\n", + " for path in files:\n", + " with open(path, 'rb') as f:\n", + " contents.append(f.read())\n", + " return contents" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def train_model(preds, in_images, img_train, label_train, is_retrain = False, train_epoch = 10, learning_rate=None):\n", + " \"\"\" training model \"\"\"\n", + " from keras.objectives import binary_crossentropy\n", + " from tqdm import tqdm\n", + " \n", + " learning_rate = learning_rate if learning_rate else 0.001 if is_retrain else 0.01\n", + " \n", + " # Specify the loss function\n", + " in_labels = tf.placeholder(tf.float32, shape=(None, 2)) \n", + " cross_entropy = tf.reduce_mean(binary_crossentropy(in_labels, preds))\n", + " optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cross_entropy)\n", + "\n", + " def chunks(a, b, n):\n", + " \"\"\"Yield successive n-sized chunks from a and b.\"\"\"\n", + " if (len(a) != len(b)):\n", + " print(\"a and b are not equal in chunks(a,b,n)\")\n", + " raise ValueError(\"Parameter error\")\n", + "\n", + " for i in range(0, len(a), n):\n", + " yield a[i:i + n], b[i:i + n]\n", + "\n", + " chunk_size = 16\n", + " chunk_num = len(label_train) / chunk_size\n", + "\n", + " sess = tf.get_default_session()\n", + " for epoch in range(train_epoch):\n", + " avg_loss = 0\n", + " for img_chunk, label_chunk in tqdm(chunks(img_train, label_train, chunk_size)):\n", + " contents = read_files(img_chunk)\n", + " _, loss = sess.run([optimizer, cross_entropy],\n", + " feed_dict={in_images: contents,\n", + " in_labels: label_chunk,\n", + " K.learning_phase(): 1})\n", + " avg_loss += loss / chunk_num\n", + " print(\"Epoch:\", (epoch + 1), \"loss = \", \"{:.3f}\".format(avg_loss))\n", + " \n", + " # Reach desired performance\n", + " if (avg_loss < 0.001):\n", + " break" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 5. Test Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def test_model(preds, in_images, img_test, label_test):\n", + " \"\"\"Test the model\"\"\"\n", + " from keras.metrics import categorical_accuracy\n", + "\n", + " in_labels = tf.placeholder(tf.float32, shape=(None, 2))\n", + " accuracy = tf.reduce_mean(categorical_accuracy(in_labels, preds))\n", + " contents = read_files(img_test)\n", + "\n", + " accuracy = accuracy.eval(feed_dict={in_images: contents,\n", + " in_labels: label_test,\n", + " K.learning_phase(): 0})\n", + " return accuracy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 6. Execute steps\n", + "You can run through the Transfer Learning section, then skip to Model Deployment. By default, because the custom weights section takes much longer for training twice, it is all saved as Raw NBConvert mode. This means it is not executable, but you can change them to Code type to run through them.\n", + "\n", + "\n", + "### 6.a. Training using Transfer Learning" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Launch the training\n", + "tf.reset_default_graph()\n", + "sess = tf.Session(graph=tf.get_default_graph())\n", + "\n", + "with sess.as_default():\n", + " in_images, image_tensors, features, preds, featurizer = construct_model(quantized=True)\n", + " train_model(preds, in_images, img_train, label_train, is_retrain=False, train_epoch=10, learning_rate=0.01) \n", + " accuracy = test_model(preds, in_images, img_test, label_test) \n", + " print(\"Accuracy:\", accuracy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Save Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model_name = 'resnet50-catsanddogs-tl'\n", + "model_save_path = os.path.join(saved_model_dir, model_name)\n", + "\n", + "tf.saved_model.simple_save(sess, model_save_path,\n", + " inputs={'images': in_images},\n", + " outputs={'output_alias': preds})\n", + "\n", + "input_tensors = in_images.name\n", + "output_tensors = preds.name\n", + "\n", + "print(input_tensors)\n", + "print(output_tensors)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 6.b. Traning using Custom Weights\n", + "\n", + "Because the quantized graph defintion and the float32 graph defintion share the same node names in the graph definitions, we can initally train the weights in float32, and then reload them with the quantized operations (which take longer) to fine-tune the model.\n", + "\n", + "First we train the model with custom weights but without quantization. Training is done with native float precision (32-bit floats). We load the training data set and batch the training with 10 epochs. When the performance reaches desired level or starts decredation, we stop the training iteration and save the weights as tensorflow checkpoint files. " + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "# Launch the training\n", + "tf.reset_default_graph()\n", + "sess = tf.Session(graph=tf.get_default_graph())\n", + "\n", + "with sess.as_default():\n", + " in_images, image_tensors, features, preds, featurizer = construct_model(quantized=False)\n", + " train_model(preds, in_images, img_train, label_train, is_retrain=False, train_epoch=10) \n", + " accuracy = test_model(preds, in_images, img_test, label_test) \n", + " print(\"Accuracy:\", accuracy)\n", + " featurizer.save_weights(custom_weights_dir + \"/rn50\", tf.get_default_session())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Test Model\n", + "After training, we evaluate the trained model's accuracy on test dataset with quantization. So that we know the model's performance if it is deployed on the FPGA." + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "tf.reset_default_graph()\n", + "sess = tf.Session(graph=tf.get_default_graph())\n", + "\n", + "with sess.as_default():\n", + " print(\"Testing trained model with quantization\")\n", + " in_images, image_tensors, features, preds, quantized_featurizer = construct_model(quantized=True, starting_weights_directory=custom_weights_dir)\n", + " accuracy = test_model(preds, in_images, img_test, label_test) \n", + " print(\"Accuracy:\", accuracy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Fine-Tune Model\n", + "Sometimes, the model's accuracy can drop significantly after quantization. In those cases, we need to retrain the model enabled with quantization to get better model accuracy." + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "if (accuracy < 0.93):\n", + " with sess.as_default():\n", + " print(\"Fine-tuning model with quantization\")\n", + " train_model(preds, in_images, img_train, label_train, is_retrain=True, train_epoch=10)\n", + " accuracy = test_model(preds, in_images, img_test, label_test) \n", + " print(\"Accuracy:\", accuracy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Save Model" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "model_name = 'resnet50-catsanddogs-cw'\n", + "model_save_path = os.path.join(saved_model_dir, model_name)\n", + "\n", + "tf.saved_model.simple_save(sess, model_save_path,\n", + " inputs={'images': in_images},\n", + " outputs={'output_alias': preds})\n", + "\n", + "input_tensors = in_images.name\n", + "output_tensors = preds.name" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 7. Create AccelContainerImage\n", + "Below we will execute all the same steps as in the [Quickstart](accelerated-models-quickstart.ipynb) to package the model we have saved locally into an accelerated Docker image saved in our workspace. To complete all the steps, it may take a few minutes. For more details on each step, check out the [Quickstart section on model registration](accelerated-models-quickstart.ipynb#register-model)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core import Workspace\n", + "from azureml.core.model import Model\n", + "from azureml.core.image import Image\n", + "from azureml.accel import AccelOnnxConverter\n", + "from azureml.accel import AccelContainerImage\n", + "\n", + "# Retrieve workspace\n", + "ws = Workspace.from_config()\n", + "print(\"Successfully retrieved workspace:\", ws.name, ws.resource_group, ws.location, ws.subscription_id, '\\n')\n", + "\n", + "# Register model\n", + "registered_model = Model.register(workspace = ws,\n", + " model_path = model_save_path,\n", + " model_name = model_name)\n", + "print(\"Successfully registered: \", registered_model.name, registered_model.description, registered_model.version, '\\n', sep = '\\t')\n", + "\n", + "# Convert model\n", + "convert_request = AccelOnnxConverter.convert_tf_model(ws, registered_model, input_tensors, output_tensors)\n", + "# If it fails, you can run wait_for_completion again with show_output=True.\n", + "convert_request.wait_for_completion(show_output=False)\n", + "converted_model = convert_request.result\n", + "print(\"\\nSuccessfully converted: \", converted_model.name, converted_model.url, converted_model.version, \n", + " converted_model.id, converted_model.created_time, '\\n')\n", + "\n", + "# Package into AccelContainerImage\n", + "image_config = AccelContainerImage.image_configuration()\n", + "# Image name must be lowercase\n", + "image_name = \"{}-image\".format(model_name)\n", + "image = Image.create(name = image_name,\n", + " models = [converted_model],\n", + " image_config = image_config, \n", + " workspace = ws)\n", + "image.wait_for_creation()\n", + "print(\"Created AccelContainerImage: {} {} {}\\n\".format(image.name, image.creation_state, image.image_location))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 8. Deploy image\n", + "Once you have an Azure ML Accelerated Image in your Workspace, you can deploy it to two destinations, to a Databox Edge machine or to an AKS cluster. \n", + "\n", + "### 8.a. Deploy to Databox Edge Machine using IoT Hub\n", + "See the sample [here](https://github.com/Azure-Samples/aml-real-time-ai/) for using the Azure IoT CLI extension for deploying your Docker image to your Databox Edge Machine.\n", + "\n", + "### 8.b. Deploy to AKS Cluster" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Create AKS ComputeTarget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core.compute import AksCompute, ComputeTarget\n", + "\n", + "# Uses the specific FPGA enabled VM (sku: Standard_PB6s)\n", + "# Authentication is enabled by default, but for testing we specify False\n", + "prov_config = AksCompute.provisioning_configuration(vm_size = \"Standard_PB6s\",\n", + " agent_count = 1)\n", + "\n", + "aks_name = 'my-aks-pb6-training'\n", + "# Create the cluster\n", + "aks_target = ComputeTarget.create(workspace = ws, \n", + " name = aks_name, \n", + " provisioning_configuration = prov_config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Provisioning an AKS cluster might take awhile (15 or so minutes), and we want to wait until it's successfully provisioned before we can deploy a service to it. If you interrupt this cell, provisioning of the cluster will continue. You can re-run it or check the status in your Workspace under Compute." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "aks_target.wait_for_completion(show_output = True)\n", + "print(aks_target.provisioning_state)\n", + "print(aks_target.provisioning_errors)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Deploy AccelContainerImage to AKS ComputeTarget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core.webservice import Webservice, AksWebservice\n", + "\n", + "# Set the web service configuration (for creating a test service, we don't want autoscale enabled)\n", + "aks_config = AksWebservice.deploy_configuration(autoscale_enabled=False,\n", + " num_replicas=1,\n", + " auth_enabled = False)\n", + "\n", + "aks_service_name ='my-aks-service'\n", + "\n", + "aks_service = Webservice.deploy_from_image(workspace = ws,\n", + " name = aks_service_name,\n", + " image = image,\n", + " deployment_config = aks_config,\n", + " deployment_target = aks_target)\n", + "aks_service.wait_for_deployment(show_output = True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 9. Test the service\n", + "\n", + "\n", + "### 9.a. Create Client\n", + "The image supports gRPC and the TensorFlow Serving \"predict\" API. We have a client that can call into the docker image to get predictions. \n", + "\n", + "**Note:** If you chose to use auth_enabled=True when creating your AksWebservice.deploy_configuration(), see documentation [here](https://docs.microsoft.com/en-us/python/api/azureml-core/azureml.core.webservice(class)?view=azure-ml-py#get-keys--) on how to retrieve your keys and use either key as an argument to PredictionClient(...,access_token=key)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Using the grpc client in AzureML Accelerated Models SDK\n", + "from azureml.accel.client import PredictionClient\n", + "\n", + "address = aks_service.scoring_uri\n", + "ssl_enabled = address.startswith(\"https\")\n", + "address = address[address.find('/')+2:].strip('/')\n", + "port = 443 if ssl_enabled else 80\n", + "\n", + "# Initialize AzureML Accelerated Models client\n", + "client = PredictionClient(address=address,\n", + " port=port,\n", + " use_ssl=ssl_enabled,\n", + " service_name=aks_service.name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 9.b. Serve the model\n", + "Let's see how our service does on a few images. It may get a few wrong." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Specify an image to classify\n", + "print('CATS')\n", + "for image_file in cat_files[:8]:\n", + " results = client.score_file(path=image_file, \n", + " input_name=input_tensors, \n", + " outputs=output_tensors)\n", + " result = 'CORRECT ' if results[0] > results[1] else 'WRONG '\n", + " print(result + str(results))\n", + "print('DOGS')\n", + "for image_file in dog_files[:8]:\n", + " results = client.score_file(path=image_file, \n", + " input_name=input_tensors, \n", + " outputs=output_tensors)\n", + " result = 'CORRECT ' if results[1] > results[0] else 'WRONG '\n", + " print(result + str(results))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 10. Cleanup\n", + "It's important to clean up your resources, so that you won't incur unnecessary costs." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "aks_service.delete()\n", + "aks_target.delete()\n", + "image.delete()\n", + "registered_model.delete()\n", + "converted_model.delete()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 11. Appendix" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "License for plot_confusion_matrix:\n", + "\n", + "New BSD License\n", + "\n", + "Copyright (c) 2007-2018 The scikit-learn developers.\n", + "All rights reserved.\n", + "\n", + "\n", + "Redistribution and use in source and binary forms, with or without\n", + "modification, are permitted provided that the following conditions are met:\n", + "\n", + " a. Redistributions of source code must retain the above copyright notice,\n", + " this list of conditions and the following disclaimer.\n", + " b. Redistributions in binary form must reproduce the above copyright\n", + " notice, this list of conditions and the following disclaimer in the\n", + " documentation and/or other materials provided with the distribution.\n", + " c. Neither the name of the Scikit-learn Developers nor the names of\n", + " its contributors may be used to endorse or promote products\n", + " derived from this software without specific prior written\n", + " permission. \n", + "\n", + "\n", + "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n", + "AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n", + "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n", + "ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR\n", + "ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n", + "DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n", + "SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n", + "CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n", + "LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n", + "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\n", + "DAMAGE.\n" + ] + } + ], + "metadata": { + "authors": [ + { + "name": "coverste" + }, + { + "name": "paledger" + } + ], + "kernelspec": { + "display_name": "Python 3.6", + "language": "python", + "name": "python36" + }, + "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.5.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/how-to-use-azureml/deployment/accelerated-models/meeting.jpg b/how-to-use-azureml/deployment/accelerated-models/meeting.jpg new file mode 100644 index 0000000000000000000000000000000000000000..af8654f08c105e881dee4a8a49d588078acbf65b GIT binary patch literal 75394 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

MJ@xNnt6-gne@lFZ@Db#rB*HFcUOY_ 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 literal 0 HcmV?d00001 diff --git a/how-to-use-azureml/deployment/accelerated-models/snowleopardgaze.jpg b/how-to-use-azureml/deployment/accelerated-models/snowleopardgaze.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3c5ebf9b88b4d95edf4bc4e787c18f6d72e81dd7 GIT binary patch literal 80556 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 H|0ezi@yXK@ literal 0 HcmV?d00001 From 0fffa11b2a66e09f2bb111e713ef213f4000e044 Mon Sep 17 00:00:00 2001 From: Paula Ledgerwood Date: Mon, 29 Apr 2019 10:20:55 -0700 Subject: [PATCH 2/2] Update links and code formatting --- .../deployment/accelerated-models/README.md | 41 +++++++++++++------ .../accelerated-models-object-detection.ipynb | 8 ++-- .../accelerated-models-quickstart.ipynb | 8 ++-- .../accelerated-models-training.ipynb | 35 ++++++++++------ 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/how-to-use-azureml/deployment/accelerated-models/README.md b/how-to-use-azureml/deployment/accelerated-models/README.md index fca1fba5..23ad499b 100644 --- a/how-to-use-azureml/deployment/accelerated-models/README.md +++ b/how-to-use-azureml/deployment/accelerated-models/README.md @@ -9,7 +9,7 @@ Easily create and train a model using various deep neural networks (DNNs) as a f * VGG-16 * SSD-VGG -To learn more about the azureml-accel-model classes, see the section [Model Classes](#model-classes) below or the [Azure ML Python SDK documentation](https://docs.microsoft.com/en-us/python/api/overview/azure/ml/intro?view=azure-ml-py). +To learn more about the azureml-accel-model classes, see the section [Model Classes](#model-classes) below or the [Azure ML Accel Models SDK documentation](https://docs.microsoft.com/en-us/python/api/azureml-accel-models/azureml.accel?view=azure-ml-py). ### Step 1: Create an Azure ML workspace Follow [these instructions](https://docs.microsoft.com/en-us/azure/machine-learning/service/quickstart-create-workspace-with-python) to install the Azure ML SDK on your local machine, create an Azure ML workspace, and set up your notebook environment, which is required for the next step. @@ -19,21 +19,21 @@ Once you have set up your environment, install the Azure ML Accel Models SDK. Th If you already have tensorflow >= 1.6,<2.0 installed in your development environment, you can install the SDK package using: -`` +``` pip install azureml-accel-models -`` +``` If you do not have tensorflow >= 1.6,<2.0 and are using a CPU-only development environment, our SDK with tensorflow can be installed using: -`` +``` pip install azureml-accel-models[cpu] -`` +``` If your machine supports GPU (for example, on an [Azure DSVM](https://docs.microsoft.com/en-us/azure/machine-learning/data-science-virtual-machine/overview)), then you can leverage the tensorflow-gpu functionality using: -`` +``` pip install azureml-accel-models[gpu] -`` +``` ### Step 3: Follow our notebooks @@ -49,13 +49,28 @@ As stated above, we support 5 Accelerated Models. Here's more information on the **Available models and output tensors** The available models and the corresponding default classifier output tensors are below. This is the value that you would use during inferencing if you used the default classifier. -* Resnet50, QuantizedResnet50 (output_tensors = "classifier_1/resnet_v1_50/predictions/Softmax:0") -* Resnet152, QuantizedResnet152 (output_tensors = "classifier/resnet_v1_152/predictions/Softmax:0") -* Densenet121, QuantizedDensenet121 (output_tensors = "classifier/densenet121/predictions/Softmax:0") -* Vgg16, QuantizedVgg16 (output_tensors = "classifier/vgg_16/fc8/squeezed:0") -* SsdVgg, QuantizedSsdVgg (output_tensors = ['ssd_300_vgg/block4_box/Reshape_1:0', 'ssd_300_vgg/block7_box/Reshape_1:0', 'ssd_300_vgg/block8_box/Reshape_1:0', 'ssd_300_vgg/block9_box/Reshape_1:0', 'ssd_300_vgg/block10_box/Reshape_1:0', 'ssd_300_vgg/block11_box/Reshape_1:0', 'ssd_300_vgg/block4_box/Reshape:0', 'ssd_300_vgg/block7_box/Reshape:0', 'ssd_300_vgg/block8_box/Reshape:0', 'ssd_300_vgg/block9_box/Reshape:0', 'ssd_300_vgg/block10_box/Reshape:0', 'ssd_300_vgg/block11_box/Reshape:0']) +* Resnet50, QuantizedResnet50 +`` +output_tensors = "classifier_1/resnet_v1_50/predictions/Softmax:0" +`` +* Resnet152, QuantizedResnet152 +`` +output_tensors = "classifier/resnet_v1_152/predictions/Softmax:0" +`` +* Densenet121, QuantizedDensenet121 +`` +output_tensors = "classifier/densenet121/predictions/Softmax:0" +`` +* Vgg16, QuantizedVgg16 +`` +output_tensors = "classifier/vgg_16/fc8/squeezed:0" +`` +* SsdVgg, QuantizedSsdVgg +`` +output_tensors = ['ssd_300_vgg/block4_box/Reshape_1:0', 'ssd_300_vgg/block7_box/Reshape_1:0', 'ssd_300_vgg/block8_box/Reshape_1:0', 'ssd_300_vgg/block9_box/Reshape_1:0', 'ssd_300_vgg/block10_box/Reshape_1:0', 'ssd_300_vgg/block11_box/Reshape_1:0', 'ssd_300_vgg/block4_box/Reshape:0', 'ssd_300_vgg/block7_box/Reshape:0', 'ssd_300_vgg/block8_box/Reshape:0', 'ssd_300_vgg/block9_box/Reshape:0', 'ssd_300_vgg/block10_box/Reshape:0', 'ssd_300_vgg/block11_box/Reshape:0'] +`` -For more information, please reference the azureml.accel.models package in the [Azure ML Python SDK documentation](https://docs.microsoft.com/en-us/python/api/overview/azure/ml/?view=azure-ml-py). +For more information, please reference the azureml.accel.models package in the [Azure ML Python SDK documentation](https://docs.microsoft.com/en-us/python/api/azureml-accel-models/azureml.accel.models?view=azure-ml-py). **Input tensors** diff --git a/how-to-use-azureml/deployment/accelerated-models/accelerated-models-object-detection.ipynb b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-object-detection.ipynb index 4338aa67..be6894e8 100644 --- a/how-to-use-azureml/deployment/accelerated-models/accelerated-models-object-detection.ipynb +++ b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-object-detection.ipynb @@ -203,7 +203,7 @@ "source": [ "\n", "## 3. Create AccelContainerImage\n", - "Below we will execute all the same steps as in the [Quickstart](accelerated-models-quickstart.ipynb) to package the model we have saved locally into an accelerated Docker image saved in our workspace. To complete all the steps, it may take a few minutes. For more details on each step, check out the [Quickstart section on model registration](accelerated-models-quickstart.ipynb#register-model)." + "Below we will execute all the same steps as in the [Quickstart](./accelerated-models-quickstart.ipynb#create-image) to package the model we have saved locally into an accelerated Docker image saved in our workspace. To complete all the steps, it may take a few minutes. For more details on each step, check out the [Quickstart section on model registration](./accelerated-models-quickstart.ipynb#register-model)." ] }, { @@ -260,7 +260,7 @@ "See the sample [here](https://github.com/Azure-Samples/aml-real-time-ai/) for using the Azure IoT CLI extension for deploying your Docker image to your Databox Edge Machine.\n", "\n", "### 4.b. Deploy to AKS Cluster\n", - "Same as in the [Quickstart section on image deployment](accelerated-models-quickstart.ipynb#deploy-image), we are going to create an AKS cluster with FPGA-enabled machines, then deploy our service to it.\n", + "Same as in the [Quickstart section on image deployment](./accelerated-models-quickstart.ipynb#deploy-image), we are going to create an AKS cluster with FPGA-enabled machines, then deploy our service to it.\n", "#### Create AKS ComputeTarget" ] }, @@ -438,7 +438,7 @@ "source": [ "\n", "## 6. Cleanup\n", - "It's important to clean up your resources, so that you won't incur unnecessary costs. In the [next notebook](accelerated-models-training.ipynb) you will learn how to train a classfier on a new dataset using transfer learning." + "It's important to clean up your resources, so that you won't incur unnecessary costs. In the [next notebook](./accelerated-models-training.ipynb) you will learn how to train a classfier on a new dataset using transfer learning." ] }, { @@ -482,7 +482,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.6" + "version": "3.6.0" } }, "nbformat": 4, diff --git a/how-to-use-azureml/deployment/accelerated-models/accelerated-models-quickstart.ipynb b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-quickstart.ipynb index 46209333..fb6c4976 100644 --- a/how-to-use-azureml/deployment/accelerated-models/accelerated-models-quickstart.ipynb +++ b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-quickstart.ipynb @@ -20,7 +20,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This tutorial will show you how to deploy an image recognition service based on the ResNet 50 classifier using the Azure Machine Learning Accelerated Models service. Get more information about our service from our [documentation](https://docs.microsoft.com/en-us/azure/machine-learning/service/concept-accelerate-with-fpgas) or [forum](https://aka.ms/aml-forum).\n", + "This tutorial will show you how to deploy an image recognition service based on the ResNet 50 classifier using the Azure Machine Learning Accelerated Models service. Get more information about our service from our [documentation](https://docs.microsoft.com/en-us/azure/machine-learning/service/concept-accelerate-with-fpgas), [API reference](https://docs.microsoft.com/en-us/python/api/azureml-accel-models/azureml.accel?view=azure-ml-py), or [forum](https://aka.ms/aml-forum).\n", "\n", "We will use an accelerated ResNet50 featurizer running on an FPGA. Our Accelerated Models Service handles translating deep neural networks (DNN) into an FPGA program.\n", "\n", @@ -137,7 +137,7 @@ "metadata": {}, "source": [ "### 2.c. Classifier\n", - "The model we downloaded includes a classifier which takes the output of the ResNet50 and identifies an image. This classifier is trained on the ImageNet dataset. We are going to use this classifier for our service. The next [notebook](project-brainwave-trainsfer-learning.ipynb) shows how to train a classifier for a different data set. The input to the classifier is a tensor matching the output of our ResNet50 featurizer." + "The model we downloaded includes a classifier which takes the output of the ResNet50 and identifies an image. This classifier is trained on the ImageNet dataset. We are going to use this classifier for our service. The next [notebook](./accelerated-models-training.ipynb) shows how to train a classifier for a different data set. The input to the classifier is a tensor matching the output of our ResNet50 featurizer." ] }, { @@ -492,7 +492,7 @@ "source": [ "\n", "## 8. Clean-up\n", - "Run the cell below to delete your webservice, image, and model (must be done in that order). In the [next notebook](project-brainwave-custom-weights.ipynb) you will learn how to train a classfier on a new dataset using transfer learning and finetune the weights." + "Run the cell below to delete your webservice, image, and model (must be done in that order). In the [next notebook](./accelerated-models-training.ipynb) you will learn how to train a classfier on a new dataset using transfer learning and finetune the weights." ] }, { @@ -536,7 +536,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.6" + "version": "3.6.0" } }, "nbformat": 4, diff --git a/how-to-use-azureml/deployment/accelerated-models/accelerated-models-training.ipynb b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-training.ipynb index 0b6bc349..f0d645fe 100644 --- a/how-to-use-azureml/deployment/accelerated-models/accelerated-models-training.ipynb +++ b/how-to-use-azureml/deployment/accelerated-models/accelerated-models-training.ipynb @@ -59,7 +59,7 @@ "source": [ "\n", "## 1. Setup Environment\n", - "#### 1.a. Please set up your environment as described in the [Quickstart](project-brainwave-quickstart.ipynb), meaning:\n", + "#### 1.a. Please set up your environment as described in the [Quickstart](./accelerated-models-quickstart.ipynb), meaning:\n", "* Make sure your Workspace config.json exists and has the correct info\n", "* Install Tensorflow\n", "\n", @@ -398,7 +398,7 @@ "source": [ "\n", "## 6. Execute steps\n", - "You can run through the Transfer Learning section, then skip to Model Deployment. By default, because the custom weights section takes much longer for training twice, it is all saved as Raw NBConvert mode. This means it is not executable, but you can change them to Code type to run through them.\n", + "You can run through the Transfer Learning section, then skip to Create AccelContainerImage. By default, because the custom weights section takes much longer for training twice, it is not saved as executable cells. You can copy the code or change cell type to 'Code'.\n", "\n", "\n", "### 6.a. Training using Transfer Learning" @@ -461,10 +461,11 @@ ] }, { - "cell_type": "raw", + "cell_type": "markdown", "metadata": {}, "source": [ - "# Launch the training\n", + "#### Launch the training\n", + "```\n", "tf.reset_default_graph()\n", "sess = tf.Session(graph=tf.get_default_graph())\n", "\n", @@ -473,7 +474,8 @@ " train_model(preds, in_images, img_train, label_train, is_retrain=False, train_epoch=10) \n", " accuracy = test_model(preds, in_images, img_test, label_test) \n", " print(\"Accuracy:\", accuracy)\n", - " featurizer.save_weights(custom_weights_dir + \"/rn50\", tf.get_default_session())" + " featurizer.save_weights(custom_weights_dir + \"/rn50\", tf.get_default_session())\n", + "```" ] }, { @@ -485,9 +487,10 @@ ] }, { - "cell_type": "raw", + "cell_type": "markdown", "metadata": {}, "source": [ + "```\n", "tf.reset_default_graph()\n", "sess = tf.Session(graph=tf.get_default_graph())\n", "\n", @@ -495,7 +498,8 @@ " print(\"Testing trained model with quantization\")\n", " in_images, image_tensors, features, preds, quantized_featurizer = construct_model(quantized=True, starting_weights_directory=custom_weights_dir)\n", " accuracy = test_model(preds, in_images, img_test, label_test) \n", - " print(\"Accuracy:\", accuracy)" + " print(\"Accuracy:\", accuracy)\n", + "```" ] }, { @@ -507,15 +511,17 @@ ] }, { - "cell_type": "raw", + "cell_type": "markdown", "metadata": {}, "source": [ + "```\n", "if (accuracy < 0.93):\n", " with sess.as_default():\n", " print(\"Fine-tuning model with quantization\")\n", " train_model(preds, in_images, img_train, label_train, is_retrain=True, train_epoch=10)\n", " accuracy = test_model(preds, in_images, img_test, label_test) \n", - " print(\"Accuracy:\", accuracy)" + " print(\"Accuracy:\", accuracy)\n", + "```" ] }, { @@ -526,9 +532,10 @@ ] }, { - "cell_type": "raw", + "cell_type": "markdown", "metadata": {}, "source": [ + "```\n", "model_name = 'resnet50-catsanddogs-cw'\n", "model_save_path = os.path.join(saved_model_dir, model_name)\n", "\n", @@ -537,7 +544,8 @@ " outputs={'output_alias': preds})\n", "\n", "input_tensors = in_images.name\n", - "output_tensors = preds.name" + "output_tensors = preds.name\n", + "```" ] }, { @@ -546,7 +554,8 @@ "source": [ "\n", "## 7. Create AccelContainerImage\n", - "Below we will execute all the same steps as in the [Quickstart](accelerated-models-quickstart.ipynb) to package the model we have saved locally into an accelerated Docker image saved in our workspace. To complete all the steps, it may take a few minutes. For more details on each step, check out the [Quickstart section on model registration](accelerated-models-quickstart.ipynb#register-model)." + "\n", + "Below we will execute all the same steps as in the [Quickstart](./accelerated-models-quickstart.ipynb#create-image) to package the model we have saved locally into an accelerated Docker image saved in our workspace. To complete all the steps, it may take a few minutes. For more details on each step, check out the [Quickstart section on model registration](./accelerated-models-quickstart.ipynb#register-model)." ] }, { @@ -841,7 +850,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.6" + "version": "3.6.0" } }, "nbformat": 4,