|
| 1 | +# Tutorial: Getting started with torch-neuron (resnet-50 tutorial) |
| 2 | + |
| 3 | +## Steps Overview: |
| 4 | + |
| 5 | +1. Launch an EC2 compilation instance (recommended instance: c5.4xlarge or larger) |
| 6 | +2. Install Torch-Neuron and Neuron-Compiler on the Compilation Instance |
| 7 | +3. Compile the compute-graph on the compilation-instance, and copy the artifacts into the deployment-instance |
| 8 | +4. Install Torch-Neuron and Neuron-Runtime on Inf1 (deployment Instance) |
| 9 | +5. Run inference on the Inf1 instance |
| 10 | + |
| 11 | +## Step 1: Launch EC2 compilation instance |
| 12 | + |
| 13 | +A typical workflow with the Neuron SDK will be to compile trained ML models on a general compute instance (the compilation instance), and then distribute the artifacts to a fleet of Inf1 instances (the deployment instances) for inference execution. Neuron enables PyTorch for both of these steps. |
| 14 | + |
| 15 | +1.1. Select an AMI of your choice. This may be may be Ubuntu 16.x, Ubuntu 18.x, Amazon Linux 2 based on the Deep Learning AMI (DLAMI). |
| 16 | + |
| 17 | +1.2. Select and launch an EC2 instance |
| 18 | + |
| 19 | +* A c5.4xlarge or larger is recommended. For this example we will use a c5.4xlarge. |
| 20 | +* Users may choose to compile and deploy on the same instance, in which case an inf1.6xlarge instance or larger is recommended. If you choose “launch instance” and search for “neuron” in the AWS EC2 console you will see a short list of the DLAMI images to select from. |
| 21 | + |
| 22 | +## Step 2: Compilation instance installations |
| 23 | + |
| 24 | +Install both Neuron Compiler and Torch-Neuron on the compilation instance. |
| 25 | + |
| 26 | +2.1. Install Python3 virtual environment module if needed: |
| 27 | + |
| 28 | +If using an Ubuntu DLAMI: |
| 29 | + |
| 30 | +``` |
| 31 | +# Ubuntu |
| 32 | +sudo apt-get update |
| 33 | +sudo apt-get install -y python3-venv g++ |
| 34 | +``` |
| 35 | + |
| 36 | +Note: If you see the following errors during apt-get install, please wait a minute or so for background updates to finish and retry apt-get install: |
| 37 | + |
| 38 | +``` |
| 39 | +E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable) |
| 40 | +E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it? |
| 41 | +``` |
| 42 | + |
| 43 | +If using Amazon Linux 2 DLAMI: |
| 44 | + |
| 45 | +``` |
| 46 | +# Amazon Linux 2 |
| 47 | +sudo yum update |
| 48 | +sudo yum install -y python3 gcc-c++ |
| 49 | +``` |
| 50 | + |
| 51 | +2.2. Create a tutorial folder and cd into it |
| 52 | + |
| 53 | +``` |
| 54 | +mkdir -p tutorial |
| 55 | +cd tutorial |
| 56 | +``` |
| 57 | + |
| 58 | +2.3. Setup a new Python virtual environment: |
| 59 | + |
| 60 | +``` |
| 61 | +python3 -m venv test_venv |
| 62 | +source test_venv/bin/activate |
| 63 | +pip install -U pip |
| 64 | +``` |
| 65 | + |
| 66 | +2.4. Modify Pip repository configurations to point to the Neuron repository. |
| 67 | + |
| 68 | +``` |
| 69 | +tee $VIRTUAL_ENV/pip.conf > /dev/null <<EOF |
| 70 | +[global] |
| 71 | +extra-index-url = https://pip.repos.neuron.amazonaws.com |
| 72 | +EOF |
| 73 | +``` |
| 74 | + |
| 75 | +2.5. Install Torch-Neuron and Neuron Compiler |
| 76 | + |
| 77 | +``` |
| 78 | +pip install torch-neuron |
| 79 | +``` |
| 80 | + |
| 81 | +``` |
| 82 | +# Install compiler. |
| 83 | +# NOTE: please make sure tensorflow option is provided; this is not necessary for inference-only purposes. |
| 84 | +pip install neuron-cc[tensorflow] |
| 85 | +``` |
| 86 | + |
| 87 | +2.6 Install torchvision for the pretrained resnet50 model (we use no-deps here because we already have Neuron version of torch installed through torch-neuron) |
| 88 | + |
| 89 | +``` |
| 90 | +pip install pillow |
| 91 | +
|
| 92 | +# We use the --no-deps here to prevent torchvision installing standard torch |
| 93 | +pip install torchvision --no-deps |
| 94 | +``` |
| 95 | + |
| 96 | +## Step 3: Compile on compilation instance |
| 97 | + |
| 98 | +A trained model must be compiled to Inferentia target before it can be deployed on Inf1 instances. In this step we compile the torchvision ResNet50 model and export it as a SavedModel which is in the torchscript format for PyTorch models. |
| 99 | + |
| 100 | +3.1. Create a python script named `trace_resnet50.py` with the following content: |
| 101 | + |
| 102 | +``` |
| 103 | +import torch |
| 104 | +import numpy as np |
| 105 | +import os |
| 106 | +from urllib import request |
| 107 | +
|
| 108 | +from torchvision import models, transforms, datasets |
| 109 | +
|
| 110 | +import torch_neuron |
| 111 | +
|
| 112 | +## Create an image directory containing a small kitten |
| 113 | +os.makedirs("./images", exist_ok=True) |
| 114 | +request.urlretrieve("https://raw.githubusercontent.com/awslabs/mxnet-model-server/master/docs/images/kitten_small.jpg", |
| 115 | + "./images/kitten_small.jpg") |
| 116 | +
|
| 117 | +## Import our image and normalize it into a tensor |
| 118 | +normalize = transforms.Normalize( |
| 119 | + mean=[0.485, 0.456, 0.406], |
| 120 | + std=[0.229, 0.224, 0.225]) |
| 121 | +
|
| 122 | +eval_dataset = datasets.ImageFolder( |
| 123 | + os.path.dirname('./'), |
| 124 | + transforms.Compose([ |
| 125 | + transforms.Resize([224, 224]), |
| 126 | + transforms.ToTensor(), |
| 127 | + normalize, |
| 128 | + ]) |
| 129 | +) |
| 130 | +
|
| 131 | +image, _ = eval_dataset[0] |
| 132 | +image = torch.tensor(image.numpy()[np.newaxis, ...]) |
| 133 | +
|
| 134 | +## Load a pretrained ResNet50 model |
| 135 | +model = models.resnet50(pretrained=True) |
| 136 | +
|
| 137 | +## Tell the model we are using it for evaluation (not training) |
| 138 | +model.eval() |
| 139 | +
|
| 140 | +model_neuron = torch.neuron.trace(model, example_inputs=[image]) |
| 141 | +
|
| 142 | +model_neuron.save( "resnet50_neuron.pt" ) |
| 143 | +``` |
| 144 | + |
| 145 | + |
| 146 | +3.2. Run the compilation script, which will take a few minutes on c5.4xlarge. At the end of script execution, the compiled SavedModel is zipped as `resnet50_neuron.pt` in local directory: |
| 147 | + |
| 148 | +``` |
| 149 | +python trace_resnet50.py |
| 150 | +``` |
| 151 | + |
| 152 | +You should see: |
| 153 | + |
| 154 | +``` |
| 155 | +INFO:Neuron:compiling module ResNet with neuron-cc |
| 156 | +``` |
| 157 | + |
| 158 | +3.3 **WARNING**: If you run the inference script below on you CPU instance you will get output, but see this warning: |
| 159 | + |
| 160 | +``` |
| 161 | +[E neuron_op_impl.cpp:53] Warning: Tensor output are *** NOT CALCULATED *** during CPU |
| 162 | +execution and only indicate tensor shape |
| 163 | +``` |
| 164 | + |
| 165 | +This is an artifact of the way we trace a model on your compile instance. **Do not perform inference with a neuron traced model on a non neuron supported instance, results will not be calculated.** |
| 166 | + |
| 167 | +3.4. If not compiling and inferring on the same instance, copy the compiled artifacts to the inference server: |
| 168 | + |
| 169 | +``` |
| 170 | +scp -i <PEM key file> ./resnet50_neuron.pt ubuntu@<instance DNS>:~/ # if Ubuntu-based AMI |
| 171 | +scp -i <PEM key file> ./resnet50_neuron.pt ec2-user@<instance DNS>:~/ # if using AML2-based AMI |
| 172 | +``` |
| 173 | + |
| 174 | +## Step 4: Deployment Instance Installations |
| 175 | + |
| 176 | +On the instance you are going to use for inference, install Torch-Neuron and Neuron Runtime |
| 177 | + |
| 178 | +4.1. Follow Step 2 above to install Torch-Neuron. |
| 179 | + |
| 180 | +* Install neuron-cc[tensorflow] if compilation on inference instance is desired (see notes above on recommended Inf1 sizes for compilation) |
| 181 | +* Skip neuron-cc if compilation is not done on inference instance |
| 182 | + |
| 183 | +4.2. Install the Neuron Runtime using instructions from [Getting started: Installing and Configuring Neuron-RTD](https://github.com/aws/aws-neuron-sdk/blob/master/docs/neuron-runtime/nrt_start.md). |
| 184 | + |
| 185 | + |
| 186 | +## Step 5: Run inference |
| 187 | + |
| 188 | +In this step we run inference on inf1 instances using the model compiled in Step 3. |
| 189 | + |
| 190 | +5.1. On the inf1, create a inference Python script named `infer_resnet50.py` with the following content: |
| 191 | + |
| 192 | + |
| 193 | +``` |
| 194 | +import os |
| 195 | +import time |
| 196 | +import torch |
| 197 | +import torch_neuron |
| 198 | +import json |
| 199 | +import numpy as np |
| 200 | +
|
| 201 | +from urllib import request |
| 202 | +
|
| 203 | +from torchvision import models, transforms, datasets |
| 204 | +
|
| 205 | +## Create an image directory containing a small kitten |
| 206 | +os.makedirs("./images", exist_ok=True) |
| 207 | +request.urlretrieve("https://raw.githubusercontent.com/awslabs/mxnet-model-server/master/docs/images/kitten_small.jpg", |
| 208 | + "./images/kitten_small.jpg") |
| 209 | +
|
| 210 | +
|
| 211 | +## Fetch labels to output the top classifications |
| 212 | +request.urlretrieve("https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json","imagenet_class_index.json") |
| 213 | +idx2label = [] |
| 214 | +
|
| 215 | +with open("imagenet_class_index.json", "r") as read_file: |
| 216 | + `class_idx `**`=`**` json`**`.`**`load``(``read_file``)` |
| 217 | + idx2label = [class_idx[str(k)][1] for k in range(len(class_idx))] |
| 218 | +
|
| 219 | +## Import a sample image and normalize it into a tensor |
| 220 | +normalize = transforms.Normalize( |
| 221 | + mean=[0.485, 0.456, 0.406], |
| 222 | + std=[0.229, 0.224, 0.225]) |
| 223 | +
|
| 224 | +eval_dataset = datasets.ImageFolder( |
| 225 | + os.path.dirname("./"), |
| 226 | + transforms.Compose([ |
| 227 | + transforms.Resize([224, 224]), |
| 228 | + transforms.ToTensor(), |
| 229 | + normalize, |
| 230 | + ]) |
| 231 | +) |
| 232 | +
|
| 233 | +image, _ = eval_dataset[0] |
| 234 | +image = torch.tensor(image.numpy()[np.newaxis, ...]) |
| 235 | +
|
| 236 | +## Load model |
| 237 | +model_neuron = torch.jit.load( 'resnet50_neuron.pt' ) |
| 238 | +
|
| 239 | +## Predict |
| 240 | +results = model_neuron( image ) |
| 241 | +
|
| 242 | +# Get the top 5 results |
| 243 | +top5_idx = results[0].sort()[1][-5:] |
| 244 | +
|
| 245 | +# Lookup and print the top 5 labels |
| 246 | +top5_labels = [idx2label[idx] for idx in top5_idx] |
| 247 | +
|
| 248 | +print("Top 5 labels:\n {}".format(top5_labels) ) |
| 249 | +``` |
| 250 | + |
| 251 | + |
| 252 | +5.2. Run the inference: |
| 253 | + |
| 254 | +``` |
| 255 | +['tiger', 'lynx', 'tiger_cat', 'Egyptian_cat', 'tabby'] |
| 256 | +``` |
| 257 | + |
| 258 | +## Step 6: Terminate instances |
| 259 | + |
| 260 | +Don’t forget to terminate your instances (compile and inference) from the AWS console so that you don’t continue paying for them once you are done |
0 commit comments