PyTorch iOS Runtime 101

Using PyTorch on iOS: A Comprehensive Guide

Welcome to our tutorial on using PyTorch on iOS. I'm Tao, a software engineer on the PyTorch Mobile team, and I'll be guiding you through this comprehensive guide.

Improvements and New Features in PyTorch 1.9

Before we dive into the demo, let's quickly introduce some of the new features we released in PyTorch 1.9. These include mobile interpreter, Metal back-end, custom builds, and Torch Vision Ops. We'll be covering most of these features in this demo. If you want to learn more, please refer to our in-depth tutorials and demo apps.

Setting Up the Project

To follow along, you need PyTorch Ice Cream version 12 or higher on macOS, Cocoapods installed on your machine, and an Apple Developer account with an iOS device running at least iOS 12. You should also be using PyTorch 1.9 or higher. Let's set up the project to include Python iOS Runtime.

First, we need to install PyTorch Ice Cream. Once installed, open a terminal and run `pip3 install torch torchvision` to install the required packages. Next, create a new folder for your project and navigate to it in the terminal. Create a new file called `requirements.txt` and add `torch torchvision numpy pandas` to it.

Now, let's install Cocoapods by running `gem install cocoapods` in the terminal. After installing Cocoapods, we can install PyTorch iOS Runtime using `pod init`. This will create a new `Podfile` in your project directory.

We need to specify that we want to use PyTorch 1.9 and enable the Python iOS Runtime by adding the following lines to our `Podfile`:

```ruby

target 'YourProject' do

pod 'PyTorch/Python', :path => '../Python'

end

```

Now, let's run `pod install` to install PyTorch iOS Runtime.

Resizing and Normalizing Images

To prepare the input image for our model, we need to resize it to 2x2 by 2x2 and normalize it. We can do this using the following Python code:

```python

import torch

from PIL import Image

def resize_image(image):

return image.resize((2, 2))

def normalize_image(image):

return image.convert('L').point(lambda x: min(255, max(0, x)))

image = Image.open('input_image.jpg')

resized_image = resize_image(image)

normalized_image = normalize_image(resized_image)

# Convert the normalized image to a tensor

tensor = torch.from_numpy(normalized_image).float()

```

Creating and Training the Model

Next, we'll create and train our model using PyTorch. We'll use a simple convolutional neural network (CNN) as an example.

```python

import torch.nn as nn

class CNN(nn.Module):

def __init__(self):

super(CNN, self).__init__()

self.conv1 = nn.Conv2d(1, 10, kernel_size=5)

self.pool = nn.MaxPool2d(2, 2)

self.fc1 = nn.Linear(320, 50)

self.fc2 = nn.Linear(50, 10)

def forward(self, x):

x = self.pool(torch.relu(self.conv1(x)))

x = x.view(-1, 320)

x = torch.relu(self.fc1(x))

x = self.fc2(x)

return x

model = CNN()

criterion = nn.CrossEntropyLoss()

optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

for epoch in range(10):

optimizer.zero_grad()

outputs = model(tensor)

loss = criterion(outputs, torch.tensor([1]))

loss.backward()

optimizer.step()

print('Epoch {}: Loss = {:.4f}'.format(epoch+1, loss.item()))

```

Running the Model on GPU

To run our model on the GPU, we need to install PyTorch Nightly Builds. We'll also update our Cocoapods to use the nightly build.

```bash

pip3 install torch torchvision --upgrade --pre

pod update --repo-url https://github.com/pytorch/pytorch.git --update-binary-dependencies

```

Next, let's make some changes to our Python script to run the model on the GPU. We'll add a `metal` parameter to the `optimize_for_mobile` function and specify the GPU back-end as `Metal`.

```python

import torch

def optimize_for_mobile(model, tensor):

return model.optimize_for_mobile(metal=True)

model = CNN()

tensor = torch.randn(1, 1, 28, 28)

gpu_model = optimize_for_mobile(model, tensor)

# Update Cocoapods to use the nightly build

pod update --repo-url https://github.com/pytorch/pytorch.git --update-binary-dependencies

# Open the Xcode project and add the GPU back-end

```

Using Custom Build to Reduce Binary Size

To reduce the binary size of our app, we can create a custom library that only contains the operators we need. We'll use PyTorch's `operator` module to dump the root operators from our model and save them to a YAML file.

```python

import torch

from pytorchOperators import get_root_operators

def dump_operators(model):

operators = get_root_operators(model)

with open('operators.yaml', 'w') as f:

for operator in operators:

f.write(str(operator) + '\n')

model = CNN()

dump_operators(model)

# Use the YAML file to build our custom library

```

We'll use PyTorch's `operator` module to generate a Python repository checkout from GitHub. We'll then run the `build` command on the screen.

```bash

python3 -m pip install --pre install-pytorch-operators

git clone https://github.com/pytorch/pytorch.git pytorch-operators

cd pytorch-operators

./configure --with-oplayers=/path/to/operations.yaml --prefix=/path/to/build/dir

```

We can then add the custom library to our `Podfile` using the following lines:

```ruby

target 'YourProject' do

pod 'PyTorch/Python', :path => '../Python'

end

target 'YourProject' do

pod 'PyTorch/Operators', :path => '../operators'

end

```

Now, let's run `pod install` to install our custom library.

Conclusion

In this tutorial, we've learned how to create and train a PyTorch model using a convolutional neural network (CNN) as an example. We've also learned how to run the model on the GPU and use a custom library to reduce the binary size of our app.

"WEBVTTKind: captionsLanguage: enwelcome to the 2021 high torch annual hack my name is tao i'm a software engineer on pytorch mobile team in this video i'll be talking about how to use pytorch on ios some of the improvements we made last year and this year finally i'll be showing you a demo of how to use pytorch to build an image classification knob the pi towards ios runtime is a c plot plus static library that have been installed using cocoapods we provide an end-to-end workflow that allows you to further optimize your model to get most performance out of the device i'll be walking through how to use python apis in the diagram in the following demo before we dive into the demo i'd like to quickly introduce some of the new features we released in 1.9 which includes mobile interpreter the metal back-end custom builds and torch vision ops we'll be covering most of these features in the demo if you want to learn more please refer to our in-depth tutorials and the demo apps in this demo we'll be building an image classification app using a pre-trained mobilenas v2 model from torch vision to follow along you need ice cold version 12 or higher on mic os you need to have cocoapods installed on your machine and if you want to deploy to the device you need an apple developer account in an ios device running at least ios 12. you should also be using high torque 1.9 or higher in particular i'll show you how to set up the project to include python ios runtime how to export your model to torscript the optimized python model format how to further optimize your model to for better performance how to call the model from your code how to run your model on ios gpu and finally i'll be showing you how to use the custom build to reduce the size of your app let's dive in so first thing first let's install python on your machine to do that i'm going to create a new kunda environment you also need to install numpy now let's install pytorch cool now pi torch has been successfully installed next in this python script i'll be showing you how to setup and optimize your model for pytorch mobile the model we are going to use is a pre-trained mobile v2 from torque vision to run this model on device we need to convert it to its first grid format note i come out of the evol here to turn off things in the model you don't want during the inference time training only layers like dropout and autograph are now supported on mobile next we use pytorch mobile optimizer to further optimize the model this optimized for mobile apis runs a list of optimization passes on the graph such as drop of removal comrade fusion and other optimizations to learn more about this function please refer to our tutorial linked at the end of the presentation finally let's save the model to disk the underscore save for light interpreter is a new api we introduced in 1.9 a six hour tour screen model in a light interpreter compatible format now let's run the script cool now we have our model prepared let's go back to xcode in this actual project we are going to use our model to build an image classifier let's quickly run the code and see what the app looks like as you can see we are trying to predict the category of this image so how can we do that using pytorch let's start off by installing the cocoapods lip torch library first we need to add lip sword slide to our pod file and then run pod install now we are going to close the project file and open up the workspace file now how do we call python from raw code since the lib torch library is implemented in c plus plus swift cannot interact with it directly so we need to create an object wrapper as a bridge i'm going to copy the red profiles from the resource folder you can find the link to all resources in our demo app on github iscode is going to ask me to creating this bridging header and uh just click yes in this bridging header we are going to import torch module.h so you can see in the health there are only two methods that are really interesting one which initialize the python's runtime with the model passed as a parameter and the second one does the actual prediction when you pass in the pointer of an image buffer and here we are using the load for mobile to load our model this is our new mobile interpreter api introduced in 1.9 and we should always use this api to load models that were saved for light interpreter okay now let's go back to the view controller let's first load our model next i'm going to load labels from a text file which contains 1000 categories that the model recognized again you can find these files in the demo apps on github we are ready to add inference code since we don't want to block the main thread we will dispatch the inference to the background thread so the first step is to resize the input image to 2 to 4 by 2 to 4 and normalize it this normalization method is a category method on your image and next we take the image buffer and pass it to module.predict after that we retrieve the label from the predict category and display the top three results in textview now let's run the app cool there we are the model thinks the wolf is a wolf in this part of the video i'm going to show you how to run your model on ios gpu let's first install the pi torsionally builds now let's make some changes to our python script as you can see here i added a second parameter to the optimize for mobile function and metal is the name of our ios gpu back-end and i also give our a model with the new name now let's run the script again now we have our gpu model converted we need to update our cocoapods to use the nightly build as well let's add a new pod target to our pod file but before we do pod install we need to remove the existing cocoa box information from our project then we can do part update now let's open up the actual project the first thing we need to do is to make some changes to our object c wrapper to run the model on gpu we need to call down manual to move the input tensor from cpu to gpu and call cpu to move the output tensor back from gpu to cpu now let's go back to the view controller to load our model now let's run the app cool we got the same result from our gpu model in the last part of the tutorial i'm going to show you how to use custom build to reduce the size of your app by default the leapfrog library contains all pi torch operators but your model may only need a few of them so it would be great if you can have a library that only contains the operators we want so how can we do that instead of using the static library from cocoapods this time we are going to build custom libraries from python source code but before we jump into the detail we need to figure out how to get operators we want from the model let's go back to our python script as you can see here i dump the root operators from the 12 screen model and save them to a yaml file let's run the script now we have this yama file generated let's use it to build our custom library here i have a python repository checkout from github make sure you are in the root directory and run the build command on the screen since you are building everything from source this building process could take a while to finish now let's copy the library files and hydro files to our project folder before we open the xcode we need to remove the cocoapods information from the project file we can do that using part d integrate cool now let's open the xcode the first thing we need to do is to add our custom libraries and headers to the project next i'm going to do a few configurations to set up xcode to make sure our libraries can be loaded properly all these steps have been documented in our ios tutorial the last step is to make some changes to our object wrapper here we need to manually include the headers we need now let's run the app as you can see we got the same results the custom library works however this time the binary size is much smaller you can check out the number by clicking the binary inside the app file we have lots of resources if you are interested in learning more uh our tutorial a mobile optimizer tutorial a mobile interpreter tutorial and all our ios demo apps i've linked all resources mentioned in this tutorial in the comments section of the video thank you for watching our video today we hope it was helpful good luck on the hackathon\n"